Esempio n. 1
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt_pre> renderer_base;
        typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
        typedef agg::scanline_u8 scanline;

        pixfmt_pre pixf(rbuf_window());
        renderer_base ren_base(pixf);
        ren_base.clear(agg::rgba(1.0, 1.0, 0.95));
        renderer_scanline ren(ren_base);

        agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> ras;
        agg::scanline_u8 sl;
        agg::conv_transform<agg::compound_shape> shape(m_shape, m_scale);
        agg::conv_stroke<agg::conv_transform<agg::compound_shape> > stroke(shape);

        m_shape.approximation_scale(m_scale.scale());

        unsigned i;
        agg::path_storage tmp_path;

        ras.clip_box(0, 0, width(), height());

        // This is an alternative method of Flash rasterization. 
        // We decompose the compound shape into separate paths
        // and select the ones that fit the given style (left or right).
        // So that, we form a sub-shape and draw it as a whole.
        // 
        // Here the regular scanline rasterizer is used, but it doesn't
        // automatically close the polygons. So that, the rasterizer 
        // actually works with a set of polylines instead of polygons.
        // Of course, the data integrity must be preserved, that is, 
        // the polylines must eventually form a closed contour
        // (or a set of closed contours). So that, first we set 
        // auto_close(false);
        // 
        // The second important thing is that one path can be rasterized 
        // twice, if it has both, left and right fill. Sometimes the 
        // path has equal left and right fill, so that, the same path
        // will be added twice even for a single sub-shape. If the 
        // rasterizer can tolerate these degenerates you can add them, 
        // but it's also fine just to omit them.
        //
        // The third thing is that for one side (left or right)
        // you should invert the direction of the paths.
        //
        // The main disadvantage of this method is imperfect stitching
        // of the adjacent polygons. The problem can be solved if we use
        // compositing operation "plus" instead of alpha-blend. But
        // in this case we are forced to use an RGBA buffer, clean it with 
        // zero, rasterize using "plus" operation, and then alpha-blend
        // the result over the final scene. It can be too expensive.
        //------------------------------------------------------------
        ras.auto_close(false);
        //ras.filling_rule(agg::fill_even_odd);
        start_timer();
        for(int s = m_shape.min_style(); s <= m_shape.max_style(); s++)
        {
            ras.reset();
            for(i = 0; i < m_shape.paths(); i++)
            {
                const agg::path_style& style = m_shape.style(i);
                if(style.left_fill != style.right_fill)
                {
                    if(style.left_fill == s)
                    {
                        ras.add_path(shape, style.path_id);
                    }
                    if(style.right_fill == s)
                    {
                        tmp_path.remove_all();
                        tmp_path.concat_path(shape, style.path_id);
                        tmp_path.invert_polygon(0);
                        ras.add_path(tmp_path);
                    }
                }
            }
            agg::render_scanlines_aa_solid(ras, sl, ren_base, m_colors[s]);
        }
        double tfill = elapsed_time();
        ras.auto_close(true);

        // Draw strokes
        //----------------------
        start_timer();
        stroke.width(sqrt(m_scale.scale()));
        stroke.line_join(agg::round_join);
        stroke.line_cap(agg::round_cap);
        for(i = 0; i < m_shape.paths(); i++)
        {
            ras.reset();
            if(m_shape.style(i).line >= 0)
            {
                ras.add_path(stroke, m_shape.style(i).path_id);
                ren.color(agg::srgba8(0,0,0, 128));
                agg::render_scanlines(ras, sl, ren);
            }
        }
        double tstroke = elapsed_time();


        char buf[256]; 
        agg::gsv_text t;
        t.size(8.0);
        t.flip(true);

        agg::conv_stroke<agg::gsv_text> ts(t);
        ts.width(1.6);
        ts.line_cap(agg::round_cap);

        sprintf(buf, "Fill=%.2fms (%dFPS) Stroke=%.2fms (%dFPS) Total=%.2fms (%dFPS)\n\n"
                     "Space: Next Shape\n\n"
                     "+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)",
                     tfill, int(1000.0 / tfill),
                     tstroke, int(1000.0 / tstroke),
                     tfill+tstroke, int(1000.0 / (tfill+tstroke)));

        t.start_point(10.0, 20.0);
        t.text(buf);

        ras.add_path(ts);
        ren.color(agg::rgba(0,0,0));
        agg::render_scanlines(ras, sl, ren);
    }
