agg_scanline_boolean_algebra.h
来自「这是VCF框架的代码」· C头文件 代码 · 共 1,568 行 · 第 1/4 页
H
1,568 行
{ 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); } }; //-------------------------------------------sbool_xor_formula_abs_diff struct sbool_xor_formula_abs_diff { static AGG_INLINE unsigned calculate(unsigned a, unsigned b) { return unsigned(abs(int(a) - int(b))); } }; //----------------------------------------------------sbool_xor_spans_aa // Functor. // XOR two spans preserving the anti-aliasing information. // The result is added to the "sl" scanline. //------------------ 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; // Calculate the operation code and choose the // proper combination algorithm. // 0 = Both spans are of AA type // 1 = span1 is solid, span2 is AA // 2 = span1 is AA, span2 is solid // 3 = Both spans are of solid type //----------------- switch((span1->len < 0) | ((span2->len < 0) << 1)) { case 0: // Both are AA spans 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: // span1 is solid, span2 is AA 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: // span1 is AA, span2 is solid 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: // Both are solid spans cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); if(cover) sl.add_span(x, len, cover); break; } } }; //-----------------------------------------------sbool_subtract_spans_aa // Functor. // Unite two spans preserving the anti-aliasing information. // The result is added to the "sl" scanline. //------------------ 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; // Calculate the operation code and choose the // proper combination algorithm. // 0 = Both spans are of AA type // 1 = span1 is solid, span2 is AA // 2 = span1 is AA, span2 is solid // 3 = Both spans are of solid type //----------------- switch((span1->len < 0) | ((span2->len < 0) << 1)) { case 0: // Both are AA spans 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: // span1 is solid, span2 is AA 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: // span1 is AA, span2 is solid 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: // Both are solid spans 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; } } }; //--------------------------------------------sbool_add_spans_and_render 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); } //---------------------------------------------sbool_intersect_scanlines // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. // The combine_spans functor can be of type sbool_combine_spans_bin or // sbool_intersect_spans_aa. First is a general functor to combine // two spans without Anti-Aliasing, the second preserves the AA // information, but works slower // 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; // Determine what spans we should advance in the next step // The span with the least ending X should be advanced // advance_both is just an optimization when we ending // coordinates are the same and we can advance both //-------------- bool advance_span1 = xe1 < xe2; bool advance_both = xe1 == xe2; // Find the intersection of the spans // and check if they intersect //-------------- if(xb1 < xb2) xb1 = xb2; if(xe1 > xe2) xe1 = xe2; if(xb1 <= xe1) { combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); } // Advance the spans //-------------- if(advance_both) { --num1; --num2; if(num1) ++span1; if(num2) ++span2; } else { if(advance_span1) { --num1; if(num1) ++span1; } else { --num2; if(num2) ++span2; } } } } //------------------------------------------------sbool_intersect_shapes // Intersect the scanline shapes. Here the "Scanline Generator" // abstraction is used. ScanlineGen1 and ScanlineGen2 are // the generators, and can be of type rasterizer_scanline_aa<>. // There function requires three scanline containers that can be of // different types. // "sl1" and "sl2" are used to retrieve scanlines from the generators, // "sl" is ised as the resulting scanline to render it. // The external "sl1" and "sl2" are used only for the sake of // optimization and reusing of the scanline objects. // the function calls sbool_intersect_scanlines with CombineSpansFunctor // as the last argument. See sbool_intersect_scanlines for details. //---------- 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) { // Prepare the scanline generators. // If anyone of them doesn't contain // any scanlines, then return. //----------------- if(!sg1.rewind_scanlines()) return; if(!sg2.rewind_scanlines()) return; // Get the bounding boxes //---------------- 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()); // Calculate the intersection of the bounding // boxes and return if they don't intersect. //----------------- rect_i ir = intersect_rectangles(r1, r2); if(!ir.is_valid()) return; // Reset the scanlines and get two first ones //----------------- 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?