示例#1
0
    virtual void on_draw()
    {
        pixfmt pf(rbuf_window());
        renderer_base ren_base(pf);
        ren_base.clear(agg::rgba(0.5, 0.75, 0.85));
        renderer_scanline ren(ren_base);

        rasterizer_scanline ras;
        scanline sl;

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

        // Pattern source. Must have an interface:
        // width() const
        // height() const
        // pixel(int x, int y) const
        // Any agg::renderer_base<> or derived
        // is good for the use as a source.
        //-----------------------------------
        pattern_src_brightness_to_alpha_rgba8 p1(rbuf_img(0));

        agg::pattern_filter_bilinear_rgba8 fltr;           // Filtering functor

        // agg::line_image_pattern is the main container for the patterns. It creates
        // a copy of the patterns extended according to the needs of the filter.
        // agg::line_image_pattern can operate with arbitrary image width, but if the 
        // width of the pattern is power of 2, it's better to use the modified
        // version agg::line_image_pattern_pow2 because it works about 15-25 percent
        // faster than agg::line_image_pattern (because of using simple masking instead 
        // of expensive '%' operation). 
        typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
        typedef agg::renderer_base<pixfmt> base_ren_type;
        typedef agg::renderer_outline_image<base_ren_type, pattern_type> renderer_img_type;
        typedef agg::rasterizer_outline_aa<renderer_img_type, agg::line_coord_sat> rasterizer_img_type;

        typedef agg::renderer_outline_aa<base_ren_type> renderer_line_type;
        typedef agg::rasterizer_outline_aa<renderer_line_type, agg::line_coord_sat> rasterizer_line_type;


        //-- Create with specifying the source
        //pattern_type patt(fltr, src);   

        //-- Create uninitialized and set the source
        pattern_type patt(fltr);        
        patt.create(p1);
        renderer_img_type ren_img(ren_base, patt);
        rasterizer_img_type ras_img(ren_img);


        //-- create uninitialized and set parameters
        agg::line_profile_aa profile;
        profile.smoother_width(10.0);                    //optional
        profile.width(8.0);                              //mandatory!
        renderer_line_type ren_line(ren_base, profile);
        ren_line.color(agg::rgba8(0,0,127));            //mandatory!
        rasterizer_line_type ras_line(ren_line);
        ras_line.round_cap(true);                       //optional
        //ras_line.line_join(agg::outline_no_join);     //optional

        // Calculate the dilation value so that, the line caps were
        // drawn correctly.
        //---------------
        double w2 = 9.0;//p1.height() / 2 + 2;


        // Set the clip box a bit bigger than you expect. You need it
        // to draw the clipped line caps correctly. The correct result
        // is achieved with raster clipping.
        //------------------------
        ren_img.scale_x(m_scale_x.value());
        ren_img.start_x(m_start_x.value());
        ren_img.clip_box (50-w2, 50-w2, width()-50+w2, height()-50+w2);
        ren_line.clip_box(50-w2, 50-w2, width()-50+w2, height()-50+w2);

        // First, draw polyline without raster clipping just to show the idea
        //------------------------
        draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points());
        draw_polyline(ras_img,  ren_img,  m_line1.polygon(), m_line1.num_points());

        // Clear the area, almost opaque, but not completely
        //------------------------
        ren_base.blend_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1), 200);


        // Set the raster clip box and then, draw again. 
        // In reality there shouldn't be two calls above. 
        // It's done only for demonstration
        //------------------------
        ren_base.clip_box((int)50, (int)50, (int)width()-50, (int)height()-50);

        // This "copy_bar" is also for demonstration only
        //------------------------
        ren_base.copy_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1));

        // Finally draw polyline correctly clipped: We use double clipping, 
        // first is vector clipping, with extended clip box, second is raster 
        // clipping with normal clip box.
        //------------------------
        ren_img.scale_x(m_scale_x.value());
        ren_img.start_x(m_start_x.value());
        draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points());
        draw_polyline(ras_img, ren_img,   m_line1.polygon(), m_line1.num_points());


        // Reset clipping and draw the controls and stuff
        ren_base.reset_clipping(true);

        m_line1.line_width(1/m_scale.scale());
        m_line1.point_radius(5/m_scale.scale());

        agg::render_ctrl(ras, sl, ren_base, m_line1);
        agg::render_ctrl(ras, sl, ren_base, m_scale_x);
        agg::render_ctrl(ras, sl, ren_base, m_start_x);


        char buf[256]; 
        agg::gsv_text t;
        t.size(10.0);

        agg::conv_stroke<agg::gsv_text> pt(t);
        pt.width(1.5);
        pt.line_cap(agg::round_cap);

        const double* p = m_line1.polygon();
        sprintf(buf, "Len=%.2f", agg::calc_distance(p[0], p[1], p[2], p[3]) * m_scale.scale());

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

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

    }
