1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
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"
25 //================================================render_scanline_aa_solid
26 template<class Scanline
, class BaseRenderer
, class ColorT
>
27 void render_scanline_aa_solid(const Scanline
& sl
,
32 unsigned num_spans
= sl
.num_spans();
33 typename
Scanline::const_iterator span
= sl
.begin();
40 ren
.blend_solid_hspan(x
, y
, (unsigned)span
->len
,
46 ren
.blend_hline(x
, y
, (unsigned)(x
- span
->len
- 1),
50 if(--num_spans
== 0) break;
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 //-------------------------------
80 unsigned num_spans
= sl
.num_spans();
81 typename
Scanline::const_iterator span
= sl
.begin();
88 ren
.blend_solid_hspan(x
, y
, (unsigned)span
->len
,
94 ren
.blend_hline(x
, y
, (unsigned)(x
- span
->len
- 1),
98 if(--num_spans
== 0) break;
105 //==============================================renderer_scanline_aa_solid
106 template<class BaseRenderer
> class renderer_scanline_aa_solid
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
)
120 //--------------------------------------------------------------------
121 void color(const color_type
& c
) { m_color
= c
; }
122 const color_type
& color() const { return m_color
; }
124 //--------------------------------------------------------------------
127 //--------------------------------------------------------------------
128 template<class Scanline
> void render(const Scanline
& sl
)
130 render_scanline_aa_solid(sl
, *m_ren
, m_color
);
134 base_ren_type
* m_ren
;
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
)
158 unsigned num_spans
= sl
.num_spans();
159 typename
Scanline::const_iterator span
= sl
.begin();
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;
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());
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
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
,
207 span_gen_type
& span_gen
) :
210 m_span_gen(&span_gen
)
212 void attach(base_ren_type
& ren
,
214 span_gen_type
& span_gen
)
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
);
231 base_ren_type
* m_ren
;
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
,
247 unsigned num_spans
= sl
.num_spans();
248 typename
Scanline::const_iterator span
= sl
.begin();
251 ren
.blend_hline(span
->x
,
253 span
->x
- 1 + ((span
->len
< 0) ?
258 if(--num_spans
== 0) break;
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();
291 ren
.blend_hline(span
->x
,
293 span
->x
- 1 + ((span
->len
< 0) ?
298 if(--num_spans
== 0) break;
305 //=============================================renderer_scanline_bin_solid
306 template<class BaseRenderer
> class renderer_scanline_bin_solid
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
)
320 //--------------------------------------------------------------------
321 void color(const color_type
& c
) { m_color
= c
; }
322 const color_type
& color() const { return m_color
; }
324 //--------------------------------------------------------------------
327 //--------------------------------------------------------------------
328 template<class Scanline
> void render(const Scanline
& sl
)
330 render_scanline_bin_solid(sl
, *m_ren
, m_color
);
334 base_ren_type
* m_ren
;
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
)
353 unsigned num_spans
= sl
.num_spans();
354 typename
Scanline::const_iterator span
= sl
.begin();
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;
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());
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
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
,
398 span_gen_type
& span_gen
) :
401 m_span_gen(&span_gen
)
403 void attach(base_ren_type
& ren
,
405 span_gen_type
& span_gen
)
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
);
422 base_ren_type
* m_ren
;
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());
444 while(ras
.sweep_scanline(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
,
458 const ColorStorage
& as
,
459 const PathId
& path_id
,
462 for(unsigned i
= 0; i
< num_paths
; i
++)
465 ras
.add_path(vs
, path_id
[i
]);
467 render_scanlines(ras
, sl
, r
);
479 //=============================================render_scanlines_compound
480 template<class Rasterizer
,
486 void render_scanlines_compound(Rasterizer
& ras
,
490 SpanAllocator
& alloc
,
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
);
508 while((num_styles
= ras
.sweep_styles()) > 0)
510 typename
ScanlineAA::const_iterator span_aa
;
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
))
521 //-----------------------
522 render_scanline_aa_solid(sl_aa
, ren
, sh
.color(style
));
526 // Arbitrary span generator
527 //-----------------------
528 span_aa
= sl_aa
.begin();
529 num_spans
= sl_aa
.num_spans();
533 sh
.generate_span(color_span
,
539 ren
.blend_color_hspan(span_aa
->x
,
544 if(--num_spans
== 0) break;
552 int sl_start
= ras
.scanline_start();
553 unsigned sl_len
= ras
.scanline_length();
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;
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
))
577 cover_type
* src_covers
;
578 cover_type
* dst_covers
;
579 span_aa
= sl_aa
.begin();
580 num_spans
= sl_aa
.num_spans();
585 //-----------------------
588 color_type c
= sh
.color(style
);
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
;
596 if(*dst_covers
+ cover
> cover_full
)
598 cover
= cover_full
- *dst_covers
;
602 colors
->add(c
, cover
);
603 *dst_covers
+= cover
;
610 if(--num_spans
== 0) break;
616 // Arbitrary span generator
617 //-----------------------
621 colors
= mix_buffer
+ span_aa
->x
- min_x
;
623 sh
.generate_span(cspan
,
628 src_covers
= span_aa
->covers
;
629 dst_covers
= cover_buffer
+ span_aa
->x
- min_x
;
633 if(*dst_covers
+ cover
> cover_full
)
635 cover
= cover_full
- *dst_covers
;
639 colors
->add(*cspan
, cover
);
640 *dst_covers
+= cover
;
648 if(--num_spans
== 0) break;
654 ren
.blend_color_hspan(sl_start
,
657 mix_buffer
+ sl_start
- min_x
,
661 } //if(num_styles == 1) ... else
662 } //while((num_styles = ras.sweep_styles()) > 0)
663 } //if(ras.rewind_scanlines())