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