示例#2
0
    virtual void on_draw()
    {
        typedef agg::pixfmt_gray8 pixfmt_gray8;
        typedef agg::renderer_base<pixfmt_gray8> ren_base_gray8;

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

        pixfmt_gray8 pixf_gray8(m_gray8_rbuf);
        ren_base_gray8 renb_gray8(pixf_gray8);
        renb_gray8.clear(agg::gray8(0));

        // Testing enhanced compositing operations. 
        // Uncomment and replace renb.blend_from_* to renb_blend.blend_from_*
        //----------------
        //typedef agg::comp_op_rgba_minus<color_type, component_order> blender_type;
        //typedef agg::comp_adaptor_rgba<blender_type> blend_adaptor_type;
        //typedef agg::pixfmt_custom_blend_rgba<blend_adaptor_type, agg::rendering_buffer> pixfmt_type;
        //typedef agg::renderer_base<pixfmt_type> ren_base;
        //pixfmt_type pixf_blend(rbuf_window());
        //agg::renderer_base<pixfmt_type> renb_blend(pixf_blend);

        pixfmt pixf(rbuf_window());
        agg::renderer_base<pixfmt> renb(pixf);
        renb.clear(agg::rgba(1, 0.95, 0.95));

        agg::trans_perspective shadow_persp(m_shape_bounds.x1, m_shape_bounds.y1, 
                                            m_shape_bounds.x2, m_shape_bounds.y2,
                                            m_shadow_ctrl.polygon());

        agg::conv_transform<shape_type, 
                            agg::trans_perspective> shadow_trans(m_shape, 
                                                                 shadow_persp);

        start_timer();

        // Render shadow
        m_ras.add_path(shadow_trans);
        agg::render_scanlines_aa_solid(m_ras, m_sl, renb_gray8, agg::gray8(255));

        // Calculate the bounding box and extend it by the blur radius
        agg::rect_d bbox;
        agg::bounding_rect_single(shadow_trans, 0, &bbox.x1, &bbox.y1, &bbox.x2, &bbox.y2);

        bbox.x1 -= m_radius.value();
        bbox.y1 -= m_radius.value();
        bbox.x2 += m_radius.value();
        bbox.y2 += m_radius.value();

        if(bbox.clip(agg::rect_d(0, 0, width(), height())))
        {
            // Create a new pixel renderer and attach it to the main one as a child image. 
            // It returns true if the attachment suceeded. It fails if the rectangle 
            // (bbox) is fully clipped.
            //------------------
            pixfmt_gray8 pixf2(m_gray8_rbuf2);
            if(pixf2.attach(pixf_gray8, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2)))
            {
                // Blur it
                agg::stack_blur_gray8(pixf2, agg::uround(m_radius.value()), 
                                             agg::uround(m_radius.value()));
            }
            if(m_method.cur_item() == 0)
            {
                renb.blend_from_color(pixf2, 
                                      agg::rgba8(0, 100, 0), 
                                      0, 
                                      int(bbox.x1), 
                                      int(bbox.y1));
            }
            else
            {
                renb.blend_from_lut(pixf2, 
                                    m_color_lut.data(),
                                    0, 
                                    int(bbox.x1), 
                                    int(bbox.y1));
            }
        }
        double tm = elapsed_time();

        char buf[64]; 
        agg::gsv_text t;
        t.size(10.0);

        agg::conv_stroke<agg::gsv_text> st(t);
        st.width(1.5);

        sprintf(buf, "%3.2f ms", tm);
        t.start_point(140.0, 30.0);
        t.text(buf);

        m_ras.add_path(st);
        agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0,0,0));

        agg::render_ctrl(m_ras, m_sl, renb, m_method);
        agg::render_ctrl(m_ras, m_sl, renb, m_radius);
        agg::render_ctrl(m_ras, m_sl, renb, m_shadow_ctrl);
    }
示例#3
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<agg::pixfmt_bgr24> ren_base;

        agg::pixfmt_bgr24 pixf(rbuf_window());
        ren_base renb(pixf);
        renb.clear(agg::rgba(1, 1, 1));
        m_ras.clip_box(0,0, width(), height());

        agg::trans_perspective shadow_persp(m_shape_bounds.x1, m_shape_bounds.y1, 
                                            m_shape_bounds.x2, m_shape_bounds.y2,
                                            m_shadow_ctrl.polygon());

        agg::conv_transform<shape_type, 
                            agg::trans_perspective> shadow_trans(m_shape, 
                                                                 shadow_persp);

        // Render shadow
        m_ras.add_path(shadow_trans);
        agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0.2,0.3,0));

        // Calculate the bounding box and extend it by the blur radius
        agg::rect_d bbox;
        agg::bounding_rect_single(shadow_trans, 0, &bbox.x1, &bbox.y1, &bbox.x2, &bbox.y2);

        bbox.x1 -= m_radius.value();
        bbox.y1 -= m_radius.value();
        bbox.x2 += m_radius.value();
        bbox.y2 += m_radius.value();

        if(m_method.cur_item() == 1)
        {
            // The recursive blur method represents the true Gussian Blur,
            // with theoretically infinite kernel. The restricted window size
            // results in extra influence of edge pixels. It's impossible to
            // solve correctly, but extending the right and top areas to another
            // radius value produces fair result.
            //------------------
            bbox.x2 += m_radius.value();
            bbox.y2 += m_radius.value();
        }

        start_timer();
        if(m_method.cur_item() != 2)
        {
            // Create a new pixel renderer and attach it to the main one as a child image. 
            // It returns true if the attachment suceeded. It fails if the rectangle 
            // (bbox) is fully clipped.
            //------------------
            agg::pixfmt_bgr24 pixf2(m_rbuf2);
            if(pixf2.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2)))
            {
                // Blur it
                if(m_method.cur_item() == 0)
                {
                    // More general method, but 30-40% slower.
                    //------------------
                    //m_stack_blur.blur(pixf2, agg::uround(m_radius.value()));

                    // Faster, but bore specific. 
                    // Works only for 8 bits per channel and only with radii <= 254.
                    //------------------
                    agg::stack_blur_rgb24(pixf2, agg::uround(m_radius.value()), 
                                                 agg::uround(m_radius.value()));
                }
                else
                {
                    // True Gaussian Blur, 3-5 times slower than Stack Blur,
                    // but still constant time of radius. Very sensitive
                    // to precision, doubles are must here.
                    //------------------
                    m_recursive_blur.blur(pixf2, m_radius.value());
                }
            }
        }
        else
        {
            // Blur separate channels
            //------------------
            if(m_channel_r.status())
            {
                typedef agg::pixfmt_alpha_blend_gray<
                    agg::blender_gray8, 
                    agg::rendering_buffer,
                    3, 2> pixfmt_gray8r;

                pixfmt_gray8r pixf2r(m_rbuf2);
                if(pixf2r.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2)))
                {
                    agg::stack_blur_gray8(pixf2r, agg::uround(m_radius.value()), 
                                                  agg::uround(m_radius.value()));
                }
            }

            if(m_channel_g.status())
            {
                typedef agg::pixfmt_alpha_blend_gray<
                    agg::blender_gray8, 
                    agg::rendering_buffer,
                    3, 1> pixfmt_gray8g;

                pixfmt_gray8g pixf2g(m_rbuf2);
                if(pixf2g.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2)))
                {
                    agg::stack_blur_gray8(pixf2g, agg::uround(m_radius.value()), 
                                                  agg::uround(m_radius.value()));
                }
            }

            if(m_channel_b.status())
            {
                typedef agg::pixfmt_alpha_blend_gray<
                    agg::blender_gray8, 
                    agg::rendering_buffer,
                    3, 0> pixfmt_gray8b;

                pixfmt_gray8b pixf2b(m_rbuf2);
                if(pixf2b.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2)))
                {
                    agg::stack_blur_gray8(pixf2b, agg::uround(m_radius.value()), 
                                                  agg::uround(m_radius.value()));
                }
            }
        }
        double tm = elapsed_time();

        agg::render_ctrl(m_ras, m_sl, renb, m_shadow_ctrl);

        // Render the shape itself
        //------------------
        m_ras.add_path(m_shape);
        agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0.6,0.9,0.7, 0.8));

        char buf[64]; 
        agg::gsv_text t;
        t.size(10.0);

        agg::conv_stroke<agg::gsv_text> st(t);
        st.width(1.5);

        sprintf(buf, "%3.2f ms", tm);
        t.start_point(140.0, 30.0);
        t.text(buf);

        m_ras.add_path(st);
        agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0,0,0));


        agg::render_ctrl(m_ras, m_sl, renb, m_method);
        agg::render_ctrl(m_ras, m_sl, renb, m_radius);
        agg::render_ctrl(m_ras, m_sl, renb, m_channel_r);
        agg::render_ctrl(m_ras, m_sl, renb, m_channel_g);
        agg::render_ctrl(m_ras, m_sl, renb, m_channel_b);
    }