#ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED
#define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED
#include <stdlib.h>
#include <math.h>
#include "agg_basics.h"
namespace agg
{
template<class Scanline1,
class Scanline2,
class Scanline>
struct sbool_combine_spans_bin
{
void operator () (const typename Scanline1::const_iterator&,
const typename Scanline2::const_iterator&,
int x, unsigned len,
Scanline& sl) const
{
sl.add_span(x, len, cover_full);
}
};
template<class Scanline1,
class Scanline2,
class Scanline>
struct sbool_combine_spans_empty
{
void operator () (const typename Scanline1::const_iterator&,
const typename Scanline2::const_iterator&,
int, unsigned,
Scanline&) const
{}
};
template<class Scanline1,
class Scanline>
struct sbool_add_span_empty
{
void operator () (const typename Scanline1::const_iterator&,
int, unsigned,
Scanline&) const
{}
};
template<class Scanline1,
class Scanline>
struct sbool_add_span_bin
{
void operator () (const typename Scanline1::const_iterator&,
int x, unsigned len,
Scanline& sl) const
{
sl.add_span(x, len, cover_full);
}
};
template<class Scanline1,
class Scanline>
struct sbool_add_span_aa
{
void operator () (const typename Scanline1::const_iterator& span,
int x, unsigned len,
Scanline& sl) const
{
if(span->len < 0)
{
sl.add_span(x, len, *span->covers);
}
else
if(span->len > 0)
{
const typename Scanline1::cover_type* covers = span->covers;
if(span->x < x) covers += x - span->x;
sl.add_cells(x, len, covers);
}
}
};
template<class Scanline1,
class Scanline2,
class Scanline,
unsigned CoverShift = cover_shift>
struct sbool_intersect_spans_aa
{
enum cover_scale_e
{
cover_shift = CoverShift,
cover_size = 1 << cover_shift,
cover_mask = cover_size - 1,
cover_full = cover_mask
};
void operator () (const typename Scanline1::const_iterator& span1,
const typename Scanline2::const_iterator& span2,
int x, unsigned len,
Scanline& sl) const
{
unsigned cover;
const typename Scanline1::cover_type* covers1;
const typename Scanline2::cover_type* covers2;
switch((span1->len < 0) | ((span2->len < 0) << 1))
{
case 0:
covers1 = span1->covers;
covers2 = span2->covers;
if(span1->x < x) covers1 += x - span1->x;
if(span2->x < x) covers2 += x - span2->x;
do
{
cover = *covers1++ * *covers2++;
sl.add_cell(x++,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
while(--len);
break;
case 1:
covers2 = span2->covers;
if(span2->x < x) covers2 += x - span2->x;
if(*(span1->covers) == cover_full)
{
sl.add_cells(x, len, covers2);
}
else
{
do
{
cover = *(span1->covers) * *covers2++;
sl.add_cell(x++,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
while(--len);
}
break;
case 2:
covers1 = span1->covers;
if(span1->x < x) covers1 += x - span1->x;
if(*(span2->covers) == cover_full)
{
sl.add_cells(x, len, covers1);
}
else
{
do
{
cover = *covers1++ * *(span2->covers);
sl.add_cell(x++,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
while(--len);
}
break;
case 3:
cover = *(span1->covers) * *(span2->covers);
sl.add_span(x, len,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
break;
}
}
};
template<class Scanline1,
class Scanline2,
class Scanline,
unsigned CoverShift = cover_shift>
struct sbool_unite_spans_aa
{
enum cover_scale_e
{
cover_shift = CoverShift,
cover_size = 1 << cover_shift,
cover_mask = cover_size - 1,
cover_full = cover_mask
};
void operator () (const typename Scanline1::const_iterator& span1,
const typename Scanline2::const_iterator& span2,
int x, unsigned len,
Scanline& sl) const
{
unsigned cover;
const typename Scanline1::cover_type* covers1;
const typename Scanline2::cover_type* covers2;
switch((span1->len < 0) | ((span2->len < 0) << 1))
{
case 0:
covers1 = span1->covers;
covers2 = span2->covers;
if(span1->x < x) covers1 += x - span1->x;
if(span2->x < x) covers2 += x - span2->x;
do
{
cover = cover_mask * cover_mask -
(cover_mask - *covers1++) *
(cover_mask - *covers2++);
sl.add_cell(x++,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
while(--len);
break;
case 1:
covers2 = span2->covers;
if(span2->x < x) covers2 += x - span2->x;
if(*(span1->covers) == cover_full)
{
sl.add_span(x, len, cover_full);
}
else
{
do
{
cover = cover_mask * cover_mask -
(cover_mask - *(span1->covers)) *
(cover_mask - *covers2++);
sl.add_cell(x++,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
while(--len);
}
break;
case 2:
covers1 = span1->covers;
if(span1->x < x) covers1 += x - span1->x;
if(*(span2->covers) == cover_full)
{
sl.add_span(x, len, cover_full);
}
else
{
do
{
cover = cover_mask * cover_mask -
(cover_mask - *covers1++) *
(cover_mask - *(span2->covers));
sl.add_cell(x++,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
while(--len);
}
break;
case 3:
cover = cover_mask * cover_mask -
(cover_mask - *(span1->covers)) *
(cover_mask - *(span2->covers));
sl.add_span(x, len,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
break;
}
}
};
template<unsigned CoverShift = cover_shift>
struct sbool_xor_formula_linear
{
enum cover_scale_e
{
cover_shift = CoverShift,
cover_size = 1 << cover_shift,
cover_mask = cover_size - 1
};
static AGG_INLINE unsigned calculate(unsigned a, unsigned b)
{
unsigned cover = a + b;
if(cover > cover_mask) cover = cover_mask + cover_mask - cover;
return cover;
}
};
template<unsigned CoverShift = cover_shift>
struct sbool_xor_formula_saddle
{
enum cover_scale_e
{
cover_shift = CoverShift,
cover_size = 1 << cover_shift,
cover_mask = cover_size - 1
};
static AGG_INLINE unsigned calculate(unsigned a, unsigned b)
{
unsigned k = a * b;
if(k == cover_mask * cover_mask) return 0;
a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift;
b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift;
return cover_mask - ((a * b) >> cover_shift);
}
};
struct sbool_xor_formula_abs_diff
{
static AGG_INLINE unsigned calculate(unsigned a, unsigned b)
{
return unsigned(abs(int(a) - int(b)));
}
};
template<class Scanline1,
class Scanline2,
class Scanline,
class XorFormula,
unsigned CoverShift = cover_shift>
struct sbool_xor_spans_aa
{
enum cover_scale_e
{
cover_shift = CoverShift,
cover_size = 1 << cover_shift,
cover_mask = cover_size - 1,
cover_full = cover_mask
};
void operator () (const typename Scanline1::const_iterator& span1,
const typename Scanline2::const_iterator& span2,
int x, unsigned len,
Scanline& sl) const
{
unsigned cover;
const typename Scanline1::cover_type* covers1;
const typename Scanline2::cover_type* covers2;
switch((span1->len < 0) | ((span2->len < 0) << 1))
{
case 0:
covers1 = span1->covers;
covers2 = span2->covers;
if(span1->x < x) covers1 += x - span1->x;
if(span2->x < x) covers2 += x - span2->x;
do
{
cover = XorFormula::calculate(*covers1++, *covers2++);
if(cover) sl.add_cell(x, cover);
++x;
}
while(--len);
break;
case 1:
covers2 = span2->covers;
if(span2->x < x) covers2 += x - span2->x;
do
{
cover = XorFormula::calculate(*(span1->covers), *covers2++);
if(cover) sl.add_cell(x, cover);
++x;
}
while(--len);
break;
case 2:
covers1 = span1->covers;
if(span1->x < x) covers1 += x - span1->x;
do
{
cover = XorFormula::calculate(*covers1++, *(span2->covers));
if(cover) sl.add_cell(x, cover);
++x;
}
while(--len);
break;
case 3:
cover = XorFormula::calculate(*(span1->covers), *(span2->covers));
if(cover) sl.add_span(x, len, cover);
break;
}
}
};
template<class Scanline1,
class Scanline2,
class Scanline,
unsigned CoverShift = cover_shift>
struct sbool_subtract_spans_aa
{
enum cover_scale_e
{
cover_shift = CoverShift,
cover_size = 1 << cover_shift,
cover_mask = cover_size - 1,
cover_full = cover_mask
};
void operator () (const typename Scanline1::const_iterator& span1,
const typename Scanline2::const_iterator& span2,
int x, unsigned len,
Scanline& sl) const
{
unsigned cover;
const typename Scanline1::cover_type* covers1;
const typename Scanline2::cover_type* covers2;
switch((span1->len < 0) | ((span2->len < 0) << 1))
{
case 0:
covers1 = span1->covers;
covers2 = span2->covers;
if(span1->x < x) covers1 += x - span1->x;
if(span2->x < x) covers2 += x - span2->x;
do
{
cover = *covers1++ * (cover_mask - *covers2++);
if(cover)
{
sl.add_cell(x,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
++x;
}
while(--len);
break;
case 1:
covers2 = span2->covers;
if(span2->x < x) covers2 += x - span2->x;
do
{
cover = *(span1->covers) * (cover_mask - *covers2++);
if(cover)
{
sl.add_cell(x,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
++x;
}
while(--len);
break;
case 2:
covers1 = span1->covers;
if(span1->x < x) covers1 += x - span1->x;
if(*(span2->covers) != cover_full)
{
do
{
cover = *covers1++ * (cover_mask - *(span2->covers));
if(cover)
{
sl.add_cell(x,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
++x;
}
while(--len);
}
break;
case 3:
cover = *(span1->covers) * (cover_mask - *(span2->covers));
if(cover)
{
sl.add_span(x, len,
(cover == cover_full * cover_full) ?
cover_full :
(cover >> cover_shift));
}
break;
}
}
};
template<class Scanline1,
class Scanline,
class Renderer,
class AddSpanFunctor>
void sbool_add_spans_and_render(const Scanline1& sl1,
Scanline& sl,
Renderer& ren,
AddSpanFunctor add_span)
{
sl.reset_spans();
typename Scanline1::const_iterator span = sl1.begin();
unsigned num_spans = sl1.num_spans();
for(;;)
{
add_span(span, span->x, abs((int)span->len), sl);
if(--num_spans == 0) break;
++span;
}
sl.finalize(sl1.y());
ren.render(sl);
}
template<class Scanline1,
class Scanline2,
class Scanline,
class CombineSpansFunctor>
void sbool_intersect_scanlines(const Scanline1& sl1,
const Scanline2& sl2,
Scanline& sl,
CombineSpansFunctor combine_spans)
{
sl.reset_spans();
unsigned num1 = sl1.num_spans();
if(num1 == 0) return;
unsigned num2 = sl2.num_spans();
if(num2 == 0) return;
typename Scanline1::const_iterator span1 = sl1.begin();
typename Scanline2::const_iterator span2 = sl2.begin();
while(num1 && num2)
{
int xb1 = span1->x;
int xb2 = span2->x;
int xe1 = xb1 + abs((int)span1->len) - 1;
int xe2 = xb2 + abs((int)span2->len) - 1;
bool advance_span1 = xe1 < xe2;
bool advance_both = xe1 == xe2;
if(xb1 < xb2) xb1 = xb2;
if(xe1 > xe2) xe1 = xe2;
if(xb1 <= xe1)
{
combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl);
}
if(advance_both)
{
--num1;
--num2;
if(num1) ++span1;
if(num2) ++span2;
}
else
{
if(advance_span1)
{
--num1;
if(num1) ++span1;
}
else
{
--num2;
if(num2) ++span2;
}
}
}
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer,
class CombineSpansFunctor>
void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren,
CombineSpansFunctor combine_spans)
{
if(!sg1.rewind_scanlines()) return;
if(!sg2.rewind_scanlines()) return;
rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y());
rect_i ir = intersect_rectangles(r1, r2);
if(!ir.is_valid()) return;
sl.reset(ir.x1, ir.x2);
sl1.reset(sg1.min_x(), sg1.max_x());
sl2.reset(sg2.min_x(), sg2.max_x());
if(!sg1.sweep_scanline(sl1)) return;
if(!sg2.sweep_scanline(sl2)) return;
ren.prepare();
for(;;)
{
while(sl1.y() < sl2.y())
{
if(!sg1.sweep_scanline(sl1)) return;
}
while(sl2.y() < sl1.y())
{
if(!sg2.sweep_scanline(sl2)) return;
}
if(sl1.y() == sl2.y())
{
sbool_intersect_scanlines(sl1, sl2, sl, combine_spans);
if(sl.num_spans())
{
sl.finalize(sl1.y());
ren.render(sl);
}
if(!sg1.sweep_scanline(sl1)) return;
if(!sg2.sweep_scanline(sl2)) return;
}
}
}
template<class Scanline1,
class Scanline2,
class Scanline,
class AddSpanFunctor1,
class AddSpanFunctor2,
class CombineSpansFunctor>
void sbool_unite_scanlines(const Scanline1& sl1,
const Scanline2& sl2,
Scanline& sl,
AddSpanFunctor1 add_span1,
AddSpanFunctor2 add_span2,
CombineSpansFunctor combine_spans)
{
sl.reset_spans();
unsigned num1 = sl1.num_spans();
unsigned num2 = sl2.num_spans();
typename Scanline1::const_iterator span1;
typename Scanline2::const_iterator span2;
enum invalidation_e
{
invalid_b = 0xFFFFFFF,
invalid_e = invalid_b - 1
};
int xb1 = invalid_b;
int xb2 = invalid_b;
int xe1 = invalid_e;
int xe2 = invalid_e;
if(num1)
{
span1 = sl1.begin();
xb1 = span1->x;
xe1 = xb1 + abs((int)span1->len) - 1;
--num1;
}
if(num2)
{
span2 = sl2.begin();
xb2 = span2->x;
xe2 = xb2 + abs((int)span2->len) - 1;
--num2;
}
for(;;)
{
if(num1 && xb1 > xe1)
{
--num1;
++span1;
xb1 = span1->x;
xe1 = xb1 + abs((int)span1->len) - 1;
}
if(num2 && xb2 > xe2)
{
--num2;
++span2;
xb2 = span2->x;
xe2 = xb2 + abs((int)span2->len) - 1;
}
if(xb1 > xe1 && xb2 > xe2) break;
int xb = xb1;
int xe = xe1;
if(xb < xb2) xb = xb2;
if(xe > xe2) xe = xe2;
int len = xe - xb + 1;
if(len > 0)
{
if(xb1 < xb2)
{
add_span1(span1, xb1, xb2 - xb1, sl);
xb1 = xb2;
}
else
if(xb2 < xb1)
{
add_span2(span2, xb2, xb1 - xb2, sl);
xb2 = xb1;
}
combine_spans(span1, span2, xb, len, sl);
if(xe1 < xe2)
{
xb1 = invalid_b;
xe1 = invalid_e;
xb2 += len;
}
else
if(xe2 < xe1)
{
xb2 = invalid_b;
xe2 = invalid_e;
xb1 += len;
}
else
{
xb1 = invalid_b;
xb2 = invalid_b;
xe1 = invalid_e;
xe2 = invalid_e;
}
}
else
{
if(xb1 < xb2)
{
if(xb1 <= xe1)
{
add_span1(span1, xb1, xe1 - xb1 + 1, sl);
}
xb1 = invalid_b;
xe1 = invalid_e;
}
else
{
if(xb2 <= xe2)
{
add_span2(span2, xb2, xe2 - xb2 + 1, sl);
}
xb2 = invalid_b;
xe2 = invalid_e;
}
}
}
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer,
class AddSpanFunctor1,
class AddSpanFunctor2,
class CombineSpansFunctor>
void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren,
AddSpanFunctor1 add_span1,
AddSpanFunctor2 add_span2,
CombineSpansFunctor combine_spans)
{
bool flag1 = sg1.rewind_scanlines();
bool flag2 = sg2.rewind_scanlines();
if(!flag1 && !flag2) return;
rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y());
rect_i ur(1,1,0,0);
if(flag1 && flag2) ur = unite_rectangles(r1, r2);
else if(flag1) ur = r1;
else if(flag2) ur = r2;
if(!ur.is_valid()) return;
ren.prepare();
sl.reset(ur.x1, ur.x2);
if(flag1)
{
sl1.reset(sg1.min_x(), sg1.max_x());
flag1 = sg1.sweep_scanline(sl1);
}
if(flag2)
{
sl2.reset(sg2.min_x(), sg2.max_x());
flag2 = sg2.sweep_scanline(sl2);
}
while(flag1 || flag2)
{
if(flag1 && flag2)
{
if(sl1.y() == sl2.y())
{
sbool_unite_scanlines(sl1, sl2, sl,
add_span1, add_span2, combine_spans);
if(sl.num_spans())
{
sl.finalize(sl1.y());
ren.render(sl);
}
flag1 = sg1.sweep_scanline(sl1);
flag2 = sg2.sweep_scanline(sl2);
}
else
{
if(sl1.y() < sl2.y())
{
sbool_add_spans_and_render(sl1, sl, ren, add_span1);
flag1 = sg1.sweep_scanline(sl1);
}
else
{
sbool_add_spans_and_render(sl2, sl, ren, add_span2);
flag2 = sg2.sweep_scanline(sl2);
}
}
}
else
{
if(flag1)
{
sbool_add_spans_and_render(sl1, sl, ren, add_span1);
flag1 = sg1.sweep_scanline(sl1);
}
if(flag2)
{
sbool_add_spans_and_render(sl2, sl, ren, add_span2);
flag2 = sg2.sweep_scanline(sl2);
}
}
}
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer,
class AddSpanFunctor1,
class CombineSpansFunctor>
void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren,
AddSpanFunctor1 add_span1,
CombineSpansFunctor combine_spans)
{
if(!sg1.rewind_scanlines()) return;
bool flag2 = sg2.rewind_scanlines();
rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
sl.reset(sg1.min_x(), sg1.max_x());
sl1.reset(sg1.min_x(), sg1.max_x());
sl2.reset(sg2.min_x(), sg2.max_x());
if(!sg1.sweep_scanline(sl1)) return;
if(flag2) flag2 = sg2.sweep_scanline(sl2);
ren.prepare();
sbool_add_span_empty<Scanline2, Scanline> add_span2;
bool flag1 = true;
do
{
while(flag2 && sl2.y() < sl1.y())
{
flag2 = sg2.sweep_scanline(sl2);
}
if(flag2 && sl2.y() == sl1.y())
{
sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans);
if(sl.num_spans())
{
sl.finalize(sl1.y());
ren.render(sl);
}
}
else
{
sbool_add_spans_and_render(sl1, sl, ren, add_span1);
}
flag1 = sg1.sweep_scanline(sl1);
}
while(flag1);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor;
sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor;
sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_aa<Scanline1, Scanline> add_functor1;
sbool_add_span_aa<Scanline2, Scanline> add_functor2;
sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor;
sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor1, add_functor2, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_bin<Scanline1, Scanline> add_functor1;
sbool_add_span_bin<Scanline2, Scanline> add_functor2;
sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor;
sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor1, add_functor2, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_aa<Scanline1, Scanline> add_functor1;
sbool_add_span_aa<Scanline2, Scanline> add_functor2;
sbool_xor_spans_aa<Scanline1, Scanline2, Scanline,
sbool_xor_formula_linear<> > combine_functor;
sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor1, add_functor2, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_aa<Scanline1, Scanline> add_functor1;
sbool_add_span_aa<Scanline2, Scanline> add_functor2;
sbool_xor_spans_aa<Scanline1,
Scanline2,
Scanline,
sbool_xor_formula_saddle<> > combine_functor;
sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor1, add_functor2, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_aa<Scanline1, Scanline> add_functor1;
sbool_add_span_aa<Scanline2, Scanline> add_functor2;
sbool_xor_spans_aa<Scanline1,
Scanline2,
Scanline,
sbool_xor_formula_abs_diff> combine_functor;
sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor1, add_functor2, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_bin<Scanline1, Scanline> add_functor1;
sbool_add_span_bin<Scanline2, Scanline> add_functor2;
sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor;
sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor1, add_functor2, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_aa<Scanline1, Scanline> add_functor;
sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor;
sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor, combine_functor);
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
sbool_add_span_bin<Scanline1, Scanline> add_functor;
sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor;
sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren,
add_functor, combine_functor);
}
enum sbool_op_e
{
sbool_or,
sbool_and,
sbool_xor,
sbool_xor_saddle,
sbool_xor_abs_diff,
sbool_a_minus_b,
sbool_b_minus_a
};
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_combine_shapes_bin(sbool_op_e op,
ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
switch(op)
{
case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_xor :
case sbool_xor_saddle :
case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break;
}
}
template<class ScanlineGen1,
class ScanlineGen2,
class Scanline1,
class Scanline2,
class Scanline,
class Renderer>
void sbool_combine_shapes_aa(sbool_op_e op,
ScanlineGen1& sg1, ScanlineGen2& sg2,
Scanline1& sl1, Scanline2& sl2,
Scanline& sl, Renderer& ren)
{
switch(op)
{
case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break;
}
}
}
#endif