Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_scanline_boolean_algebra.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines