void render_pattern<image_rgba8>(rasterizer & ras,
                                 marker_svg const& marker,
                                 agg::trans_affine const& tr,
                                 double opacity,
                                 image_rgba8 & image)
{
    using pixfmt = agg::pixfmt_rgba32_pre;
    using renderer_base = agg::renderer_base<pixfmt>;
    using renderer_solid = agg::renderer_scanline_aa_solid<renderer_base>;
    agg::scanline_u8 sl;

    mapnik::box2d<double> const& bbox = marker.bounding_box() * tr;
    mapnik::coord<double,2> c = bbox.center();
    agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
    mtx.translate(0.5 * bbox.width(), 0.5 * bbox.height());
    mtx = tr * mtx;

    agg::rendering_buffer buf(image.bytes(), image.width(), image.height(), image.row_size());
    pixfmt pixf(buf);
    renderer_base renb(pixf);

    mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(marker.get_data()->source());
    mapnik::svg::svg_path_adapter svg_path(stl_storage);
    mapnik::svg::svg_renderer_agg<mapnik::svg::svg_path_adapter,
                                  agg::pod_bvector<mapnik::svg::path_attributes>,
                                  renderer_solid,
                                  pixfmt > svg_renderer(svg_path,
                                                        marker.get_data()->attributes());

    svg_renderer.render(ras, sl, renb, mtx, opacity, bbox);
}
Exemple #2
0
    void operator() (marker_svg const& marker)
    {
        using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
        using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
        agg::scanline_bin sl;

        grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
        pixfmt_type pixf(buf);

        grid_renderer_base_type renb(pixf);
        renderer_type ren(renb);

        ras_ptr_->reset();

        box2d<double> const& bbox = marker.get_data()->bounding_box();
        coord<double,2> c = bbox.center();
        // center the svg marker on '0,0'
        agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
        // apply symbol transformation to get to map space
        mtx *= tr_;
        mtx *= agg::trans_affine_scaling(common_.scale_factor_);
        // render the marker at the center of the marker box
        mtx.translate(pos_.x, pos_.y);
        using namespace mapnik::svg;
        vertex_stl_adapter<svg_path_storage> stl_storage(marker.get_data()->source());
        svg_path_adapter svg_path(stl_storage);
        svg_renderer_agg<svg_path_adapter,
            agg::pod_bvector<path_attributes>,
            renderer_type,
            pixfmt_type> svg_renderer(svg_path,
                                                marker.get_data()->attributes());

        svg_renderer.render_id(*ras_ptr_, sl, renb, feature_.id(), mtx, opacity_, bbox);
    }
    cairo_surface_ptr operator()(marker_svg const & marker) const
    {
        box2d<double> bbox(marker.bounding_box());
        agg::trans_affine tr(transform(bbox));

        double width = std::max(1.0, std::round(bbox.width()));
        double height = std::max(1.0, std::round(bbox.height()));
        cairo_rectangle_t extent { 0, 0, width, height };
        cairo_surface_ptr surface(
            cairo_recording_surface_create(
                CAIRO_CONTENT_COLOR_ALPHA, &extent),
            cairo_surface_closer());

        cairo_ptr cairo = create_context(surface);
        cairo_context context(cairo);

        svg_storage_type & svg = *marker.get_data();
        svg_attribute_type const& svg_attributes = svg.attributes();
        svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(
            svg.source());
        svg::svg_path_adapter svg_path(stl_storage);

        render_vector_marker(context, svg_path, svg_attributes,
            bbox, tr, opacity_);

        return surface;
    }
    void operator() (marker_svg const& mark) const
    {
        using namespace mapnik::svg;

        // https://github.com/mapnik/mapnik/issues/1316
        bool snap_to_pixels = !mapnik::marker_cache::instance().is_uri(filename_);

        agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);

        svg_path_ptr stock_vector_marker = mark.get_data();
        svg_path_ptr marker_ptr = stock_vector_marker;
        bool is_ellipse = false;

        svg_attribute_type s_attributes;
        auto const& r_attributes = get_marker_attributes(stock_vector_marker, s_attributes);

        // special case for simple ellipse markers
        // to allow for full control over rx/ry dimensions
        if (filename_ == "shape://ellipse"
           && (has_key(sym_,keys::width) || has_key(sym_,keys::height)))
        {
            marker_ptr = std::make_shared<svg_storage_type>();
            is_ellipse = true;
        }
        else
        {
            box2d<double> const& bbox = mark.bounding_box();
            setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature_, common_.vars_, sym_);
        }

        vertex_stl_adapter<svg_path_storage> stl_storage(marker_ptr->source());
        svg_path_adapter svg_path(stl_storage);

        if (is_ellipse)
        {
            build_ellipse(sym_, feature_, common_.vars_, *marker_ptr, svg_path);
        }

        if (auto image_transform = get_optional<transform_type>(sym_, keys::image_transform))
        {
            evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_);
        }

        vector_dispatch_type rasterizer_dispatch(marker_ptr,
                                                 svg_path,
                                                 r_attributes,
                                                 image_tr,
                                                 sym_,
                                                 *common_.detector_,
                                                 common_.scale_factor_,
                                                 feature_,
                                                 common_.vars_,
                                                 snap_to_pixels,
                                                 renderer_context_);

        render_marker(mark, rasterizer_dispatch);
    }
 void operator() (marker_svg const& marker) const
 {
     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;
     mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
     render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
     render(image);
 }
 void operator() (marker_svg const& marker)
 {
     mapnik::rasterizer ras;
     mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr_;
     mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
     render_pattern<image_rgba8>(ras, marker, image_tr_, 1.0, image);
     cairo_pattern pattern(image, opacity_);
     pattern.set_extend(CAIRO_EXTEND_REPEAT);
     pattern.set_origin(offset_x_, offset_y_);
     context_.set_pattern(pattern);
 }
Exemple #7
0
 void operator() (marker_svg const& marker)
 {
     mapnik::svg_path_ptr vmarker = marker.get_data();
     if (vmarker)
     {
         box2d<double> bbox = vmarker->bounding_box();
         agg::trans_affine marker_tr = tr_;
         if (recenter_)
         {
             coord<double,2> c = bbox.center();
             marker_tr = agg::trans_affine_translation(-c.x,-c.y);
             marker_tr *= tr_;
         }
         marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
         agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes();
         svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source());
         svg::svg_path_adapter svg_path(stl_storage);
         marker_tr.translate(pos_.x, pos_.y);
         render_vector_marker(context_, svg_path, attributes, bbox, marker_tr, opacity_);
     }
 }
    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_svg const& marker)
    {
        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);
        mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
        mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
        render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);

        agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(),
                                  current_buffer_->height(), current_buffer_->row_size());
        ras_ptr_->reset();
        value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
        gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
        if (gamma != gamma_ || gamma_method != gamma_method_)
        {
            set_gamma_method(ras_ptr_, gamma, gamma_method);
            gamma_method_ = gamma_method;
            gamma_ = gamma;
        }

        value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
        value_double opacity = get<double, keys::opacity>(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_);

        box2d<double> clip_box = clipping_extent(common_);

        using color = agg::rgba8;
        using order = agg::order_rgba;
        using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
        using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;

        using wrap_x_type = agg::wrap_mode_repeat;
        using wrap_y_type = agg::wrap_mode_repeat;
        using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
                                                         wrap_x_type,
                                                         wrap_y_type>;

        using span_gen_type = agg::span_pattern_rgba<img_source_type>;
        using ren_base = agg::renderer_base<pixfmt_type>;

        using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
                                                              agg::span_allocator<agg::rgba8>,
                                                              span_gen_type>;

        pixfmt_type pixf(buf);
        pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
        ren_base renb(pixf);

        unsigned w = image.width();
        unsigned h = image.height();
        agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
        agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
        img_source_type img_src(pixf_pattern);

        pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
        unsigned offset_x=0;
        unsigned offset_y=0;

        if (alignment == LOCAL_ALIGNMENT)
        {
            double x0 = 0;
            double y0 = 0;
            using apply_local_alignment = detail::apply_local_alignment;
            apply_local_alignment apply(common_.t_,prj_trans_, clip_box, x0, y0);
            util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature_.get_geometry());
            offset_x = unsigned(current_buffer_->width() - x0);
            offset_y = unsigned(current_buffer_->height() - y0);
        }

        span_gen_type sg(img_src, offset_x, offset_y);

        agg::span_allocator<agg::rgba8> sa;
        renderer_type rp(renb,sa, sg, unsigned(opacity * 255));

        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_);
        using vertex_converter_type = vertex_converter<clip_poly_tag,
                                                       transform_tag,
                                                       affine_transform_tag,
                                                       simplify_tag,
                                                       smooth_tag>;

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


        if (prj_trans_.equal() && clip) converter.set<clip_poly_tag>();
        converter.set<transform_tag>(); //always transform
        converter.set<affine_transform_tag>(); // optional affine transform
        if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
        if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

        using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer>;
        using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
        apply_vertex_converter_type apply(converter, *ras_ptr_);
        mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
        agg::scanline_u8 sl;
        ras_ptr_->filling_rule(agg::fill_even_odd);
        agg::render_scanlines(*ras_ptr_, sl, rp);
    }
    void operator() (marker_svg const& mark)
    {
        using namespace mapnik::svg;
        bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
        double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
        double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
        double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);

        // https://github.com/mapnik/mapnik/issues/1316
        bool snap_to_pixels = !mapnik::marker_cache::instance().is_uri(filename_);

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

        boost::optional<svg_path_ptr> const& stock_vector_marker = mark.get_data();

        // special case for simple ellipse markers
        // to allow for full control over rx/ry dimensions
        if (filename_ == "shape://ellipse"
           && (has_key(sym_,keys::width) || has_key(sym_,keys::height)))
        {
            svg_path_ptr marker_ellipse = std::make_shared<svg_storage_type>();
            vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse->source());
            svg_path_adapter svg_path(stl_storage);
            build_ellipse(sym_, feature_, common_.vars_, *marker_ellipse, svg_path);
            svg_attribute_type attributes;
            bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym_, feature_, common_.vars_);
            auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
            if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
            vector_dispatch_type rasterizer_dispatch(marker_ellipse,
                                                     svg_path,
                                                     result ? attributes : (*stock_vector_marker)->attributes(),
                                                     image_tr,
                                                     sym_,
                                                     *common_.detector_,
                                                     common_.scale_factor_,
                                                     feature_,
                                                     common_.vars_,
                                                     snap_to_pixels,
                                                     renderer_context_);

            vertex_converter_type converter(clip_box_,
                                            sym_,
                                            common_.t_,
                                            prj_trans_,
                                            geom_tr,
                                            feature_,
                                            common_.vars_,
                                            common_.scale_factor_);
            if (clip) // optional clip (default: true)
            {
                geometry::geometry_types type = geometry::geometry_type(feature_.get_geometry());
                if (type == geometry::geometry_types::Polygon || type == geometry::geometry_types::MultiPolygon)
                    converter.template set<clip_poly_tag>();
                else if (type == geometry::geometry_types::LineString || type == geometry::geometry_types::MultiLineString)
                    converter.template set<clip_line_tag>();
            }

            converter.template set<transform_tag>(); //always transform
            if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
            converter.template set<affine_transform_tag>(); // optional affine transform
            if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
            if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
            apply_markers_multi(feature_, common_.vars_, converter, rasterizer_dispatch, sym_);
        }
        else
        {
            box2d<double> const& bbox = mark.bounding_box();
            setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature_, common_.vars_, sym_);
            auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
            if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
            vertex_stl_adapter<svg_path_storage> stl_storage((*stock_vector_marker)->source());
            svg_path_adapter svg_path(stl_storage);
            svg_attribute_type attributes;
            bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym_, feature_, common_.vars_);
            vector_dispatch_type rasterizer_dispatch(*stock_vector_marker,
                                                     svg_path,
                                                     result ? attributes : (*stock_vector_marker)->attributes(),
                                                     image_tr,
                                                     sym_,
                                                     *common_.detector_,
                                                     common_.scale_factor_,
                                                     feature_,
                                                     common_.vars_,
                                                     snap_to_pixels,
                                                     renderer_context_);

            vertex_converter_type converter(clip_box_,
                                            sym_,
                                            common_.t_,
                                            prj_trans_,
                                            geom_tr,
                                            feature_,
                                            common_.vars_,
                                            common_.scale_factor_);
            if (clip) // optional clip (default: true)
            {
                geometry::geometry_types type = geometry::geometry_type(feature_.get_geometry());
                if (type == geometry::geometry_types::Polygon || type == geometry::geometry_types::MultiPolygon)
                    converter.template set<clip_poly_tag>();
                else if (type == geometry::geometry_types::LineString || type == geometry::geometry_types::MultiLineString)
                    converter.template set<clip_line_tag>();
            }

            converter.template set<transform_tag>(); //always transform
            if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
            converter.template set<affine_transform_tag>(); // optional affine transform
            if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
            if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
            apply_markers_multi(feature_, common_.vars_, converter, rasterizer_dispatch,  sym_);
        }
    }