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