agg_scanline_boolean_algebra.h

来自「这是VCF框架的代码」· C头文件 代码 · 共 1,568 行 · 第 1/4 页

H
1,568
字号
        ren.prepare();        // The main loop        // Here we synchronize the scanlines with         // the same Y coordinate, ignoring all other ones.        // Only scanlines having the same Y-coordinate         // are to be combined.        //-----------------        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())            {                // The Y coordinates are the same.                // Combine the scanlines, render if they contain any spans,                // and advance both generators to the next scanlines                //----------------------                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;            }        }    }    //-------------------------------------------------sbool_unite_scanlines    // Unite 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 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;// = sl1.begin();        typename Scanline2::const_iterator span2;// = sl2.begin();        enum invalidation_e         {             invalid_b = 0xFFFFFFF,             invalid_e = invalid_b - 1         };        // Initialize the spans as invalid        //---------------        int xb1 = invalid_b;        int xb2 = invalid_b;        int xe1 = invalid_e;        int xe2 = invalid_e;        // Initialize span1 if there are spans        //---------------        if(num1)        {            span1 = sl1.begin();            xb1 = span1->x;            xe1 = xb1 + abs((int)span1->len) - 1;            --num1;        }        // Initialize span2 if there are spans        //---------------        if(num2)        {            span2 = sl2.begin();            xb2 = span2->x;            xe2 = xb2 + abs((int)span2->len) - 1;            --num2;        }        for(;;)        {            // Retrieve a new span1 if it's invalid            //----------------            if(num1 && xb1 > xe1)             {                --num1;                ++span1;                xb1 = span1->x;                xe1 = xb1 + abs((int)span1->len) - 1;            }            // Retrieve a new span2 if it's invalid            //----------------            if(num2 && xb2 > xe2)             {                --num2;                ++span2;                xb2 = span2->x;                xe2 = xb2 + abs((int)span2->len) - 1;            }            if(xb1 > xe1 && xb2 > xe2) break;            // Calculate the intersection            //----------------            int xb = xb1;            int xe = xe1;            if(xb < xb2) xb = xb2;            if(xe > xe2) xe = xe2;            int len = xe - xb + 1; // The length of the intersection            if(len > 0)            {                // The spans intersect,                // add the beginning of the span                //----------------                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;                }                // Add the combination part of the spans                //----------------                combine_spans(span1, span2, xb, len, sl);                // Invalidate the fully processed span or both                //----------------                if(xe1 < xe2)                {                    // Invalidate span1 and eat                    // the processed part of span2                    //--------------                    xb1 = invalid_b;                        xe1 = invalid_e;                    xb2 += len;                }                else                if(xe2 < xe1)                {                    // Invalidate span2 and eat                    // the processed part of span1                    //--------------                    xb2 = invalid_b;                      xe2 = invalid_e;                    xb1 += len;                }                else                {                    xb1 = invalid_b;  // Invalidate both                    xb2 = invalid_b;                    xe1 = invalid_e;                    xe2 = invalid_e;                }            }            else            {                // The spans do not intersect                //--------------                if(xb1 < xb2)                 {                    // Advance span1                    //---------------                    if(xb1 <= xe1)                    {                        add_span1(span1, xb1, xe1 - xb1 + 1, sl);                    }                    xb1 = invalid_b; // Invalidate                    xe1 = invalid_e;                }                else                {                    // Advance span2                    //---------------                    if(xb2 <= xe2)                    {                        add_span2(span2, xb2, xe2 - xb2 + 1, sl);                    }                    xb2 = invalid_b; // Invalidate                    xe2 = invalid_e;                }            }        }    }    //----------------------------------------------------sbool_unite_shapes    // Unite 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 type.    // "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_unite_scanlines with CombineSpansFunctor     // as the last argument. See sbool_unite_scanlines for details.    //----------    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)    {        // Prepare the scanline generators.        // If anyone of them doesn't contain         // any scanlines, then return.        //-----------------        bool flag1 = sg1.rewind_scanlines();        bool flag2 = sg2.rewind_scanlines();        if(!flag1 && !flag2) 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 union of the bounding boxes        //-----------------        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();        // Reset the scanlines and get two first ones        //-----------------        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);        }        // The main loop        // Here we synchronize the scanlines with         // the same Y coordinate.        //-----------------        while(flag1 || flag2)        {            if(flag1 && flag2)            {                if(sl1.y() == sl2.y())                {                    // The Y coordinates are the same.                    // Combine the scanlines, render if they contain any spans,                    // and advance both generators to the next scanlines                    //----------------------                    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);                }            }        }    }    //-------------------------------------------------sbool_subtract_shapes    // Subtract the scanline shapes, "sg1-sg2". 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 combine_scanlines_sub for details.    //----------    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)    {        // Prepare the scanline generators.        // Here "sg1" is master, "sg2" is slave.        //-----------------        if(!sg1.rewind_scanlines()) return;        bool flag2 = sg2.rewind_scanlines();        // Get the bounding box        //----------------        rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());        // Reset the scanlines and get two first ones        //-----------------        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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?