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 + -
显示快捷键?