Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED 00026 #define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED 00027 00028 #include <stdlib.h> 00029 #include <math.h> 00030 #include "agg_basics.h" 00031 00032 00033 namespace agg 00034 { 00035 00036 //-----------------------------------------------sbool_combine_spans_bin 00037 // Functor. 00038 // Combine two binary encoded spans, i.e., when we don't have any 00039 // anti-aliasing information, but only X and Length. The function 00040 // is compatible with any type of scanlines. 00041 //---------------- 00042 template<class Scanline1, 00043 class Scanline2, 00044 class Scanline> 00045 struct sbool_combine_spans_bin 00046 { 00047 void operator () (const typename Scanline1::const_iterator&, 00048 const typename Scanline2::const_iterator&, 00049 int x, unsigned len, 00050 Scanline& sl) const 00051 { 00052 sl.add_span(x, len, cover_full); 00053 } 00054 }; 00055 00056 00057 00058 //---------------------------------------------sbool_combine_spans_empty 00059 // Functor. 00060 // Combine two spans as empty ones. The functor does nothing 00061 // and is used to XOR binary spans. 00062 //---------------- 00063 template<class Scanline1, 00064 class Scanline2, 00065 class Scanline> 00066 struct sbool_combine_spans_empty 00067 { 00068 void operator () (const typename Scanline1::const_iterator&, 00069 const typename Scanline2::const_iterator&, 00070 int, unsigned, 00071 Scanline&) const 00072 {} 00073 }; 00074 00075 00076 00077 //--------------------------------------------------sbool_add_span_empty 00078 // Functor. 00079 // Add nothing. Used in conbine_shapes_sub 00080 //---------------- 00081 template<class Scanline1, 00082 class Scanline> 00083 struct sbool_add_span_empty 00084 { 00085 void operator () (const typename Scanline1::const_iterator&, 00086 int, unsigned, 00087 Scanline&) const 00088 {} 00089 }; 00090 00091 00092 //----------------------------------------------------sbool_add_span_bin 00093 // Functor. 00094 // Add a binary span 00095 //---------------- 00096 template<class Scanline1, 00097 class Scanline> 00098 struct sbool_add_span_bin 00099 { 00100 void operator () (const typename Scanline1::const_iterator&, 00101 int x, unsigned len, 00102 Scanline& sl) const 00103 { 00104 sl.add_span(x, len, cover_full); 00105 } 00106 }; 00107 00108 00109 00110 00111 //-----------------------------------------------------sbool_add_span_aa 00112 // Functor. 00113 // Add an anti-aliased span 00114 // anti-aliasing information, but only X and Length. The function 00115 // is compatible with any type of scanlines. 00116 //---------------- 00117 template<class Scanline1, 00118 class Scanline> 00119 struct sbool_add_span_aa 00120 { 00121 void operator () (const typename Scanline1::const_iterator& span, 00122 int x, unsigned len, 00123 Scanline& sl) const 00124 { 00125 if(span->len < 0) 00126 { 00127 sl.add_span(x, len, *span->covers); 00128 } 00129 else 00130 if(span->len > 0) 00131 { 00132 const typename Scanline1::cover_type* covers = span->covers; 00133 if(span->x < x) covers += x - span->x; 00134 sl.add_cells(x, len, covers); 00135 } 00136 } 00137 }; 00138 00139 00140 00141 00142 //----------------------------------------------sbool_intersect_spans_aa 00143 // Functor. 00144 // Intersect two spans preserving the anti-aliasing information. 00145 // The result is added to the "sl" scanline. 00146 //------------------ 00147 template<class Scanline1, 00148 class Scanline2, 00149 class Scanline, 00150 unsigned CoverShift = cover_shift> 00151 struct sbool_intersect_spans_aa 00152 { 00153 enum cover_scale_e 00154 { 00155 cover_shift = CoverShift, 00156 cover_size = 1 << cover_shift, 00157 cover_mask = cover_size - 1, 00158 cover_full = cover_mask 00159 }; 00160 00161 00162 void operator () (const typename Scanline1::const_iterator& span1, 00163 const typename Scanline2::const_iterator& span2, 00164 int x, unsigned len, 00165 Scanline& sl) const 00166 { 00167 unsigned cover; 00168 const typename Scanline1::cover_type* covers1; 00169 const typename Scanline2::cover_type* covers2; 00170 00171 // Calculate the operation code and choose the 00172 // proper combination algorithm. 00173 // 0 = Both spans are of AA type 00174 // 1 = span1 is solid, span2 is AA 00175 // 2 = span1 is AA, span2 is solid 00176 // 3 = Both spans are of solid type 00177 //----------------- 00178 switch((span1->len < 0) | ((span2->len < 0) << 1)) 00179 { 00180 case 0: // Both are AA spans 00181 covers1 = span1->covers; 00182 covers2 = span2->covers; 00183 if(span1->x < x) covers1 += x - span1->x; 00184 if(span2->x < x) covers2 += x - span2->x; 00185 do 00186 { 00187 cover = *covers1++ * *covers2++; 00188 sl.add_cell(x++, 00189 (cover == cover_full * cover_full) ? 00190 cover_full : 00191 (cover >> cover_shift)); 00192 } 00193 while(--len); 00194 break; 00195 00196 case 1: // span1 is solid, span2 is AA 00197 covers2 = span2->covers; 00198 if(span2->x < x) covers2 += x - span2->x; 00199 if(*(span1->covers) == cover_full) 00200 { 00201 sl.add_cells(x, len, covers2); 00202 } 00203 else 00204 { 00205 do 00206 { 00207 cover = *(span1->covers) * *covers2++; 00208 sl.add_cell(x++, 00209 (cover == cover_full * cover_full) ? 00210 cover_full : 00211 (cover >> cover_shift)); 00212 } 00213 while(--len); 00214 } 00215 break; 00216 00217 case 2: // span1 is AA, span2 is solid 00218 covers1 = span1->covers; 00219 if(span1->x < x) covers1 += x - span1->x; 00220 if(*(span2->covers) == cover_full) 00221 { 00222 sl.add_cells(x, len, covers1); 00223 } 00224 else 00225 { 00226 do 00227 { 00228 cover = *covers1++ * *(span2->covers); 00229 sl.add_cell(x++, 00230 (cover == cover_full * cover_full) ? 00231 cover_full : 00232 (cover >> cover_shift)); 00233 } 00234 while(--len); 00235 } 00236 break; 00237 00238 case 3: // Both are solid spans 00239 cover = *(span1->covers) * *(span2->covers); 00240 sl.add_span(x, len, 00241 (cover == cover_full * cover_full) ? 00242 cover_full : 00243 (cover >> cover_shift)); 00244 break; 00245 } 00246 } 00247 }; 00248 00249 00250 00251 00252 00253 00254 //--------------------------------------------------sbool_unite_spans_aa 00255 // Functor. 00256 // Unite two spans preserving the anti-aliasing information. 00257 // The result is added to the "sl" scanline. 00258 //------------------ 00259 template<class Scanline1, 00260 class Scanline2, 00261 class Scanline, 00262 unsigned CoverShift = cover_shift> 00263 struct sbool_unite_spans_aa 00264 { 00265 enum cover_scale_e 00266 { 00267 cover_shift = CoverShift, 00268 cover_size = 1 << cover_shift, 00269 cover_mask = cover_size - 1, 00270 cover_full = cover_mask 00271 }; 00272 00273 00274 void operator () (const typename Scanline1::const_iterator& span1, 00275 const typename Scanline2::const_iterator& span2, 00276 int x, unsigned len, 00277 Scanline& sl) const 00278 { 00279 unsigned cover; 00280 const typename Scanline1::cover_type* covers1; 00281 const typename Scanline2::cover_type* covers2; 00282 00283 // Calculate the operation code and choose the 00284 // proper combination algorithm. 00285 // 0 = Both spans are of AA type 00286 // 1 = span1 is solid, span2 is AA 00287 // 2 = span1 is AA, span2 is solid 00288 // 3 = Both spans are of solid type 00289 //----------------- 00290 switch((span1->len < 0) | ((span2->len < 0) << 1)) 00291 { 00292 case 0: // Both are AA spans 00293 covers1 = span1->covers; 00294 covers2 = span2->covers; 00295 if(span1->x < x) covers1 += x - span1->x; 00296 if(span2->x < x) covers2 += x - span2->x; 00297 do 00298 { 00299 cover = cover_mask * cover_mask - 00300 (cover_mask - *covers1++) * 00301 (cover_mask - *covers2++); 00302 sl.add_cell(x++, 00303 (cover == cover_full * cover_full) ? 00304 cover_full : 00305 (cover >> cover_shift)); 00306 } 00307 while(--len); 00308 break; 00309 00310 case 1: // span1 is solid, span2 is AA 00311 covers2 = span2->covers; 00312 if(span2->x < x) covers2 += x - span2->x; 00313 if(*(span1->covers) == cover_full) 00314 { 00315 sl.add_span(x, len, cover_full); 00316 } 00317 else 00318 { 00319 do 00320 { 00321 cover = cover_mask * cover_mask - 00322 (cover_mask - *(span1->covers)) * 00323 (cover_mask - *covers2++); 00324 sl.add_cell(x++, 00325 (cover == cover_full * cover_full) ? 00326 cover_full : 00327 (cover >> cover_shift)); 00328 } 00329 while(--len); 00330 } 00331 break; 00332 00333 case 2: // span1 is AA, span2 is solid 00334 covers1 = span1->covers; 00335 if(span1->x < x) covers1 += x - span1->x; 00336 if(*(span2->covers) == cover_full) 00337 { 00338 sl.add_span(x, len, cover_full); 00339 } 00340 else 00341 { 00342 do 00343 { 00344 cover = cover_mask * cover_mask - 00345 (cover_mask - *covers1++) * 00346 (cover_mask - *(span2->covers)); 00347 sl.add_cell(x++, 00348 (cover == cover_full * cover_full) ? 00349 cover_full : 00350 (cover >> cover_shift)); 00351 } 00352 while(--len); 00353 } 00354 break; 00355 00356 case 3: // Both are solid spans 00357 cover = cover_mask * cover_mask - 00358 (cover_mask - *(span1->covers)) * 00359 (cover_mask - *(span2->covers)); 00360 sl.add_span(x, len, 00361 (cover == cover_full * cover_full) ? 00362 cover_full : 00363 (cover >> cover_shift)); 00364 break; 00365 } 00366 } 00367 }; 00368 00369 00370 //---------------------------------------------sbool_xor_formula_linear 00371 template<unsigned CoverShift = cover_shift> 00372 struct sbool_xor_formula_linear 00373 { 00374 enum cover_scale_e 00375 { 00376 cover_shift = CoverShift, 00377 cover_size = 1 << cover_shift, 00378 cover_mask = cover_size - 1 00379 }; 00380 00381 static AGG_INLINE unsigned calculate(unsigned a, unsigned b) 00382 { 00383 unsigned cover = a + b; 00384 if(cover > cover_mask) cover = cover_mask + cover_mask - cover; 00385 return cover; 00386 } 00387 }; 00388 00389 00390 //---------------------------------------------sbool_xor_formula_saddle 00391 template<unsigned CoverShift = cover_shift> 00392 struct sbool_xor_formula_saddle 00393 { 00394 enum cover_scale_e 00395 { 00396 cover_shift = CoverShift, 00397 cover_size = 1 << cover_shift, 00398 cover_mask = cover_size - 1 00399 }; 00400 00401 static AGG_INLINE unsigned calculate(unsigned a, unsigned b) 00402 { 00403 unsigned k = a * b; 00404 if(k == cover_mask * cover_mask) return 0; 00405 00406 a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift; 00407 b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift; 00408 return cover_mask - ((a * b) >> cover_shift); 00409 } 00410 }; 00411 00412 00413 //-------------------------------------------sbool_xor_formula_abs_diff 00414 struct sbool_xor_formula_abs_diff 00415 { 00416 static AGG_INLINE unsigned calculate(unsigned a, unsigned b) 00417 { 00418 return unsigned(abs(int(a) - int(b))); 00419 } 00420 }; 00421 00422 00423 00424 //----------------------------------------------------sbool_xor_spans_aa 00425 // Functor. 00426 // XOR two spans preserving the anti-aliasing information. 00427 // The result is added to the "sl" scanline. 00428 //------------------ 00429 template<class Scanline1, 00430 class Scanline2, 00431 class Scanline, 00432 class XorFormula, 00433 unsigned CoverShift = cover_shift> 00434 struct sbool_xor_spans_aa 00435 { 00436 enum cover_scale_e 00437 { 00438 cover_shift = CoverShift, 00439 cover_size = 1 << cover_shift, 00440 cover_mask = cover_size - 1, 00441 cover_full = cover_mask 00442 }; 00443 00444 00445 void operator () (const typename Scanline1::const_iterator& span1, 00446 const typename Scanline2::const_iterator& span2, 00447 int x, unsigned len, 00448 Scanline& sl) const 00449 { 00450 unsigned cover; 00451 const typename Scanline1::cover_type* covers1; 00452 const typename Scanline2::cover_type* covers2; 00453 00454 // Calculate the operation code and choose the 00455 // proper combination algorithm. 00456 // 0 = Both spans are of AA type 00457 // 1 = span1 is solid, span2 is AA 00458 // 2 = span1 is AA, span2 is solid 00459 // 3 = Both spans are of solid type 00460 //----------------- 00461 switch((span1->len < 0) | ((span2->len < 0) << 1)) 00462 { 00463 case 0: // Both are AA spans 00464 covers1 = span1->covers; 00465 covers2 = span2->covers; 00466 if(span1->x < x) covers1 += x - span1->x; 00467 if(span2->x < x) covers2 += x - span2->x; 00468 do 00469 { 00470 cover = XorFormula::calculate(*covers1++, *covers2++); 00471 if(cover) sl.add_cell(x, cover); 00472 ++x; 00473 } 00474 while(--len); 00475 break; 00476 00477 case 1: // span1 is solid, span2 is AA 00478 covers2 = span2->covers; 00479 if(span2->x < x) covers2 += x - span2->x; 00480 do 00481 { 00482 cover = XorFormula::calculate(*(span1->covers), *covers2++); 00483 if(cover) sl.add_cell(x, cover); 00484 ++x; 00485 } 00486 while(--len); 00487 break; 00488 00489 case 2: // span1 is AA, span2 is solid 00490 covers1 = span1->covers; 00491 if(span1->x < x) covers1 += x - span1->x; 00492 do 00493 { 00494 cover = XorFormula::calculate(*covers1++, *(span2->covers)); 00495 if(cover) sl.add_cell(x, cover); 00496 ++x; 00497 } 00498 while(--len); 00499 break; 00500 00501 case 3: // Both are solid spans 00502 cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); 00503 if(cover) sl.add_span(x, len, cover); 00504 break; 00505 00506 } 00507 } 00508 }; 00509 00510 00511 00512 00513 00514 //-----------------------------------------------sbool_subtract_spans_aa 00515 // Functor. 00516 // Unite two spans preserving the anti-aliasing information. 00517 // The result is added to the "sl" scanline. 00518 //------------------ 00519 template<class Scanline1, 00520 class Scanline2, 00521 class Scanline, 00522 unsigned CoverShift = cover_shift> 00523 struct sbool_subtract_spans_aa 00524 { 00525 enum cover_scale_e 00526 { 00527 cover_shift = CoverShift, 00528 cover_size = 1 << cover_shift, 00529 cover_mask = cover_size - 1, 00530 cover_full = cover_mask 00531 }; 00532 00533 00534 void operator () (const typename Scanline1::const_iterator& span1, 00535 const typename Scanline2::const_iterator& span2, 00536 int x, unsigned len, 00537 Scanline& sl) const 00538 { 00539 unsigned cover; 00540 const typename Scanline1::cover_type* covers1; 00541 const typename Scanline2::cover_type* covers2; 00542 00543 // Calculate the operation code and choose the 00544 // proper combination algorithm. 00545 // 0 = Both spans are of AA type 00546 // 1 = span1 is solid, span2 is AA 00547 // 2 = span1 is AA, span2 is solid 00548 // 3 = Both spans are of solid type 00549 //----------------- 00550 switch((span1->len < 0) | ((span2->len < 0) << 1)) 00551 { 00552 case 0: // Both are AA spans 00553 covers1 = span1->covers; 00554 covers2 = span2->covers; 00555 if(span1->x < x) covers1 += x - span1->x; 00556 if(span2->x < x) covers2 += x - span2->x; 00557 do 00558 { 00559 cover = *covers1++ * (cover_mask - *covers2++); 00560 if(cover) 00561 { 00562 sl.add_cell(x, 00563 (cover == cover_full * cover_full) ? 00564 cover_full : 00565 (cover >> cover_shift)); 00566 } 00567 ++x; 00568 } 00569 while(--len); 00570 break; 00571 00572 case 1: // span1 is solid, span2 is AA 00573 covers2 = span2->covers; 00574 if(span2->x < x) covers2 += x - span2->x; 00575 do 00576 { 00577 cover = *(span1->covers) * (cover_mask - *covers2++); 00578 if(cover) 00579 { 00580 sl.add_cell(x, 00581 (cover == cover_full * cover_full) ? 00582 cover_full : 00583 (cover >> cover_shift)); 00584 } 00585 ++x; 00586 } 00587 while(--len); 00588 break; 00589 00590 case 2: // span1 is AA, span2 is solid 00591 covers1 = span1->covers; 00592 if(span1->x < x) covers1 += x - span1->x; 00593 if(*(span2->covers) != cover_full) 00594 { 00595 do 00596 { 00597 cover = *covers1++ * (cover_mask - *(span2->covers)); 00598 if(cover) 00599 { 00600 sl.add_cell(x, 00601 (cover == cover_full * cover_full) ? 00602 cover_full : 00603 (cover >> cover_shift)); 00604 } 00605 ++x; 00606 } 00607 while(--len); 00608 } 00609 break; 00610 00611 case 3: // Both are solid spans 00612 cover = *(span1->covers) * (cover_mask - *(span2->covers)); 00613 if(cover) 00614 { 00615 sl.add_span(x, len, 00616 (cover == cover_full * cover_full) ? 00617 cover_full : 00618 (cover >> cover_shift)); 00619 } 00620 break; 00621 } 00622 } 00623 }; 00624 00625 00626 00627 00628 00629 00630 //--------------------------------------------sbool_add_spans_and_render 00631 template<class Scanline1, 00632 class Scanline, 00633 class Renderer, 00634 class AddSpanFunctor> 00635 void sbool_add_spans_and_render(const Scanline1& sl1, 00636 Scanline& sl, 00637 Renderer& ren, 00638 AddSpanFunctor add_span) 00639 { 00640 sl.reset_spans(); 00641 typename Scanline1::const_iterator span = sl1.begin(); 00642 unsigned num_spans = sl1.num_spans(); 00643 for(;;) 00644 { 00645 add_span(span, span->x, abs((int)span->len), sl); 00646 if(--num_spans == 0) break; 00647 ++span; 00648 } 00649 sl.finalize(sl1.y()); 00650 ren.render(sl); 00651 } 00652 00653 00654 00655 00656 00657 00658 00659 //---------------------------------------------sbool_intersect_scanlines 00660 // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. 00661 // The combine_spans functor can be of type sbool_combine_spans_bin or 00662 // sbool_intersect_spans_aa. First is a general functor to combine 00663 // two spans without Anti-Aliasing, the second preserves the AA 00664 // information, but works slower 00665 // 00666 template<class Scanline1, 00667 class Scanline2, 00668 class Scanline, 00669 class CombineSpansFunctor> 00670 void sbool_intersect_scanlines(const Scanline1& sl1, 00671 const Scanline2& sl2, 00672 Scanline& sl, 00673 CombineSpansFunctor combine_spans) 00674 { 00675 sl.reset_spans(); 00676 00677 unsigned num1 = sl1.num_spans(); 00678 if(num1 == 0) return; 00679 00680 unsigned num2 = sl2.num_spans(); 00681 if(num2 == 0) return; 00682 00683 typename Scanline1::const_iterator span1 = sl1.begin(); 00684 typename Scanline2::const_iterator span2 = sl2.begin(); 00685 00686 while(num1 && num2) 00687 { 00688 int xb1 = span1->x; 00689 int xb2 = span2->x; 00690 int xe1 = xb1 + abs((int)span1->len) - 1; 00691 int xe2 = xb2 + abs((int)span2->len) - 1; 00692 00693 // Determine what spans we should advance in the next step 00694 // The span with the least ending X should be advanced 00695 // advance_both is just an optimization when we ending 00696 // coordinates are the same and we can advance both 00697 //-------------- 00698 bool advance_span1 = xe1 < xe2; 00699 bool advance_both = xe1 == xe2; 00700 00701 // Find the intersection of the spans 00702 // and check if they intersect 00703 //-------------- 00704 if(xb1 < xb2) xb1 = xb2; 00705 if(xe1 > xe2) xe1 = xe2; 00706 if(xb1 <= xe1) 00707 { 00708 combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); 00709 } 00710 00711 // Advance the spans 00712 //-------------- 00713 if(advance_both) 00714 { 00715 --num1; 00716 --num2; 00717 if(num1) ++span1; 00718 if(num2) ++span2; 00719 } 00720 else 00721 { 00722 if(advance_span1) 00723 { 00724 --num1; 00725 if(num1) ++span1; 00726 } 00727 else 00728 { 00729 --num2; 00730 if(num2) ++span2; 00731 } 00732 } 00733 } 00734 } 00735 00736 00737 00738 00739 00740 00741 00742 00743 //------------------------------------------------sbool_intersect_shapes 00744 // Intersect the scanline shapes. Here the "Scanline Generator" 00745 // abstraction is used. ScanlineGen1 and ScanlineGen2 are 00746 // the generators, and can be of type rasterizer_scanline_aa<>. 00747 // There function requires three scanline containers that can be of 00748 // different types. 00749 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 00750 // "sl" is ised as the resulting scanline to render it. 00751 // The external "sl1" and "sl2" are used only for the sake of 00752 // optimization and reusing of the scanline objects. 00753 // the function calls sbool_intersect_scanlines with CombineSpansFunctor 00754 // as the last argument. See sbool_intersect_scanlines for details. 00755 //---------- 00756 template<class ScanlineGen1, 00757 class ScanlineGen2, 00758 class Scanline1, 00759 class Scanline2, 00760 class Scanline, 00761 class Renderer, 00762 class CombineSpansFunctor> 00763 void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, 00764 Scanline1& sl1, Scanline2& sl2, 00765 Scanline& sl, Renderer& ren, 00766 CombineSpansFunctor combine_spans) 00767 { 00768 // Prepare the scanline generators. 00769 // If anyone of them doesn't contain 00770 // any scanlines, then return. 00771 //----------------- 00772 if(!sg1.rewind_scanlines()) return; 00773 if(!sg2.rewind_scanlines()) return; 00774 00775 // Get the bounding boxes 00776 //---------------- 00777 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); 00778 rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); 00779 00780 // Calculate the intersection of the bounding 00781 // boxes and return if they don't intersect. 00782 //----------------- 00783 rect_i ir = intersect_rectangles(r1, r2); 00784 if(!ir.is_valid()) return; 00785 00786 // Reset the scanlines and get two first ones 00787 //----------------- 00788 sl.reset(ir.x1, ir.x2); 00789 sl1.reset(sg1.min_x(), sg1.max_x()); 00790 sl2.reset(sg2.min_x(), sg2.max_x()); 00791 if(!sg1.sweep_scanline(sl1)) return; 00792 if(!sg2.sweep_scanline(sl2)) return; 00793 00794 ren.prepare(); 00795 00796 // The main loop 00797 // Here we synchronize the scanlines with 00798 // the same Y coordinate, ignoring all other ones. 00799 // Only scanlines having the same Y-coordinate 00800 // are to be combined. 00801 //----------------- 00802 for(;;) 00803 { 00804 while(sl1.y() < sl2.y()) 00805 { 00806 if(!sg1.sweep_scanline(sl1)) return; 00807 } 00808 while(sl2.y() < sl1.y()) 00809 { 00810 if(!sg2.sweep_scanline(sl2)) return; 00811 } 00812 00813 if(sl1.y() == sl2.y()) 00814 { 00815 // The Y coordinates are the same. 00816 // Combine the scanlines, render if they contain any spans, 00817 // and advance both generators to the next scanlines 00818 //---------------------- 00819 sbool_intersect_scanlines(sl1, sl2, sl, combine_spans); 00820 if(sl.num_spans()) 00821 { 00822 sl.finalize(sl1.y()); 00823 ren.render(sl); 00824 } 00825 if(!sg1.sweep_scanline(sl1)) return; 00826 if(!sg2.sweep_scanline(sl2)) return; 00827 } 00828 } 00829 } 00830 00831 00832 00833 00834 00835 00836 00837 //-------------------------------------------------sbool_unite_scanlines 00838 // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one. 00839 // The combine_spans functor can be of type sbool_combine_spans_bin or 00840 // sbool_intersect_spans_aa. First is a general functor to combine 00841 // two spans without Anti-Aliasing, the second preserves the AA 00842 // information, but works slower 00843 // 00844 template<class Scanline1, 00845 class Scanline2, 00846 class Scanline, 00847 class AddSpanFunctor1, 00848 class AddSpanFunctor2, 00849 class CombineSpansFunctor> 00850 void sbool_unite_scanlines(const Scanline1& sl1, 00851 const Scanline2& sl2, 00852 Scanline& sl, 00853 AddSpanFunctor1 add_span1, 00854 AddSpanFunctor2 add_span2, 00855 CombineSpansFunctor combine_spans) 00856 { 00857 sl.reset_spans(); 00858 00859 unsigned num1 = sl1.num_spans(); 00860 unsigned num2 = sl2.num_spans(); 00861 00862 typename Scanline1::const_iterator span1;// = sl1.begin(); 00863 typename Scanline2::const_iterator span2;// = sl2.begin(); 00864 00865 enum invalidation_e 00866 { 00867 invalid_b = 0xFFFFFFF, 00868 invalid_e = invalid_b - 1 00869 }; 00870 00871 // Initialize the spans as invalid 00872 //--------------- 00873 int xb1 = invalid_b; 00874 int xb2 = invalid_b; 00875 int xe1 = invalid_e; 00876 int xe2 = invalid_e; 00877 00878 // Initialize span1 if there are spans 00879 //--------------- 00880 if(num1) 00881 { 00882 span1 = sl1.begin(); 00883 xb1 = span1->x; 00884 xe1 = xb1 + abs((int)span1->len) - 1; 00885 --num1; 00886 } 00887 00888 // Initialize span2 if there are spans 00889 //--------------- 00890 if(num2) 00891 { 00892 span2 = sl2.begin(); 00893 xb2 = span2->x; 00894 xe2 = xb2 + abs((int)span2->len) - 1; 00895 --num2; 00896 } 00897 00898 00899 for(;;) 00900 { 00901 // Retrieve a new span1 if it's invalid 00902 //---------------- 00903 if(num1 && xb1 > xe1) 00904 { 00905 --num1; 00906 ++span1; 00907 xb1 = span1->x; 00908 xe1 = xb1 + abs((int)span1->len) - 1; 00909 } 00910 00911 // Retrieve a new span2 if it's invalid 00912 //---------------- 00913 if(num2 && xb2 > xe2) 00914 { 00915 --num2; 00916 ++span2; 00917 xb2 = span2->x; 00918 xe2 = xb2 + abs((int)span2->len) - 1; 00919 } 00920 00921 if(xb1 > xe1 && xb2 > xe2) break; 00922 00923 // Calculate the intersection 00924 //---------------- 00925 int xb = xb1; 00926 int xe = xe1; 00927 if(xb < xb2) xb = xb2; 00928 if(xe > xe2) xe = xe2; 00929 int len = xe - xb + 1; // The length of the intersection 00930 if(len > 0) 00931 { 00932 // The spans intersect, 00933 // add the beginning of the span 00934 //---------------- 00935 if(xb1 < xb2) 00936 { 00937 add_span1(span1, xb1, xb2 - xb1, sl); 00938 xb1 = xb2; 00939 } 00940 else 00941 if(xb2 < xb1) 00942 { 00943 add_span2(span2, xb2, xb1 - xb2, sl); 00944 xb2 = xb1; 00945 } 00946 00947 // Add the combination part of the spans 00948 //---------------- 00949 combine_spans(span1, span2, xb, len, sl); 00950 00951 00952 // Invalidate the fully processed span or both 00953 //---------------- 00954 if(xe1 < xe2) 00955 { 00956 // Invalidate span1 and eat 00957 // the processed part of span2 00958 //-------------- 00959 xb1 = invalid_b; 00960 xe1 = invalid_e; 00961 xb2 += len; 00962 } 00963 else 00964 if(xe2 < xe1) 00965 { 00966 // Invalidate span2 and eat 00967 // the processed part of span1 00968 //-------------- 00969 xb2 = invalid_b; 00970 xe2 = invalid_e; 00971 xb1 += len; 00972 } 00973 else 00974 { 00975 xb1 = invalid_b; // Invalidate both 00976 xb2 = invalid_b; 00977 xe1 = invalid_e; 00978 xe2 = invalid_e; 00979 } 00980 } 00981 else 00982 { 00983 // The spans do not intersect 00984 //-------------- 00985 if(xb1 < xb2) 00986 { 00987 // Advance span1 00988 //--------------- 00989 if(xb1 <= xe1) 00990 { 00991 add_span1(span1, xb1, xe1 - xb1 + 1, sl); 00992 } 00993 xb1 = invalid_b; // Invalidate 00994 xe1 = invalid_e; 00995 } 00996 else 00997 { 00998 // Advance span2 00999 //--------------- 01000 if(xb2 <= xe2) 01001 { 01002 add_span2(span2, xb2, xe2 - xb2 + 1, sl); 01003 } 01004 xb2 = invalid_b; // Invalidate 01005 xe2 = invalid_e; 01006 } 01007 } 01008 } 01009 } 01010 01011 01012 01013 01014 //----------------------------------------------------sbool_unite_shapes 01015 // Unite the scanline shapes. Here the "Scanline Generator" 01016 // abstraction is used. ScanlineGen1 and ScanlineGen2 are 01017 // the generators, and can be of type rasterizer_scanline_aa<>. 01018 // There function requires three scanline containers that can be 01019 // of different type. 01020 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 01021 // "sl" is ised as the resulting scanline to render it. 01022 // The external "sl1" and "sl2" are used only for the sake of 01023 // optimization and reusing of the scanline objects. 01024 // the function calls sbool_unite_scanlines with CombineSpansFunctor 01025 // as the last argument. See sbool_unite_scanlines for details. 01026 //---------- 01027 template<class ScanlineGen1, 01028 class ScanlineGen2, 01029 class Scanline1, 01030 class Scanline2, 01031 class Scanline, 01032 class Renderer, 01033 class AddSpanFunctor1, 01034 class AddSpanFunctor2, 01035 class CombineSpansFunctor> 01036 void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, 01037 Scanline1& sl1, Scanline2& sl2, 01038 Scanline& sl, Renderer& ren, 01039 AddSpanFunctor1 add_span1, 01040 AddSpanFunctor2 add_span2, 01041 CombineSpansFunctor combine_spans) 01042 { 01043 // Prepare the scanline generators. 01044 // If anyone of them doesn't contain 01045 // any scanlines, then return. 01046 //----------------- 01047 bool flag1 = sg1.rewind_scanlines(); 01048 bool flag2 = sg2.rewind_scanlines(); 01049 if(!flag1 && !flag2) return; 01050 01051 // Get the bounding boxes 01052 //---------------- 01053 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); 01054 rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); 01055 01056 // Calculate the union of the bounding boxes 01057 //----------------- 01058 rect_i ur(1,1,0,0); 01059 if(flag1 && flag2) ur = unite_rectangles(r1, r2); 01060 else if(flag1) ur = r1; 01061 else if(flag2) ur = r2; 01062 01063 if(!ur.is_valid()) return; 01064 01065 ren.prepare(); 01066 01067 // Reset the scanlines and get two first ones 01068 //----------------- 01069 sl.reset(ur.x1, ur.x2); 01070 if(flag1) 01071 { 01072 sl1.reset(sg1.min_x(), sg1.max_x()); 01073 flag1 = sg1.sweep_scanline(sl1); 01074 } 01075 01076 if(flag2) 01077 { 01078 sl2.reset(sg2.min_x(), sg2.max_x()); 01079 flag2 = sg2.sweep_scanline(sl2); 01080 } 01081 01082 // The main loop 01083 // Here we synchronize the scanlines with 01084 // the same Y coordinate. 01085 //----------------- 01086 while(flag1 || flag2) 01087 { 01088 if(flag1 && flag2) 01089 { 01090 if(sl1.y() == sl2.y()) 01091 { 01092 // The Y coordinates are the same. 01093 // Combine the scanlines, render if they contain any spans, 01094 // and advance both generators to the next scanlines 01095 //---------------------- 01096 sbool_unite_scanlines(sl1, sl2, sl, 01097 add_span1, add_span2, combine_spans); 01098 if(sl.num_spans()) 01099 { 01100 sl.finalize(sl1.y()); 01101 ren.render(sl); 01102 } 01103 flag1 = sg1.sweep_scanline(sl1); 01104 flag2 = sg2.sweep_scanline(sl2); 01105 } 01106 else 01107 { 01108 if(sl1.y() < sl2.y()) 01109 { 01110 sbool_add_spans_and_render(sl1, sl, ren, add_span1); 01111 flag1 = sg1.sweep_scanline(sl1); 01112 } 01113 else 01114 { 01115 sbool_add_spans_and_render(sl2, sl, ren, add_span2); 01116 flag2 = sg2.sweep_scanline(sl2); 01117 } 01118 } 01119 } 01120 else 01121 { 01122 if(flag1) 01123 { 01124 sbool_add_spans_and_render(sl1, sl, ren, add_span1); 01125 flag1 = sg1.sweep_scanline(sl1); 01126 } 01127 if(flag2) 01128 { 01129 sbool_add_spans_and_render(sl2, sl, ren, add_span2); 01130 flag2 = sg2.sweep_scanline(sl2); 01131 } 01132 } 01133 } 01134 } 01135 01136 01137 01138 01139 01140 01141 01142 01143 //-------------------------------------------------sbool_subtract_shapes 01144 // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator" 01145 // abstraction is used. ScanlineGen1 and ScanlineGen2 are 01146 // the generators, and can be of type rasterizer_scanline_aa<>. 01147 // There function requires three scanline containers that can be of 01148 // different types. 01149 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 01150 // "sl" is ised as the resulting scanline to render it. 01151 // The external "sl1" and "sl2" are used only for the sake of 01152 // optimization and reusing of the scanline objects. 01153 // the function calls sbool_intersect_scanlines with CombineSpansFunctor 01154 // as the last argument. See combine_scanlines_sub for details. 01155 //---------- 01156 template<class ScanlineGen1, 01157 class ScanlineGen2, 01158 class Scanline1, 01159 class Scanline2, 01160 class Scanline, 01161 class Renderer, 01162 class AddSpanFunctor1, 01163 class CombineSpansFunctor> 01164 void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, 01165 Scanline1& sl1, Scanline2& sl2, 01166 Scanline& sl, Renderer& ren, 01167 AddSpanFunctor1 add_span1, 01168 CombineSpansFunctor combine_spans) 01169 { 01170 // Prepare the scanline generators. 01171 // Here "sg1" is master, "sg2" is slave. 01172 //----------------- 01173 if(!sg1.rewind_scanlines()) return; 01174 bool flag2 = sg2.rewind_scanlines(); 01175 01176 // Get the bounding box 01177 //---------------- 01178 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); 01179 01180 // Reset the scanlines and get two first ones 01181 //----------------- 01182 sl.reset(sg1.min_x(), sg1.max_x()); 01183 sl1.reset(sg1.min_x(), sg1.max_x()); 01184 sl2.reset(sg2.min_x(), sg2.max_x()); 01185 if(!sg1.sweep_scanline(sl1)) return; 01186 01187 if(flag2) flag2 = sg2.sweep_scanline(sl2); 01188 01189 ren.prepare(); 01190 01191 // A fake span2 processor 01192 sbool_add_span_empty<Scanline2, Scanline> add_span2; 01193 01194 // The main loop 01195 // Here we synchronize the scanlines with 01196 // the same Y coordinate, ignoring all other ones. 01197 // Only scanlines having the same Y-coordinate 01198 // are to be combined. 01199 //----------------- 01200 bool flag1 = true; 01201 do 01202 { 01203 // Synchronize "slave" with "master" 01204 //----------------- 01205 while(flag2 && sl2.y() < sl1.y()) 01206 { 01207 flag2 = sg2.sweep_scanline(sl2); 01208 } 01209 01210 01211 if(flag2 && sl2.y() == sl1.y()) 01212 { 01213 // The Y coordinates are the same. 01214 // Combine the scanlines and render if they contain any spans. 01215 //---------------------- 01216 sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); 01217 if(sl.num_spans()) 01218 { 01219 sl.finalize(sl1.y()); 01220 ren.render(sl); 01221 } 01222 } 01223 else 01224 { 01225 sbool_add_spans_and_render(sl1, sl, ren, add_span1); 01226 } 01227 01228 // Advance the "master" 01229 flag1 = sg1.sweep_scanline(sl1); 01230 } 01231 while(flag1); 01232 } 01233 01234 01235 01236 01237 01238 01239 01240 //---------------------------------------------sbool_intersect_shapes_aa 01241 // Intersect two anti-aliased scanline shapes. 01242 // Here the "Scanline Generator" abstraction is used. 01243 // ScanlineGen1 and ScanlineGen2 are the generators, and can be of 01244 // type rasterizer_scanline_aa<>. There function requires three 01245 // scanline containers that can be of different types. 01246 // "sl1" and "sl2" are used to retrieve scanlines from the generators, 01247 // "sl" is ised as the resulting scanline to render it. 01248 // The external "sl1" and "sl2" are used only for the sake of 01249 // optimization and reusing of the scanline objects. 01250 //---------- 01251 template<class ScanlineGen1, 01252 class ScanlineGen2, 01253 class Scanline1, 01254 class Scanline2, 01255 class Scanline, 01256 class Renderer> 01257 void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 01258 Scanline1& sl1, Scanline2& sl2, 01259 Scanline& sl, Renderer& ren) 01260 { 01261 sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; 01262 sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); 01263 } 01264 01265 01266 01267 01268 01269 //--------------------------------------------sbool_intersect_shapes_bin 01270 // Intersect two binary scanline shapes (without anti-aliasing). 01271 // See intersect_shapes_aa for more comments 01272 //---------- 01273 template<class ScanlineGen1, 01274 class ScanlineGen2, 01275 class Scanline1, 01276 class Scanline2, 01277 class Scanline, 01278 class Renderer> 01279 void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 01280 Scanline1& sl1, Scanline2& sl2, 01281 Scanline& sl, Renderer& ren) 01282 { 01283 sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; 01284 sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); 01285 } 01286 01287 01288 01289 01290 01291 //-------------------------------------------------sbool_unite_shapes_aa 01292 // Unite two anti-aliased scanline shapes 01293 // See intersect_shapes_aa for more comments 01294 //---------- 01295 template<class ScanlineGen1, 01296 class ScanlineGen2, 01297 class Scanline1, 01298 class Scanline2, 01299 class Scanline, 01300 class Renderer> 01301 void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 01302 Scanline1& sl1, Scanline2& sl2, 01303 Scanline& sl, Renderer& ren) 01304 { 01305 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 01306 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 01307 sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; 01308 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 01309 add_functor1, add_functor2, combine_functor); 01310 } 01311 01312 01313 01314 01315 01316 //------------------------------------------------sbool_unite_shapes_bin 01317 // Unite two binary scanline shapes (without anti-aliasing). 01318 // See intersect_shapes_aa for more comments 01319 //---------- 01320 template<class ScanlineGen1, 01321 class ScanlineGen2, 01322 class Scanline1, 01323 class Scanline2, 01324 class Scanline, 01325 class Renderer> 01326 void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 01327 Scanline1& sl1, Scanline2& sl2, 01328 Scanline& sl, Renderer& ren) 01329 { 01330 sbool_add_span_bin<Scanline1, Scanline> add_functor1; 01331 sbool_add_span_bin<Scanline2, Scanline> add_functor2; 01332 sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; 01333 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 01334 add_functor1, add_functor2, combine_functor); 01335 } 01336 01337 01338 01339 01340 01341 01342 01343 01344 01345 //---------------------------------------------------sbool_xor_shapes_aa 01346 // Apply eXclusive OR to two anti-aliased scanline shapes. There's 01347 // a modified "Linear" XOR used instead of classical "Saddle" one. 01348 // The reason is to have the result absolutely conststent with what 01349 // the scanline rasterizer produces. 01350 // See intersect_shapes_aa for more comments 01351 //---------- 01352 template<class ScanlineGen1, 01353 class ScanlineGen2, 01354 class Scanline1, 01355 class Scanline2, 01356 class Scanline, 01357 class Renderer> 01358 void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 01359 Scanline1& sl1, Scanline2& sl2, 01360 Scanline& sl, Renderer& ren) 01361 { 01362 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 01363 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 01364 sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, 01365 sbool_xor_formula_linear<> > combine_functor; 01366 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 01367 add_functor1, add_functor2, combine_functor); 01368 } 01369 01370 01371 01372 //------------------------------------------sbool_xor_shapes_saddle_aa 01373 // Apply eXclusive OR to two anti-aliased scanline shapes. 01374 // There's the classical "Saddle" used to calculate the 01375 // Anti-Aliasing values, that is: 01376 // a XOR b : 1-((1-a+a*b)*(1-b+a*b)) 01377 // See intersect_shapes_aa for more comments 01378 //---------- 01379 template<class ScanlineGen1, 01380 class ScanlineGen2, 01381 class Scanline1, 01382 class Scanline2, 01383 class Scanline, 01384 class Renderer> 01385 void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 01386 Scanline1& sl1, Scanline2& sl2, 01387 Scanline& sl, Renderer& ren) 01388 { 01389 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 01390 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 01391 sbool_xor_spans_aa<Scanline1, 01392 Scanline2, 01393 Scanline, 01394 sbool_xor_formula_saddle<> > combine_functor; 01395 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 01396 add_functor1, add_functor2, combine_functor); 01397 } 01398 01399 01400 //--------------------------------------sbool_xor_shapes_abs_diff_aa 01401 // Apply eXclusive OR to two anti-aliased scanline shapes. 01402 // There's the absolute difference used to calculate 01403 // Anti-Aliasing values, that is: 01404 // a XOR b : abs(a-b) 01405 // See intersect_shapes_aa for more comments 01406 //---------- 01407 template<class ScanlineGen1, 01408 class ScanlineGen2, 01409 class Scanline1, 01410 class Scanline2, 01411 class Scanline, 01412 class Renderer> 01413 void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 01414 Scanline1& sl1, Scanline2& sl2, 01415 Scanline& sl, Renderer& ren) 01416 { 01417 sbool_add_span_aa<Scanline1, Scanline> add_functor1; 01418 sbool_add_span_aa<Scanline2, Scanline> add_functor2; 01419 sbool_xor_spans_aa<Scanline1, 01420 Scanline2, 01421 Scanline, 01422 sbool_xor_formula_abs_diff> combine_functor; 01423 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 01424 add_functor1, add_functor2, combine_functor); 01425 } 01426 01427 01428 01429 //--------------------------------------------------sbool_xor_shapes_bin 01430 // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). 01431 // See intersect_shapes_aa for more comments 01432 //---------- 01433 template<class ScanlineGen1, 01434 class ScanlineGen2, 01435 class Scanline1, 01436 class Scanline2, 01437 class Scanline, 01438 class Renderer> 01439 void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 01440 Scanline1& sl1, Scanline2& sl2, 01441 Scanline& sl, Renderer& ren) 01442 { 01443 sbool_add_span_bin<Scanline1, Scanline> add_functor1; 01444 sbool_add_span_bin<Scanline2, Scanline> add_functor2; 01445 sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; 01446 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, 01447 add_functor1, add_functor2, combine_functor); 01448 } 01449 01450 01451 01452 01453 01454 01455 //----------------------------------------------sbool_subtract_shapes_aa 01456 // Subtract shapes "sg1-sg2" with anti-aliasing 01457 // See intersect_shapes_aa for more comments 01458 //---------- 01459 template<class ScanlineGen1, 01460 class ScanlineGen2, 01461 class Scanline1, 01462 class Scanline2, 01463 class Scanline, 01464 class Renderer> 01465 void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, 01466 Scanline1& sl1, Scanline2& sl2, 01467 Scanline& sl, Renderer& ren) 01468 { 01469 sbool_add_span_aa<Scanline1, Scanline> add_functor; 01470 sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; 01471 sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, 01472 add_functor, combine_functor); 01473 } 01474 01475 01476 01477 01478 01479 //---------------------------------------------sbool_subtract_shapes_bin 01480 // Subtract binary shapes "sg1-sg2" without anti-aliasing 01481 // See intersect_shapes_aa for more comments 01482 //---------- 01483 template<class ScanlineGen1, 01484 class ScanlineGen2, 01485 class Scanline1, 01486 class Scanline2, 01487 class Scanline, 01488 class Renderer> 01489 void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, 01490 Scanline1& sl1, Scanline2& sl2, 01491 Scanline& sl, Renderer& ren) 01492 { 01493 sbool_add_span_bin<Scanline1, Scanline> add_functor; 01494 sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; 01495 sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, 01496 add_functor, combine_functor); 01497 } 01498 01499 01500 01501 01502 01503 01504 //------------------------------------------------------------sbool_op_e 01505 enum sbool_op_e 01506 { 01507 sbool_or, //----sbool_or 01508 sbool_and, //----sbool_and 01509 sbool_xor, //----sbool_xor 01510 sbool_xor_saddle, //----sbool_xor_saddle 01511 sbool_xor_abs_diff, //----sbool_xor_abs_diff 01512 sbool_a_minus_b, //----sbool_a_minus_b 01513 sbool_b_minus_a //----sbool_b_minus_a 01514 }; 01515 01516 01517 01518 01519 01520 01521 //----------------------------------------------sbool_combine_shapes_bin 01522 template<class ScanlineGen1, 01523 class ScanlineGen2, 01524 class Scanline1, 01525 class Scanline2, 01526 class Scanline, 01527 class Renderer> 01528 void sbool_combine_shapes_bin(sbool_op_e op, 01529 ScanlineGen1& sg1, ScanlineGen2& sg2, 01530 Scanline1& sl1, Scanline2& sl2, 01531 Scanline& sl, Renderer& ren) 01532 { 01533 switch(op) 01534 { 01535 case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; 01536 case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; 01537 case sbool_xor : 01538 case sbool_xor_saddle : 01539 case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; 01540 case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; 01541 case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; 01542 } 01543 } 01544 01545 01546 01547 01548 //-----------------------------------------------sbool_combine_shapes_aa 01549 template<class ScanlineGen1, 01550 class ScanlineGen2, 01551 class Scanline1, 01552 class Scanline2, 01553 class Scanline, 01554 class Renderer> 01555 void sbool_combine_shapes_aa(sbool_op_e op, 01556 ScanlineGen1& sg1, ScanlineGen2& sg2, 01557 Scanline1& sl1, Scanline2& sl2, 01558 Scanline& sl, Renderer& ren) 01559 { 01560 switch(op) 01561 { 01562 case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 01563 case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 01564 case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 01565 case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; 01566 case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; 01567 case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; 01568 case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; 01569 } 01570 } 01571 01572 } 01573 01574 01575 #endif 01576