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_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED 17 #define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED 18 19 #include <stdlib.h> 20 #include <math.h> 21 #include "agg_basics.h" 22 23 24 namespace agg 25 { 26 27 //-----------------------------------------------sbool_combine_spans_bin 28 // Functor. 29 // Combine two binary encoded spans, i.e., when we don't have any 30 // anti-aliasing information, but only X and Length. The function 31 // is compatible with any type of scanlines. 32 //---------------- 33 template<class Scanline1, 34 class Scanline2, 35 class Scanline> 36 struct sbool_combine_spans_bin 37 { operatorsbool_combine_spans_bin38 void operator () (const typename Scanline1::const_iterator&, 39 const typename Scanline2::const_iterator&, 40 int x, unsigned len, 41 Scanline& sl) const 42 { 43 sl.add_span(x, len, cover_full); 44 } 45 }; 46 47 48 49 //---------------------------------------------sbool_combine_spans_empty 50 // Functor. 51 // Combine two spans as empty ones. The functor does nothing 52 // and is used to XOR binary spans. 53 //---------------- 54 template<class Scanline1, 55 class Scanline2, 56 class Scanline> 57 struct sbool_combine_spans_empty 58 { operatorsbool_combine_spans_empty59 void operator () (const typename Scanline1::const_iterator&, 60 const typename Scanline2::const_iterator&, 61 int, unsigned, 62 Scanline&) const 63 {} 64 }; 65 66 67 68 //--------------------------------------------------sbool_add_span_empty 69 // Functor. 70 // Add nothing. Used in conbine_shapes_sub 71 //---------------- 72 template<class Scanline1, 73 class Scanline> 74 struct sbool_add_span_empty 75 { operatorsbool_add_span_empty76 void operator () (const typename Scanline1::const_iterator&, 77 int, unsigned, 78 Scanline&) const 79 {} 80 }; 81 82 83 //----------------------------------------------------sbool_add_span_bin 84 // Functor. 85 // Add a binary span 86 //---------------- 87 template<class Scanline1, 88 class Scanline> 89 struct sbool_add_span_bin 90 { operatorsbool_add_span_bin91 void operator () (const typename Scanline1::const_iterator&, 92 int x, unsigned len, 93 Scanline& sl) const 94 { 95 sl.add_span(x, len, cover_full); 96 } 97 }; 98 99 100 101 102 //-----------------------------------------------------sbool_add_span_aa 103 // Functor. 104 // Add an anti-aliased span 105 // anti-aliasing information, but only X and Length. The function 106 // is compatible with any type of scanlines. 107 //---------------- 108 template<class Scanline1, 109 class Scanline> 110 struct sbool_add_span_aa 111 { operatorsbool_add_span_aa112 void operator () (const typename Scanline1::const_iterator& span, 113 int x, unsigned len, 114 Scanline& sl) const 115 { 116 if(span->len < 0) 117 { 118 sl.add_span(x, len, *span->covers); 119 } 120 else 121 if(span->len > 0) 122 { 123 const typename Scanline1::cover_type* covers = span->covers; 124 if(span->x < x) covers += x - span->x; 125 sl.add_cells(x, len, covers); 126 } 127 } 128 }; 129 130 131 132 133 //----------------------------------------------sbool_intersect_spans_aa 134 // Functor. 135 // Intersect two spans preserving the anti-aliasing information. 136 // The result is added to the "sl" scanline. 137 //------------------ 138 template<class Scanline1, 139 class Scanline2, 140 class Scanline, 141 unsigned CoverShift = cover_shift> 142 struct sbool_intersect_spans_aa 143 { 144 enum cover_scale_e 145 { 146 cover_shift = CoverShift, 147 cover_size = 1 << cover_shift, 148 cover_mask = cover_size - 1, 149 cover_full = cover_mask 150 }; 151 152 operatorsbool_intersect_spans_aa153 void operator () (const typename Scanline1::const_iterator& span1, 154 const typename Scanline2::const_iterator& span2, 155 int x, unsigned len, 156 Scanline& sl) const 157 { 158 unsigned cover; 159 const typename Scanline1::cover_type* covers1; 160 const typename Scanline2::cover_type* covers2; 161 162 // Calculate the operation code and choose the 163 // proper combination algorithm. 164 // 0 = Both spans are of AA type 165 // 1 = span1 is solid, span2 is AA 166 // 2 = span1 is AA, span2 is solid 167 // 3 = Both spans are of solid type 168 //----------------- 169 switch((span1->len < 0) | ((span2->len < 0) << 1)) 170 { 171 case 0: // Both are AA spans 172 covers1 = span1->covers; 173 covers2 = span2->covers; 174 if(span1->x < x) covers1 += x - span1->x; 175 if(span2->x < x) covers2 += x - span2->x; 176 do 177 { 178 cover = *covers1++ * *covers2++; 179 sl.add_cell(x++, 180 (cover == cover_full * cover_full) ? 181 cover_full : 182 (cover >> cover_shift)); 183 } 184 while(--len); 185 break; 186 187 case 1: // span1 is solid, span2 is AA 188 covers2 = span2->covers; 189 if(span2->x < x) covers2 += x - span2->x; 190 if(*(span1->covers) == cover_full) 191 { 192 sl.add_cells(x, len, covers2); 193 } 194 else 195 { 196 do 197 { 198 cover = *(span1->covers) * *covers2++; 199 sl.add_cell(x++, 200 (cover == cover_full * cover_full) ? 201 cover_full : 202 (cover >> cover_shift)); 203 } 204 while(--len); 205 } 206 break; 207 208 case 2: // span1 is AA, span2 is solid 209 covers1 = span1->covers; 210 if(span1->x < x) covers1 += x - span1->x; 211 if(*(span2->covers) == cover_full) 212 { 213 sl.add_cells(x, len, covers1); 214 } 215 else 216 { 217 do 218 { 219 cover = *covers1++ * *(span2->covers); 220 sl.add_cell(x++, 221 (cover == cover_full * cover_full) ? 222 cover_full : 223 (cover >> cover_shift)); 224 } 225 while(--len); 226 } 227 break; 228 229 case 3: // Both are solid spans 230 cover = *(span1->covers) * *(span2->covers); 231 sl.add_span(x, len, 232 (cover == cover_full * cover_full) ? 233 cover_full : 234 (cover >> cover_shift)); 235 break; 236 } 237 } 238 }; 239 240 241 242 243 244 245 //--------------------------------------------------sbool_unite_spans_aa 246 // Functor. 247 // Unite two spans preserving the anti-aliasing information. 248 // The result is added to the "sl" scanline. 249 //------------------ 250 template<class Scanline1, 251 class Scanline2, 252 class Scanline, 253 unsigned CoverShift = cover_shift> 254 struct sbool_unite_spans_aa 255 { 256 enum cover_scale_e 257 { 258 cover_shift = CoverShift, 259 cover_size = 1 << cover_shift, 260 cover_mask = cover_size - 1, 261 cover_full = cover_mask 262 }; 263 264 operatorsbool_unite_spans_aa265 void operator () (const typename Scanline1::const_iterator& span1, 266 const typename Scanline2::const_iterator& span2, 267 int x, unsigned len, 268 Scanline& sl) const 269 { 270 unsigned cover; 271 const typename Scanline1::cover_type* covers1; 272 const typename Scanline2::cover_type* covers2; 273 274 // Calculate the operation code and choose the 275 // proper combination algorithm. 276 // 0 = Both spans are of AA type 277 // 1 = span1 is solid, span2 is AA 278 // 2 = span1 is AA, span2 is solid 279 // 3 = Both spans are of solid type 280 //----------------- 281 switch((span1->len < 0) | ((span2->len < 0) << 1)) 282 { 283 case 0: // Both are AA spans 284 covers1 = span1->covers; 285 covers2 = span2->covers; 286 if(span1->x < x) covers1 += x - span1->x; 287 if(span2->x < x) covers2 += x - span2->x; 288 do 289 { 290 cover = cover_mask * cover_mask - 291 (cover_mask - *covers1++) * 292 (cover_mask - *covers2++); 293 sl.add_cell(x++, 294 (cover == cover_full * cover_full) ? 295 cover_full : 296 (cover >> cover_shift)); 297 } 298 while(--len); 299 break; 300 301 case 1: // span1 is solid, span2 is AA 302 covers2 = span2->covers; 303 if(span2->x < x) covers2 += x - span2->x; 304 if(*(span1->covers) == cover_full) 305 { 306 sl.add_span(x, len, cover_full); 307 } 308 else 309 { 310 do 311 { 312 cover = cover_mask * cover_mask - 313 (cover_mask - *(span1->covers)) * 314 (cover_mask - *covers2++); 315 sl.add_cell(x++, 316 (cover == cover_full * cover_full) ? 317 cover_full : 318 (cover >> cover_shift)); 319 } 320 while(--len); 321 } 322 break; 323 324 case 2: // span1 is AA, span2 is solid 325 covers1 = span1->covers; 326 if(span1->x < x) covers1 += x - span1->x; 327 if(*(span2->covers) == cover_full) 328 { 329 sl.add_span(x, len, cover_full); 330 } 331 else 332 { 333 do 334 { 335 cover = cover_mask * cover_mask - 336 (cover_mask - *covers1++) * 337 (cover_mask - *(span2->covers)); 338 sl.add_cell(x++, 339 (cover == cover_full * cover_full) ? 340 cover_full : 341 (cover >> cover_shift)); 342 } 343 while(--len); 344 } 345 break; 346 347 case 3: // Both are solid spans 348 cover = cover_mask * cover_mask - 349 (cover_mask - *(span1->covers)) * 350 (cover_mask - *(span2->covers)); 351 sl.add_span(x, len, 352 (cover == cover_full * cover_full) ? 353 cover_full : 354 (cover >> cover_shift)); 355 break; 356 } 357 } 358 }; 359 360 361 //---------------------------------------------sbool_xor_formula_linear 362 template<unsigned CoverShift = cover_shift> 363 struct sbool_xor_formula_linear 364 { 365 enum cover_scale_e 366 { 367 cover_shift = CoverShift, 368 cover_size = 1 << cover_shift, 369 cover_mask = cover_size - 1 370 }; 371 calculatesbool_xor_formula_linear372 static AGG_INLINE unsigned calculate(unsigned a, unsigned b) 373 { 374 unsigned cover = a + b; 375 if(cover > cover_mask) cover = cover_mask + cover_mask - cover; 376 return cover; 377 } 378 }; 379 380 381 //---------------------------------------------sbool_xor_formula_saddle 382 template<unsigned CoverShift = cover_shift> 383 struct sbool_xor_formula_saddle 384 { 385 enum cover_scale_e 386 { 387 cover_shift = CoverShift, 388 cover_size = 1 << cover_shift, 389 cover_mask = cover_size - 1 390 }; 391 calculatesbool_xor_formula_saddle392 static AGG_INLINE unsigned calculate(unsigned a, unsigned b) 393 { 394 unsigned k = a * b; 395 if(k == cover_mask * cover_mask) return 0; 396 397 a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift; 398 b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift; 399 return cover_mask - ((a * b) >> cover_shift); 400 } 401 }; 402 403 404 //-------------------------------------------sbool_xor_formula_abs_diff 405 struct sbool_xor_formula_abs_diff 406 { calculatesbool_xor_formula_abs_diff407 static AGG_INLINE unsigned calculate(unsigned a, unsigned b) 408 { 409 return unsigned(abs(int(a) - int(b))); 410 } 411 }; 412 413 414 415 //----------------------------------------------------sbool_xor_spans_aa 416 // Functor. 417 // XOR two spans preserving the anti-aliasing information. 418 // The result is added to the "sl" scanline. 419 //------------------ 420 template<class Scanline1, 421 class Scanline2, 422 class Scanline, 423 class XorFormula, 424 unsigned CoverShift = cover_shift> 425 struct sbool_xor_spans_aa 426 { 427 enum cover_scale_e 428 { 429 cover_shift = CoverShift, 430 cover_size = 1 << cover_shift, 431 cover_mask = cover_size - 1, 432 cover_full = cover_mask 433 }; 434 435 operatorsbool_xor_spans_aa436 void operator () (const typename Scanline1::const_iterator& span1, 437 const typename Scanline2::const_iterator& span2, 438 int x, unsigned len, 439 Scanline& sl) const 440 { 441 unsigned cover; 442 const typename Scanline1::cover_type* covers1; 443 const typename Scanline2::cover_type* covers2; 444 445 // Calculate the operation code and choose the 446 // proper combination algorithm. 447 // 0 = Both spans are of AA type 448 // 1 = span1 is solid, span2 is AA 449 // 2 = span1 is AA, span2 is solid 450 // 3 = Both spans are of solid type 451 //----------------- 452 switch((span1->len < 0) | ((span2->len < 0) << 1)) 453 { 454 case 0: // Both are AA spans 455 covers1 = span1->covers; 456 covers2 = span2->covers; 457 if(span1->x < x) covers1 += x - span1->x; 458 if(span2->x < x) covers2 += x - span2->x; 459 do 460 { 461 cover = XorFormula::calculate(*covers1++, *covers2++); 462 if(cover) sl.add_cell(x, cover); 463 ++x; 464 } 465 while(--len); 466 break; 467 468 case 1: // span1 is solid, span2 is AA 469 covers2 = span2->covers; 470 if(span2->x < x) covers2 += x - span2->x; 471 do 472 { 473 cover = XorFormula::calculate(*(span1->covers), *covers2++); 474 if(cover) sl.add_cell(x, cover); 475 ++x; 476 } 477 while(--len); 478 break; 479 480 case 2: // span1 is AA, span2 is solid 481 covers1 = span1->covers; 482 if(span1->x < x) covers1 += x - span1->x; 483 do 484 { 485 cover = XorFormula::calculate(*covers1++, *(span2->covers)); 486 if(cover) sl.add_cell(x, cover); 487 ++x; 488 } 489 while(--len); 490 break; 491 492 case 3: // Both are solid spans 493 cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); 494 if(cover) sl.add_span(x, len, cover); 495 break; 496 497 } 498 } 499 }; 500 501 502 503 504 505 //-----------------------------------------------sbool_subtract_spans_aa 506 // Functor. 507 // Unite two spans preserving the anti-aliasing information. 508 // The result is added to the "sl" scanline. 509 //------------------ 510 template<class Scanline1, 511 class Scanline2, 512 class Scanline, 513 unsigned CoverShift = cover_shift> 514 struct sbool_subtract_spans_aa 515 { 516 enum cover_scale_e 517 { 518 cover_shift = CoverShift, 519 cover_size = 1 << cover_shift, 520 cover_mask = cover_size - 1, 521 cover_full = cover_mask 522 }; 523 524 operatorsbool_subtract_spans_aa525 void operator () (const typename Scanline1::const_iterator& span1, 526 const typename Scanline2::const_iterator& span2, 527 int x, unsigned len, 528 Scanline& sl) const 529 { 530 unsigned cover; 531 const typename Scanline1::cover_type* covers1; 532 const typename Scanline2::cover_type* covers2; 533 534 // Calculate the operation code and choose the 535 // proper combination algorithm. 536 // 0 = Both spans are of AA type 537 // 1 = span1 is solid, span2 is AA 538 // 2 = span1 is AA, span2 is solid 539 // 3 = Both spans are of solid type 540 //----------------- 541 switch((span1->len < 0) | ((span2->len < 0) << 1)) 542 { 543 case 0: // Both are AA spans 544 covers1 = span1->covers; 545 covers2 = span2->covers; 546 if(span1->x < x) covers1 += x - span1->x; 547 if(span2->x < x) covers2 += x - span2->x; 548 do 549 { 550 cover = *covers1++ * (cover_mask - *covers2++); 551 if(cover) 552 { 553 sl.add_cell(x, 554 (cover == cover_full * cover_full) ? 555 cover_full : 556 (cover >> cover_shift)); 557 } 558 ++x; 559 } 560 while(--len); 561 break; 562 563 case 1: // span1 is solid, span2 is AA 564 covers2 = span2->covers; 565 if(span2->x < x) covers2 += x - span2->x; 566 do 567 { 568 cover = *(span1->covers) * (cover_mask - *covers2++); 569 if(cover) 570 { 571 sl.add_cell(x, 572 (cover == cover_full * cover_full) ? 573 cover_full : 574 (cover >> cover_shift)); 575 } 576 ++x; 577 } 578 while(--len); 579 break; 580 581 case 2: // span1 is AA, span2 is solid 582 covers1 = span1->covers; 583 if(span1->x < x) covers1 += x - span1->x; 584 if(*(span2->covers) != cover_full) 585 { 586 do 587 { 588 cover = *covers1++ * (cover_mask - *(span2->covers)); 589 if(cover) 590 { 591 sl.add_cell(x, 592 (cover == cover_full * cover_full) ? 593 cover_full : 594 (cover >> cover_shift)); 595 } 596 ++x; 597 } 598 while(--len); 599 } 600 break; 601 602 case 3: // Both are solid spans 603 cover = *(span1->covers) * (cover_mask - *(span2->covers)); 604 if(cover) 605 { 606 sl.add_span(x, len, 607 (cover == cover_full * cover_full) ? 608 cover_full : 609 (cover >> cover_shift)); 610 } 611 break; 612 } 613 } 614 }; 615 616 617 618 619 620 621 //--------------------------------------------sbool_add_spans_and_render 622 template<class Scanline1, 623 class Scanline, 624 class Renderer, 625 class AddSpanFunctor> sbool_add_spans_and_render(const Scanline1 & sl1,Scanline & sl,Renderer & ren,AddSpanFunctor add_span)626 void sbool_add_spans_and_render(const Scanline1& sl1, 627 Scanline& sl, 628 Renderer& ren, 629 AddSpanFunctor add_span) 630 { 631 sl.reset_spans(); 632 typename Scanline1::const_iterator span = sl1.begin(); 633 unsigned num_spans = sl1.num_spans(); 634 for(;;) 635 { 636 add_span(span, span->x, abs((int)span->len), sl); 637 if(--num_spans == 0) break; 638 ++span; 639 } 640 sl.finalize(sl1.y()); 641 ren.render(sl); 642 } 643 644 645 646 647 648 649 650 //---------------------------------------------sbool_intersect_scanlines 651 // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. 652 // The combine_spans functor can be of type sbool_combine_spans_bin or 653 // sbool_intersect_spans_aa. First is a general functor to combine 654 // two spans without Anti-Aliasing, the second preserves the AA 655 // information, but works slower 656 // 657 template<class Scanline1, 658 class Scanline2, 659 class Scanline, 660 class CombineSpansFunctor> sbool_intersect_scanlines(const Scanline1 & sl1,const Scanline2 & sl2,Scanline & sl,CombineSpansFunctor combine_spans)661 void sbool_intersect_scanlines(const Scanline1& sl1, 662 const Scanline2& sl2, 663 Scanline& sl, 664 CombineSpansFunctor combine_spans) 665 { 666 sl.reset_spans(); 667 668 unsigned num1 = sl1.num_spans(); 669 if(num1 == 0) return; 670 671 unsigned num2 = sl2.num_spans(); 672 if(num2 == 0) return; 673 674 typename Scanline1::const_iterator span1 = sl1.begin(); 675 typename Scanline2::const_iterator span2 = sl2.begin(); 676 677 while(num1 && num2) 678 { 679 int xb1 = span1->x; 680 int xb2 = span2->x; 681 int xe1 = xb1 + abs((int)span1->len) - 1; 682 int xe2 = xb2 + abs((int)span2->len) - 1; 683 684 // Determine what spans we should advance in the next step 685 // The span with the least ending X should be advanced 686 // advance_both is just an optimization when we ending 687 // coordinates are the same and we can advance both 688 //-------------- 689 bool advance_span1 = xe1 < xe2; 690 bool advance_both = xe1 == xe2; 691 692 // Find the intersection of the spans 693 // and check if they intersect 694 //-------------- 695 if(xb1 < xb2) xb1 = xb2; 696 if(xe1 > xe2) xe1 = xe2; 697 if(xb1 <= xe1) 698 { 699 combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); 700 } 701 702 // Advance the spans 703 //-------------- 704 if(advance_both) 705 { 706 --num1; 707 --num2; 708 if(num1) ++span1; 709 if(num2) ++span2; 710 } 711 else 712 { 713 if(advance_span1) 714 { 715 --num1; 716 if(num1) ++span1; 717 } 718 else 719 { 720 --num2; 721 if(num2) ++span2; 722 } 723 } 724 } 725 } 726 727 728 729 730 731 732 733 734 //------------------------------------------------sbool_intersect_shapes 735 // Intersect the scanline shapes. Here the "Scanline Generator" 736 // abstraction is used. ScanlineGen1 and ScanlineGen2 are 737 // the generators, and can be of type rasterizer_scanline_aa<>. 738 // There function requires three scanline containers that can be of 739 // different types. 740 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 741 // "sl" is ised as the resulting scanline to render it. 742 // The external "sl1" and "sl2" are used only for the sake of 743 // optimization and reusing of the scanline objects. 744 // the function calls sbool_intersect_scanlines with CombineSpansFunctor 745 // as the last argument. See sbool_intersect_scanlines for details. 746 //---------- 747 template<class ScanlineGen1, 748 class ScanlineGen2, 749 class Scanline1, 750 class Scanline2, 751 class Scanline, 752 class Renderer, 753 class CombineSpansFunctor> sbool_intersect_shapes(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren,CombineSpansFunctor combine_spans)754 void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, 755 Scanline1& sl1, Scanline2& sl2, 756 Scanline& sl, Renderer& ren, 757 CombineSpansFunctor combine_spans) 758 { 759 // Prepare the scanline generators. 760 // If anyone of them doesn't contain 761 // any scanlines, then return. 762 //----------------- 763 if(!sg1.rewind_scanlines()) return; 764 if(!sg2.rewind_scanlines()) return; 765 766 // Get the bounding boxes 767 //---------------- 768 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); 769 rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); 770 771 // Calculate the intersection of the bounding 772 // boxes and return if they don't intersect. 773 //----------------- 774 rect_i ir = intersect_rectangles(r1, r2); 775 if(!ir.is_valid()) return; 776 777 // Reset the scanlines and get two first ones 778 //----------------- 779 sl.reset(ir.x1, ir.x2); 780 sl1.reset(sg1.min_x(), sg1.max_x()); 781 sl2.reset(sg2.min_x(), sg2.max_x()); 782 if(!sg1.sweep_scanline(sl1)) return; 783 if(!sg2.sweep_scanline(sl2)) return; 784 785 ren.prepare(); 786 787 // The main loop 788 // Here we synchronize the scanlines with 789 // the same Y coordinate, ignoring all other ones. 790 // Only scanlines having the same Y-coordinate 791 // are to be combined. 792 //----------------- 793 for(;;) 794 { 795 while(sl1.y() < sl2.y()) 796 { 797 if(!sg1.sweep_scanline(sl1)) return; 798 } 799 while(sl2.y() < sl1.y()) 800 { 801 if(!sg2.sweep_scanline(sl2)) return; 802 } 803 804 if(sl1.y() == sl2.y()) 805 { 806 // The Y coordinates are the same. 807 // Combine the scanlines, render if they contain any spans, 808 // and advance both generators to the next scanlines 809 //---------------------- 810 sbool_intersect_scanlines(sl1, sl2, sl, combine_spans); 811 if(sl.num_spans()) 812 { 813 sl.finalize(sl1.y()); 814 ren.render(sl); 815 } 816 if(!sg1.sweep_scanline(sl1)) return; 817 if(!sg2.sweep_scanline(sl2)) return; 818 } 819 } 820 } 821 822 823 824 825 826 827 828 //-------------------------------------------------sbool_unite_scanlines 829 // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one. 830 // The combine_spans functor can be of type sbool_combine_spans_bin or 831 // sbool_intersect_spans_aa. First is a general functor to combine 832 // two spans without Anti-Aliasing, the second preserves the AA 833 // information, but works slower 834 // 835 template<class Scanline1, 836 class Scanline2, 837 class Scanline, 838 class AddSpanFunctor1, 839 class AddSpanFunctor2, 840 class CombineSpansFunctor> sbool_unite_scanlines(const Scanline1 & sl1,const Scanline2 & sl2,Scanline & sl,AddSpanFunctor1 add_span1,AddSpanFunctor2 add_span2,CombineSpansFunctor combine_spans)841 void sbool_unite_scanlines(const Scanline1& sl1, 842 const Scanline2& sl2, 843 Scanline& sl, 844 AddSpanFunctor1 add_span1, 845 AddSpanFunctor2 add_span2, 846 CombineSpansFunctor combine_spans) 847 { 848 sl.reset_spans(); 849 850 unsigned num1 = sl1.num_spans(); 851 unsigned num2 = sl2.num_spans(); 852 853 typename Scanline1::const_iterator span1;// = sl1.begin(); 854 typename Scanline2::const_iterator span2;// = sl2.begin(); 855 856 enum invalidation_e 857 { 858 invalid_b = 0xFFFFFFF, 859 invalid_e = invalid_b - 1 860 }; 861 862 // Initialize the spans as invalid 863 //--------------- 864 int xb1 = invalid_b; 865 int xb2 = invalid_b; 866 int xe1 = invalid_e; 867 int xe2 = invalid_e; 868 869 // Initialize span1 if there are spans 870 //--------------- 871 if(num1) 872 { 873 span1 = sl1.begin(); 874 xb1 = span1->x; 875 xe1 = xb1 + abs((int)span1->len) - 1; 876 --num1; 877 } 878 879 // Initialize span2 if there are spans 880 //--------------- 881 if(num2) 882 { 883 span2 = sl2.begin(); 884 xb2 = span2->x; 885 xe2 = xb2 + abs((int)span2->len) - 1; 886 --num2; 887 } 888 889 890 for(;;) 891 { 892 // Retrieve a new span1 if it's invalid 893 //---------------- 894 if(num1 && xb1 > xe1) 895 { 896 --num1; 897 ++span1; 898 xb1 = span1->x; 899 xe1 = xb1 + abs((int)span1->len) - 1; 900 } 901 902 // Retrieve a new span2 if it's invalid 903 //---------------- 904 if(num2 && xb2 > xe2) 905 { 906 --num2; 907 ++span2; 908 xb2 = span2->x; 909 xe2 = xb2 + abs((int)span2->len) - 1; 910 } 911 912 if(xb1 > xe1 && xb2 > xe2) break; 913 914 // Calculate the intersection 915 //---------------- 916 int xb = xb1; 917 int xe = xe1; 918 if(xb < xb2) xb = xb2; 919 if(xe > xe2) xe = xe2; 920 int len = xe - xb + 1; // The length of the intersection 921 if(len > 0) 922 { 923 // The spans intersect, 924 // add the beginning of the span 925 //---------------- 926 if(xb1 < xb2) 927 { 928 add_span1(span1, xb1, xb2 - xb1, sl); 929 xb1 = xb2; 930 } 931 else 932 if(xb2 < xb1) 933 { 934 add_span2(span2, xb2, xb1 - xb2, sl); 935 xb2 = xb1; 936 } 937 938 // Add the combination part of the spans 939 //---------------- 940 combine_spans(span1, span2, xb, len, sl); 941 942 943 // Invalidate the fully processed span or both 944 //---------------- 945 if(xe1 < xe2) 946 { 947 // Invalidate span1 and eat 948 // the processed part of span2 949 //-------------- 950 xb1 = invalid_b; 951 xe1 = invalid_e; 952 xb2 += len; 953 } 954 else 955 if(xe2 < xe1) 956 { 957 // Invalidate span2 and eat 958 // the processed part of span1 959 //-------------- 960 xb2 = invalid_b; 961 xe2 = invalid_e; 962 xb1 += len; 963 } 964 else 965 { 966 xb1 = invalid_b; // Invalidate both 967 xb2 = invalid_b; 968 xe1 = invalid_e; 969 xe2 = invalid_e; 970 } 971 } 972 else 973 { 974 // The spans do not intersect 975 //-------------- 976 if(xb1 < xb2) 977 { 978 // Advance span1 979 //--------------- 980 if(xb1 <= xe1) 981 { 982 add_span1(span1, xb1, xe1 - xb1 + 1, sl); 983 } 984 xb1 = invalid_b; // Invalidate 985 xe1 = invalid_e; 986 } 987 else 988 { 989 // Advance span2 990 //--------------- 991 if(xb2 <= xe2) 992 { 993 add_span2(span2, xb2, xe2 - xb2 + 1, sl); 994 } 995 xb2 = invalid_b; // Invalidate 996 xe2 = invalid_e; 997 } 998 } 999 } 1000 } 1001 1002 1003 1004 1005 //----------------------------------------------------sbool_unite_shapes 1006 // Unite the scanline shapes. Here the "Scanline Generator" 1007 // abstraction is used. ScanlineGen1 and ScanlineGen2 are 1008 // the generators, and can be of type rasterizer_scanline_aa<>. 1009 // There function requires three scanline containers that can be 1010 // of different type. 1011 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 1012 // "sl" is ised as the resulting scanline to render it. 1013 // The external "sl1" and "sl2" are used only for the sake of 1014 // optimization and reusing of the scanline objects. 1015 // the function calls sbool_unite_scanlines with CombineSpansFunctor 1016 // as the last argument. See sbool_unite_scanlines for details. 1017 //---------- 1018 template<class ScanlineGen1, 1019 class ScanlineGen2, 1020 class Scanline1, 1021 class Scanline2, 1022 class Scanline, 1023 class Renderer, 1024 class AddSpanFunctor1, 1025 class AddSpanFunctor2, 1026 class CombineSpansFunctor> sbool_unite_shapes(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren,AddSpanFunctor1 add_span1,AddSpanFunctor2 add_span2,CombineSpansFunctor combine_spans)1027 void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, 1028 Scanline1& sl1, Scanline2& sl2, 1029 Scanline& sl, Renderer& ren, 1030 AddSpanFunctor1 add_span1, 1031 AddSpanFunctor2 add_span2, 1032 CombineSpansFunctor combine_spans) 1033 { 1034 // Prepare the scanline generators. 1035 // If anyone of them doesn't contain 1036 // any scanlines, then return. 1037 //----------------- 1038 bool flag1 = sg1.rewind_scanlines(); 1039 bool flag2 = sg2.rewind_scanlines(); 1040 if(!flag1 && !flag2) return; 1041 1042 // Get the bounding boxes 1043 //---------------- 1044 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); 1045 rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); 1046 1047 // Calculate the union of the bounding boxes 1048 //----------------- 1049 rect_i ur(1,1,0,0); 1050 if(flag1 && flag2) ur = unite_rectangles(r1, r2); 1051 else if(flag1) ur = r1; 1052 else if(flag2) ur = r2; 1053 1054 if(!ur.is_valid()) return; 1055 1056 ren.prepare(); 1057 1058 // Reset the scanlines and get two first ones 1059 //----------------- 1060 sl.reset(ur.x1, ur.x2); 1061 if(flag1) 1062 { 1063 sl1.reset(sg1.min_x(), sg1.max_x()); 1064 flag1 = sg1.sweep_scanline(sl1); 1065 } 1066 1067 if(flag2) 1068 { 1069 sl2.reset(sg2.min_x(), sg2.max_x()); 1070 flag2 = sg2.sweep_scanline(sl2); 1071 } 1072 1073 // The main loop 1074 // Here we synchronize the scanlines with 1075 // the same Y coordinate. 1076 //----------------- 1077 while(flag1 || flag2) 1078 { 1079 if(flag1 && flag2) 1080 { 1081 if(sl1.y() == sl2.y()) 1082 { 1083 // The Y coordinates are the same. 1084 // Combine the scanlines, render if they contain any spans, 1085 // and advance both generators to the next scanlines 1086 //---------------------- 1087 sbool_unite_scanlines(sl1, sl2, sl, 1088 add_span1, add_span2, combine_spans); 1089 if(sl.num_spans()) 1090 { 1091 sl.finalize(sl1.y()); 1092 ren.render(sl); 1093 } 1094 flag1 = sg1.sweep_scanline(sl1); 1095 flag2 = sg2.sweep_scanline(sl2); 1096 } 1097 else 1098 { 1099 if(sl1.y() < sl2.y()) 1100 { 1101 sbool_add_spans_and_render(sl1, sl, ren, add_span1); 1102 flag1 = sg1.sweep_scanline(sl1); 1103 } 1104 else 1105 { 1106 sbool_add_spans_and_render(sl2, sl, ren, add_span2); 1107 flag2 = sg2.sweep_scanline(sl2); 1108 } 1109 } 1110 } 1111 else 1112 { 1113 if(flag1) 1114 { 1115 sbool_add_spans_and_render(sl1, sl, ren, add_span1); 1116 flag1 = sg1.sweep_scanline(sl1); 1117 } 1118 if(flag2) 1119 { 1120 sbool_add_spans_and_render(sl2, sl, ren, add_span2); 1121 flag2 = sg2.sweep_scanline(sl2); 1122 } 1123 } 1124 } 1125 } 1126 1127 1128 1129 1130 1131 1132 1133 1134 //-------------------------------------------------sbool_subtract_shapes 1135 // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator" 1136 // abstraction is used. ScanlineGen1 and ScanlineGen2 are 1137 // the generators, and can be of type rasterizer_scanline_aa<>. 1138 // There function requires three scanline containers that can be of 1139 // different types. 1140 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 1141 // "sl" is ised as the resulting scanline to render it. 1142 // The external "sl1" and "sl2" are used only for the sake of 1143 // optimization and reusing of the scanline objects. 1144 // the function calls sbool_intersect_scanlines with CombineSpansFunctor 1145 // as the last argument. See combine_scanlines_sub for details. 1146 //---------- 1147 template<class ScanlineGen1, 1148 class ScanlineGen2, 1149 class Scanline1, 1150 class Scanline2, 1151 class Scanline, 1152 class Renderer, 1153 class AddSpanFunctor1, 1154 class CombineSpansFunctor> sbool_subtract_shapes(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren,AddSpanFunctor1 add_span1,CombineSpansFunctor combine_spans)1155 void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, 1156 Scanline1& sl1, Scanline2& sl2, 1157 Scanline& sl, Renderer& ren, 1158 AddSpanFunctor1 add_span1, 1159 CombineSpansFunctor combine_spans) 1160 { 1161 // Prepare the scanline generators. 1162 // Here "sg1" is master, "sg2" is slave. 1163 //----------------- 1164 if(!sg1.rewind_scanlines()) return; 1165 bool flag2 = sg2.rewind_scanlines(); 1166 1167 // Get the bounding box 1168 //---------------- 1169 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); 1170 1171 // Reset the scanlines and get two first ones 1172 //----------------- 1173 sl.reset(sg1.min_x(), sg1.max_x()); 1174 sl1.reset(sg1.min_x(), sg1.max_x()); 1175 sl2.reset(sg2.min_x(), sg2.max_x()); 1176 if(!sg1.sweep_scanline(sl1)) return; 1177 1178 if(flag2) flag2 = sg2.sweep_scanline(sl2); 1179 1180 ren.prepare(); 1181 1182 // A fake span2 processor 1183 sbool_add_span_empty<Scanline2, Scanline> add_span2; 1184 1185 // The main loop 1186 // Here we synchronize the scanlines with 1187 // the same Y coordinate, ignoring all other ones. 1188 // Only scanlines having the same Y-coordinate 1189 // are to be combined. 1190 //----------------- 1191 bool flag1 = true; 1192 do 1193 { 1194 // Synchronize "slave" with "master" 1195 //----------------- 1196 while(flag2 && sl2.y() < sl1.y()) 1197 { 1198 flag2 = sg2.sweep_scanline(sl2); 1199 } 1200 1201 1202 if(flag2 && sl2.y() == sl1.y()) 1203 { 1204 // The Y coordinates are the same. 1205 // Combine the scanlines and render if they contain any spans. 1206 //---------------------- 1207 sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); 1208 if(sl.num_spans()) 1209 { 1210 sl.finalize(sl1.y()); 1211 ren.render(sl); 1212 } 1213 } 1214 else 1215 { 1216 sbool_add_spans_and_render(sl1, sl, ren, add_span1); 1217 } 1218 1219 // Advance the "master" 1220 flag1 = sg1.sweep_scanline(sl1); 1221 } 1222 while(flag1); 1223 } 1224 1225 1226 1227 1228 1229 1230 1231 //---------------------------------------------sbool_intersect_shapes_aa 1232 // Intersect two anti-aliased scanline shapes. 1233 // Here the "Scanline Generator" abstraction is used. 1234 // ScanlineGen1 and ScanlineGen2 are the generators, and can be of 1235 // type rasterizer_scanline_aa<>. There function requires three 1236 // scanline containers that can be of different types. 1237 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 1238 // "sl" is ised as the resulting scanline to render it. 1239 // The external "sl1" and "sl2" are used only for the sake of 1240 // optimization and reusing of the scanline objects. 1241 //---------- 1242 template<class ScanlineGen1, 1243 class ScanlineGen2, 1244 class Scanline1, 1245 class Scanline2, 1246 class Scanline, 1247 class Renderer> sbool_intersect_shapes_aa(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1248 void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 1249 Scanline1& sl1, Scanline2& sl2, 1250 Scanline& sl, Renderer& ren) 1251 { 1252 sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; 1253 sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); 1254 } 1255 1256 1257 1258 1259 1260 //--------------------------------------------sbool_intersect_shapes_bin 1261 // Intersect two binary scanline shapes (without anti-aliasing). 1262 // See intersect_shapes_aa for more comments 1263 //---------- 1264 template<class ScanlineGen1, 1265 class ScanlineGen2, 1266 class Scanline1, 1267 class Scanline2, 1268 class Scanline, 1269 class Renderer> sbool_intersect_shapes_bin(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1270 void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 1271 Scanline1& sl1, Scanline2& sl2, 1272 Scanline& sl, Renderer& ren) 1273 { 1274 sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; 1275 sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); 1276 } 1277 1278 1279 1280 1281 1282 //-------------------------------------------------sbool_unite_shapes_aa 1283 // Unite two anti-aliased scanline shapes 1284 // See intersect_shapes_aa for more comments 1285 //---------- 1286 template<class ScanlineGen1, 1287 class ScanlineGen2, 1288 class Scanline1, 1289 class Scanline2, 1290 class Scanline, 1291 class Renderer> sbool_unite_shapes_aa(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1292 void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 1293 Scanline1& sl1, Scanline2& sl2, 1294 Scanline& sl, Renderer& ren) 1295 { 1296 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 1297 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 1298 sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; 1299 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 1300 add_functor1, add_functor2, combine_functor); 1301 } 1302 1303 1304 1305 1306 1307 //------------------------------------------------sbool_unite_shapes_bin 1308 // Unite two binary scanline shapes (without anti-aliasing). 1309 // See intersect_shapes_aa for more comments 1310 //---------- 1311 template<class ScanlineGen1, 1312 class ScanlineGen2, 1313 class Scanline1, 1314 class Scanline2, 1315 class Scanline, 1316 class Renderer> sbool_unite_shapes_bin(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1317 void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 1318 Scanline1& sl1, Scanline2& sl2, 1319 Scanline& sl, Renderer& ren) 1320 { 1321 sbool_add_span_bin<Scanline1, Scanline> add_functor1; 1322 sbool_add_span_bin<Scanline2, Scanline> add_functor2; 1323 sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; 1324 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 1325 add_functor1, add_functor2, combine_functor); 1326 } 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 //---------------------------------------------------sbool_xor_shapes_aa 1337 // Apply eXclusive OR to two anti-aliased scanline shapes. There's 1338 // a modified "Linear" XOR used instead of classical "Saddle" one. 1339 // The reason is to have the result absolutely conststent with what 1340 // the scanline rasterizer produces. 1341 // See intersect_shapes_aa for more comments 1342 //---------- 1343 template<class ScanlineGen1, 1344 class ScanlineGen2, 1345 class Scanline1, 1346 class Scanline2, 1347 class Scanline, 1348 class Renderer> sbool_xor_shapes_aa(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1349 void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 1350 Scanline1& sl1, Scanline2& sl2, 1351 Scanline& sl, Renderer& ren) 1352 { 1353 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 1354 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 1355 sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, 1356 sbool_xor_formula_linear<> > combine_functor; 1357 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 1358 add_functor1, add_functor2, combine_functor); 1359 } 1360 1361 1362 1363 //------------------------------------------sbool_xor_shapes_saddle_aa 1364 // Apply eXclusive OR to two anti-aliased scanline shapes. 1365 // There's the classical "Saddle" used to calculate the 1366 // Anti-Aliasing values, that is: 1367 // a XOR b : 1-((1-a+a*b)*(1-b+a*b)) 1368 // See intersect_shapes_aa for more comments 1369 //---------- 1370 template<class ScanlineGen1, 1371 class ScanlineGen2, 1372 class Scanline1, 1373 class Scanline2, 1374 class Scanline, 1375 class Renderer> sbool_xor_shapes_saddle_aa(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1376 void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 1377 Scanline1& sl1, Scanline2& sl2, 1378 Scanline& sl, Renderer& ren) 1379 { 1380 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 1381 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 1382 sbool_xor_spans_aa<Scanline1, 1383 Scanline2, 1384 Scanline, 1385 sbool_xor_formula_saddle<> > combine_functor; 1386 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 1387 add_functor1, add_functor2, combine_functor); 1388 } 1389 1390 1391 //--------------------------------------sbool_xor_shapes_abs_diff_aa 1392 // Apply eXclusive OR to two anti-aliased scanline shapes. 1393 // There's the absolute difference used to calculate 1394 // Anti-Aliasing values, that is: 1395 // a XOR b : abs(a-b) 1396 // See intersect_shapes_aa for more comments 1397 //---------- 1398 template<class ScanlineGen1, 1399 class ScanlineGen2, 1400 class Scanline1, 1401 class Scanline2, 1402 class Scanline, 1403 class Renderer> sbool_xor_shapes_abs_diff_aa(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1404 void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 1405 Scanline1& sl1, Scanline2& sl2, 1406 Scanline& sl, Renderer& ren) 1407 { 1408 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 1409 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 1410 sbool_xor_spans_aa<Scanline1, 1411 Scanline2, 1412 Scanline, 1413 sbool_xor_formula_abs_diff> combine_functor; 1414 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 1415 add_functor1, add_functor2, combine_functor); 1416 } 1417 1418 1419 1420 //--------------------------------------------------sbool_xor_shapes_bin 1421 // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). 1422 // See intersect_shapes_aa for more comments 1423 //---------- 1424 template<class ScanlineGen1, 1425 class ScanlineGen2, 1426 class Scanline1, 1427 class Scanline2, 1428 class Scanline, 1429 class Renderer> sbool_xor_shapes_bin(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1430 void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 1431 Scanline1& sl1, Scanline2& sl2, 1432 Scanline& sl, Renderer& ren) 1433 { 1434 sbool_add_span_bin<Scanline1, Scanline> add_functor1; 1435 sbool_add_span_bin<Scanline2, Scanline> add_functor2; 1436 sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; 1437 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 1438 add_functor1, add_functor2, combine_functor); 1439 } 1440 1441 1442 1443 1444 1445 1446 //----------------------------------------------sbool_subtract_shapes_aa 1447 // Subtract shapes "sg1-sg2" with anti-aliasing 1448 // See intersect_shapes_aa for more comments 1449 //---------- 1450 template<class ScanlineGen1, 1451 class ScanlineGen2, 1452 class Scanline1, 1453 class Scanline2, 1454 class Scanline, 1455 class Renderer> sbool_subtract_shapes_aa(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1456 void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 1457 Scanline1& sl1, Scanline2& sl2, 1458 Scanline& sl, Renderer& ren) 1459 { 1460 sbool_add_span_aa<Scanline1, Scanline> add_functor; 1461 sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; 1462 sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, 1463 add_functor, combine_functor); 1464 } 1465 1466 1467 1468 1469 1470 //---------------------------------------------sbool_subtract_shapes_bin 1471 // Subtract binary shapes "sg1-sg2" without anti-aliasing 1472 // See intersect_shapes_aa for more comments 1473 //---------- 1474 template<class ScanlineGen1, 1475 class ScanlineGen2, 1476 class Scanline1, 1477 class Scanline2, 1478 class Scanline, 1479 class Renderer> sbool_subtract_shapes_bin(ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1480 void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 1481 Scanline1& sl1, Scanline2& sl2, 1482 Scanline& sl, Renderer& ren) 1483 { 1484 sbool_add_span_bin<Scanline1, Scanline> add_functor; 1485 sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; 1486 sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, 1487 add_functor, combine_functor); 1488 } 1489 1490 1491 1492 1493 1494 1495 //------------------------------------------------------------sbool_op_e 1496 enum sbool_op_e 1497 { 1498 sbool_or, //----sbool_or 1499 sbool_and, //----sbool_and 1500 sbool_xor, //----sbool_xor 1501 sbool_xor_saddle, //----sbool_xor_saddle 1502 sbool_xor_abs_diff, //----sbool_xor_abs_diff 1503 sbool_a_minus_b, //----sbool_a_minus_b 1504 sbool_b_minus_a //----sbool_b_minus_a 1505 }; 1506 1507 1508 1509 1510 1511 1512 //----------------------------------------------sbool_combine_shapes_bin 1513 template<class ScanlineGen1, 1514 class ScanlineGen2, 1515 class Scanline1, 1516 class Scanline2, 1517 class Scanline, 1518 class Renderer> sbool_combine_shapes_bin(sbool_op_e op,ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1519 void sbool_combine_shapes_bin(sbool_op_e op, 1520 ScanlineGen1& sg1, ScanlineGen2& sg2, 1521 Scanline1& sl1, Scanline2& sl2, 1522 Scanline& sl, Renderer& ren) 1523 { 1524 switch(op) 1525 { 1526 case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; 1527 case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; 1528 case sbool_xor : 1529 case sbool_xor_saddle : 1530 case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; 1531 case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; 1532 case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; 1533 } 1534 } 1535 1536 1537 1538 1539 //-----------------------------------------------sbool_combine_shapes_aa 1540 template<class ScanlineGen1, 1541 class ScanlineGen2, 1542 class Scanline1, 1543 class Scanline2, 1544 class Scanline, 1545 class Renderer> sbool_combine_shapes_aa(sbool_op_e op,ScanlineGen1 & sg1,ScanlineGen2 & sg2,Scanline1 & sl1,Scanline2 & sl2,Scanline & sl,Renderer & ren)1546 void sbool_combine_shapes_aa(sbool_op_e op, 1547 ScanlineGen1& sg1, ScanlineGen2& sg2, 1548 Scanline1& sl1, Scanline2& sl2, 1549 Scanline& sl, Renderer& ren) 1550 { 1551 switch(op) 1552 { 1553 case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 1554 case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 1555 case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 1556 case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; 1557 case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; 1558 case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 1559 case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; 1560 } 1561 } 1562 1563 } 1564 1565 1566 #endif 1567 1568