16 #ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED 17 #define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED 20 #include "agg_basics.h" 32 template<
class Scanline1,
37 void operator () (
const typename Scanline1::const_iterator&,
38 const typename Scanline2::const_iterator&,
42 sl.add_span(x, len, cover_full);
53 template<
class Scanline1,
58 void operator () (
const typename Scanline1::const_iterator&,
59 const typename Scanline2::const_iterator&,
71 template<
class Scanline1,
75 void operator () (
const typename Scanline1::const_iterator&,
86 template<
class Scanline1,
90 void operator () (
const typename Scanline1::const_iterator&,
94 sl.add_span(x, len, cover_full);
107 template<
class Scanline1,
111 void operator () (
const typename Scanline1::const_iterator& span,
117 sl.add_span(x, len, *span->covers);
122 const typename Scanline1::cover_type* covers = span->covers;
123 if(span->x < x) covers += x - span->x;
124 sl.add_cells(x, len, covers);
137 template<
class Scanline1,
140 unsigned CoverShift = cover_shift>
145 cover_shift = CoverShift,
146 cover_size = 1 << cover_shift,
147 cover_mask = cover_size - 1,
148 cover_full = cover_mask
152 void operator () (
const typename Scanline1::const_iterator& span1,
153 const typename Scanline2::const_iterator& span2,
158 const typename Scanline1::cover_type* covers1;
159 const typename Scanline2::cover_type* covers2;
168 switch((span1->len < 0) | ((span2->len < 0) << 1))
171 covers1 = span1->covers;
172 covers2 = span2->covers;
173 if(span1->x < x) covers1 += x - span1->x;
174 if(span2->x < x) covers2 += x - span2->x;
177 cover = *covers1++ * *covers2++;
179 (cover == cover_full * cover_full) ?
181 (cover >> cover_shift));
187 covers2 = span2->covers;
188 if(span2->x < x) covers2 += x - span2->x;
189 if(*(span1->covers) == cover_full)
191 sl.add_cells(x, len, covers2);
197 cover = *(span1->covers) * *covers2++;
199 (cover == cover_full * cover_full) ?
201 (cover >> cover_shift));
208 covers1 = span1->covers;
209 if(span1->x < x) covers1 += x - span1->x;
210 if(*(span2->covers) == cover_full)
212 sl.add_cells(x, len, covers1);
218 cover = *covers1++ * *(span2->covers);
220 (cover == cover_full * cover_full) ?
222 (cover >> cover_shift));
229 cover = *(span1->covers) * *(span2->covers);
231 (cover == cover_full * cover_full) ?
233 (cover >> cover_shift));
249 template<
class Scanline1,
252 unsigned CoverShift = cover_shift>
257 cover_shift = CoverShift,
258 cover_size = 1 << cover_shift,
259 cover_mask = cover_size - 1,
260 cover_full = cover_mask
264 void operator () (
const typename Scanline1::const_iterator& span1,
265 const typename Scanline2::const_iterator& span2,
270 const typename Scanline1::cover_type* covers1;
271 const typename Scanline2::cover_type* covers2;
280 switch((span1->len < 0) | ((span2->len < 0) << 1))
283 covers1 = span1->covers;
284 covers2 = span2->covers;
285 if(span1->x < x) covers1 += x - span1->x;
286 if(span2->x < x) covers2 += x - span2->x;
289 cover = cover_mask * cover_mask -
290 (cover_mask - *covers1++) *
291 (cover_mask - *covers2++);
293 (cover == cover_full * cover_full) ?
295 (cover >> cover_shift));
301 covers2 = span2->covers;
302 if(span2->x < x) covers2 += x - span2->x;
303 if(*(span1->covers) == cover_full)
305 sl.add_span(x, len, cover_full);
311 cover = cover_mask * cover_mask -
312 (cover_mask - *(span1->covers)) *
313 (cover_mask - *covers2++);
315 (cover == cover_full * cover_full) ?
317 (cover >> cover_shift));
324 covers1 = span1->covers;
325 if(span1->x < x) covers1 += x - span1->x;
326 if(*(span2->covers) == cover_full)
328 sl.add_span(x, len, cover_full);
334 cover = cover_mask * cover_mask -
335 (cover_mask - *covers1++) *
336 (cover_mask - *(span2->covers));
338 (cover == cover_full * cover_full) ?
340 (cover >> cover_shift));
347 cover = cover_mask * cover_mask -
348 (cover_mask - *(span1->covers)) *
349 (cover_mask - *(span2->covers));
351 (cover == cover_full * cover_full) ?
353 (cover >> cover_shift));
361 template<
unsigned CoverShift = cover_shift>
366 cover_shift = CoverShift,
367 cover_size = 1 << cover_shift,
368 cover_mask = cover_size - 1
371 static AGG_INLINE
unsigned calculate(
unsigned a,
unsigned b)
373 unsigned cover = a + b;
374 if(cover > cover_mask) cover = cover_mask + cover_mask - cover;
381 template<
unsigned CoverShift = cover_shift>
386 cover_shift = CoverShift,
387 cover_size = 1 << cover_shift,
388 cover_mask = cover_size - 1
391 static AGG_INLINE
unsigned calculate(
unsigned a,
unsigned b)
394 if(k == cover_mask * cover_mask)
return 0;
396 a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift;
397 b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift;
398 return cover_mask - ((a * b) >> cover_shift);
406 static AGG_INLINE
unsigned calculate(
unsigned a,
unsigned b)
408 return unsigned(std::abs(
int(a) -
int(b)));
419 template<
class Scanline1,
423 unsigned CoverShift = cover_shift>
428 cover_shift = CoverShift,
429 cover_size = 1 << cover_shift,
430 cover_mask = cover_size - 1,
431 cover_full = cover_mask
435 void operator () (
const typename Scanline1::const_iterator& span1,
436 const typename Scanline2::const_iterator& span2,
441 const typename Scanline1::cover_type* covers1;
442 const typename Scanline2::cover_type* covers2;
451 switch((span1->len < 0) | ((span2->len < 0) << 1))
454 covers1 = span1->covers;
455 covers2 = span2->covers;
456 if(span1->x < x) covers1 += x - span1->x;
457 if(span2->x < x) covers2 += x - span2->x;
460 cover = XorFormula::calculate(*covers1++, *covers2++);
461 if(cover) sl.add_cell(x, cover);
468 covers2 = span2->covers;
469 if(span2->x < x) covers2 += x - span2->x;
472 cover = XorFormula::calculate(*(span1->covers), *covers2++);
473 if(cover) sl.add_cell(x, cover);
480 covers1 = span1->covers;
481 if(span1->x < x) covers1 += x - span1->x;
484 cover = XorFormula::calculate(*covers1++, *(span2->covers));
485 if(cover) sl.add_cell(x, cover);
492 cover = XorFormula::calculate(*(span1->covers), *(span2->covers));
493 if(cover) sl.add_span(x, len, cover);
509 template<
class Scanline1,
512 unsigned CoverShift = cover_shift>
517 cover_shift = CoverShift,
518 cover_size = 1 << cover_shift,
519 cover_mask = cover_size - 1,
520 cover_full = cover_mask
524 void operator () (
const typename Scanline1::const_iterator& span1,
525 const typename Scanline2::const_iterator& span2,
530 const typename Scanline1::cover_type* covers1;
531 const typename Scanline2::cover_type* covers2;
540 switch((span1->len < 0) | ((span2->len < 0) << 1))
543 covers1 = span1->covers;
544 covers2 = span2->covers;
545 if(span1->x < x) covers1 += x - span1->x;
546 if(span2->x < x) covers2 += x - span2->x;
549 cover = *covers1++ * (cover_mask - *covers2++);
553 (cover == cover_full * cover_full) ?
555 (cover >> cover_shift));
563 covers2 = span2->covers;
564 if(span2->x < x) covers2 += x - span2->x;
567 cover = *(span1->covers) * (cover_mask - *covers2++);
571 (cover == cover_full * cover_full) ?
573 (cover >> cover_shift));
581 covers1 = span1->covers;
582 if(span1->x < x) covers1 += x - span1->x;
583 if(*(span2->covers) != cover_full)
587 cover = *covers1++ * (cover_mask - *(span2->covers));
591 (cover == cover_full * cover_full) ?
593 (cover >> cover_shift));
602 cover = *(span1->covers) * (cover_mask - *(span2->covers));
606 (cover == cover_full * cover_full) ?
608 (cover >> cover_shift));
621 template<
class Scanline1,
624 class AddSpanFunctor>
625 void sbool_add_spans_and_render(
const Scanline1& sl1,
628 AddSpanFunctor add_span)
631 typename Scanline1::const_iterator span = sl1.begin();
632 unsigned num_spans = sl1.num_spans();
635 add_span(span, span->x, std::abs((
int)span->len), sl);
636 if(--num_spans == 0)
break;
639 sl.finalize(sl1.y());
656 template<
class Scanline1,
659 class CombineSpansFunctor>
660 void sbool_intersect_scanlines(
const Scanline1& sl1,
661 const Scanline2& sl2,
663 CombineSpansFunctor combine_spans)
667 unsigned num1 = sl1.num_spans();
668 if(num1 == 0)
return;
670 unsigned num2 = sl2.num_spans();
671 if(num2 == 0)
return;
673 typename Scanline1::const_iterator span1 = sl1.begin();
674 typename Scanline2::const_iterator span2 = sl2.begin();
680 int xe1 = xb1 + std::abs((
int)span1->len) - 1;
681 int xe2 = xb2 + std::abs((
int)span2->len) - 1;
688 bool advance_span1 = xe1 < xe2;
689 bool advance_both = xe1 == xe2;
694 if(xb1 < xb2) xb1 = xb2;
695 if(xe1 > xe2) xe1 = xe2;
698 combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl);
746 template<
class ScanlineGen1,
752 class CombineSpansFunctor>
753 void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
754 Scanline1& sl1, Scanline2& sl2,
755 Scanline& sl, Renderer& ren,
756 CombineSpansFunctor combine_spans)
762 if(!sg1.rewind_scanlines())
return;
763 if(!sg2.rewind_scanlines())
return;
767 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
768 rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y());
773 rect_i ir = intersect_rectangles(r1, r2);
774 if(!ir.is_valid())
return;
778 sl.reset(ir.x1, ir.x2);
779 sl1.reset(sg1.min_x(), sg1.max_x());
780 sl2.reset(sg2.min_x(), sg2.max_x());
781 if(!sg1.sweep_scanline(sl1))
return;
782 if(!sg2.sweep_scanline(sl2))
return;
794 while(sl1.y() < sl2.y())
796 if(!sg1.sweep_scanline(sl1))
return;
798 while(sl2.y() < sl1.y())
800 if(!sg2.sweep_scanline(sl2))
return;
803 if(sl1.y() == sl2.y())
809 sbool_intersect_scanlines(sl1, sl2, sl, combine_spans);
812 sl.finalize(sl1.y());
815 if(!sg1.sweep_scanline(sl1))
return;
816 if(!sg2.sweep_scanline(sl2))
return;
834 template<
class Scanline1,
837 class AddSpanFunctor1,
838 class AddSpanFunctor2,
839 class CombineSpansFunctor>
840 void sbool_unite_scanlines(
const Scanline1& sl1,
841 const Scanline2& sl2,
843 AddSpanFunctor1 add_span1,
844 AddSpanFunctor2 add_span2,
845 CombineSpansFunctor combine_spans)
849 unsigned num1 = sl1.num_spans();
850 unsigned num2 = sl2.num_spans();
852 typename Scanline1::const_iterator span1;
853 typename Scanline2::const_iterator span2;
857 invalid_b = 0xFFFFFFF,
858 invalid_e = invalid_b - 1
874 xe1 = xb1 + std::abs((
int)span1->len) - 1;
884 xe2 = xb2 + std::abs((
int)span2->len) - 1;
893 if(num1 && xb1 > xe1)
898 xe1 = xb1 + std::abs((
int)span1->len) - 1;
903 if(num2 && xb2 > xe2)
908 xe2 = xb2 + std::abs((
int)span2->len) - 1;
911 if(xb1 > xe1 && xb2 > xe2)
break;
917 if(xb < xb2) xb = xb2;
918 if(xe > xe2) xe = xe2;
919 int len = xe - xb + 1;
927 add_span1(span1, xb1, xb2 - xb1, sl);
933 add_span2(span2, xb2, xb1 - xb2, sl);
939 combine_spans(span1, span2, xb, len, sl);
981 add_span1(span1, xb1, xe1 - xb1 + 1, sl);
992 add_span2(span2, xb2, xe2 - xb2 + 1, sl);
1017 template<
class ScanlineGen1,
1023 class AddSpanFunctor1,
1024 class AddSpanFunctor2,
1025 class CombineSpansFunctor>
1026 void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
1027 Scanline1& sl1, Scanline2& sl2,
1028 Scanline& sl, Renderer& ren,
1029 AddSpanFunctor1 add_span1,
1030 AddSpanFunctor2 add_span2,
1031 CombineSpansFunctor combine_spans)
1037 bool flag1 = sg1.rewind_scanlines();
1038 bool flag2 = sg2.rewind_scanlines();
1039 if(!flag1 && !flag2)
return;
1043 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
1044 rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y());
1049 if(flag1 && flag2) ur = unite_rectangles(r1, r2);
1050 else if(flag1) ur = r1;
1051 else if(flag2) ur = r2;
1053 if(!ur.is_valid())
return;
1059 sl.reset(ur.x1, ur.x2);
1062 sl1.reset(sg1.min_x(), sg1.max_x());
1063 flag1 = sg1.sweep_scanline(sl1);
1068 sl2.reset(sg2.min_x(), sg2.max_x());
1069 flag2 = sg2.sweep_scanline(sl2);
1076 while(flag1 || flag2)
1080 if(sl1.y() == sl2.y())
1086 sbool_unite_scanlines(sl1, sl2, sl,
1087 add_span1, add_span2, combine_spans);
1090 sl.finalize(sl1.y());
1093 flag1 = sg1.sweep_scanline(sl1);
1094 flag2 = sg2.sweep_scanline(sl2);
1098 if(sl1.y() < sl2.y())
1100 sbool_add_spans_and_render(sl1, sl, ren, add_span1);
1101 flag1 = sg1.sweep_scanline(sl1);
1105 sbool_add_spans_and_render(sl2, sl, ren, add_span2);
1106 flag2 = sg2.sweep_scanline(sl2);
1114 sbool_add_spans_and_render(sl1, sl, ren, add_span1);
1115 flag1 = sg1.sweep_scanline(sl1);
1119 sbool_add_spans_and_render(sl2, sl, ren, add_span2);
1120 flag2 = sg2.sweep_scanline(sl2);
1146 template<
class ScanlineGen1,
1152 class AddSpanFunctor1,
1153 class CombineSpansFunctor>
1154 void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
1155 Scanline1& sl1, Scanline2& sl2,
1156 Scanline& sl, Renderer& ren,
1157 AddSpanFunctor1 add_span1,
1158 CombineSpansFunctor combine_spans)
1163 if(!sg1.rewind_scanlines())
return;
1164 bool flag2 = sg2.rewind_scanlines();
1168 rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
1172 sl.reset(sg1.min_x(), sg1.max_x());
1173 sl1.reset(sg1.min_x(), sg1.max_x());
1174 sl2.reset(sg2.min_x(), sg2.max_x());
1175 if(!sg1.sweep_scanline(sl1))
return;
1177 if(flag2) flag2 = sg2.sweep_scanline(sl2);
1195 while(flag2 && sl2.y() < sl1.y())
1197 flag2 = sg2.sweep_scanline(sl2);
1201 if(flag2 && sl2.y() == sl1.y())
1206 sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans);
1209 sl.finalize(sl1.y());
1215 sbool_add_spans_and_render(sl1, sl, ren, add_span1);
1219 flag1 = sg1.sweep_scanline(sl1);
1241 template<
class ScanlineGen1,
1247 void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
1248 Scanline1& sl1, Scanline2& sl2,
1249 Scanline& sl, Renderer& ren)
1252 sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor);
1263 template<
class ScanlineGen1,
1269 void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
1270 Scanline1& sl1, Scanline2& sl2,
1271 Scanline& sl, Renderer& ren)
1274 sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor);
1285 template<
class ScanlineGen1,
1291 void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
1292 Scanline1& sl1, Scanline2& sl2,
1293 Scanline& sl, Renderer& ren)
1298 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
1299 add_functor1, add_functor2, combine_functor);
1310 template<
class ScanlineGen1,
1316 void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
1317 Scanline1& sl1, Scanline2& sl2,
1318 Scanline& sl, Renderer& ren)
1323 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
1324 add_functor1, add_functor2, combine_functor);
1342 template<
class ScanlineGen1,
1348 void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
1349 Scanline1& sl1, Scanline2& sl2,
1350 Scanline& sl, Renderer& ren)
1356 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
1357 add_functor1, add_functor2, combine_functor);
1369 template<
class ScanlineGen1,
1375 void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
1376 Scanline1& sl1, Scanline2& sl2,
1377 Scanline& sl, Renderer& ren)
1385 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
1386 add_functor1, add_functor2, combine_functor);
1397 template<
class ScanlineGen1,
1403 void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
1404 Scanline1& sl1, Scanline2& sl2,
1405 Scanline& sl, Renderer& ren)
1413 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
1414 add_functor1, add_functor2, combine_functor);
1423 template<
class ScanlineGen1,
1429 void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
1430 Scanline1& sl1, Scanline2& sl2,
1431 Scanline& sl, Renderer& ren)
1436 sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
1437 add_functor1, add_functor2, combine_functor);
1449 template<
class ScanlineGen1,
1455 void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
1456 Scanline1& sl1, Scanline2& sl2,
1457 Scanline& sl, Renderer& ren)
1461 sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren,
1462 add_functor, combine_functor);
1473 template<
class ScanlineGen1,
1479 void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
1480 Scanline1& sl1, Scanline2& sl2,
1481 Scanline& sl, Renderer& ren)
1485 sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren,
1486 add_functor, combine_functor);
1512 template<
class ScanlineGen1,
1518 void sbool_combine_shapes_bin(sbool_op_e op,
1519 ScanlineGen1& sg1, ScanlineGen2& sg2,
1520 Scanline1& sl1, Scanline2& sl2,
1521 Scanline& sl, Renderer& ren)
1525 case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren);
break;
1526 case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren);
break;
1528 case sbool_xor_saddle :
1529 case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren);
break;
1530 case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren);
break;
1531 case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren);
break;
1539 template<
class ScanlineGen1,
1545 void sbool_combine_shapes_aa(sbool_op_e op,
1546 ScanlineGen1& sg1, ScanlineGen2& sg2,
1547 Scanline1& sl1, Scanline2& sl2,
1548 Scanline& sl, Renderer& ren)
1552 case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren);
break;
1553 case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren);
break;
1554 case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren);
break;
1555 case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren);
break;
1556 case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren);
break;
1557 case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren);
break;
1558 case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren);
break;