Esempio n. 2
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt> renderer_base;
        typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
        typedef agg::scanline_u8 scanline;

        pixfmt pixf(rbuf_window());
        renderer_base ren_base(pixf);
        ren_base.clear(agg::rgba(1.0, 1.0, 0.95));
        renderer_scanline ren(ren_base);

        unsigned i;
        unsigned w = unsigned(width());
        m_gradient.resize(w);
        agg::rgba8 c1(255, 0, 0, 180);
        agg::rgba8 c2(0, 0, 255, 180);
        for(i = 0; i < w; i++)
        {
            m_gradient[i] = c1.gradient(c2, i / width());
            m_gradient[i].premultiply();
        }

        agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> ras;
        agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_dbl> rasc;
        agg::scanline_u8 sl;
        agg::scanline_bin sl_bin;
        agg::conv_transform<agg::compound_shape> shape(m_shape, m_scale);
        agg::conv_stroke<agg::conv_transform<agg::compound_shape> > stroke(shape);

        agg::test_styles style_handler(m_colors, m_gradient.data());
        agg::span_allocator<agg::rgba8> alloc;

        m_shape.approximation_scale(m_scale.scale());

        // Fill shape
        //----------------------
        rasc.clip_box(0, 0, width(), height());
        rasc.reset();
        //rasc.filling_rule(agg::fill_even_odd);
        start_timer();
        for(i = 0; i < m_shape.paths(); i++)
        {
            
            if(m_shape.style(i).left_fill >= 0 || 
               m_shape.style(i).right_fill >= 0)
            {
                rasc.styles(m_shape.style(i).left_fill, 
                            m_shape.style(i).right_fill);
                rasc.add_path(shape, m_shape.style(i).path_id);
            }
        }
        agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, style_handler);
        double tfill = elapsed_time();

        // Hit-test test
        bool draw_strokes = true;
        if(m_hit_x >= 0 && m_hit_y >= 0)
        {
            if(rasc.hit_test(m_hit_x, m_hit_y))
            {
                draw_strokes = false;
            }
        }

        // Draw strokes
        //----------------------
        start_timer();
        if(draw_strokes)
        {
            ras.clip_box(0, 0, width(), height());
            stroke.width(sqrt(m_scale.scale()));
            stroke.line_join(agg::round_join);
            stroke.line_cap(agg::round_cap);
            for(i = 0; i < m_shape.paths(); i++)
            {
                ras.reset();
                if(m_shape.style(i).line >= 0)
                {
                    ras.add_path(stroke, m_shape.style(i).path_id);
                    ren.color(agg::rgba8(0,0,0, 128));
                    agg::render_scanlines(ras, sl, ren);
                }
            }
        }
        double tstroke = elapsed_time();


        char buf[256]; 
        agg::gsv_text t;
        t.size(8.0);
        t.flip(true);

        agg::conv_stroke<agg::gsv_text> ts(t);
        ts.width(1.6);
        ts.line_cap(agg::round_cap);

        sprintf(buf, "Fill=%.2fms (%dFPS) Stroke=%.2fms (%dFPS) Total=%.2fms (%dFPS)\n\n"
                     "Space: Next Shape\n\n"
                     "+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)",
                     tfill, int(1000.0 / tfill),
                     tstroke, int(1000.0 / tstroke),
                     tfill+tstroke, int(1000.0 / (tfill+tstroke)));

        t.start_point(10.0, 20.0);
        t.text(buf);

        ras.add_path(ts);
        ren.color(agg::rgba(0,0,0));
        agg::render_scanlines(ras, sl, ren);

        if(m_gamma.gamma() != 1.0)
        {
            pixf.apply_gamma_inv(m_gamma);
        }
    }