btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_renderer_scanline.h
blob615fffb42b52e7471e133583d974cc83c52595b0
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 #ifndef AGG_RENDERER_SCANLINE_INCLUDED
17 #define AGG_RENDERER_SCANLINE_INCLUDED
19 #include "agg_basics.h"
20 #include "agg_renderer_base.h"
22 namespace agg
25 //================================================render_scanline_aa_solid
26 template<class Scanline, class BaseRenderer, class ColorT>
27 void render_scanline_aa_solid(const Scanline& sl,
28 BaseRenderer& ren,
29 const ColorT& color)
31 int y = sl.y();
32 unsigned num_spans = sl.num_spans();
33 typename Scanline::const_iterator span = sl.begin();
35 for(;;)
37 int x = span->x;
38 if(span->len > 0)
40 ren.blend_solid_hspan(x, y, (unsigned)span->len,
41 color,
42 span->covers);
44 else
46 ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
47 color,
48 *(span->covers));
50 if(--num_spans == 0) break;
51 ++span;
55 //===============================================render_scanlines_aa_solid
56 template<class Rasterizer, class Scanline,
57 class BaseRenderer, class ColorT>
58 void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl,
59 BaseRenderer& ren, const ColorT& color)
61 if(ras.rewind_scanlines())
63 // Explicitly convert "color" to the BaseRenderer color type.
64 // For example, it can be called with color type "rgba", while
65 // "rgba8" is needed. Otherwise it will be implicitly
66 // converted in the loop many times.
67 //----------------------
68 typename BaseRenderer::color_type ren_color(color);
70 sl.reset(ras.min_x(), ras.max_x());
71 while(ras.sweep_scanline(sl))
73 //render_scanline_aa_solid(sl, ren, ren_color);
75 // This code is equivalent to the above call (copy/paste).
76 // It's just a "manual" optimization for old compilers,
77 // like Microsoft Visual C++ v6.0
78 //-------------------------------
79 int y = sl.y();
80 unsigned num_spans = sl.num_spans();
81 typename Scanline::const_iterator span = sl.begin();
83 for(;;)
85 int x = span->x;
86 if(span->len > 0)
88 ren.blend_solid_hspan(x, y, (unsigned)span->len,
89 ren_color,
90 span->covers);
92 else
94 ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
95 ren_color,
96 *(span->covers));
98 if(--num_spans == 0) break;
99 ++span;
105 //==============================================renderer_scanline_aa_solid
106 template<class BaseRenderer> class renderer_scanline_aa_solid
108 public:
109 typedef BaseRenderer base_ren_type;
110 typedef typename base_ren_type::color_type color_type;
112 //--------------------------------------------------------------------
113 renderer_scanline_aa_solid() : m_ren(0) {}
114 renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
115 void attach(base_ren_type& ren)
117 m_ren = &ren;
120 //--------------------------------------------------------------------
121 void color(const color_type& c) { m_color = c; }
122 const color_type& color() const { return m_color; }
124 //--------------------------------------------------------------------
125 void prepare() {}
127 //--------------------------------------------------------------------
128 template<class Scanline> void render(const Scanline& sl)
130 render_scanline_aa_solid(sl, *m_ren, m_color);
133 private:
134 base_ren_type* m_ren;
135 color_type m_color;
150 //======================================================render_scanline_aa
151 template<class Scanline, class BaseRenderer,
152 class SpanAllocator, class SpanGenerator>
153 void render_scanline_aa(const Scanline& sl, BaseRenderer& ren,
154 SpanAllocator& alloc, SpanGenerator& span_gen)
156 int y = sl.y();
158 unsigned num_spans = sl.num_spans();
159 typename Scanline::const_iterator span = sl.begin();
160 for(;;)
162 int x = span->x;
163 int len = span->len;
164 const typename Scanline::cover_type* covers = span->covers;
166 if(len < 0) len = -len;
167 typename BaseRenderer::color_type* colors = alloc.allocate(len);
168 span_gen.generate(colors, x, y, len);
169 ren.blend_color_hspan(x, y, len, colors,
170 (span->len < 0) ? 0 : covers, *covers);
172 if(--num_spans == 0) break;
173 ++span;
177 //=====================================================render_scanlines_aa
178 template<class Rasterizer, class Scanline, class BaseRenderer,
179 class SpanAllocator, class SpanGenerator>
180 void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
181 SpanAllocator& alloc, SpanGenerator& span_gen)
183 if(ras.rewind_scanlines())
185 sl.reset(ras.min_x(), ras.max_x());
186 span_gen.prepare();
187 while(ras.sweep_scanline(sl))
189 render_scanline_aa(sl, ren, alloc, span_gen);
194 //====================================================renderer_scanline_aa
195 template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
196 class renderer_scanline_aa
198 public:
199 typedef BaseRenderer base_ren_type;
200 typedef SpanAllocator alloc_type;
201 typedef SpanGenerator span_gen_type;
203 //--------------------------------------------------------------------
204 renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {}
205 renderer_scanline_aa(base_ren_type& ren,
206 alloc_type& alloc,
207 span_gen_type& span_gen) :
208 m_ren(&ren),
209 m_alloc(&alloc),
210 m_span_gen(&span_gen)
212 void attach(base_ren_type& ren,
213 alloc_type& alloc,
214 span_gen_type& span_gen)
216 m_ren = &ren;
217 m_alloc = &alloc;
218 m_span_gen = &span_gen;
221 //--------------------------------------------------------------------
222 void prepare() { m_span_gen->prepare(); }
224 //--------------------------------------------------------------------
225 template<class Scanline> void render(const Scanline& sl)
227 render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen);
230 private:
231 base_ren_type* m_ren;
232 alloc_type* m_alloc;
233 span_gen_type* m_span_gen;
241 //===============================================render_scanline_bin_solid
242 template<class Scanline, class BaseRenderer, class ColorT>
243 void render_scanline_bin_solid(const Scanline& sl,
244 BaseRenderer& ren,
245 const ColorT& color)
247 unsigned num_spans = sl.num_spans();
248 typename Scanline::const_iterator span = sl.begin();
249 for(;;)
251 ren.blend_hline(span->x,
252 sl.y(),
253 span->x - 1 + ((span->len < 0) ?
254 -span->len :
255 span->len),
256 color,
257 cover_full);
258 if(--num_spans == 0) break;
259 ++span;
263 //==============================================render_scanlines_bin_solid
264 template<class Rasterizer, class Scanline,
265 class BaseRenderer, class ColorT>
266 void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl,
267 BaseRenderer& ren, const ColorT& color)
269 if(ras.rewind_scanlines())
271 // Explicitly convert "color" to the BaseRenderer color type.
272 // For example, it can be called with color type "rgba", while
273 // "rgba8" is needed. Otherwise it will be implicitly
274 // converted in the loop many times.
275 //----------------------
276 typename BaseRenderer::color_type ren_color(color);
278 sl.reset(ras.min_x(), ras.max_x());
279 while(ras.sweep_scanline(sl))
281 //render_scanline_bin_solid(sl, ren, ren_color);
283 // This code is equivalent to the above call (copy/paste).
284 // It's just a "manual" optimization for old compilers,
285 // like Microsoft Visual C++ v6.0
286 //-------------------------------
287 unsigned num_spans = sl.num_spans();
288 typename Scanline::const_iterator span = sl.begin();
289 for(;;)
291 ren.blend_hline(span->x,
292 sl.y(),
293 span->x - 1 + ((span->len < 0) ?
294 -span->len :
295 span->len),
296 ren_color,
297 cover_full);
298 if(--num_spans == 0) break;
299 ++span;
305 //=============================================renderer_scanline_bin_solid
306 template<class BaseRenderer> class renderer_scanline_bin_solid
308 public:
309 typedef BaseRenderer base_ren_type;
310 typedef typename base_ren_type::color_type color_type;
312 //--------------------------------------------------------------------
313 renderer_scanline_bin_solid() : m_ren(0) {}
314 renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
315 void attach(base_ren_type& ren)
317 m_ren = &ren;
320 //--------------------------------------------------------------------
321 void color(const color_type& c) { m_color = c; }
322 const color_type& color() const { return m_color; }
324 //--------------------------------------------------------------------
325 void prepare() {}
327 //--------------------------------------------------------------------
328 template<class Scanline> void render(const Scanline& sl)
330 render_scanline_bin_solid(sl, *m_ren, m_color);
333 private:
334 base_ren_type* m_ren;
335 color_type m_color;
345 //======================================================render_scanline_bin
346 template<class Scanline, class BaseRenderer,
347 class SpanAllocator, class SpanGenerator>
348 void render_scanline_bin(const Scanline& sl, BaseRenderer& ren,
349 SpanAllocator& alloc, SpanGenerator& span_gen)
351 int y = sl.y();
353 unsigned num_spans = sl.num_spans();
354 typename Scanline::const_iterator span = sl.begin();
355 for(;;)
357 int x = span->x;
358 int len = span->len;
359 if(len < 0) len = -len;
360 typename BaseRenderer::color_type* colors = alloc.allocate(len);
361 span_gen.generate(colors, x, y, len);
362 ren.blend_color_hspan(x, y, len, colors, 0, cover_full);
363 if(--num_spans == 0) break;
364 ++span;
368 //=====================================================render_scanlines_bin
369 template<class Rasterizer, class Scanline, class BaseRenderer,
370 class SpanAllocator, class SpanGenerator>
371 void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
372 SpanAllocator& alloc, SpanGenerator& span_gen)
374 if(ras.rewind_scanlines())
376 sl.reset(ras.min_x(), ras.max_x());
377 span_gen.prepare();
378 while(ras.sweep_scanline(sl))
380 render_scanline_bin(sl, ren, alloc, span_gen);
385 //====================================================renderer_scanline_bin
386 template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
387 class renderer_scanline_bin
389 public:
390 typedef BaseRenderer base_ren_type;
391 typedef SpanAllocator alloc_type;
392 typedef SpanGenerator span_gen_type;
394 //--------------------------------------------------------------------
395 renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {}
396 renderer_scanline_bin(base_ren_type& ren,
397 alloc_type& alloc,
398 span_gen_type& span_gen) :
399 m_ren(&ren),
400 m_alloc(&alloc),
401 m_span_gen(&span_gen)
403 void attach(base_ren_type& ren,
404 alloc_type& alloc,
405 span_gen_type& span_gen)
407 m_ren = &ren;
408 m_alloc = &alloc;
409 m_span_gen = &span_gen;
412 //--------------------------------------------------------------------
413 void prepare() { m_span_gen->prepare(); }
415 //--------------------------------------------------------------------
416 template<class Scanline> void render(const Scanline& sl)
418 render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen);
421 private:
422 base_ren_type* m_ren;
423 alloc_type* m_alloc;
424 span_gen_type* m_span_gen;
436 //========================================================render_scanlines
437 template<class Rasterizer, class Scanline, class Renderer>
438 void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren)
440 if(ras.rewind_scanlines())
442 sl.reset(ras.min_x(), ras.max_x());
443 ren.prepare();
444 while(ras.sweep_scanline(sl))
446 ren.render(sl);
451 //========================================================render_all_paths
452 template<class Rasterizer, class Scanline, class Renderer,
453 class VertexSource, class ColorStorage, class PathId>
454 void render_all_paths(Rasterizer& ras,
455 Scanline& sl,
456 Renderer& r,
457 VertexSource& vs,
458 const ColorStorage& as,
459 const PathId& path_id,
460 unsigned num_paths)
462 for(unsigned i = 0; i < num_paths; i++)
464 ras.reset();
465 ras.add_path(vs, path_id[i]);
466 r.color(as[i]);
467 render_scanlines(ras, sl, r);
479 //=============================================render_scanlines_compound
480 template<class Rasterizer,
481 class ScanlineAA,
482 class ScanlineBin,
483 class BaseRenderer,
484 class SpanAllocator,
485 class StyleHandler>
486 void render_scanlines_compound(Rasterizer& ras,
487 ScanlineAA& sl_aa,
488 ScanlineBin& sl_bin,
489 BaseRenderer& ren,
490 SpanAllocator& alloc,
491 StyleHandler& sh)
493 if(ras.rewind_scanlines())
495 int min_x = ras.min_x();
496 int len = ras.max_x() - min_x + 2;
497 sl_aa.reset(min_x, ras.max_x());
499 typedef typename BaseRenderer::color_type color_type;
500 color_type* color_span = alloc.allocate(len * 2);
501 color_type* mix_buffer = color_span + len;
502 cover_type* cover_buffer = ras.allocate_cover_buffer(len);
503 unsigned num_spans;
505 unsigned num_styles;
506 unsigned style;
507 bool solid;
508 while((num_styles = ras.sweep_styles()) > 0)
510 typename ScanlineAA::const_iterator span_aa;
511 if(num_styles == 1)
513 // Optimization for a single style. Happens often
514 //-------------------------
515 if(ras.sweep_scanline(sl_aa, 0))
517 style = ras.style(0);
518 if(sh.is_solid(style))
520 // Just solid fill
521 //-----------------------
522 render_scanline_aa_solid(sl_aa, ren, sh.color(style));
524 else
526 // Arbitrary span generator
527 //-----------------------
528 span_aa = sl_aa.begin();
529 num_spans = sl_aa.num_spans();
530 for(;;)
532 len = span_aa->len;
533 sh.generate_span(color_span,
534 span_aa->x,
535 sl_aa.y(),
536 len,
537 style);
539 ren.blend_color_hspan(span_aa->x,
540 sl_aa.y(),
541 span_aa->len,
542 color_span,
543 span_aa->covers);
544 if(--num_spans == 0) break;
545 ++span_aa;
550 else
552 int sl_start = ras.scanline_start();
553 unsigned sl_len = ras.scanline_length();
555 if(sl_len)
557 memset(mix_buffer + sl_start - min_x,
559 sl_len * sizeof(color_type));
561 memset(cover_buffer + sl_start - min_x,
563 sl_len * sizeof(cover_type));
565 int sl_y = 0x7FFFFFFF;
566 unsigned i;
567 for(i = 0; i < num_styles; i++)
569 style = ras.style(i);
570 solid = sh.is_solid(style);
572 if(ras.sweep_scanline(sl_aa, i))
574 unsigned cover;
575 color_type* colors;
576 color_type* cspan;
577 cover_type* src_covers;
578 cover_type* dst_covers;
579 span_aa = sl_aa.begin();
580 num_spans = sl_aa.num_spans();
581 sl_y = sl_aa.y();
582 if(solid)
584 // Just solid fill
585 //-----------------------
586 for(;;)
588 color_type c = sh.color(style);
589 len = span_aa->len;
590 colors = mix_buffer + span_aa->x - min_x;
591 src_covers = span_aa->covers;
592 dst_covers = cover_buffer + span_aa->x - min_x;
595 cover = *src_covers;
596 if(*dst_covers + cover > cover_full)
598 cover = cover_full - *dst_covers;
600 if(cover)
602 colors->add(c, cover);
603 *dst_covers += cover;
605 ++colors;
606 ++src_covers;
607 ++dst_covers;
609 while(--len);
610 if(--num_spans == 0) break;
611 ++span_aa;
614 else
616 // Arbitrary span generator
617 //-----------------------
618 for(;;)
620 len = span_aa->len;
621 colors = mix_buffer + span_aa->x - min_x;
622 cspan = color_span;
623 sh.generate_span(cspan,
624 span_aa->x,
625 sl_aa.y(),
626 len,
627 style);
628 src_covers = span_aa->covers;
629 dst_covers = cover_buffer + span_aa->x - min_x;
632 cover = *src_covers;
633 if(*dst_covers + cover > cover_full)
635 cover = cover_full - *dst_covers;
637 if(cover)
639 colors->add(*cspan, cover);
640 *dst_covers += cover;
642 ++cspan;
643 ++colors;
644 ++src_covers;
645 ++dst_covers;
647 while(--len);
648 if(--num_spans == 0) break;
649 ++span_aa;
654 ren.blend_color_hspan(sl_start,
655 sl_y,
656 sl_len,
657 mix_buffer + sl_start - min_x,
659 cover_full);
660 } //if(sl_len)
661 } //if(num_styles == 1) ... else
662 } //while((num_styles = ras.sweep_styles()) > 0)
663 } //if(ras.rewind_scanlines())
669 #endif