void agg_renderer<T0,T1>::process(debug_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { debug_symbolizer_mode_enum mode = get<debug_symbolizer_mode_enum>(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); ras_ptr->reset(); if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0) { ras_ptr->gamma(agg::gamma_power()); gamma_method_ = GAMMA_POWER; gamma_ = 1.0; } if (mode == DEBUG_SYM_MODE_RINGS) { RingRenderer<buffer_type> renderer(*ras_ptr,*current_buffer_,common_.t_,prj_trans); render_ring_visitor<buffer_type> apply(renderer); mapnik::util::apply_visitor(apply,feature.get_geometry()); } else if (mode == DEBUG_SYM_MODE_COLLISION) { for (auto const& n : *common_.detector_) { draw_rect(pixmap_, n.get().box); } } else if (mode == DEBUG_SYM_MODE_VERTEX) { using apply_vertex_mode = apply_vertex_mode<buffer_type>; apply_vertex_mode apply(pixmap_, common_.t_, prj_trans); util::apply_visitor(geometry::vertex_processor<apply_vertex_mode>(apply), feature.get_geometry()); } }
void cairo_renderer<T>::process(debug_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { cairo_save_restore guard(context_); debug_symbolizer_mode_enum mode = get<debug_symbolizer_mode_enum>(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); context_.set_operator(src_over); context_.set_color(mapnik::color(255, 0, 0), 1.0); context_.set_line_join(MITER_JOIN); context_.set_line_cap(BUTT_CAP); context_.set_miter_limit(4.0); context_.set_line_width(1.0); if (mode == DEBUG_SYM_MODE_COLLISION) { for (auto & n : *common_.detector_) { render_debug_box(context_, n.get().box); } } else if (mode == DEBUG_SYM_MODE_VERTEX) { using apply_vertex_mode = apply_vertex_mode<cairo_context>; apply_vertex_mode apply(context_, common_.t_, prj_trans); util::apply_visitor(geometry::vertex_processor<apply_vertex_mode>(apply), feature.get_geometry()); } }
void render_building_symbolizer(mapnik::feature_impl const& feature, double height, F1 face_func, F2 frame_func, F3 roof_func) { auto const& geom = feature.get_geometry(); if (geom.is<geometry::polygon<double> >()) { auto const& poly = geom.get<geometry::polygon<double> >(); detail::make_building(poly, height, face_func, frame_func, roof_func); } else if (geom.is<geometry::multi_polygon<double> >()) { auto const& multi_poly = geom.get<geometry::multi_polygon<double> >(); for (auto const& poly : multi_poly) { detail::make_building(poly, height, face_func, frame_func, roof_func); } } }
bool svg_renderer<OutputIterator>::process(rule::symbolizers const& syms, mapnik::feature_impl & feature, proj_transform const& prj_trans) { // svg renderer supports processing of multiple symbolizers. typedef coord_transform<CoordTransform, geometry_type> path_type; bool process_path = false; // process each symbolizer to collect its (path) information. // path information (attributes from line_ and polygon_ symbolizers) // is collected with the path_attributes_ data member. for (symbolizer const& sym : syms) { if (is_path_based(sym)) { process_path = true; } boost::apply_visitor(symbol_dispatch(*this, feature, prj_trans), sym); } if (process_path) { // generate path output for each geometry of the current feature. for(std::size_t i=0; i<feature.num_geometries(); ++i) { geometry_type & geom = feature.get_geometry(i); if(geom.size() > 0) { path_type path(t_, geom, prj_trans); generator_.generate_path(path, path_attributes_); } } // set the previously collected values back to their defaults // for the feature that will be processed next. path_attributes_.reset(); } return true; }
void cairo_renderer<T>::process(line_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_); 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_); color stroke = get<color, keys::stroke>(sym, feature, common_.vars_); value_double stroke_opacity = get<value_double, keys::stroke_opacity>(sym, feature, common_.vars_); line_join_enum stroke_join = get<line_join_enum, keys::stroke_linejoin>(sym, feature, common_.vars_); line_cap_enum stroke_cap = get<line_cap_enum, keys::stroke_linecap>(sym, feature, common_.vars_); value_double miterlimit = get<value_double, keys::stroke_miterlimit>(sym, feature, common_.vars_); value_double width = get<value_double, keys::stroke_width>(sym, feature, common_.vars_); auto dash = get_optional<dash_array>(sym, keys::stroke_dasharray, feature, common_.vars_); cairo_save_restore guard(context_); context_.set_operator(comp_op); context_.set_color(stroke, stroke_opacity); context_.set_line_join(stroke_join); context_.set_line_cap(stroke_cap); context_.set_miter_limit(miterlimit); context_.set_line_width(width * common_.scale_factor_); if (dash) { context_.set_dash(*dash, common_.scale_factor_); } agg::trans_affine tr; auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } box2d<double> clipping_extent = common_.query_extent_; if (clip) { double padding = (double)(common_.query_extent_.width()/common_.width_); double half_stroke = 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_; clipping_extent.pad(padding); } using vertex_converter_type = vertex_converter<clip_line_tag, clip_poly_tag, transform_tag, affine_transform_tag, simplify_tag, smooth_tag, offset_transform_tag>; vertex_converter_type converter(clipping_extent,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) { 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.set<transform_tag>(); // always transform if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset 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, cairo_context>; using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>; apply_vertex_converter_type apply(converter, context_); mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry()); // stroke context_.set_fill_rule(CAIRO_FILL_RULE_WINDING); context_.stroke(); }
void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_); std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); value_bool clip = get<value_bool, keys::clip>(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_); 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); cairo_save_restore guard(context_); context_.set_operator(comp_op); boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance().find(filename,true); if (!marker || !(*marker)) return; unsigned offset_x=0; unsigned offset_y=0; box2d<double> const& clip_box = clipping_extent(common_); pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common_.vars_); if (alignment == LOCAL_ALIGNMENT) { double x0 = 0.0; double y0 = 0.0; if (feature.num_geometries() > 0) { using clipped_geometry_type = agg::conv_clip_polygon<geometry_type>; using path_type = transform_path_adapter<view_transform,clipped_geometry_type>; clipped_geometry_type clipped(feature.get_geometry(0)); clipped.clip_box(clip_box.minx(), clip_box.miny(), clip_box.maxx(), clip_box.maxy()); path_type path(common_.t_, clipped, prj_trans); path.vertex(&x0, &y0); } offset_x = std::abs(clip_box.width() - x0); offset_y = std::abs(clip_box.height() - y0); } if ((*marker)->is_bitmap()) { cairo_pattern pattern(**((*marker)->get_bitmap_data()), opacity); pattern.set_extend(CAIRO_EXTEND_REPEAT); pattern.set_origin(offset_x, offset_y); context_.set_pattern(pattern); } else { mapnik::rasterizer ras; image_ptr image = render_pattern(ras, **marker, image_tr, 1.0); // cairo_pattern pattern(*image, opacity); pattern.set_extend(CAIRO_EXTEND_REPEAT); pattern.set_origin(offset_x, offset_y); context_.set_pattern(pattern); } agg::trans_affine tr; auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } vertex_converter<cairo_context,clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true) converter.set<transform_tag>(); //always transform converter.set<affine_transform_tag>(); if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter for ( geometry_type & geom : feature.paths()) { if (geom.size() > 2) { converter.apply(geom); } } // fill polygon context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); context_.fill(); }
coord<unsigned, 2> offset(Sym const & sym, mapnik::feature_impl const & feature, proj_transform const & prj_trans, renderer_common const & common, box2d<double> const & clip_box) { coord<unsigned, 2> off(0, 0); pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common.vars_); if (alignment == LOCAL_ALIGNMENT) { coord<double, 2> alignment(0, 0); apply_local_alignment apply(common.t_, prj_trans, clip_box, alignment.x, alignment.y); util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature.get_geometry()); off.x = std::abs(clip_box.width() - alignment.x); off.y = std::abs(clip_box.height() - alignment.y); } return off; }
void cairo_renderer<T>::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_); 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_); if (filename.empty()) { return; } std::shared_ptr<mapnik::marker const> marker = marker_cache::instance().find(filename, true); if (marker->is<mapnik::marker_null>()) return; unsigned width = marker->width(); unsigned height = marker->height(); cairo_save_restore guard(context_); context_.set_operator(comp_op); // TODO - re-implement at renderer level like polygon_pattern symbolizer cairo_renderer_process_visitor_l visit(common_, sym, feature, width, height); std::shared_ptr<cairo_pattern> pattern = util::apply_visitor(visit, *marker); context_.set_line_width(height); pattern->set_extend(CAIRO_EXTEND_REPEAT); pattern->set_filter(CAIRO_FILTER_BILINEAR); agg::trans_affine tr; auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } box2d<double> clipping_extent = common_.query_extent_; if (clip) { double padding = (double)(common_.query_extent_.width()/common_.width_); double half_stroke = 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_; clipping_extent.pad(padding); } using rasterizer_type = line_pattern_rasterizer<cairo_context>; rasterizer_type ras(context_, *pattern, width, height); 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(clipping_extent,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 (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset 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_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 agg_renderer<T0,T1>::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); if (filename.empty()) return; std::shared_ptr<mapnik::marker const> marker = marker_cache::instance().find(filename, true); buffer_type & current_buffer = buffers_.top().get(); 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_); 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); common_pattern_process_visitor<polygon_pattern_symbolizer, rasterizer> visitor(*ras_ptr, common_, sym, feature); image_rgba8 image(util::apply_visitor(visitor, *marker)); 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); box2d<double> clip_box = clipping_extent(common_); coord<unsigned, 2> offset(detail::offset(sym, feature, prj_trans, common_, clip_box)); 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 grid_renderer<T>::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); if (filename.empty()) return; std::shared_ptr<mapnik::marker const> mark = marker_cache::instance().find(filename, true); if (mark->is<mapnik::marker_null>()) return; if (!mark->is<mapnik::marker_rgba8>()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } 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_); using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using color_type = typename grid_renderer_base_type::pixfmt_type::color_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(); line_pattern_enum pattern = get<line_pattern_enum, keys::line_pattern>(sym, feature, common_.vars_); std::size_t stroke_width = (pattern == LINE_PATTERN_WARP) ? mark->width() : get<value_double, keys::stroke_width>(sym, feature, common_.vars_); 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> clipping_extent = common_.query_extent_; if (clip) { double pad_per_pixel = static_cast<double>(common_.query_extent_.width()/common_.width_); double pixels = std::ceil(std::max(stroke_width / 2.0 + std::fabs(offset), (std::fabs(offset) * offset_converter_default_threshold))); double padding = pad_per_pixel * pixels * common_.scale_factor_; clipping_extent.pad(padding); } // to avoid the complexity of using an agg pattern filter instead // we create a line_symbolizer in order to fake the pattern line_symbolizer line; put<value_double>(line, keys::stroke_width, value_double(stroke_width)); // TODO: really should pass the offset to the fake line too, but // this wasn't present in the previous version and makes the test // fail - in this case, probably the test should be updated. //put<value_double>(line, keys::offset, value_double(offset)); put<value_double>(line, keys::simplify_tolerance, value_double(simplify_tolerance)); put<value_double>(line, keys::smooth, value_double(smooth)); using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag, affine_transform_tag, simplify_tag,smooth_tag, offset_transform_tag,stroke_tag>; vertex_converter_type converter(clipping_extent,line,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 (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset 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 converter.set<stroke_tag>(); //always stroke using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type,grid_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()); // render id ren.color(color_type(feature.id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void agg_renderer<T0,T1>::process(line_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { color const& col = get<color, keys::stroke>(sym, feature, common_.vars_); unsigned r=col.red(); unsigned g=col.green(); unsigned b=col.blue(); unsigned a=col.alpha(); double gamma = get<value_double, keys::stroke_gamma>(sym, feature, common_.vars_); gamma_method_enum gamma_method = get<gamma_method_enum, keys::stroke_gamma_method>(sym, feature, common_.vars_); ras_ptr->reset(); if (gamma != gamma_ || gamma_method != gamma_method_) { set_gamma_method(ras_ptr, gamma, gamma_method); gamma_method_ = gamma_method; gamma_ = gamma; } agg::rendering_buffer buf(current_buffer_->bytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->row_size()); using color_type = agg::rgba8; using order_type = agg::order_rgba; using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>; using renderer_base = agg::renderer_base<pixfmt_comp_type>; pixfmt_comp_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 renb(pixf); 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_); value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_); value_double width = get<value_double, keys::stroke_width>(sym, feature, common_.vars_); value_double opacity = get<value_double,keys::stroke_opacity>(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_); line_rasterizer_enum rasterizer_e = get<line_rasterizer_enum, keys::line_rasterizer>(sym, feature, common_.vars_); if (clip) { double padding = static_cast<double>(common_.query_extent_.width()/pixmap_.width()); double half_stroke = 0.5 * 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); // debugging //box2d<double> inverse = query_extent_; //inverse.pad(-padding); //draw_geo_extent(inverse,mapnik::color("red")); } if (rasterizer_e == RASTERIZER_FAST) { using renderer_type = agg::renderer_outline_aa<renderer_base>; using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>; agg::line_profile_aa profile(width * common_.scale_factor_, agg::gamma_power(gamma)); renderer_type ren(renb, profile); ren.color(agg::rgba8_pre(r, g, b, int(a * opacity))); rasterizer_type ras(ren); set_join_caps_aa(sym, ras, feature, common_.vars_); 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>(); // optional clip (default: true) converter.set<transform_tag>(); // always transform if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset 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_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()); } else { using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag, affine_transform_tag, simplify_tag, smooth_tag, offset_transform_tag, dash_tag, stroke_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>(); // optional clip (default: true) converter.set<transform_tag>(); // always transform if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset 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 if (has_key(sym, keys::stroke_dasharray)) converter.set<dash_tag>(); converter.set<stroke_tag>(); //always stroke 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()); using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>; renderer_type ren(renb); ren.color(agg::rgba8_pre(r, g, b, int(a * opacity))); agg::scanline_u8 sl; ras_ptr->filling_rule(agg::fill_non_zero); agg::render_scanlines(*ras_ptr, sl, ren); } }
void render_point_symbolizer(point_symbolizer const &sym, mapnik::feature_impl &feature, proj_transform const &prj_trans, RendererType &common, F render_marker) { std::string filename = get<std::string>(sym, keys::file, feature, common.vars_); boost::optional<mapnik::marker_ptr> marker = filename.empty() ? std::make_shared<mapnik::marker>() : marker_cache::instance().find(filename, true); if (marker) { double opacity = get<double>(sym,keys::opacity,feature, common.vars_, 1.0); bool allow_overlap = get<bool>(sym, keys::allow_overlap, feature, common.vars_, false); bool ignore_placement = get<bool>(sym, keys::ignore_placement, feature, common.vars_, false); point_placement_enum placement= get<point_placement_enum>(sym, keys::point_placement_type, feature, common.vars_, CENTROID_POINT_PLACEMENT); box2d<double> const& bbox = (*marker)->bounding_box(); coord2d center = bbox.center(); agg::trans_affine tr; auto image_transform = get_optional<transform_type>(sym, keys::image_transform); if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; box2d<double> label_ext = bbox * recenter_tr * agg::trans_affine_scaling(common.scale_factor_); for (std::size_t i=0; i<feature.num_geometries(); ++i) { geometry_type const& geom = feature.get_geometry(i); double x; double y; double z=0; if (placement == CENTROID_POINT_PLACEMENT) { if (!label::centroid(geom, x, y)) return; } else { if (!label::interior_position(geom ,x, y)) return; } prj_trans.backward(x,y,z); common.t_.forward(&x,&y); label_ext.re_center(x,y); if (allow_overlap || common.detector_->has_placement(label_ext)) { render_marker(pixel_position(x, y), **marker, tr, opacity); if (!ignore_placement) common.detector_->insert(label_ext); } } } }
void agg_renderer<T>::process(building_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { typedef coord_transform<CoordTransform,geometry_type> path_type; typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; typedef agg::renderer_scanline_aa_solid<ren_base> renderer; agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32 pixf(buf); ren_base renb(pixf); color const& fill_ = sym.get_fill(); unsigned r=fill_.red(); unsigned g=fill_.green(); unsigned b=fill_.blue(); unsigned a=fill_.alpha(); renderer ren(renb); agg::scanline_u8 sl; ras_ptr->reset(); ras_ptr->gamma(agg::gamma_power()); double height = 0.0; expression_ptr height_expr = sym.height(); if (height_expr) { value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr); height = result.to_double() * scale_factor_; } for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.size() > 2) { boost::scoped_ptr<geometry_type> frame(new geometry_type(LineString)); boost::scoped_ptr<geometry_type> roof(new geometry_type(Polygon)); std::deque<segment_t> face_segments; double x0 = 0; double y0 = 0; double x,y; geom.rewind(0); for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END; cm = geom.vertex(&x, &y)) { if (cm == SEG_MOVETO) { frame->move_to(x,y); } else if (cm == SEG_LINETO || cm == SEG_CLOSE) { frame->line_to(x,y); face_segments.push_back(segment_t(x0,y0,x,y)); } x0 = x; y0 = y; } std::sort(face_segments.begin(),face_segments.end(), y_order); std::deque<segment_t>::const_iterator itr=face_segments.begin(); std::deque<segment_t>::const_iterator end=face_segments.end(); for (; itr!=end; ++itr) { boost::scoped_ptr<geometry_type> faces(new geometry_type(Polygon)); faces->move_to(itr->get<0>(),itr->get<1>()); faces->line_to(itr->get<2>(),itr->get<3>()); faces->line_to(itr->get<2>(),itr->get<3>() + height); faces->line_to(itr->get<0>(),itr->get<1>() + height); path_type faces_path (t_,*faces,prj_trans); ras_ptr->add_path(faces_path); ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); // frame->move_to(itr->get<0>(),itr->get<1>()); frame->line_to(itr->get<0>(),itr->get<1>()+height); } geom.rewind(0); for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END; cm = geom.vertex(&x, &y)) { if (cm == SEG_MOVETO) { frame->move_to(x,y+height); roof->move_to(x,y+height); } else if (cm == SEG_LINETO || cm == SEG_CLOSE) { frame->line_to(x,y+height); roof->line_to(x,y+height); } } path_type path(t_,*frame,prj_trans); agg::conv_stroke<path_type> stroke(path); stroke.width(scale_factor_); ras_ptr->add_path(stroke); ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); path_type roof_path (t_,*roof,prj_trans); ras_ptr->add_path(roof_path); ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); } } }
void render_point_symbolizer(point_symbolizer const &sym, mapnik::feature_impl &feature, proj_transform const &prj_trans, RendererType &common, F render_marker) { std::string filename = get<std::string,keys::file>(sym,feature, common.vars_); std::shared_ptr<mapnik::marker const> mark = filename.empty() ? std::make_shared<mapnik::marker const>(mapnik::marker_rgba8()) : marker_cache::instance().find(filename, true); if (!mark->is<mapnik::marker_null>()) { value_double opacity = get<value_double,keys::opacity>(sym, feature, common.vars_); value_bool allow_overlap = get<value_bool, keys::allow_overlap>(sym, feature, common.vars_); value_bool ignore_placement = get<value_bool, keys::ignore_placement>(sym, feature, common.vars_); point_placement_enum placement= get<point_placement_enum, keys::point_placement_type>(sym, feature, common.vars_); box2d<double> const& bbox = mark->bounding_box(); coord2d center = bbox.center(); agg::trans_affine tr; auto image_transform = get_optional<transform_type>(sym, keys::image_transform); if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform, common.scale_factor_); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; box2d<double> label_ext = bbox * recenter_tr * agg::trans_affine_scaling(common.scale_factor_); mapnik::geometry::geometry<double> const& geometry = feature.get_geometry(); mapnik::geometry::point<double> pt; geometry::geometry_types type = geometry::geometry_type(geometry); if (placement == CENTROID_POINT_PLACEMENT || type == geometry::geometry_types::Point || type == geometry::geometry_types::MultiPoint) { if (!geometry::centroid(geometry, pt)) return; } else if (type == mapnik::geometry::geometry_types::Polygon) { auto const& poly = mapnik::util::get<geometry::polygon<double> >(geometry); geometry::polygon_vertex_adapter<double> va(poly); if (!label::interior_position(va ,pt.x, pt.y)) return; } else { MAPNIK_LOG_WARN(point_symbolizer) << "TODO: unhandled geometry type for point symbolizer"; return; } double x = pt.x; double y = pt.y; double z = 0; prj_trans.backward(x,y,z); common.t_.forward(&x,&y); label_ext.re_center(x,y); if (allow_overlap || common.detector_->has_placement(label_ext)) { render_marker(pixel_position(x, y), *mark, tr, opacity); if (!ignore_placement) common.detector_->insert(label_ext); } } }
void agg_renderer<T>::process(point_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature); boost::optional<mapnik::marker_ptr> marker; if ( !filename.empty() ) { marker = marker_cache::instance()->find(filename, true); } else { marker.reset(boost::make_shared<mapnik::marker>()); } if (marker) { box2d<double> const& bbox = (*marker)->bounding_box(); coord2d center = bbox.center(); agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_image_transform()); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; box2d<double> label_ext = bbox * recenter_tr; for (unsigned i=0; i<feature.num_geometries(); ++i) { geometry_type const& geom = feature.get_geometry(i); double x; double y; double z=0; if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT) { if (!label::centroid(geom, x, y)) return; } else { if (!label::interior_position(geom ,x, y)) return; } prj_trans.backward(x,y,z); t_.forward(&x,&y); label_ext.re_center(x,y); if (sym.get_allow_overlap() || detector_->has_placement(label_ext)) { render_marker(pixel_position(x, y), **marker, tr, sym.get_opacity(), sym.comp_op()); if (!sym.get_ignore_placement()) detector_->insert(label_ext); } } } }
void grid_renderer<T>::process(line_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using color_type = typename grid_renderer_base_type::pixfmt_type::color_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(); 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> clipping_extent = common_.query_extent_; bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, false); double width = get<value_double>(sym, keys::stroke_width, feature, common_.vars_,1.0); 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); bool has_dash = has_key(sym, keys::stroke_dasharray); if (clip) { double padding = (double)(common_.query_extent_.width()/pixmap_.width()); double half_stroke = 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_; clipping_extent.pad(padding); } using vertex_converter_type = vertex_converter<clip_line_tag, clip_poly_tag, transform_tag, affine_transform_tag, simplify_tag, smooth_tag, offset_transform_tag, dash_tag, stroke_tag>; vertex_converter_type converter(clipping_extent,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (clip) { 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.set<transform_tag>(); // always transform if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset 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 if (has_dash) converter.set<dash_tag>(); converter.set<stroke_tag>(); //always stroke using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, grid_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()); // render id ren.color(color_type(feature.id())); ras_ptr->filling_rule(agg::fill_non_zero); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_); std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); value_bool clip = get<value_bool, keys::clip>(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_); 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); cairo_save_restore guard(context_); context_.set_operator(comp_op); std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(filename,true); if (marker->is<mapnik::marker_null>()) return; unsigned offset_x=0; unsigned offset_y=0; box2d<double> const& clip_box = clipping_extent(common_); pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common_.vars_); if (alignment == LOCAL_ALIGNMENT) { double x0 = 0.0; double y0 = 0.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 = std::abs(clip_box.width() - x0); offset_y = std::abs(clip_box.height() - y0); } util::apply_visitor(cairo_renderer_process_visitor_p(context_, image_tr, offset_x, offset_y, opacity), *marker); agg::trans_affine tr; auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_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>(); //optional clip (default: true) converter.set<transform_tag>(); //always transform converter.set<affine_transform_tag>(); 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, cairo_context>; using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>; apply_vertex_converter_type apply(converter, context_); mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry()); // fill polygon context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); context_.fill(); }
void agg_renderer<T0,T1>::process(dot_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { double width = 0.0; double height = 0.0; bool has_width = has_key(sym,keys::width); bool has_height = has_key(sym,keys::height); if (has_width && has_height) { width = get<double>(sym, keys::width, feature, common_.vars_, 0.0); height = get<double>(sym, keys::height, feature, common_.vars_, 0.0); } else if (has_width) { width = height = get<double>(sym, keys::width, feature, common_.vars_, 0.0); } else if (has_height) { width = height = get<double>(sym, keys::height, feature, common_.vars_, 0.0); } double rx = width/2.0; double ry = height/2.0; double opacity = get<double>(sym, keys::opacity, feature, common_.vars_, 1.0); color const& fill = get<mapnik::color>(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); ras_ptr->reset(); agg::rendering_buffer buf(current_buffer_->bytes(),current_buffer_->width(),current_buffer_->height(),current_buffer_->row_size()); using blender_type = agg::comp_op_adaptor_rgba_pre<agg::rgba8, agg::order_rgba>; using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>; using renderer_base = agg::renderer_base<pixfmt_comp_type>; using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>; pixfmt_comp_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 renb(pixf); renderer_type ren(renb); ren.color(agg::rgba8_pre(fill.red(), fill.green(), fill.blue(), int(fill.alpha() * opacity))); using render_dot_symbolizer_type = detail::render_dot_symbolizer<rasterizer, renderer_type, renderer_common, proj_transform>; render_dot_symbolizer_type apply(rx, ry, *ras_ptr, ren, common_, prj_trans); mapnik::util::apply_visitor(geometry::vertex_processor<render_dot_symbolizer_type>(apply), feature.get_geometry()); }
void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_); if (filename.empty()) return; mapnik::marker const& mark = marker_cache::instance().find(filename, true); if (mark.is<mapnik::marker_null>()) return; if (!mark.is<mapnik::marker_rgba8>()) { MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer"; return; } ras_ptr->reset(); value_bool clip = get<value_bool, keys::clip>(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::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,smooth_tag>; vertex_converter_type converter(common_.query_extent_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true) converter.set<transform_tag>(); //always transform converter.set<affine_transform_tag>(); 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, grid_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()); using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using color_type = typename grid_renderer_base_type::pixfmt_type::color_type; using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>; 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); // render id ren.color(color_type(feature.id())); agg::scanline_bin sl; ras_ptr->filling_rule(agg::fill_even_odd); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }