Example #1
0
  virtual void on_draw() {
    typedef agg::renderer_base<pixfmt_type> base_ren_type;

    pixfmt_type pf(rbuf_window());
    base_ren_type ren_base(pf);
    ren_base.clear(agg::rgba(1, 1, 1));

    render();

    agg::render_ctrl(m_ras, m_sl, ren_base, m_polygons);
    agg::render_ctrl(m_ras, m_sl, ren_base, m_operation);
  }
void  agg_renderer<T>::process(line_pattern_symbolizer const& sym,
                               mapnik::feature_ptr const& feature,
                               proj_transform const& prj_trans)
{
    typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
    typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
    typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
    typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base;
    typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
    typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;

    agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
    agg::pixfmt_rgba32_plain pixf(buf);

    std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature);

    boost::optional<marker_ptr> mark = marker_cache::instance()->find(filename,true);
    if (!mark) return;

    if (!(*mark)->is_bitmap())
    {
        std::clog << "### Warning only images (not '" << filename << "') are supported in the line_pattern_symbolizer\n";
        return;
    }

    boost::optional<image_ptr> pat = (*mark)->get_bitmap_data();

    if (!pat) return;

    box2d<double> ext = query_extent_ * 1.1;
    renderer_base ren_base(pixf);
    agg::pattern_filter_bilinear_rgba8 filter;
    pattern_source source(*(*pat));
    pattern_type pattern (filter,source);
    renderer_type ren(ren_base, pattern);
    // TODO - should be sensitive to buffer size
    ren.clip_box(0,0,width_,height_);
    rasterizer_type ras(ren);
    //metawriter_with_properties writer = sym.get_metawriter();
    for (unsigned i=0;i<feature->num_geometries();++i)
    {
        geometry_type & geom = feature->get_geometry(i);
        if (geom.num_points() > 1)
        {
            clipped_geometry_type clipped(geom);
            clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
            path_type path(t_,clipped,prj_trans);
            ras.add_path(path);
            //if (writer.first) writer.first->add_line(path, *feature, t_, writer.second);
        }
    }
}
Example #3
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<agg::pixfmt_bgr24> base_ren_type;

        agg::pixfmt_bgr24 pf(rbuf_window());
        base_ren_type ren_base(pf);
        ren_base.clear(agg::rgba(1,1,1));

        agg::scanline_u8 sl;
        agg::rasterizer_scanline_aa<> ras;

        render_clipper(sl, ras);

        agg::render_ctrl(ras, sl, ren_base, m_polygons);
        agg::render_ctrl(ras, sl, ren_base, m_operation);
    }
Example #4
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt> base_ren_type;

        pixfmt pf(rbuf_window());
        base_ren_type ren_base(pf);
        ren_base.clear(agg::rgba(1,1,1));

        agg::scanline_u8 sl;
        agg::rasterizer_scanline_aa<> ras;

        render_gouraud(sl, ras);

        ras.gamma(agg::gamma_none());
        agg::render_ctrl(ras, sl, ren_base, m_dilation);
        agg::render_ctrl(ras, sl, ren_base, m_gamma);
        agg::render_ctrl(ras, sl, ren_base, m_alpha);
    }
void  agg_renderer<T>::process(line_pattern_symbolizer const& sym,
                               Feature const& feature,
                               proj_transform const& prj_trans)
{
    typedef  coord_transform2<CoordTransform,geometry_type> path_type;
    typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
    typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base;
    typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
    typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;

    agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
    agg::pixfmt_rgba32_plain pixf(buf);
    
    std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);

    boost::optional<marker_ptr> mark = marker_cache::instance()->find(filename,true);
    if (!mark || !(*mark)->is_bitmap()) return;

    boost::optional<image_ptr> pat = (*mark)->get_bitmap_data();

    if (!pat) return;
      
    renderer_base ren_base(pixf);
    agg::pattern_filter_bilinear_rgba8 filter;
    pattern_source source(*(*pat));
    pattern_type pattern (filter,source);
    renderer_type ren(ren_base, pattern);
    ren.clip_box(0,0,width_,height_);
    rasterizer_type ras(ren);
    metawriter_with_properties writer = sym.get_metawriter();
    for (unsigned i=0;i<feature.num_geometries();++i)
    {
        geometry_type const& geom = feature.get_geometry(i);
        if (geom.num_points() > 1)
        {
            path_type path(t_,geom,prj_trans);
            ras.add_path(path);
            if (writer.first) writer.first->add_line(path, feature, t_, writer.second);
        }
    }
}
Example #6
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt> base_ren_type;
        typedef agg::renderer_scanline_aa_solid<base_ren_type> renderer_solid;

        pixfmt pf(rbuf_window());
        base_ren_type ren_base(pf);
        renderer_solid ren_solid(ren_base);
        ren_base.clear(agg::rgba(1,1,1));

        agg::scanline_u8 sl;
        agg::rasterizer_scanline_aa<> ras;
        agg::rasterizer_scanline_aa<> ras2;

        agg::render_ctrl(ras, sl, ren_base, m_polygons);
        agg::render_ctrl(ras, sl, ren_base, m_fill_rule);
        agg::render_ctrl(ras, sl, ren_base, m_scanline_type);
        agg::render_ctrl(ras, sl, ren_base, m_operation);

        render_sbool(ras, ras2);

    }
    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);
        }
    }
Example #8
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);

    }
Example #9
0
    void render_gouraud(Scanline& sl, Ras& ras)
    {
        unsigned alpha = int(m_alpha.value() * 255.0);
        unsigned brc = 255;

        typedef agg::renderer_base<pixfmt> base_ren_type;
#ifdef AGG_GRAY8
        typedef agg::span_gouraud_gray8<> gouraud_span_gen_type;
#else
        typedef agg::span_gouraud_rgba8<> gouraud_span_gen_type;
#endif
        typedef agg::span_allocator<gouraud_span_gen_type::color_type> gouraud_span_alloc_type;
        typedef agg::renderer_scanline_u<base_ren_type, gouraud_span_gen_type> renderer_gouraud;
        
        pixfmt pf(rbuf_window());
        base_ren_type ren_base(pf);

        gouraud_span_alloc_type span_alloc;
        gouraud_span_gen_type   span_gen(span_alloc);
        renderer_gouraud        ren_gouraud(ren_base, span_gen);

        ras.gamma(agg::gamma_linear(0.0, m_gamma.value()));

        double d = m_dilation.value();

        // Single triangle
        //span_gen.colors(agg::rgba8(255,   0,   0,  alpha),
        //                agg::rgba8(0,   255,   0,  alpha),
        //                agg::rgba8(0,     0, 255,  alpha));
        //span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], m_x[2], m_y[2], d);
        //ras.add_path(span_gen);
        //ras.render(sl, ren_gouraud);


        // Six triangles
        double xc = (m_x[0] + m_x[1] + m_x[2]) / 3.0;
        double yc = (m_y[0] + m_y[1] + m_y[2]) / 3.0;

        double x1 = (m_x[1] + m_x[0]) / 2 - (xc - (m_x[1] + m_x[0]) / 2);
        double y1 = (m_y[1] + m_y[0]) / 2 - (yc - (m_y[1] + m_y[0]) / 2);

        double x2 = (m_x[2] + m_x[1]) / 2 - (xc - (m_x[2] + m_x[1]) / 2);
        double y2 = (m_y[2] + m_y[1]) / 2 - (yc - (m_y[2] + m_y[1]) / 2);

        double x3 = (m_x[0] + m_x[2]) / 2 - (xc - (m_x[0] + m_x[2]) / 2);
        double y3 = (m_y[0] + m_y[2]) / 2 - (yc - (m_y[0] + m_y[2]) / 2);

        span_gen.colors(agg::rgba8(255,   0,   0,  alpha),
                        agg::rgba8(0,   255,   0,  alpha),
                        agg::rgba8(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], xc, yc, d);
        ras.add_path(span_gen);
        ras.render(sl, ren_gouraud);


        span_gen.colors(agg::rgba8(0,   255,   0,  alpha),
                        agg::rgba8(0,   0,   255,  alpha),
                        agg::rgba8(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[1], m_y[1], m_x[2], m_y[2], xc, yc, d);
        ras.add_path(span_gen);
        ras.render(sl, ren_gouraud);


        span_gen.colors(agg::rgba8(0,   0,   255, alpha),
                        agg::rgba8(255, 0,   0,   alpha),
                        agg::rgba8(brc, brc, brc, alpha));
        span_gen.triangle(m_x[2], m_y[2], m_x[0], m_y[0], xc, yc, d);
        ras.add_path(span_gen);
        ras.render(sl, ren_gouraud);


        brc = 255-brc;
        span_gen.colors(agg::rgba8(255,   0,   0,  alpha),
                        agg::rgba8(0,   255,   0,  alpha),
                        agg::rgba8(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], x1, y1, d);
        ras.add_path(span_gen);
        ras.render(sl, ren_gouraud);


        span_gen.colors(agg::rgba8(0,   255,   0,  alpha),
                        agg::rgba8(0,     0, 255,  alpha),
                        agg::rgba8(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[1], m_y[1], m_x[2], m_y[2], x2, y2, d);
        ras.add_path(span_gen);
        ras.render(sl, ren_gouraud);


        span_gen.colors(agg::rgba8(0,     0, 255,  alpha),
                        agg::rgba8(255,   0,   0,  alpha),
                        agg::rgba8(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[2], m_y[2], m_x[0], m_y[0], x3, y3, d);
        ras.add_path(span_gen);
        ras.render(sl, ren_gouraud);
    }
Example #10
0
  virtual void on_draw() {
    typedef agg::renderer_base<pixfmt> base_ren_type;

    pixfmt pf(rbuf_window());
    base_ren_type ren_base(pf);
    ren_base.clear(agg::rgba(1, 1, 1));

    agg::scanline_u8 sl;
    agg::rasterizer_scanline_aa<> ras;

    // Draw some background
    agg::ellipse ell;
    srand(1234);
    unsigned i;
    unsigned w = unsigned(width());
    unsigned h = unsigned(height());
    for (i = 0; i < 100; i++) {
      ell.init(rand() % w, rand() % h, rand() % 60 + 5, rand() % 60 + 5, 50);
      ras.add_path(ell);
      agg::render_scanlines_aa_solid(
          ras, sl, ren_base,
          agg::rgba(rand() / double(RAND_MAX), rand() / double(RAND_MAX),
                    rand() / double(RAND_MAX),
                    rand() / double(RAND_MAX) / 2.0));
    }

    double parallelogram[6];
    parallelogram[0] = m_x[0];
    parallelogram[1] = m_y[0];
    parallelogram[2] = m_x[1];
    parallelogram[3] = m_y[1];
    parallelogram[4] = m_x[2];
    parallelogram[5] = m_y[2];

    // Gradient shape function (linear, radial, custom, etc)
    //-----------------
    typedef agg::gradient_circle gradient_func_type;

    // Alpha gradient shape function (linear, radial, custom, etc)
    //-----------------
    typedef agg::gradient_xy gradient_alpha_func_type;

    // Span interpolator. This object is used in all span generators
    // that operate with transformations during iterating of the spans,
    // for example, image transformers use the interpolator too.
    //-----------------
    typedef agg::span_interpolator_linear<> interpolator_type;

    // Span allocator is an object that allocates memory for
    // the array of colors that will be used to render the
    // color spans. One object can be shared between different
    // span generators.
    //-----------------
    typedef agg::span_allocator<color_type> span_allocator_type;

    // Gradient colors array adaptor
    //-----------------
    typedef agg::pod_auto_array<color_type, 256> gradient_colors_type;

    // Finally, the gradient span generator working with the color_type
    // color type.
    //-----------------
    typedef agg::span_gradient<color_type, interpolator_type,
                               gradient_func_type,
                               gradient_colors_type> span_gradient_type;

    // Gradient alpha array adaptor
    //-----------------
    typedef agg::pod_auto_array<color_type::value_type, 256>
        gradient_alpha_type;

    // The alpha gradient span converter working with the color_type
    // color type.
    //-----------------
    typedef agg::span_gradient_alpha<
        color_type, interpolator_type, gradient_alpha_func_type,
        gradient_alpha_type> span_gradient_alpha_type;

    // Span converter type
    //-----------------
    typedef agg::span_converter<span_gradient_type, span_gradient_alpha_type>
        span_conv_type;

    // The gradient objects declarations
    //----------------
    gradient_func_type gradient_func;     // The gradient function
    gradient_alpha_func_type alpha_func;  // The gradient function
    agg::trans_affine gradient_mtx;       // Gradient affine transformer
    agg::trans_affine alpha_mtx;          // Alpha affine transformer
    interpolator_type span_interpolator(
        gradient_mtx);  // Span gradient interpolator
    interpolator_type span_interpolator_alpha(
        alpha_mtx);                      // Span alpha interpolator
    span_allocator_type span_allocator;  // Span Allocator
    gradient_colors_type color_array;    // The gradient colors

    // Declare the gradient span itself.
    // The last two arguments are so called "d1" and "d2"
    // defining two distances in pixels, where the gradient starts
    // and where it ends. The actual meaning of "d1" and "d2" depands
    // on the gradient function.
    //----------------
    span_gradient_type span_gradient(span_interpolator, gradient_func,
                                     color_array, 0, 150);

    // Declare the gradient span itself.
    // The last two arguments are so called "d1" and "d2"
    // defining two distances in pixels, where the gradient starts
    // and where it ends. The actual meaning of "d1" and "d2" depands
    // on the gradient function.
    //----------------
    gradient_alpha_type alpha_array;
    span_gradient_alpha_type span_gradient_alpha(
        span_interpolator_alpha, alpha_func, alpha_array, 0, 100);

    // Span converter declaration
    span_conv_type span_conv(span_gradient, span_gradient_alpha);

    // Finally we can draw a circle.
    //----------------
    gradient_mtx *= agg::trans_affine_scaling(0.75, 1.2);
    gradient_mtx *= agg::trans_affine_rotation(-agg::pi / 3.0);
    gradient_mtx *= agg::trans_affine_translation(width() / 2, height() / 2);
    gradient_mtx.invert();
    alpha_mtx.parl_to_rect(parallelogram, -100, -100, 100, 100);
    fill_color_array(color_array, agg::rgba(0, 0.19, 0.19),
                     agg::rgba(0.7, 0.7, 0.19), agg::rgba(0.31, 0, 0));

    // Fill Alpha array
    //----------------
    for (i = 0; i < 256; i++) {
      alpha_array[i] = color_type::from_double(m_alpha.value(i / 255.0));
    }

    ell.init(width() / 2, height() / 2, 150, 150, 100);
    ras.add_path(ell);

    // Render the circle with gradient plus alpha-gradient
    agg::render_scanlines_aa(ras, sl, ren_base, span_allocator, span_conv);

    // Draw the control points and the parallelogram
    //-----------------
    agg::rgba color_pnt(0, 0.4, 0.4, 0.31);
    ell.init(m_x[0], m_y[0], 5, 5, 20);
    ras.add_path(ell);
    agg::render_scanlines_aa_solid(ras, sl, ren_base, color_pnt);
    ell.init(m_x[1], m_y[1], 5, 5, 20);
    ras.add_path(ell);
    agg::render_scanlines_aa_solid(ras, sl, ren_base, color_pnt);
    ell.init(m_x[2], m_y[2], 5, 5, 20);
    ras.add_path(ell);
    agg::render_scanlines_aa_solid(ras, sl, ren_base, color_pnt);

    agg::vcgen_stroke stroke;
    stroke.add_vertex(m_x[0], m_y[0], agg::path_cmd_move_to);
    stroke.add_vertex(m_x[1], m_y[1], agg::path_cmd_line_to);
    stroke.add_vertex(m_x[2], m_y[2], agg::path_cmd_line_to);
    stroke.add_vertex(m_x[0] + m_x[2] - m_x[1], m_y[0] + m_y[2] - m_y[1],
                      agg::path_cmd_line_to);
    stroke.add_vertex(0, 0, agg::path_cmd_end_poly | agg::path_flags_close);
    ras.add_path(stroke);
    agg::render_scanlines_aa_solid(ras, sl, ren_base, agg::rgba(0, 0, 0));

    agg::render_ctrl(ras, sl, ren_base, m_alpha);
  }
Example #11
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);
    }
Example #12
0
    virtual void on_draw()
    {
        pixfmt pf(rbuf_window());
        renderer_base ren_base(pf);
        ren_base.clear(agg::rgba(1.0, 1.0, 0.95));
        renderer_scanline ren(ren_base);

        rasterizer_scanline ras;
        scanline sl;

        // 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 p1(rbuf_img(0));
        pattern_src_brightness_to_alpha p2(rbuf_img(1));
        pattern_src_brightness_to_alpha p3(rbuf_img(2));
        pattern_src_brightness_to_alpha p4(rbuf_img(3));
        pattern_src_brightness_to_alpha p5(rbuf_img(4));
        pattern_src_brightness_to_alpha p6(rbuf_img(5));
        pattern_src_brightness_to_alpha p7(rbuf_img(6));
        pattern_src_brightness_to_alpha p8(rbuf_img(7));
        pattern_src_brightness_to_alpha p9(rbuf_img(8));

        agg::pattern_filter_bilinear_rgba<color_type> 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_rgba<color_type> > pattern_type;
        typedef agg::renderer_base<pixfmt> base_ren_type;
        typedef agg::renderer_outline_image<base_ren_type, pattern_type> renderer_type;
        typedef agg::rasterizer_outline_aa<renderer_type>                rasterizer_type;

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

        //-- Create uninitialized and set the source
        pattern_type patt(fltr);        
        renderer_type ren_img(ren_base, patt);
        rasterizer_type ras_img(ren_img);

        draw_curve(patt, ras_img, ren_img, p1, m_curve1.curve());
        draw_curve(patt, ras_img, ren_img, p2, m_curve2.curve());
        draw_curve(patt, ras_img, ren_img, p3, m_curve3.curve());
        draw_curve(patt, ras_img, ren_img, p4, m_curve4.curve());
        draw_curve(patt, ras_img, ren_img, p5, m_curve5.curve());
        draw_curve(patt, ras_img, ren_img, p6, m_curve6.curve());
        draw_curve(patt, ras_img, ren_img, p7, m_curve7.curve());
        draw_curve(patt, ras_img, ren_img, p8, m_curve8.curve());
        draw_curve(patt, ras_img, ren_img, p9, m_curve9.curve());

        agg::render_ctrl(ras, sl, ren_base, m_curve1);
        agg::render_ctrl(ras, sl, ren_base, m_curve2);
        agg::render_ctrl(ras, sl, ren_base, m_curve3);
        agg::render_ctrl(ras, sl, ren_base, m_curve4);
        agg::render_ctrl(ras, sl, ren_base, m_curve5);
        agg::render_ctrl(ras, sl, ren_base, m_curve6);
        agg::render_ctrl(ras, sl, ren_base, m_curve7);
        agg::render_ctrl(ras, sl, ren_base, m_curve8);
        agg::render_ctrl(ras, sl, ren_base, m_curve9);

        agg::render_ctrl(ras, sl, ren_base, m_scale_x);
        agg::render_ctrl(ras, sl, ren_base, m_start_x);
    }
Example #13
0
void grid_node_t::do_process( const render::context_t& context)
{
	Imath::Color4f color( get_value<Imath::Color4f>( param( "bgcol")));
	boost::gil::fill_pixels( image_view(), image::pixel_t( color.r, color.g, color.b, color.a));
	
	Imath::V2f size( get_absolute_value<Imath::V2f>( param( "size")));
	Imath::V2f translate( get_absolute_value<Imath::V2f>( param( "translate")));
	Imath::V2f line_width( get_absolute_value<Imath::V2f>( param( "linewidth")));
	color = get_value<Imath::Color4f>( param( "fgcol"));
	
	// adjust params
	size.x = size.x / context.subsample / aspect_ratio();
	size.y /= context.subsample;

	if( size.x == 0 || size.y == 0)
		return;
	
	translate.x = translate.x / context.subsample / aspect_ratio();
	translate.y /= context.subsample;
	
	line_width.x = line_width.x / context.subsample / aspect_ratio();
	line_width.y /= context.subsample;
	
	if( line_width.x == 0 || line_width.y == 0)
		return;
	
	// setup agg
    typedef image::agg_rgba32f_renderer_t ren_base_type;
    typedef ren_base_type::color_type color_type;
    typedef agg::renderer_scanline_aa_solid<ren_base_type> renderer_type;
	
    ren_base_type ren_base( image_view());
    renderer_type ren( ren_base);

    agg::rasterizer_scanline_aa<> ras;
    ras.gamma( agg::gamma_none());

    agg::scanline_u8 sl;
	
	ras.reset();

	agg::path_storage path;
	agg::conv_stroke<agg::path_storage> stroke_conv( path);

	// Vertical
	stroke_conv.width( line_width.x);
	
	int w = image_view().width();
	int h = image_view().height();
	
	Imath::Box2f area( defined().min - translate, 
					   defined().max - translate);
	
	float x = Imath::Math<float>::floor( area.min.x / size.x) * size.x;
	for( ; x < area.max.x + line_width.x; x += size.x)
	{
		path.move_to( x - area.min.x, 0);
		path.line_to( x - area.min.x, h);
	}

	ras.add_path( stroke_conv);
    ren.color( image::pixel_t( color.r, color.g, color.b, color.a));
    agg::render_scanlines( ras, sl, ren);

	// Horizontal
	path.remove_all();
	stroke_conv.width( line_width.y);

	float y = Imath::Math<float>::floor( area.min.y / size.y) * size.y;
	for( ; y < area.max.y + line_width.y; y += size.y)
	{
		path.move_to( 0, y - area.min.y);
		path.line_to( w, y - area.min.y);
	}

	ras.add_path( stroke_conv);
    ren.color( image::pixel_t( color.r, color.g, color.b, color.a));
    agg::render_scanlines( ras, sl, ren);
}
void  agg_renderer<T0,T1>::process(line_pattern_symbolizer const& sym,
                                   mapnik::feature_impl & feature,
                                   proj_transform const& prj_trans)
{

    using color = agg::rgba8;
    using order = agg::order_rgba;
    using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
    using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
    using pattern_type = agg::line_image_pattern<pattern_filter_type>;
    using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
    using renderer_base = agg::renderer_base<pixfmt_type>;
    using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
    using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;

    std::string filename = get<std::string>(sym, keys::file, feature, common_.vars_);
    if (filename.empty()) return;
    boost::optional<mapnik::marker_ptr> marker_ptr = marker_cache::instance().find(filename, true);
    if (!marker_ptr || !(*marker_ptr)) return;
    boost::optional<image_ptr> pat;
    // TODO - re-implement at renderer level like polygon_pattern symbolizer
    double opacity = get<value_double>(sym, keys::opacity, feature, common_.vars_,1.0);
    if ((*marker_ptr)->is_bitmap())
    {
        pat = (*marker_ptr)->get_bitmap_data();
    }
    else
    {
        agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
        auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
        if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);
        pat = render_pattern(*ras_ptr, **marker_ptr, image_tr, 1.0);
    }

    if (!pat) return;

    bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, false);
    double offset = get<value_double>(sym, keys::offset, feature, common_.vars_, 0.0);
    double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0);
    double smooth = get<value_double>(sym, keys::smooth, feature, common_.vars_, false);

    agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4);
    pixfmt_type pixf(buf);
    pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e>(sym, keys::comp_op, feature, common_.vars_, src_over)));
    renderer_base ren_base(pixf);
    agg::pattern_filter_bilinear_rgba8 filter;

    pattern_source source(*(*pat), opacity);
    pattern_type pattern (filter,source);
    renderer_type ren(ren_base, pattern);
    rasterizer_type ras(ren);

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);

    box2d<double> clip_box = clipping_extent(common_);
    if (clip)
    {
        double padding = (double)(common_.query_extent_.width()/pixmap_.width());
        double half_stroke = (*marker_ptr)->width()/2.0;
        if (half_stroke > 1)
            padding *= half_stroke;
        if (std::fabs(offset) > 0)
            padding *= std::fabs(offset) * 1.2;
        padding *= common_.scale_factor_;
        clip_box.pad(padding);
    }

    using conv_types = boost::mpl::vector<clip_line_tag, transform_tag,
          affine_transform_tag,
          simplify_tag,smooth_tag,
          offset_transform_tag>;
    vertex_converter<box2d<double>, rasterizer_type, line_pattern_symbolizer,
                     view_transform, proj_transform, agg::trans_affine, conv_types, feature_impl>
                     converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);

    if (clip) converter.set<clip_line_tag>(); //optional clip (default: true)
    converter.set<transform_tag>(); //always transform
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
    converter.set<affine_transform_tag>(); // optional affine transform
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

    for (geometry_type & geom : feature.paths())
    {
        if (geom.size() > 1)
        {
            converter.apply(geom);
        }
    }
}
Example #15
0
    void render_gouraud(Scanline& sl, Ras& ras)
    {
        double alpha = m_alpha.value();
        double brc = 1;

        typedef agg::renderer_base<pixfmt> base_ren_type;
#ifdef AGG_GRAY8
        typedef agg::span_gouraud_gray<color_type> span_gen_type;
#else
        typedef agg::span_gouraud_rgba<color_type> span_gen_type;
#endif
        typedef agg::span_allocator<color_type> span_alloc_type;
        
        pixfmt pf(rbuf_window());
        base_ren_type ren_base(pf);

        span_alloc_type span_alloc;
        span_gen_type   span_gen;

        ras.gamma(agg::gamma_linear(0.0, m_gamma.value()));

        double d = m_dilation.value();

        // Single triangle
        //span_gen.colors(agg::rgba(1,   0,   0,  alpha),
        //                agg::rgba(0,   1,   0,  alpha),
        //                agg::rgba(0,   0,   1,  alpha));
        //span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], m_x[2], m_y[2], d);
        //ras.add_path(span_gen);
        //agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);


        // Six triangles
        double xc = (m_x[0] + m_x[1] + m_x[2]) / 3.0;
        double yc = (m_y[0] + m_y[1] + m_y[2]) / 3.0;

        double x1 = (m_x[1] + m_x[0]) / 2 - (xc - (m_x[1] + m_x[0]) / 2);
        double y1 = (m_y[1] + m_y[0]) / 2 - (yc - (m_y[1] + m_y[0]) / 2);

        double x2 = (m_x[2] + m_x[1]) / 2 - (xc - (m_x[2] + m_x[1]) / 2);
        double y2 = (m_y[2] + m_y[1]) / 2 - (yc - (m_y[2] + m_y[1]) / 2);

        double x3 = (m_x[0] + m_x[2]) / 2 - (xc - (m_x[0] + m_x[2]) / 2);
        double y3 = (m_y[0] + m_y[2]) / 2 - (yc - (m_y[0] + m_y[2]) / 2);

        span_gen.colors(agg::rgba(1,   0,   0,    alpha),
                        agg::rgba(0,   1,   0,    alpha),
                        agg::rgba(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], xc, yc, d);
        ras.add_path(span_gen);
        agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);


        span_gen.colors(agg::rgba(0,   1,   0,    alpha),
                        agg::rgba(0,   0,   1,    alpha),
                        agg::rgba(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[1], m_y[1], m_x[2], m_y[2], xc, yc, d);
        ras.add_path(span_gen);
        agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);


        span_gen.colors(agg::rgba(0,   0,   1,   alpha),
                        agg::rgba(1,   0,   0,   alpha),
                        agg::rgba(brc, brc, brc, alpha));
        span_gen.triangle(m_x[2], m_y[2], m_x[0], m_y[0], xc, yc, d);
        ras.add_path(span_gen);
        agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);


        brc = 1-brc;
        span_gen.colors(agg::rgba(1,   0,   0,    alpha),
                        agg::rgba(0,   1,   0,    alpha),
                        agg::rgba(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], x1, y1, d);
        ras.add_path(span_gen);
        agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);


        span_gen.colors(agg::rgba(0,   1,   0,    alpha),
                        agg::rgba(0,   0,   1,    alpha),
                        agg::rgba(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[1], m_y[1], m_x[2], m_y[2], x2, y2, d);
        ras.add_path(span_gen);
        agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);


        span_gen.colors(agg::rgba(0,   0,   1,    alpha),
                        agg::rgba(1,   0,   0,    alpha),
                        agg::rgba(brc, brc, brc,  alpha));
        span_gen.triangle(m_x[2], m_y[2], m_x[0], m_y[0], x3, y3, d);
        ras.add_path(span_gen);
        agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen);
    }
    void operator() (marker_svg const& marker) const
    {
        using color = agg::rgba8;
        using order = agg::order_rgba;
        using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
        using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
        using pattern_type = agg::line_image_pattern<pattern_filter_type>;
        using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
        using renderer_base = agg::renderer_base<pixfmt_type>;
        using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
        using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;

        value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
        agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
        auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
        if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_);
        mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
        image_rgba8 image(bbox_image.width(), bbox_image.height());
        render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);

        value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
        value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
        value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
        value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);

        agg::rendering_buffer buf(current_buffer_->bytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->row_size());
        pixfmt_type pixf(buf);
        pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
        renderer_base ren_base(pixf);
        agg::pattern_filter_bilinear_rgba8 filter;

        pattern_source source(image, opacity);
        pattern_type pattern (filter,source);
        renderer_type ren(ren_base, pattern);
        double half_stroke = std::max(marker.width()/2.0,marker.height()/2.0);
        int rast_clip_padding = static_cast<int>(std::round(half_stroke));
        ren.clip_box(-rast_clip_padding,-rast_clip_padding,common_.width_+rast_clip_padding,common_.height_+rast_clip_padding);
        rasterizer_type ras(ren);

        agg::trans_affine tr;
        auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
        if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);

        box2d<double> clip_box = clipping_extent(common_);
        if (clip)
        {
            double padding = (double)(common_.query_extent_.width()/pixmap_.width());
            if (half_stroke > 1)
                padding *= half_stroke;
            if (std::fabs(offset) > 0)
                padding *= std::fabs(offset) * 1.2;
            padding *= common_.scale_factor_;
            clip_box.pad(padding);
        }
        using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag,
                                                       affine_transform_tag,
                                                       simplify_tag,smooth_tag,
                                                       offset_transform_tag>;

        vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);

        if (clip) converter.set<clip_line_tag>();
        converter.set<transform_tag>(); //always transform
        if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
        if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
        converter.set<affine_transform_tag>(); // optional affine transform
        if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

        using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer_type>;
        using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
        apply_vertex_converter_type apply(converter, ras);
        mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
    }
    void operator() (marker_rgba8 const& marker)
    {
        using color = agg::rgba8;
        using order = agg::order_rgba;
        using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
        using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
        using pattern_type = agg::line_image_pattern<pattern_filter_type>;
        using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
        using renderer_base = agg::renderer_base<pixfmt_type>;
        using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
        using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
        
        value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
        mapnik::image_rgba8 const& image = marker.get_data();
        
        value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
        value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
        value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
        value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);

        agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->getRowSize());
        pixfmt_type pixf(buf);
        pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
        renderer_base ren_base(pixf);
        agg::pattern_filter_bilinear_rgba8 filter;

        pattern_source source(image, opacity);
        pattern_type pattern (filter,source);
        renderer_type ren(ren_base, pattern);
        ren.clip_box(0,0,common_.width_,common_.height_);
        rasterizer_type ras(ren);

        agg::trans_affine tr;
        auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
        if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);

        box2d<double> clip_box = clipping_extent(common_);
        if (clip)
        {
            double padding = (double)(common_.query_extent_.width()/pixmap_.width());
            double half_stroke = marker.width()/2.0;
            if (half_stroke > 1)
                padding *= half_stroke;
            if (std::fabs(offset) > 0)
                padding *= std::fabs(offset) * 1.2;
            padding *= common_.scale_factor_;
            clip_box.pad(padding);
        }

        vertex_converter<rasterizer_type, clip_line_tag, transform_tag,
                         affine_transform_tag,
                         simplify_tag,smooth_tag,
                         offset_transform_tag>
            converter(clip_box,ras,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);

        if (clip) converter.set<clip_line_tag>(); //optional clip (default: true)
        converter.set<transform_tag>(); //always transform
        if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
        if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
        converter.set<affine_transform_tag>(); // optional affine transform
        if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

        for (geometry_type const& geom : feature_.paths())
        {
            if (geom.size() > 1)
            {
                vertex_adapter va(geom);
                converter.apply(va);
            }
        }
    }