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 //---------------------------------------------------------------------------- 15 16 #ifndef AGG_RENDERER_SCANLINE_INCLUDED 17 #define AGG_RENDERER_SCANLINE_INCLUDED 18 19 #include "agg_basics.h" 20 #include "agg_renderer_base.h" 21 22 namespace agg 23 { 24 25 //================================================render_scanline_aa_solid 26 template<class Scanline, class BaseRenderer, class ColorT> render_scanline_aa_solid(const Scanline & sl,BaseRenderer & ren,const ColorT & color)27 void render_scanline_aa_solid(const Scanline& sl, 28 BaseRenderer& ren, 29 const ColorT& color) 30 { 31 int y = sl.y(); 32 unsigned num_spans = sl.num_spans(); 33 typename Scanline::const_iterator span = sl.begin(); 34 35 for(;;) 36 { 37 int x = span->x; 38 if(span->len > 0) 39 { 40 ren.blend_solid_hspan(x, y, (unsigned)span->len, 41 color, 42 span->covers); 43 } 44 else 45 { 46 ren.blend_hline(x, y, (unsigned)(x - span->len - 1), 47 color, 48 *(span->covers)); 49 } 50 if(--num_spans == 0) break; 51 ++span; 52 } 53 } 54 55 //===============================================render_scanlines_aa_solid 56 template<class Rasterizer, class Scanline, 57 class BaseRenderer, class ColorT> render_scanlines_aa_solid(Rasterizer & ras,Scanline & sl,BaseRenderer & ren,const ColorT & color)58 void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, 59 BaseRenderer& ren, const ColorT& color) 60 { 61 if(ras.rewind_scanlines()) 62 { 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); 69 70 sl.reset(ras.min_x(), ras.max_x()); 71 while(ras.sweep_scanline(sl)) 72 { 73 //render_scanline_aa_solid(sl, ren, ren_color); 74 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(); 82 83 for(;;) 84 { 85 int x = span->x; 86 if(span->len > 0) 87 { 88 ren.blend_solid_hspan(x, y, (unsigned)span->len, 89 ren_color, 90 span->covers); 91 } 92 else 93 { 94 ren.blend_hline(x, y, (unsigned)(x - span->len - 1), 95 ren_color, 96 *(span->covers)); 97 } 98 if(--num_spans == 0) break; 99 ++span; 100 } 101 } 102 } 103 } 104 105 //==============================================renderer_scanline_aa_solid 106 template<class BaseRenderer> class renderer_scanline_aa_solid 107 { 108 public: 109 typedef BaseRenderer base_ren_type; 110 typedef typename base_ren_type::color_type color_type; 111 112 //-------------------------------------------------------------------- renderer_scanline_aa_solid()113 renderer_scanline_aa_solid() : m_ren(0) {} renderer_scanline_aa_solid(base_ren_type & ren)114 renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {} attach(base_ren_type & ren)115 void attach(base_ren_type& ren) 116 { 117 m_ren = &ren; 118 } 119 120 //-------------------------------------------------------------------- color(const color_type & c)121 void color(const color_type& c) { m_color = c; } color()122 const color_type& color() const { return m_color; } 123 124 //-------------------------------------------------------------------- prepare()125 void prepare() {} 126 127 //-------------------------------------------------------------------- render(const Scanline & sl)128 template<class Scanline> void render(const Scanline& sl) 129 { 130 render_scanline_aa_solid(sl, *m_ren, m_color); 131 } 132 133 private: 134 base_ren_type* m_ren; 135 color_type m_color; 136 }; 137 138 139 140 141 142 143 144 145 146 147 148 149 150 //======================================================render_scanline_aa 151 template<class Scanline, class BaseRenderer, 152 class SpanAllocator, class SpanGenerator> render_scanline_aa(const Scanline & sl,BaseRenderer & ren,SpanAllocator & alloc,SpanGenerator & span_gen)153 void render_scanline_aa(const Scanline& sl, BaseRenderer& ren, 154 SpanAllocator& alloc, SpanGenerator& span_gen) 155 { 156 int y = sl.y(); 157 158 unsigned num_spans = sl.num_spans(); 159 typename Scanline::const_iterator span = sl.begin(); 160 for(;;) 161 { 162 int x = span->x; 163 int len = span->len; 164 const typename Scanline::cover_type* covers = span->covers; 165 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); 171 172 if(--num_spans == 0) break; 173 ++span; 174 } 175 } 176 177 //=====================================================render_scanlines_aa 178 template<class Rasterizer, class Scanline, class BaseRenderer, 179 class SpanAllocator, class SpanGenerator> render_scanlines_aa(Rasterizer & ras,Scanline & sl,BaseRenderer & ren,SpanAllocator & alloc,SpanGenerator & span_gen)180 void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, 181 SpanAllocator& alloc, SpanGenerator& span_gen) 182 { 183 if(ras.rewind_scanlines()) 184 { 185 sl.reset(ras.min_x(), ras.max_x()); 186 span_gen.prepare(); 187 while(ras.sweep_scanline(sl)) 188 { 189 render_scanline_aa(sl, ren, alloc, span_gen); 190 } 191 } 192 } 193 194 //====================================================renderer_scanline_aa 195 template<class BaseRenderer, class SpanAllocator, class SpanGenerator> 196 class renderer_scanline_aa 197 { 198 public: 199 typedef BaseRenderer base_ren_type; 200 typedef SpanAllocator alloc_type; 201 typedef SpanGenerator span_gen_type; 202 203 //-------------------------------------------------------------------- renderer_scanline_aa()204 renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} renderer_scanline_aa(base_ren_type & ren,alloc_type & alloc,span_gen_type & span_gen)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) 211 {} attach(base_ren_type & ren,alloc_type & alloc,span_gen_type & span_gen)212 void attach(base_ren_type& ren, 213 alloc_type& alloc, 214 span_gen_type& span_gen) 215 { 216 m_ren = &ren; 217 m_alloc = &alloc; 218 m_span_gen = &span_gen; 219 } 220 221 //-------------------------------------------------------------------- prepare()222 void prepare() { m_span_gen->prepare(); } 223 224 //-------------------------------------------------------------------- render(const Scanline & sl)225 template<class Scanline> void render(const Scanline& sl) 226 { 227 render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); 228 } 229 230 private: 231 base_ren_type* m_ren; 232 alloc_type* m_alloc; 233 span_gen_type* m_span_gen; 234 }; 235 236 237 238 239 240 241 //===============================================render_scanline_bin_solid 242 template<class Scanline, class BaseRenderer, class ColorT> render_scanline_bin_solid(const Scanline & sl,BaseRenderer & ren,const ColorT & color)243 void render_scanline_bin_solid(const Scanline& sl, 244 BaseRenderer& ren, 245 const ColorT& color) 246 { 247 unsigned num_spans = sl.num_spans(); 248 typename Scanline::const_iterator span = sl.begin(); 249 for(;;) 250 { 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; 260 } 261 } 262 263 //==============================================render_scanlines_bin_solid 264 template<class Rasterizer, class Scanline, 265 class BaseRenderer, class ColorT> render_scanlines_bin_solid(Rasterizer & ras,Scanline & sl,BaseRenderer & ren,const ColorT & color)266 void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, 267 BaseRenderer& ren, const ColorT& color) 268 { 269 if(ras.rewind_scanlines()) 270 { 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); 277 278 sl.reset(ras.min_x(), ras.max_x()); 279 while(ras.sweep_scanline(sl)) 280 { 281 //render_scanline_bin_solid(sl, ren, ren_color); 282 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(;;) 290 { 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; 300 } 301 } 302 } 303 } 304 305 //=============================================renderer_scanline_bin_solid 306 template<class BaseRenderer> class renderer_scanline_bin_solid 307 { 308 public: 309 typedef BaseRenderer base_ren_type; 310 typedef typename base_ren_type::color_type color_type; 311 312 //-------------------------------------------------------------------- renderer_scanline_bin_solid()313 renderer_scanline_bin_solid() : m_ren(0) {} renderer_scanline_bin_solid(base_ren_type & ren)314 renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} attach(base_ren_type & ren)315 void attach(base_ren_type& ren) 316 { 317 m_ren = &ren; 318 } 319 320 //-------------------------------------------------------------------- color(const color_type & c)321 void color(const color_type& c) { m_color = c; } color()322 const color_type& color() const { return m_color; } 323 324 //-------------------------------------------------------------------- prepare()325 void prepare() {} 326 327 //-------------------------------------------------------------------- render(const Scanline & sl)328 template<class Scanline> void render(const Scanline& sl) 329 { 330 render_scanline_bin_solid(sl, *m_ren, m_color); 331 } 332 333 private: 334 base_ren_type* m_ren; 335 color_type m_color; 336 }; 337 338 339 340 341 342 343 344 345 //======================================================render_scanline_bin 346 template<class Scanline, class BaseRenderer, 347 class SpanAllocator, class SpanGenerator> render_scanline_bin(const Scanline & sl,BaseRenderer & ren,SpanAllocator & alloc,SpanGenerator & span_gen)348 void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, 349 SpanAllocator& alloc, SpanGenerator& span_gen) 350 { 351 int y = sl.y(); 352 353 unsigned num_spans = sl.num_spans(); 354 typename Scanline::const_iterator span = sl.begin(); 355 for(;;) 356 { 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; 365 } 366 } 367 368 //=====================================================render_scanlines_bin 369 template<class Rasterizer, class Scanline, class BaseRenderer, 370 class SpanAllocator, class SpanGenerator> render_scanlines_bin(Rasterizer & ras,Scanline & sl,BaseRenderer & ren,SpanAllocator & alloc,SpanGenerator & span_gen)371 void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, 372 SpanAllocator& alloc, SpanGenerator& span_gen) 373 { 374 if(ras.rewind_scanlines()) 375 { 376 sl.reset(ras.min_x(), ras.max_x()); 377 span_gen.prepare(); 378 while(ras.sweep_scanline(sl)) 379 { 380 render_scanline_bin(sl, ren, alloc, span_gen); 381 } 382 } 383 } 384 385 //====================================================renderer_scanline_bin 386 template<class BaseRenderer, class SpanAllocator, class SpanGenerator> 387 class renderer_scanline_bin 388 { 389 public: 390 typedef BaseRenderer base_ren_type; 391 typedef SpanAllocator alloc_type; 392 typedef SpanGenerator span_gen_type; 393 394 //-------------------------------------------------------------------- renderer_scanline_bin()395 renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} renderer_scanline_bin(base_ren_type & ren,alloc_type & alloc,span_gen_type & span_gen)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) 402 {} attach(base_ren_type & ren,alloc_type & alloc,span_gen_type & span_gen)403 void attach(base_ren_type& ren, 404 alloc_type& alloc, 405 span_gen_type& span_gen) 406 { 407 m_ren = &ren; 408 m_alloc = &alloc; 409 m_span_gen = &span_gen; 410 } 411 412 //-------------------------------------------------------------------- prepare()413 void prepare() { m_span_gen->prepare(); } 414 415 //-------------------------------------------------------------------- render(const Scanline & sl)416 template<class Scanline> void render(const Scanline& sl) 417 { 418 render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); 419 } 420 421 private: 422 base_ren_type* m_ren; 423 alloc_type* m_alloc; 424 span_gen_type* m_span_gen; 425 }; 426 427 428 429 430 431 432 433 434 435 436 //========================================================render_scanlines 437 template<class Rasterizer, class Scanline, class Renderer> render_scanlines(Rasterizer & ras,Scanline & sl,Renderer & ren)438 void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) 439 { 440 if(ras.rewind_scanlines()) 441 { 442 sl.reset(ras.min_x(), ras.max_x()); 443 ren.prepare(); 444 while(ras.sweep_scanline(sl)) 445 { 446 ren.render(sl); 447 } 448 } 449 } 450 451 //========================================================render_all_paths 452 template<class Rasterizer, class Scanline, class Renderer, 453 class VertexSource, class ColorStorage, class PathId> render_all_paths(Rasterizer & ras,Scanline & sl,Renderer & r,VertexSource & vs,const ColorStorage & as,const PathId & path_id,unsigned num_paths)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) 461 { 462 for(unsigned i = 0; i < num_paths; i++) 463 { 464 ras.reset(); 465 ras.add_path(vs, path_id[i]); 466 r.color(as[i]); 467 render_scanlines(ras, sl, r); 468 } 469 } 470 471 472 473 474 475 476 477 478 479 //=============================================render_scanlines_compound 480 template<class Rasterizer, 481 class ScanlineAA, 482 class ScanlineBin, 483 class BaseRenderer, 484 class SpanAllocator, 485 class StyleHandler> render_scanlines_compound(Rasterizer & ras,ScanlineAA & sl_aa,ScanlineBin & sl_bin,BaseRenderer & ren,SpanAllocator & alloc,StyleHandler & sh)486 void render_scanlines_compound(Rasterizer& ras, 487 ScanlineAA& sl_aa, 488 ScanlineBin& sl_bin, 489 BaseRenderer& ren, 490 SpanAllocator& alloc, 491 StyleHandler& sh) 492 { 493 if(ras.rewind_scanlines()) 494 { 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()); 498 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; 504 505 unsigned num_styles; 506 unsigned style; 507 bool solid; 508 while((num_styles = ras.sweep_styles()) > 0) 509 { 510 typename ScanlineAA::const_iterator span_aa; 511 if(num_styles == 1) 512 { 513 // Optimization for a single style. Happens often 514 //------------------------- 515 if(ras.sweep_scanline(sl_aa, 0)) 516 { 517 style = ras.style(0); 518 if(sh.is_solid(style)) 519 { 520 // Just solid fill 521 //----------------------- 522 render_scanline_aa_solid(sl_aa, ren, sh.color(style)); 523 } 524 else 525 { 526 // Arbitrary span generator 527 //----------------------- 528 span_aa = sl_aa.begin(); 529 num_spans = sl_aa.num_spans(); 530 for(;;) 531 { 532 len = span_aa->len; 533 sh.generate_span(color_span, 534 span_aa->x, 535 sl_aa.y(), 536 len, 537 style); 538 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; 546 } 547 } 548 } 549 } 550 else 551 { 552 int sl_start = ras.scanline_start(); 553 unsigned sl_len = ras.scanline_length(); 554 555 if(sl_len) 556 { 557 memset((void*)(mix_buffer + sl_start - min_x), 558 0, 559 sl_len * sizeof(color_type)); 560 561 memset(cover_buffer + sl_start - min_x, 562 0, 563 sl_len * sizeof(cover_type)); 564 565 int sl_y = 0x7FFFFFFF; 566 unsigned i; 567 for(i = 0; i < num_styles; i++) 568 { 569 style = ras.style(i); 570 solid = sh.is_solid(style); 571 572 if(ras.sweep_scanline(sl_aa, i)) 573 { 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) 583 { 584 // Just solid fill 585 //----------------------- 586 for(;;) 587 { 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; 593 do 594 { 595 cover = *src_covers; 596 if(*dst_covers + cover > cover_full) 597 { 598 cover = cover_full - *dst_covers; 599 } 600 if(cover) 601 { 602 colors->add(c, cover); 603 *dst_covers += cover; 604 } 605 ++colors; 606 ++src_covers; 607 ++dst_covers; 608 } 609 while(--len); 610 if(--num_spans == 0) break; 611 ++span_aa; 612 } 613 } 614 else 615 { 616 // Arbitrary span generator 617 //----------------------- 618 for(;;) 619 { 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; 630 do 631 { 632 cover = *src_covers; 633 if(*dst_covers + cover > cover_full) 634 { 635 cover = cover_full - *dst_covers; 636 } 637 if(cover) 638 { 639 colors->add(*cspan, cover); 640 *dst_covers += cover; 641 } 642 ++cspan; 643 ++colors; 644 ++src_covers; 645 ++dst_covers; 646 } 647 while(--len); 648 if(--num_spans == 0) break; 649 ++span_aa; 650 } 651 } 652 } 653 } 654 ren.blend_color_hspan(sl_start, 655 sl_y, 656 sl_len, 657 mix_buffer + sl_start - min_x, 658 0, 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()) 664 } 665 666 667 } 668 669 #endif 670