From 5ca07a26d1f73a88046dad7d6c50db33867dfb44 Mon Sep 17 00:00:00 2001 From: jhollinger2 Date: Sun, 5 Oct 2014 23:43:27 -0400 Subject: [PATCH 1/8] Refactor marker helpers for agg and grid renderer. --- include/mapnik/grid/grid_marker_helpers.hpp | 125 +++-------- include/mapnik/marker_helpers.hpp | 235 ++++++++++++-------- src/agg/process_markers_symbolizer.cpp | 4 +- 3 files changed, 180 insertions(+), 184 deletions(-) diff --git a/include/mapnik/grid/grid_marker_helpers.hpp b/include/mapnik/grid/grid_marker_helpers.hpp index b4d50dc3c..67a2066dc 100644 --- a/include/mapnik/grid/grid_marker_helpers.hpp +++ b/include/mapnik/grid/grid_marker_helpers.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include #include #include @@ -42,7 +43,7 @@ namespace mapnik { template -struct raster_markers_rasterizer_dispatch_grid : mapnik::noncopyable +struct raster_markers_rasterizer_dispatch_grid : public raster_markers_dispatch { using pixfmt_type = typename RendererBase::pixfmt_type; using color_type = typename RendererBase::pixfmt_type::color_type; @@ -56,53 +57,20 @@ struct raster_markers_rasterizer_dispatch_grid : mapnik::noncopyable markers_symbolizer const& sym, Detector & detector, double scale_factor, - mapnik::feature_impl const& feature, + mapnik::feature_impl & feature, attributes const& vars, RendererContext const& renderer_context) - : buf_(std::get<0>(renderer_context)), + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, + feature, vars, false), + buf_(std::get<0>(renderer_context)), pixf_(buf_), renb_(pixf_), ras_(std::get<1>(renderer_context)), - src_(src), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), pixmap_(std::get<2>(renderer_context)), - placed_(false) {} + placed_(false) + {} - template - void add_path(T & path) - { - agg::scanline_bin sl_; - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); - box2d bbox(0,0, src_.width(), src_.height()); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; - markers_placement_finder placement_finder( - placement_method, path, detector_, params); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = marker_trans_; - matrix.rotate(angle); - matrix.translate(x, y); - render_raster_marker(matrix); - if (!placed_) - { - pixmap_.add_feature(feature_); - placed_ = true; - } - } - } - - void render_raster_marker(agg::trans_affine const& marker_tr) + void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) { agg::scanline_bin sl_; double width = src_.width(); @@ -123,6 +91,11 @@ struct raster_markers_rasterizer_dispatch_grid : mapnik::noncopyable RendererType ren(renb_); ren.color(color_type(feature_.id())); agg::render_scanlines(ras_, sl_, ren); + if (!placed_) + { + pixmap_.add_feature(feature_); + placed_ = true; + } } private: @@ -130,20 +103,17 @@ private: pixfmt_type pixf_; RendererBase renb_; RasterizerType & ras_; - image_data_32 const& src_; - agg::trans_affine const& marker_trans_; - markers_symbolizer const& sym_; - Detector & detector_; - double scale_factor_; - mapnik::feature_impl const& feature_; - attributes const& vars_; PixMapType & pixmap_; bool placed_; + + using raster_markers_dispatch::src_; + using raster_markers_dispatch::feature_; + using raster_markers_dispatch::snap_to_pixels_; }; template -struct vector_markers_rasterizer_dispatch_grid : mapnik::noncopyable +struct vector_markers_rasterizer_dispatch_grid : public vector_markers_dispatch { using renderer_base = typename SvgRenderer::renderer_base ; using vertex_source_type = typename SvgRenderer::vertex_source_type ; @@ -161,56 +131,28 @@ struct vector_markers_rasterizer_dispatch_grid : mapnik::noncopyable markers_symbolizer const& sym, Detector & detector, double scale_factor, - mapnik::feature_impl const& feature, + mapnik::feature_impl & feature, attributes const& vars, bool snap_to_pixels, RendererContext const& renderer_context) - : buf_(std::get<0>(renderer_context)), + : vector_markers_dispatch(bbox, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels), + buf_(std::get<0>(renderer_context)), pixf_(buf_), renb_(pixf_), svg_renderer_(path, attrs), ras_(std::get<1>(renderer_context)), - bbox_(bbox), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), pixmap_(std::get<2>(renderer_context)), placed_(false) - { - } + {} - template - void add_path(T & path) + void render_vector_marker(agg::trans_affine & marker_tr, double opacity) { agg::scanline_bin sl_; - marker_placement_enum placement_method = - get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); - coord2d center = bbox_.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; - markers_placement_finder placement_finder( - placement_method, path, detector_, params); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) + svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), marker_tr, opacity, bbox_); + if (!placed_) { - agg::trans_affine matrix = recenter * marker_trans_; - matrix.rotate(angle); - matrix.translate(x, y); - svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, opacity, bbox_); - if (!placed_) - { - pixmap_.add_feature(feature_); - placed_ = true; - } + pixmap_.add_feature(feature_); + placed_ = true; } } @@ -220,15 +162,12 @@ private: renderer_base renb_; SvgRenderer svg_renderer_; RasterizerType & ras_; - box2d const& bbox_; - agg::trans_affine const& marker_trans_; - markers_symbolizer const& sym_; - Detector & detector_; - double scale_factor_; - mapnik::feature_impl const& feature_; - attributes const& vars_; PixMapType & pixmap_; bool placed_; + + using vector_markers_dispatch::bbox_; + using vector_markers_dispatch::feature_; + using vector_markers_dispatch::snap_to_pixels_; }; } diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 63cc35782..60d1b10d6 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -68,34 +68,18 @@ struct clip_poly_tag; using svg_attribute_type = agg::pod_bvector; -template -struct vector_markers_rasterizer_dispatch : mapnik::noncopyable +template +struct vector_markers_dispatch : mapnik::noncopyable { - using renderer_base = typename SvgRenderer::renderer_base ; - using vertex_source_type = typename SvgRenderer::vertex_source_type ; - using attribute_source_type = typename SvgRenderer::attribute_source_type; - using pixfmt_type = typename renderer_base::pixfmt_type ; - - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - - vector_markers_rasterizer_dispatch(vertex_source_type & path, - attribute_source_type const& attrs, - box2d const& bbox, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - : buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - svg_renderer_(path, attrs), - ras_(std::get<1>(renderer_context)), - bbox_(bbox), + vector_markers_dispatch(box2d const& bbox, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + bool snap_to_pixels) + : bbox_(bbox), marker_trans_(marker_trans), sym_(sym), detector_(detector), @@ -103,14 +87,13 @@ struct vector_markers_rasterizer_dispatch : mapnik::noncopyable vars_(vars), scale_factor_(scale_factor), snap_to_pixels_(snap_to_pixels) - { - pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature_, vars_, src_over))); - } + {} + + virtual ~vector_markers_dispatch() {} template void add_path(T & path) { - agg::scanline_u8 sl_; marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); @@ -130,22 +113,13 @@ struct vector_markers_rasterizer_dispatch : mapnik::noncopyable agg::trans_affine matrix = tr; matrix.rotate(angle); matrix.translate(x, y); - if (snap_to_pixels_) - { - // https://github.com/mapnik/mapnik/issues/1316 - matrix.tx = std::floor(matrix.tx + .5); - matrix.ty = std::floor(matrix.ty + .5); - } - svg_renderer_.render(ras_, sl_, renb_, matrix, opacity, bbox_); + render_vector_marker(matrix, opacity); } } -private: - BufferType & buf_; - pixfmt_type pixf_; - renderer_base renb_; - SvgRenderer svg_renderer_; - RasterizerType & ras_; + virtual void render_vector_marker(agg::trans_affine & marker_tr, double opacity) = 0; + +protected: box2d const& bbox_; agg::trans_affine const& marker_trans_; symbolizer_base const& sym_; @@ -156,33 +130,18 @@ private: bool snap_to_pixels_; }; -template -struct raster_markers_rasterizer_dispatch : mapnik::noncopyable +template +struct raster_markers_dispatch : mapnik::noncopyable { - using BufferType = typename std::remove_reference::type>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - - using color_type = agg::rgba8; - using order_type = agg::order_rgba; - using pixel_type = agg::pixel32_type; - using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender - using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; - using renderer_base = agg::renderer_base; - - raster_markers_rasterizer_dispatch(image_data_32 const& src, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - RendererContext const& renderer_context, - bool snap_to_pixels = false) - : buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - ras_(std::get<1>(renderer_context)), - src_(src), + raster_markers_dispatch(image_data_32 const& src, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + bool snap_to_pixels = false) + : src_(src), marker_trans_(marker_trans), sym_(sym), detector_(detector), @@ -190,9 +149,9 @@ struct raster_markers_rasterizer_dispatch : mapnik::noncopyable vars_(vars), scale_factor_(scale_factor), snap_to_pixels_(snap_to_pixels) - { - pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature_, vars_, src_over))); - } + {} + + virtual ~raster_markers_dispatch() {} template void add_path(T & path) @@ -200,12 +159,12 @@ struct raster_markers_rasterizer_dispatch : mapnik::noncopyable marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); - box2d bbox_(0,0, src_.width(),src_.height()); + box2d bbox(0,0, src_.width(), src_.height()); double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; + markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; @@ -218,14 +177,118 @@ struct raster_markers_rasterizer_dispatch : mapnik::noncopyable } } - void render_raster_marker(agg::trans_affine const& marker_tr, - double opacity) + virtual void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) = 0; + +protected: + image_data_32 const& src_; + agg::trans_affine const& marker_trans_; + symbolizer_base const& sym_; + Detector & detector_; + feature_impl & feature_; + attributes const& vars_; + double scale_factor_; + bool snap_to_pixels_; +}; + +template +struct vector_markers_rasterizer_dispatch_agg : public vector_markers_dispatch +{ + using renderer_base = typename SvgRenderer::renderer_base ; + using vertex_source_type = typename SvgRenderer::vertex_source_type ; + using attribute_source_type = typename SvgRenderer::attribute_source_type; + using pixfmt_type = typename renderer_base::pixfmt_type ; + + using BufferType = typename std::tuple_element<0,RendererContext>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + + vector_markers_rasterizer_dispatch_agg(vertex_source_type & path, + attribute_source_type const& attrs, + box2d const& bbox, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) + : vector_markers_dispatch(bbox, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels), + buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + svg_renderer_(path, attrs), + ras_(std::get<1>(renderer_context)) + { + pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature, vars, src_over))); + } + + ~vector_markers_rasterizer_dispatch_agg() {} + + void render_vector_marker(agg::trans_affine & marker_tr, double opacity) + { + agg::scanline_u8 sl_; + + if (snap_to_pixels_) + { + // https://github.com/mapnik/mapnik/issues/1316 + marker_tr.tx = std::floor(marker_tr.tx + .5); + marker_tr.ty = std::floor(marker_tr.ty + .5); + } + svg_renderer_.render(ras_, sl_, renb_, marker_tr, opacity, bbox_); + } + +private: + BufferType & buf_; + pixfmt_type pixf_; + renderer_base renb_; + SvgRenderer svg_renderer_; + RasterizerType & ras_; + + using vector_markers_dispatch::bbox_; + using vector_markers_dispatch::snap_to_pixels_; +}; + +template +struct raster_markers_rasterizer_dispatch_agg : public raster_markers_dispatch +{ + using BufferType = typename std::remove_reference::type>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + + using color_type = agg::rgba8; + using order_type = agg::order_rgba; + using pixel_type = agg::pixel32_type; + using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender + using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; + using renderer_base = agg::renderer_base; + + raster_markers_rasterizer_dispatch_agg(image_data_32 const& src, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + RendererContext const& renderer_context, + bool snap_to_pixels = false) + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, + feature, vars, snap_to_pixels), + buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + ras_(std::get<1>(renderer_context)) + { + pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature, vars, src_over))); + } + + ~raster_markers_rasterizer_dispatch_agg() {} + + void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) { using pixfmt_pre = agg::pixfmt_rgba32_pre; agg::scanline_u8 sl_; - double width = src_.width(); - double height = src_.height(); - if (std::fabs(1.0 - scale_factor_) < 0.001 + double width = this->src_.width(); + double height = this->src_.height(); + if (std::fabs(1.0 - this->scale_factor_) < 0.001 && (std::fabs(1.0 - marker_tr.sx) < agg::affine_epsilon) && (std::fabs(0.0 - marker_tr.shy) < agg::affine_epsilon) && (std::fabs(0.0 - marker_tr.shx) < agg::affine_epsilon) @@ -300,16 +363,10 @@ private: pixfmt_comp_type pixf_; renderer_base renb_; RasterizerType & ras_; - image_data_32 const& src_; - agg::trans_affine const& marker_trans_; - symbolizer_base const& sym_; - Detector & detector_; - feature_impl & feature_; - attributes const& vars_; - double scale_factor_; - bool snap_to_pixels_; -}; + using raster_markers_dispatch::src_; + using raster_markers_dispatch::snap_to_pixels_; +}; void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path); diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 3ac666fd3..78d2e28ea 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -94,8 +94,8 @@ void agg_renderer::process(markers_symbolizer const& sym, auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_); using context_type = decltype(renderer_context); - using vector_dispatch_type = vector_markers_rasterizer_dispatch; - using raster_dispatch_type = raster_markers_rasterizer_dispatch; + using vector_dispatch_type = vector_markers_rasterizer_dispatch_agg; + using raster_dispatch_type = raster_markers_rasterizer_dispatch_agg; render_markers_symbolizer( sym, feature, prj_trans, common_, clip_box, renderer_context); From 1b15e53b63db601536a7be0642e3b2e22cd0b628 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Mon, 6 Oct 2014 19:05:19 -0400 Subject: [PATCH 2/8] Refactor markers dispatchers to use a common base class to share code. --- include/mapnik/agg_render_marker.hpp | 148 +++++++++++ include/mapnik/cairo/cairo_render_vector.hpp | 8 +- include/mapnik/grid/grid_marker_helpers.hpp | 174 ------------- include/mapnik/grid/grid_render_marker.hpp | 72 ++++++ include/mapnik/marker_helpers.hpp | 229 ++---------------- .../process_markers_symbolizer.hpp | 25 +- src/agg/process_markers_symbolizer.cpp | 106 +++++++- src/cairo/cairo_render_vector.cpp | 17 +- src/cairo/cairo_renderer.cpp | 13 +- src/cairo/process_markers_symbolizer.cpp | 162 ++++--------- src/grid/process_markers_symbolizer.cpp | 124 +++++++++- src/marker_helpers.cpp | 3 + 12 files changed, 536 insertions(+), 545 deletions(-) create mode 100644 include/mapnik/agg_render_marker.hpp delete mode 100644 include/mapnik/grid/grid_marker_helpers.hpp create mode 100644 include/mapnik/grid/grid_render_marker.hpp diff --git a/include/mapnik/agg_render_marker.hpp b/include/mapnik/agg_render_marker.hpp new file mode 100644 index 000000000..2da965b73 --- /dev/null +++ b/include/mapnik/agg_render_marker.hpp @@ -0,0 +1,148 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// agg +#include "agg_color_rgba.h" +#include "agg_renderer_base.h" +#include "agg_renderer_scanline.h" +#include "agg_rendering_buffer.h" +#include "agg_scanline_u.h" +#include "agg_image_filters.h" +#include "agg_trans_affine.h" +#include "agg_span_allocator.h" +#include "agg_image_accessors.h" +#include "agg_pixfmt_rgba.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_span_interpolator_linear.h" + +namespace mapnik { + +template +void render_vector_marker(SvgRenderer & svg_renderer, RasterizerType & ras, RendererBaseType & renb, + box2d const& bbox, agg::trans_affine const& tr, + double opacity, bool snap_to_pixels) +{ + agg::scanline_u8 sl; + if (snap_to_pixels) + { + // https://github.com/mapnik/mapnik/issues/1316 + agg::trans_affine snap_tr = tr; + snap_tr.tx = std::floor(snap_tr.tx + .5); + snap_tr.ty = std::floor(snap_tr.ty + .5); + svg_renderer.render(ras, sl, renb, snap_tr, opacity, bbox); + } + else + { + svg_renderer.render(ras, sl, renb, tr, opacity, bbox); + } +} + +template +void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_32 & src, + agg::trans_affine const& tr, double opacity, + float scale_factor, bool snap_to_pixels) +{ + using color_type = agg::rgba8; + using pixfmt_pre = agg::pixfmt_rgba32_pre; + agg::scanline_u8 sl; + double width = src.width(); + double height = src.height(); + if (std::fabs(1.0 - scale_factor) < 0.001 + && (std::fabs(1.0 - tr.sx) < agg::affine_epsilon) + && (std::fabs(0.0 - tr.shy) < agg::affine_epsilon) + && (std::fabs(0.0 - tr.shx) < agg::affine_epsilon) + && (std::fabs(1.0 - tr.sy) < agg::affine_epsilon)) + { + agg::rendering_buffer src_buffer((unsigned char *)src.getBytes(),src.width(),src.height(),src.width() * 4); + pixfmt_pre pixf_mask(src_buffer); + if (snap_to_pixels) + { + renb.blend_from(pixf_mask, + 0, + std::floor(tr.tx + .5), + std::floor(tr.ty + .5), + unsigned(255*opacity)); + } + else + { + renb.blend_from(pixf_mask, + 0, + tr.tx, + tr.ty, + unsigned(255*opacity)); + } + } + else + { + using img_accessor_type = agg::image_accessor_clone; + using interpolator_type = agg::span_interpolator_linear<>; + //using span_gen_type = agg::span_image_filter_rgba_2x2; + using span_gen_type = agg::span_image_resample_rgba_affine; + using renderer_type = agg::renderer_scanline_aa_alpha, + span_gen_type>; + + double p[8]; + p[0] = 0; p[1] = 0; + p[2] = width; p[3] = 0; + p[4] = width; p[5] = height; + p[6] = 0; p[7] = height; + tr.transform(&p[0], &p[1]); + tr.transform(&p[2], &p[3]); + tr.transform(&p[4], &p[5]); + tr.transform(&p[6], &p[7]); + agg::span_allocator sa; + agg::image_filter_lut filter; + filter.calculate(agg::image_filter_bilinear(), true); + agg::rendering_buffer marker_buf((unsigned char *)src.getBytes(), + src.width(), + src.height(), + src.width()*4); + pixfmt_pre pixf(marker_buf); + img_accessor_type ia(pixf); + agg::trans_affine final_tr(p, 0, 0, width, height); + if (snap_to_pixels) + { + final_tr.tx = std::floor(final_tr.tx+.5); + final_tr.ty = std::floor(final_tr.ty+.5); + } + interpolator_type interpolator(final_tr); + span_gen_type sg(ia, interpolator, filter); + renderer_type rp(renb, sa, sg, unsigned(opacity*255)); + ras.move_to_d(p[0],p[1]); + ras.line_to_d(p[2],p[3]); + ras.line_to_d(p[4],p[5]); + ras.line_to_d(p[6],p[7]); + agg::render_scanlines(ras, sl, rp); + } +} + +} diff --git a/include/mapnik/cairo/cairo_render_vector.hpp b/include/mapnik/cairo/cairo_render_vector.hpp index 3016fad35..6141be191 100644 --- a/include/mapnik/cairo/cairo_render_vector.hpp +++ b/include/mapnik/cairo/cairo_render_vector.hpp @@ -37,13 +37,13 @@ struct pixel_position; template class box2d; namespace svg { struct path_attributes; } -void render_vector_marker(cairo_context & context, pixel_position const& pos, - svg::svg_path_adapter & svg_path, box2d const& bbox, +void render_vector_marker(cairo_context & context, svg::svg_path_adapter & svg_path, agg::pod_bvector const & attributes, - agg::trans_affine const& tr, double opacity, bool recenter); + box2d const& bbox, agg::trans_affine const& tr, + double opacity); } #endif // MAPNIK_CAIRO_RENDER_VECTOR_HPP -#endif \ No newline at end of file +#endif diff --git a/include/mapnik/grid/grid_marker_helpers.hpp b/include/mapnik/grid/grid_marker_helpers.hpp deleted file mode 100644 index 67a2066dc..000000000 --- a/include/mapnik/grid/grid_marker_helpers.hpp +++ /dev/null @@ -1,174 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2012 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_GRID_MARKER_HELPERS_HPP -#define MAPNIK_GRID_MARKER_HELPERS_HPP - -// mapnik -#include -#include -#include -#include -#include - -// agg -#include "agg_renderer_scanline.h" -#include "agg_scanline_bin.h" -#include "agg_image_filters.h" -#include "agg_trans_bilinear.h" -#include "agg_span_allocator.h" -#include "agg_image_accessors.h" -#include "agg_span_image_filter_gray.h" - - -namespace mapnik { - -template -struct raster_markers_rasterizer_dispatch_grid : public raster_markers_dispatch -{ - using pixfmt_type = typename RendererBase::pixfmt_type; - using color_type = typename RendererBase::pixfmt_type::color_type; - - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - using PixMapType = typename std::tuple_element<2,RendererContext>::type; - - raster_markers_rasterizer_dispatch_grid(image_data_32 const& src, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - mapnik::feature_impl & feature, - attributes const& vars, - RendererContext const& renderer_context) - : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, - feature, vars, false), - buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - ras_(std::get<1>(renderer_context)), - pixmap_(std::get<2>(renderer_context)), - placed_(false) - {} - - void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) - { - agg::scanline_bin sl_; - double width = src_.width(); - double height = src_.height(); - double p[8]; - p[0] = 0; p[1] = 0; - p[2] = width; p[3] = 0; - p[4] = width; p[5] = height; - p[6] = 0; p[7] = height; - marker_tr.transform(&p[0], &p[1]); - marker_tr.transform(&p[2], &p[3]); - marker_tr.transform(&p[4], &p[5]); - marker_tr.transform(&p[6], &p[7]); - ras_.move_to_d(p[0],p[1]); - ras_.line_to_d(p[2],p[3]); - ras_.line_to_d(p[4],p[5]); - ras_.line_to_d(p[6],p[7]); - RendererType ren(renb_); - ren.color(color_type(feature_.id())); - agg::render_scanlines(ras_, sl_, ren); - if (!placed_) - { - pixmap_.add_feature(feature_); - placed_ = true; - } - } - -private: - BufferType & buf_; - pixfmt_type pixf_; - RendererBase renb_; - RasterizerType & ras_; - PixMapType & pixmap_; - bool placed_; - - using raster_markers_dispatch::src_; - using raster_markers_dispatch::feature_; - using raster_markers_dispatch::snap_to_pixels_; -}; - - -template -struct vector_markers_rasterizer_dispatch_grid : public vector_markers_dispatch -{ - using renderer_base = typename SvgRenderer::renderer_base ; - using vertex_source_type = typename SvgRenderer::vertex_source_type ; - using attribute_source_type = typename SvgRenderer::attribute_source_type; - using pixfmt_type = typename renderer_base::pixfmt_type ; - - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - using PixMapType = typename std::tuple_element<2,RendererContext>::type; - - vector_markers_rasterizer_dispatch_grid(vertex_source_type & path, - attribute_source_type const& attrs, - box2d const& bbox, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - mapnik::feature_impl & feature, - attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - : vector_markers_dispatch(bbox, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels), - buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - svg_renderer_(path, attrs), - ras_(std::get<1>(renderer_context)), - pixmap_(std::get<2>(renderer_context)), - placed_(false) - {} - - void render_vector_marker(agg::trans_affine & marker_tr, double opacity) - { - agg::scanline_bin sl_; - svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), marker_tr, opacity, bbox_); - if (!placed_) - { - pixmap_.add_feature(feature_); - placed_ = true; - } - } - -private: - BufferType & buf_; - pixfmt_type pixf_; - renderer_base renb_; - SvgRenderer svg_renderer_; - RasterizerType & ras_; - PixMapType & pixmap_; - bool placed_; - - using vector_markers_dispatch::bbox_; - using vector_markers_dispatch::feature_; - using vector_markers_dispatch::snap_to_pixels_; -}; - -} -#endif diff --git a/include/mapnik/grid/grid_render_marker.hpp b/include/mapnik/grid/grid_render_marker.hpp new file mode 100644 index 000000000..bbf0b90f8 --- /dev/null +++ b/include/mapnik/grid/grid_render_marker.hpp @@ -0,0 +1,72 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_GRID_MARKER_HELPERS_HPP +#define MAPNIK_GRID_MARKER_HELPERS_HPP + +// mapnik +#include + +// agg +#include "agg_renderer_scanline.h" +#include "agg_scanline_bin.h" +#include "agg_image_filters.h" +#include "agg_trans_bilinear.h" +#include "agg_span_allocator.h" +#include "agg_image_accessors.h" +#include "agg_span_image_filter_gray.h" + + +namespace mapnik { + +template +void render_raster_marker(RendererType ren, + RasterizerType & ras, + image_data_32 & src, + mapnik::feature_impl const& feature, + agg::trans_affine const& marker_tr, + double opacity) +{ + using color_type = typename RendererType::color_type; + agg::scanline_bin sl; + double width = src.width(); + double height = src.height(); + double p[8]; + p[0] = 0; p[1] = 0; + p[2] = width; p[3] = 0; + p[4] = width; p[5] = height; + p[6] = 0; p[7] = height; + marker_tr.transform(&p[0], &p[1]); + marker_tr.transform(&p[2], &p[3]); + marker_tr.transform(&p[4], &p[5]); + marker_tr.transform(&p[6], &p[7]); + ras.move_to_d(p[0],p[1]); + ras.line_to_d(p[2],p[3]); + ras.line_to_d(p[4],p[5]); + ras.line_to_d(p[6],p[7]); + ren.color(color_type(feature.id())); + agg::render_scanlines(ras, sl, ren); +} + +} + +#endif diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 60d1b10d6..f62c5eb02 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -40,19 +40,7 @@ #include // agg -#include "agg_ellipse.h" -#include "agg_color_rgba.h" -#include "agg_renderer_base.h" -#include "agg_renderer_scanline.h" -#include "agg_rendering_buffer.h" -#include "agg_scanline_u.h" -#include "agg_image_filters.h" #include "agg_trans_affine.h" -#include "agg_span_allocator.h" -#include "agg_image_accessors.h" -#include "agg_pixfmt_rgba.h" -#include "agg_span_image_filter_rgba.h" -#include "agg_span_interpolator_linear.h" // boost #include @@ -71,22 +59,20 @@ using svg_attribute_type = agg::pod_bvector; template struct vector_markers_dispatch : mapnik::noncopyable { - vector_markers_dispatch(box2d const& bbox, + vector_markers_dispatch(svg_path_ptr const& src, agg::trans_affine const& marker_trans, symbolizer_base const& sym, Detector & detector, double scale_factor, feature_impl & feature, - attributes const& vars, - bool snap_to_pixels) - : bbox_(bbox), + attributes const& vars) + : src_(src), marker_trans_(marker_trans), sym_(sym), detector_(detector), feature_(feature), vars_(vars), - scale_factor_(scale_factor), - snap_to_pixels_(snap_to_pixels) + scale_factor_(scale_factor) {} virtual ~vector_markers_dispatch() {} @@ -101,10 +87,11 @@ struct vector_markers_dispatch : mapnik::noncopyable double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - coord2d center = bbox_.center(); + box2d const& bbox = src_->bounding_box(); + coord2d center = bbox.center(); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine tr = recenter * marker_trans_; - markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; + markers_placement_params params { bbox, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; @@ -113,42 +100,39 @@ struct vector_markers_dispatch : mapnik::noncopyable agg::trans_affine matrix = tr; matrix.rotate(angle); matrix.translate(x, y); - render_vector_marker(matrix, opacity); + render_marker(matrix, opacity); } } - virtual void render_vector_marker(agg::trans_affine & marker_tr, double opacity) = 0; + virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0; protected: - box2d const& bbox_; + svg_path_ptr const& src_; agg::trans_affine const& marker_trans_; symbolizer_base const& sym_; Detector & detector_; feature_impl & feature_; attributes const& vars_; double scale_factor_; - bool snap_to_pixels_; }; template struct raster_markers_dispatch : mapnik::noncopyable { - raster_markers_dispatch(image_data_32 const& src, + raster_markers_dispatch(image_data_32 & src, agg::trans_affine const& marker_trans, symbolizer_base const& sym, Detector & detector, double scale_factor, feature_impl & feature, - attributes const& vars, - bool snap_to_pixels = false) + attributes const& vars) : src_(src), marker_trans_(marker_trans), sym_(sym), detector_(detector), feature_(feature), vars_(vars), - scale_factor_(scale_factor), - snap_to_pixels_(snap_to_pixels) + scale_factor_(scale_factor) {} virtual ~raster_markers_dispatch() {} @@ -159,11 +143,11 @@ struct raster_markers_dispatch : mapnik::noncopyable marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); - box2d bbox(0,0, src_.width(), src_.height()); double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + box2d bbox(0,0, src_.width(), src_.height()); markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); @@ -173,199 +157,20 @@ struct raster_markers_dispatch : mapnik::noncopyable agg::trans_affine matrix = marker_trans_; matrix.rotate(angle); matrix.translate(x, y); - render_raster_marker(matrix, opacity); + render_marker(matrix, opacity); } } - virtual void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) = 0; + virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0; protected: - image_data_32 const& src_; + image_data_32 & src_; agg::trans_affine const& marker_trans_; symbolizer_base const& sym_; Detector & detector_; feature_impl & feature_; attributes const& vars_; double scale_factor_; - bool snap_to_pixels_; -}; - -template -struct vector_markers_rasterizer_dispatch_agg : public vector_markers_dispatch -{ - using renderer_base = typename SvgRenderer::renderer_base ; - using vertex_source_type = typename SvgRenderer::vertex_source_type ; - using attribute_source_type = typename SvgRenderer::attribute_source_type; - using pixfmt_type = typename renderer_base::pixfmt_type ; - - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - - vector_markers_rasterizer_dispatch_agg(vertex_source_type & path, - attribute_source_type const& attrs, - box2d const& bbox, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - : vector_markers_dispatch(bbox, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels), - buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - svg_renderer_(path, attrs), - ras_(std::get<1>(renderer_context)) - { - pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature, vars, src_over))); - } - - ~vector_markers_rasterizer_dispatch_agg() {} - - void render_vector_marker(agg::trans_affine & marker_tr, double opacity) - { - agg::scanline_u8 sl_; - - if (snap_to_pixels_) - { - // https://github.com/mapnik/mapnik/issues/1316 - marker_tr.tx = std::floor(marker_tr.tx + .5); - marker_tr.ty = std::floor(marker_tr.ty + .5); - } - svg_renderer_.render(ras_, sl_, renb_, marker_tr, opacity, bbox_); - } - -private: - BufferType & buf_; - pixfmt_type pixf_; - renderer_base renb_; - SvgRenderer svg_renderer_; - RasterizerType & ras_; - - using vector_markers_dispatch::bbox_; - using vector_markers_dispatch::snap_to_pixels_; -}; - -template -struct raster_markers_rasterizer_dispatch_agg : public raster_markers_dispatch -{ - using BufferType = typename std::remove_reference::type>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - - using color_type = agg::rgba8; - using order_type = agg::order_rgba; - using pixel_type = agg::pixel32_type; - using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender - using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; - using renderer_base = agg::renderer_base; - - raster_markers_rasterizer_dispatch_agg(image_data_32 const& src, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - RendererContext const& renderer_context, - bool snap_to_pixels = false) - : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, - feature, vars, snap_to_pixels), - buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - ras_(std::get<1>(renderer_context)) - { - pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature, vars, src_over))); - } - - ~raster_markers_rasterizer_dispatch_agg() {} - - void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) - { - using pixfmt_pre = agg::pixfmt_rgba32_pre; - agg::scanline_u8 sl_; - double width = this->src_.width(); - double height = this->src_.height(); - if (std::fabs(1.0 - this->scale_factor_) < 0.001 - && (std::fabs(1.0 - marker_tr.sx) < agg::affine_epsilon) - && (std::fabs(0.0 - marker_tr.shy) < agg::affine_epsilon) - && (std::fabs(0.0 - marker_tr.shx) < agg::affine_epsilon) - && (std::fabs(1.0 - marker_tr.sy) < agg::affine_epsilon)) - { - agg::rendering_buffer src_buffer((unsigned char *)src_.getBytes(),src_.width(),src_.height(),src_.width() * 4); - pixfmt_pre pixf_mask(src_buffer); - if (snap_to_pixels_) - { - renb_.blend_from(pixf_mask, - 0, - std::floor(marker_tr.tx + .5), - std::floor(marker_tr.ty + .5), - unsigned(255*opacity)); - } - else - { - renb_.blend_from(pixf_mask, - 0, - marker_tr.tx, - marker_tr.ty, - unsigned(255*opacity)); - } - } - else - { - using img_accessor_type = agg::image_accessor_clone; - using interpolator_type = agg::span_interpolator_linear<>; - //using span_gen_type = agg::span_image_filter_rgba_2x2; - using span_gen_type = agg::span_image_resample_rgba_affine; - using renderer_type = agg::renderer_scanline_aa_alpha, - span_gen_type>; - - double p[8]; - p[0] = 0; p[1] = 0; - p[2] = width; p[3] = 0; - p[4] = width; p[5] = height; - p[6] = 0; p[7] = height; - marker_tr.transform(&p[0], &p[1]); - marker_tr.transform(&p[2], &p[3]); - marker_tr.transform(&p[4], &p[5]); - marker_tr.transform(&p[6], &p[7]); - agg::span_allocator sa; - agg::image_filter_lut filter; - filter.calculate(agg::image_filter_bilinear(), true); - agg::rendering_buffer marker_buf((unsigned char *)src_.getBytes(), - src_.width(), - src_.height(), - src_.width()*4); - pixfmt_pre pixf(marker_buf); - img_accessor_type ia(pixf); - agg::trans_affine final_tr(p, 0, 0, width, height); - if (snap_to_pixels_) - { - final_tr.tx = std::floor(final_tr.tx+.5); - final_tr.ty = std::floor(final_tr.ty+.5); - } - interpolator_type interpolator(final_tr); - span_gen_type sg(ia, interpolator, filter); - renderer_type rp(renb_,sa, sg, unsigned(opacity*255)); - ras_.move_to_d(p[0],p[1]); - ras_.line_to_d(p[2],p[3]); - ras_.line_to_d(p[4],p[5]); - ras_.line_to_d(p[6],p[7]); - agg::render_scanlines(ras_, sl_, rp); - } - } - -private: - BufferType & buf_; - pixfmt_comp_type pixf_; - renderer_base renb_; - RasterizerType & ras_; - - using raster_markers_dispatch::src_; - using raster_markers_dispatch::snap_to_pixels_; }; void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path); diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp index 6bb1ccdd4..a8c3761c2 100644 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_markers_symbolizer.hpp @@ -32,17 +32,17 @@ namespace mapnik { -template +template void render_markers_symbolizer(markers_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans, - renderer_common const& common, + RendererType const& common, box2d const& clip_box, - T2 const& renderer_context) + ContextType const& renderer_context) { using namespace mapnik::svg; - using vector_dispatch_type = T0; - using raster_dispatch_type = T1; + using vector_dispatch_type = VD; + using raster_dispatch_type = RD; std::string filename = get(sym, keys::file, feature, common.vars_, "shape://ellipse"); bool clip = get(sym, keys::clip, feature, common.vars_, false); @@ -71,18 +71,17 @@ void render_markers_symbolizer(markers_symbolizer const& sym, if (filename == "shape://ellipse" && (has_key(sym,keys::width) || has_key(sym,keys::height))) { - svg_storage_type marker_ellipse; - vertex_stl_adapter stl_storage(marker_ellipse.source()); + svg_path_ptr marker_ellipse = std::make_shared(); + vertex_stl_adapter stl_storage(marker_ellipse->source()); svg_path_adapter svg_path(stl_storage); - build_ellipse(sym, feature, common.vars_, marker_ellipse, svg_path); + 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(sym, keys::image_transform); if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform); - box2d bbox = marker_ellipse.bounding_box(); - vector_dispatch_type rasterizer_dispatch(svg_path, + vector_dispatch_type rasterizer_dispatch(marker_ellipse, + svg_path, result ? attributes : (*stock_vector_marker)->attributes(), - bbox, image_tr, sym, *common.detector_, @@ -124,9 +123,9 @@ void render_markers_symbolizer(markers_symbolizer const& sym, 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(svg_path, + vector_dispatch_type rasterizer_dispatch(*stock_vector_marker, + svg_path, result ? attributes : (*stock_vector_marker)->attributes(), - bbox, image_tr, sym, *common.detector_, diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 78d2e28ea..22c674699 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,107 @@ namespace mapnik { +namespace detail { + +template +struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch +{ + using renderer_base = typename SvgRenderer::renderer_base; + using vertex_source_type = typename SvgRenderer::vertex_source_type; + using attribute_source_type = typename SvgRenderer::attribute_source_type; + using pixfmt_type = typename renderer_base::pixfmt_type; + + using BufferType = typename std::tuple_element<0,RendererContext>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + + vector_markers_rasterizer_dispatch(svg_path_ptr const& src, + vertex_source_type & path, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) +: vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), + buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + svg_renderer_(path, attrs), + ras_(std::get<1>(renderer_context)), + snap_to_pixels_(snap_to_pixels) + { + pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature, vars, src_over))); + } + + ~vector_markers_rasterizer_dispatch() {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) + { + render_vector_marker(svg_renderer_, ras_, renb_, this->src_->bounding_box(), + marker_tr, opacity, snap_to_pixels_); + } + +private: + BufferType & buf_; + pixfmt_type pixf_; + renderer_base renb_; + SvgRenderer svg_renderer_; + RasterizerType & ras_; + bool snap_to_pixels_; +}; + +template +struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch +{ + using BufferType = typename std::remove_reference::type>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + + using color_type = agg::rgba8; + using order_type = agg::order_rgba; + using pixel_type = agg::pixel32_type; + using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender + using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; + using renderer_base = agg::renderer_base; + + raster_markers_rasterizer_dispatch(image_data_32 & src, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + RendererContext const& renderer_context, + bool snap_to_pixels = false) + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), + buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + ras_(std::get<1>(renderer_context)), + snap_to_pixels_(snap_to_pixels) + { + pixf_.comp_op(static_cast(get(sym, keys::comp_op, feature, vars, src_over))); + } + + ~raster_markers_rasterizer_dispatch() {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) + { + render_raster_marker(renb_, ras_, this->src_, marker_tr, opacity, this->scale_factor_, snap_to_pixels_); + } + +private: + BufferType & buf_; + pixfmt_comp_type pixf_; + renderer_base renb_; + RasterizerType & ras_; + bool snap_to_pixels_; +}; + +} + template void agg_renderer::process(markers_symbolizer const& sym, feature_impl & feature, @@ -94,8 +196,8 @@ void agg_renderer::process(markers_symbolizer const& sym, auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_); using context_type = decltype(renderer_context); - using vector_dispatch_type = vector_markers_rasterizer_dispatch_agg; - using raster_dispatch_type = raster_markers_rasterizer_dispatch_agg; + using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch; + using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch; render_markers_symbolizer( sym, feature, prj_trans, common_, clip_box, renderer_context); diff --git a/src/cairo/cairo_render_vector.cpp b/src/cairo/cairo_render_vector.cpp index 31a24f33d..cfe86d6a4 100644 --- a/src/cairo/cairo_render_vector.cpp +++ b/src/cairo/cairo_render_vector.cpp @@ -32,21 +32,12 @@ namespace mapnik { -void render_vector_marker(cairo_context & context, pixel_position const& pos, - svg::svg_path_adapter & svg_path, box2d const& bbox, +void render_vector_marker(cairo_context & context, svg::svg_path_adapter & svg_path, agg::pod_bvector const & attributes, - agg::trans_affine const& tr, double opacity, bool recenter) + box2d const& bbox, agg::trans_affine const& tr, + double opacity) { using namespace mapnik::svg; - agg::trans_affine mtx = tr; - if (recenter) - { - coord c = bbox.center(); - mtx = agg::trans_affine_translation(-c.x,-c.y); - mtx *= tr; - mtx.translate(pos.x, pos.y); - } - agg::trans_affine transform; for(unsigned i = 0; i < attributes.size(); ++i) @@ -56,7 +47,7 @@ void render_vector_marker(cairo_context & context, pixel_position const& pos, continue; cairo_save_restore guard(context); transform = attr.transform; - transform *= mtx; + transform *= tr; // TODO - this 'is_valid' check is not used in the AGG renderer and also // appears to lead to bogus results with diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index 088c314c8..7f20f2b28 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -201,13 +201,20 @@ void cairo_renderer::render_marker(pixel_position const& pos, mapnik::svg_path_ptr vmarker = *marker.get_vector_data(); if (vmarker) { - agg::trans_affine marker_tr = tr; - marker_tr *=agg::trans_affine_scaling(common_.scale_factor_); box2d bbox = vmarker->bounding_box(); + agg::trans_affine marker_tr = tr; + if (recenter) + { + coord 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 const & attributes = vmarker->attributes(); svg::vertex_stl_adapter stl_storage(vmarker->source()); svg::svg_path_adapter svg_path(stl_storage); - render_vector_marker(context_, pos, svg_path, bbox, attributes, marker_tr, opacity, recenter); + marker_tr.translate(pos.x, pos.y); + render_vector_marker(context_, svg_path, attributes, bbox, marker_tr, opacity); } } else if (marker.is_bitmap()) diff --git a/src/cairo/process_markers_symbolizer.cpp b/src/cairo/process_markers_symbolizer.cpp index 6f3464577..22e4f80d0 100644 --- a/src/cairo/process_markers_symbolizer.cpp +++ b/src/cairo/process_markers_symbolizer.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include // agg @@ -43,135 +44,67 @@ namespace mapnik class feature_impl; class proj_transform; -namespace svg { struct path_attributes; } namespace detail { -template -struct markers_dispatch : mapnik::noncopyable +template +struct vector_markers_dispatch_cairo : public vector_markers_dispatch { - markers_dispatch(SvgPath & marker, - Attributes const& attributes, - box2d const& bbox, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl const& feature, - mapnik::attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - :marker_(marker), - attributes_(attributes), - bbox_(bbox), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), + vector_markers_dispatch_cairo(svg_path_ptr const& src, + svg::svg_path_adapter & path, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + mapnik::attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) + : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), + path_(path), + attr_(attrs), ctx_(std::get<0>(renderer_context)) {} - - template - void add_path(T & path) + void render_marker(agg::trans_affine const& marker_tr, double opacity) { - marker_placement_enum placement_method = get( - sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); - double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - coord2d center = bbox_.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine tr = recenter * marker_trans_; - markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; - markers_placement_finder placement_finder( - placement_method, path, detector_, params); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = tr; - matrix.rotate(angle); - matrix.translate(x, y); - render_vector_marker( - ctx_, - pixel_position(x, y), - marker_, - bbox_, - attributes_, - matrix, - opacity, - false); - } + render_vector_marker(ctx_, + path_, + attr_, + this->src_->bounding_box(), + marker_tr, + opacity); } - SvgPath & marker_; - Attributes const& attributes_; - box2d const& bbox_; - agg::trans_affine const& marker_trans_; - markers_symbolizer const& sym_; - Detector & detector_; - double scale_factor_; - feature_impl const& feature_; - attributes const& vars_; +private: + svg::svg_path_adapter & path_; + svg_attribute_type const& attr_; cairo_context & ctx_; }; template -struct raster_markers_dispatch : mapnik::noncopyable +struct raster_markers_dispatch_cairo : public raster_markers_dispatch { - raster_markers_dispatch(mapnik::image_data_32 & src, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl const& feature, - mapnik::attributes const& vars, - RendererContext const& renderer_context) - : src_(src), - detector_(detector), - sym_(sym), - marker_trans_(marker_trans), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), + raster_markers_dispatch_cairo(mapnik::image_data_32 & src, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + mapnik::attributes const& vars, + RendererContext const& renderer_context) + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), ctx_(std::get<0>(renderer_context)) {} - template - void add_path(T & path) + ~raster_markers_dispatch_cairo() {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - box2d bbox_(0,0, src_.width(),src_.height()); - markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; - markers_placement_finder placement_finder( - placement_method, path, detector_, params); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = marker_trans_; - matrix.rotate(angle); - matrix.translate(x, y); - ctx_.add_image(matrix, src_, opacity); - } + ctx_.add_image(marker_tr, this->src_, opacity); } - image_data_32 & src_; - Detector & detector_; - markers_symbolizer const& sym_; - agg::trans_affine const& marker_trans_; - double scale_factor_; - feature_impl const& feature_; - attributes const& vars_; +private: cairo_context & ctx_; }; @@ -182,8 +115,6 @@ void cairo_renderer::process(markers_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - using svg_attribute_type = agg::pod_bvector; - cairo_save_restore guard(context_); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); context_.set_operator(comp_op); @@ -192,12 +123,11 @@ void cairo_renderer::process(markers_symbolizer const& sym, auto renderer_context = std::tie(context_); using RendererContextType = decltype(renderer_context); - using vector_dispatch_type = detail::markers_dispatch >, - svg_attribute_type,label_collision_detector4>; + using vector_dispatch_type = detail::vector_markers_dispatch_cairo; - using raster_dispatch_type = detail::raster_markers_dispatch; + using raster_dispatch_type = detail::raster_markers_dispatch_cairo; render_markers_symbolizer( diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index bf0828cd4..99e6a2989 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -45,11 +45,14 @@ porting notes --> // mapnik #include +#include +#include +#include #include #include #include +#include #include -#include #include #include @@ -77,6 +80,111 @@ porting notes --> namespace mapnik { +namespace detail { + +template +struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch +{ + using renderer_base = typename SvgRenderer::renderer_base; + using vertex_source_type = typename SvgRenderer::vertex_source_type; + using attribute_source_type = typename SvgRenderer::attribute_source_type; + using pixfmt_type = typename renderer_base::pixfmt_type; + + using BufferType = typename std::tuple_element<0,RendererContext>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + using PixMapType = typename std::tuple_element<2,RendererContext>::type; + + vector_markers_rasterizer_dispatch(svg_path_ptr const& src, + vertex_source_type & path, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + mapnik::feature_impl & feature, + attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) + : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels), + buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + svg_renderer_(path, attrs), + ras_(std::get<1>(renderer_context)), + pixmap_(std::get<2>(renderer_context)), + placed_(false) + {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) + { + agg::scanline_bin sl_; + svg_renderer_.render_id(ras_, sl_, renb_, this->feature_.id(), marker_tr, opacity, this->src_->bounding_box()); + if (!placed_) + { + pixmap_.add_feature(this->feature_); + placed_ = true; + } + } + +private: + BufferType & buf_; + pixfmt_type pixf_; + renderer_base renb_; + SvgRenderer svg_renderer_; + RasterizerType & ras_; + PixMapType & pixmap_; + bool placed_; +}; + +template +struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch +{ + using pixfmt_type = typename RendererBase::pixfmt_type; + using color_type = typename RendererBase::pixfmt_type::color_type; + + using BufferType = typename std::tuple_element<0,RendererContext>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + using PixMapType = typename std::tuple_element<2,RendererContext>::type; + + raster_markers_rasterizer_dispatch(image_data_32 & src, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + mapnik::feature_impl & feature, + attributes const& vars, + RendererContext const& renderer_context) + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, + feature, vars, false), + buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + ras_(std::get<1>(renderer_context)), + pixmap_(std::get<2>(renderer_context)), + placed_(false) + {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) + { + render_raster_marker(RendererType(renb_), ras_, this->src_, this->feature_, marker_tr, opacity); + if (!placed_) + { + pixmap_.add_feature(this->feature_); + placed_ = true; + } + } + +private: + BufferType & buf_; + pixfmt_type pixf_; + RendererBase renb_; + RasterizerType & ras_; + PixMapType & pixmap_; + bool placed_; +}; + +} + template void grid_renderer::process(markers_symbolizer const& sym, mapnik::feature_impl & feature, @@ -100,13 +208,13 @@ void grid_renderer::process(markers_symbolizer const& sym, auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_); using context_type = decltype(renderer_context); - using vector_dispatch_type = vector_markers_rasterizer_dispatch_grid; - using raster_dispatch_type = raster_markers_rasterizer_dispatch_grid; + using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch; + using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch; render_markers_symbolizer( sym, feature, prj_trans, common_, clip_box,renderer_context); } diff --git a/src/marker_helpers.cpp b/src/marker_helpers.cpp index dfc7e2f91..5382878e7 100644 --- a/src/marker_helpers.cpp +++ b/src/marker_helpers.cpp @@ -23,6 +23,9 @@ // mapnik #include +#include "agg_ellipse.h" +#include "agg_color_rgba.h" + namespace mapnik { void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path) From 85622ab57501c7e62f8407b2860d75b68c3a80a5 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Mon, 13 Oct 2014 19:41:57 -0400 Subject: [PATCH 3/8] Update group symbolizer tests to use markers symbolizers. --- tests/visual_tests/styles/group-symbolizer-1.xml | 2 +- tests/visual_tests/styles/group-symbolizer-2.xml | 6 +++--- tests/visual_tests/styles/group-symbolizer-3.xml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/visual_tests/styles/group-symbolizer-1.xml b/tests/visual_tests/styles/group-symbolizer-1.xml index 5245dbdef..fa09e0470 100644 --- a/tests/visual_tests/styles/group-symbolizer-1.xml +++ b/tests/visual_tests/styles/group-symbolizer-1.xml @@ -19,7 +19,7 @@ lat,long,name1,ref1,name2,ref2 - + [name%] [ref%] diff --git a/tests/visual_tests/styles/group-symbolizer-2.xml b/tests/visual_tests/styles/group-symbolizer-2.xml index 45a3336b6..f565a5433 100644 --- a/tests/visual_tests/styles/group-symbolizer-2.xml +++ b/tests/visual_tests/styles/group-symbolizer-2.xml @@ -38,7 +38,7 @@ lat,long,name1,ref1,name2,ref2 - + [name%] [ref%] @@ -60,11 +60,11 @@ lat,long,name1,ref1,name2,ref2 + + + frame + + csv + +lat,long,nr +-1,-2,0 +-1,2,1 +1,-2,2 +1,2,3 + + + + + + + diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 49fd8dbed..b12c8a52a 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -268,6 +268,7 @@ files = { 'group-symbolizer-1':{'sizes':[(512,512)]}, 'group-symbolizer-2':{'sizes':[(512,512)]}, 'group-symbolizer-3':{'sizes':[(512,256)]}, + 'group-symbolizer-4':{'sizes':[(512,256)]}, 'group-symbolizer-line-1':{'sizes':[(512,512)]}, 'group-symbolizer-line-2':{'sizes':[(512,512)]}, 'text-charplacement':{'sizes':[(512,512)]}, From 16b1b5a77cb5112a0c9b43ba1a0e502354d8bbe7 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Mon, 13 Oct 2014 19:43:22 -0400 Subject: [PATCH 5/8] Support markers in group symbolizer. --- .../process_group_symbolizer.hpp | 46 +++++++- src/agg/process_group_symbolizer.cpp | 55 +++++++++- src/cairo/process_group_symbolizer.cpp | 31 ++++++ src/grid/process_group_symbolizer.cpp | 59 +++++++++- src/grid/process_markers_symbolizer.cpp | 5 +- .../process_group_symbolizer.cpp | 101 +++++++++++++++++- 6 files changed, 286 insertions(+), 11 deletions(-) diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index 774296f13..32a0e80b9 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include #include #include #include @@ -39,6 +40,9 @@ #include #include #include +#include +#include +#include // agg #include @@ -49,9 +53,11 @@ class proj_transform; struct glyph_info; class text_symbolizer_helper; +using svg::svg_path_adapter; +using svg_attribute_type = agg::pod_bvector; + struct virtual_renderer_common : private mapnik::noncopyable { - virtual_renderer_common(renderer_common & common) : width_(common.width_), height_(common.height_), @@ -110,6 +116,38 @@ struct point_render_thunk composite_mode_e comp_op); }; +struct vector_marker_render_thunk +{ + svg_path_ptr src_; + svg_attribute_type attrs_; + agg::trans_affine tr_; + double opacity_; + composite_mode_e comp_op_; + bool snap_to_pixels_; + + vector_marker_render_thunk(svg_path_ptr const& src, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + double opacity, + composite_mode_e comp_op, + bool snap_to_pixels); +}; + +struct raster_marker_render_thunk +{ + image_data_32 & src_; + agg::trans_affine tr_; + double opacity_; + composite_mode_e comp_op_; + bool snap_to_pixels_; + + raster_marker_render_thunk(image_data_32 & src, + agg::trans_affine const& marker_trans, + double opacity, + composite_mode_e comp_op, + bool snap_to_pixels); +}; + struct text_render_thunk { // need to keep these around, annoyingly, as the glyph_position @@ -121,7 +159,7 @@ struct text_render_thunk composite_mode_e comp_op_; halo_rasterizer_enum halo_rasterizer_; - text_render_thunk(placements_list const& placements, + text_render_thunk(placements_list const& placements, double opacity, composite_mode_e comp_op, halo_rasterizer_enum halo_rasterizer); }; @@ -130,6 +168,8 @@ struct text_render_thunk // via a static visitor later. using render_thunk = util::variant; using render_thunk_ptr = std::shared_ptr; using render_thunk_list = std::list; @@ -152,6 +192,8 @@ struct render_thunk_extractor : public util::static_visitor<> void operator()(point_symbolizer const& sym) const; + void operator()(markers_symbolizer const& sym) const; + void operator()(text_symbolizer const& sym) const; void operator()(shield_symbolizer const& sym) const; diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index b48cbf1cc..5a7e728ad 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,10 @@ #include #include #include +#include +#include +#include +#include // agg #include "agg_trans_affine.h" @@ -50,10 +55,11 @@ struct thunk_renderer : public util::static_visitor<> using text_renderer_type = agg_text_renderer; thunk_renderer(renderer_type &ren, + std::unique_ptr const& ras_ptr, buffer_type *buf, renderer_common &common, pixel_position const &offset) - : ren_(ren), buf_(buf), common_(common), offset_(offset) + : ren_(ren), ras_ptr_(ras_ptr), buf_(buf), common_(common), offset_(offset) {} void operator()(point_render_thunk const &thunk) const @@ -63,6 +69,50 @@ struct thunk_renderer : public util::static_visitor<> thunk.comp_op_); } + void operator()(vector_marker_render_thunk const &thunk) const + { + using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender + using buf_type = agg::rendering_buffer; + using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; + using renderer_base = agg::renderer_base; + using renderer_type = agg::renderer_scanline_aa_solid; + using svg_attribute_type = agg::pod_bvector; + using svg_renderer_type = svg::svg_renderer_agg; + ras_ptr_->reset(); + buf_type render_buffer(buf_->raw_data(), buf_->width(), buf_->height(), buf_->width() * 4); + pixfmt_comp_type pixf(render_buffer); + pixf.comp_op(static_cast(thunk.comp_op_)); + renderer_base renb(pixf); + svg::vertex_stl_adapter stl_storage(thunk.src_->source()); + svg_path_adapter svg_path(stl_storage); + svg_renderer_type svg_renderer(svg_path, thunk.attrs_); + + agg::trans_affine offset_tr = thunk.tr_; + offset_tr.translate(offset_.x, offset_.y); + render_vector_marker(svg_renderer, *ras_ptr_, renb, thunk.src_->bounding_box(), offset_tr, thunk.opacity_, thunk.snap_to_pixels_); + } + + void operator()(raster_marker_render_thunk const &thunk) const + { + using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender + using buf_type = agg::rendering_buffer; + using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; + using renderer_base = agg::renderer_base; + + ras_ptr_->reset(); + buf_type render_buffer(buf_->raw_data(), buf_->width(), buf_->height(), buf_->width() * 4); + pixfmt_comp_type pixf(render_buffer); + pixf.comp_op(static_cast(thunk.comp_op_)); + renderer_base renb(pixf); + + agg::trans_affine offset_tr = thunk.tr_; + offset_tr.translate(offset_.x, offset_.y); + render_raster_marker(renb, *ras_ptr_, thunk.src_, offset_tr, thunk.opacity_, common_.scale_factor_, thunk.snap_to_pixels_); + } + void operator()(text_render_thunk const &thunk) const { text_renderer_type ren(*buf_, thunk.halo_rasterizer_, thunk.comp_op_, thunk.comp_op_, @@ -92,6 +142,7 @@ struct thunk_renderer : public util::static_visitor<> private: renderer_type &ren_; + std::unique_ptr const& ras_ptr_; buffer_type *buf_; renderer_common &common_; pixel_position offset_; @@ -106,7 +157,7 @@ void agg_renderer::process(group_symbolizer const& sym, sym, feature, common_.vars_, prj_trans, clipping_extent(common_), common_, [&](render_thunk_list const& thunks, pixel_position const& render_offset) { - thunk_renderer ren(*this, current_buffer_, common_, render_offset); + thunk_renderer ren(*this, ras_ptr, current_buffer_, common_, render_offset); for (render_thunk_ptr const& thunk : thunks) { util::apply_visitor(ren, *thunk); diff --git a/src/cairo/process_group_symbolizer.cpp b/src/cairo/process_group_symbolizer.cpp index 7958a7db5..50d3fd49d 100644 --- a/src/cairo/process_group_symbolizer.cpp +++ b/src/cairo/process_group_symbolizer.cpp @@ -23,8 +23,11 @@ #if defined(HAVE_CAIRO) // mapnik +#include +#include #include #include +#include // mapnik symbolizer generics #include @@ -63,6 +66,34 @@ struct thunk_renderer : public util::static_visitor<> thunk.comp_op_); } + void operator()(vector_marker_render_thunk const &thunk) const + { + cairo_save_restore guard(context_); + context_.set_operator(thunk.comp_op_); + + svg::vertex_stl_adapter stl_storage(thunk.src_->source()); + svg::svg_path_adapter svg_path(stl_storage); + + agg::trans_affine offset_tr = thunk.tr_; + offset_tr.translate(offset_.x, offset_.y); + mapnik::render_vector_marker(context_, + svg_path, + thunk.attrs_, + thunk.src_->bounding_box(), + offset_tr, + thunk.opacity_); + } + + void operator()(raster_marker_render_thunk const &thunk) const + { + cairo_save_restore guard(context_); + context_.set_operator(thunk.comp_op_); + + agg::trans_affine offset_tr = thunk.tr_; + offset_tr.translate(offset_.x, offset_.y); + context_.add_image(offset_tr, thunk.src_, thunk.opacity_); + } + void operator()(text_render_thunk const &thunk) const { cairo_save_restore guard(context_); diff --git a/src/grid/process_group_symbolizer.cpp b/src/grid/process_group_symbolizer.cpp index aedd0b439..e2cc6debe 100644 --- a/src/grid/process_group_symbolizer.cpp +++ b/src/grid/process_group_symbolizer.cpp @@ -26,10 +26,15 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include +#include #include #include #include @@ -60,12 +65,13 @@ struct thunk_renderer : public util::static_visitor<> using text_renderer_type = grid_text_renderer; thunk_renderer(renderer_type &ren, + grid_rasterizer &ras, buffer_type &pixmap, renderer_common &common, feature_impl &feature, pixel_position const &offset) - : ren_(ren), pixmap_(pixmap), common_(common), - feature_(feature), offset_(offset) + : ren_(ren), ras_(ras), pixmap_(pixmap), + common_(common), feature_(feature), offset_(offset) {} void operator()(point_render_thunk const &thunk) const @@ -74,6 +80,51 @@ struct thunk_renderer : public util::static_visitor<> *thunk.marker_, thunk.tr_, thunk.opacity_, thunk.comp_op_); } + void operator()(vector_marker_render_thunk const &thunk) const + { + using buf_type = grid_rendering_buffer; + using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; + using renderer_type = agg::renderer_scanline_bin_solid; + + using namespace mapnik::svg; + using svg_attribute_type = agg::pod_bvector; + using svg_renderer_type = svg_renderer_agg; + + buf_type render_buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_); + ras_.reset(); + pixfmt_type pixf(render_buf); + grid_renderer_base_type renb(pixf); + renderer_type ren(renb); + vertex_stl_adapter stl_storage(thunk.src_->source()); + svg_path_adapter svg_path(stl_storage); + svg_renderer_type svg_renderer(svg_path, thunk.attrs_); + agg::trans_affine offset_tr = thunk.tr_; + offset_tr.translate(offset_.x, offset_.y); + //render_vector_marker(svg_renderer, *ras_ptr_, renb, thunk.src_->bounding_box(), offset_tr, thunk.opacity_, thunk.snap_to_pixels_); + agg::scanline_bin sl; + svg_renderer.render_id(ras_, sl, renb, feature_.id(), offset_tr, thunk.opacity_, thunk.src_->bounding_box()); + pixmap_.add_feature(feature_); + } + + void operator()(raster_marker_render_thunk const &thunk) const + { + using buf_type = grid_rendering_buffer; + using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; + using renderer_type = agg::renderer_scanline_bin_solid; + buf_type render_buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_); + ras_.reset(); + pixfmt_type pixf(render_buf); + grid_renderer_base_type renb(pixf); + renderer_type ren(renb); + agg::trans_affine offset_tr = thunk.tr_; + offset_tr.translate(offset_.x, offset_.y); + render_raster_marker(ren, ras_, thunk.src_, feature_, offset_tr, thunk.opacity_); + pixmap_.add_feature(feature_); + } + void operator()(text_render_thunk const &thunk) const { text_renderer_type ren(pixmap_, thunk.comp_op_, common_.scale_factor_); @@ -94,6 +145,7 @@ struct thunk_renderer : public util::static_visitor<> } ren.render(*glyphs, feature_id); }); + pixmap_.add_feature(feature_); } template @@ -104,6 +156,7 @@ struct thunk_renderer : public util::static_visitor<> private: renderer_type &ren_; + grid_rasterizer & ras_; buffer_type &pixmap_; renderer_common &common_; feature_impl &feature_; @@ -119,7 +172,7 @@ void grid_renderer::process(group_symbolizer const& sym, sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, [&](render_thunk_list const& thunks, pixel_position const& render_offset) { - thunk_renderer ren(*this, pixmap_, common_, feature, render_offset); + thunk_renderer ren(*this, *ras_ptr, pixmap_, common_, feature, render_offset); for (render_thunk_ptr const& thunk : thunks) { util::apply_visitor(ren, *thunk); diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 99e6a2989..a6225ca85 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -105,7 +105,7 @@ struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels), + : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), buf_(std::get<0>(renderer_context)), pixf_(buf_), renb_(pixf_), @@ -154,8 +154,7 @@ struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, - feature, vars, false), + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), buf_(std::get<0>(renderer_context)), pixf_(buf_), renb_(pixf_), diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index f894029d5..51f50d0db 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -23,6 +23,7 @@ // mapnik #include #include +#include #include namespace mapnik { @@ -34,6 +35,24 @@ point_render_thunk::point_render_thunk(pixel_position const& pos, marker const& tr_(tr), opacity_(opacity), comp_op_(comp_op) {} +vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + double opacity, + composite_mode_e comp_op, + bool snap_to_pixels) + : src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity), + comp_op_(comp_op), snap_to_pixels_(snap_to_pixels) +{} + +raster_marker_render_thunk::raster_marker_render_thunk(image_data_32 & src, + agg::trans_affine const& marker_trans, + double opacity, + composite_mode_e comp_op, + bool snap_to_pixels) + : src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op), + snap_to_pixels_(snap_to_pixels) +{} text_render_thunk::text_render_thunk(placements_list const& placements, double opacity, composite_mode_e comp_op, @@ -72,6 +91,74 @@ text_render_thunk::text_render_thunk(placements_list const& placements, } } +namespace detail { + +template +struct vector_marker_thunk_dispatch : public vector_markers_dispatch +{ + vector_marker_thunk_dispatch(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) + : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), + attrs_(attrs), comp_op_(get(sym, keys::comp_op, feature, vars, src_over)), + snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context)) + {} + + ~vector_marker_thunk_dispatch() {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) + { + vector_marker_render_thunk thunk(this->src_, this->attrs_, marker_tr, opacity, comp_op_, snap_to_pixels_); + thunks_.push_back(std::make_shared(std::move(thunk))); + } + +private: + svg_attribute_type const& attrs_; + composite_mode_e comp_op_; + bool snap_to_pixels_; + render_thunk_list & thunks_; +}; + +template +struct raster_marker_thunk_dispatch : public raster_markers_dispatch +{ + raster_marker_thunk_dispatch(image_data_32 & src, + agg::trans_affine const& marker_trans, + symbolizer_base const& sym, + Detector & detector, + double scale_factor, + feature_impl & feature, + attributes const& vars, + RendererContext const& renderer_context, + bool snap_to_pixels = false) + : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), + comp_op_(get(sym, keys::comp_op, feature, vars, src_over)), + snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context)) + {} + + ~raster_marker_thunk_dispatch() {} + + void render_marker(agg::trans_affine const& marker_tr, double opacity) + { + raster_marker_render_thunk thunk(this->src_, marker_tr, opacity, comp_op_, snap_to_pixels_); + thunks_.push_back(std::make_shared(std::move(thunk))); + } + +private: + composite_mode_e comp_op_; + bool snap_to_pixels_; + render_thunk_list & thunks_; +}; + +} render_thunk_extractor::render_thunk_extractor(box2d & box, render_thunk_list & thunks, @@ -99,6 +186,19 @@ void render_thunk_extractor::operator()(point_symbolizer const& sym) const update_box(); } +void render_thunk_extractor::operator()(markers_symbolizer const& sym) const +{ + auto renderer_context = std::tie(thunks_); + using context_type = decltype(renderer_context); + using vector_dispatch_type = detail::vector_marker_thunk_dispatch; + using raster_dispatch_type = detail::raster_marker_thunk_dispatch; + + render_markers_symbolizer( + sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context); + + update_box(); +} + void render_thunk_extractor::operator()(text_symbolizer const& sym) const { box2d clip_box = clipping_extent_; @@ -157,7 +257,6 @@ void render_thunk_extractor::update_box() const detector.clear(); } - geometry_type *origin_point(proj_transform const& prj_trans, renderer_common const& common) { From 6f4593fb4ad6e6328f495e7e31956ab70e0b5b38 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Wed, 22 Oct 2014 14:55:21 -0400 Subject: [PATCH 6/8] Update reference images for visual test group-symbolizer-1. --- ...mbolizer-1-512-512-1.0-grid-reference.json | 8 ++++---- ...mbolizer-1-512-512-2.0-grid-reference.json | 8 ++++---- ...symbolizer-1-512-512-1.0-agg-reference.png | Bin 2084 -> 2335 bytes ...mbolizer-1-512-512-1.0-cairo-reference.png | Bin 2081 -> 2308 bytes ...symbolizer-1-512-512-2.0-agg-reference.png | Bin 2912 -> 3535 bytes ...mbolizer-1-512-512-2.0-cairo-reference.png | Bin 3006 -> 3644 bytes 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/visual_tests/grids/group-symbolizer-1-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/group-symbolizer-1-512-512-1.0-grid-reference.json index 9fab528af..3a06b97aa 100644 --- a/tests/visual_tests/grids/group-symbolizer-1-512-512-1.0-grid-reference.json +++ b/tests/visual_tests/grids/group-symbolizer-1-512-512-1.0-grid-reference.json @@ -67,10 +67,10 @@ " !! !! ", " ! ! ", " !! !! ", - " !!!!!! !!!!! ", - " !!!!!! !!!!! ", - " !!!!!! !!!!! ", - " !!!!!! !!!!! ", + " !! !! ", + " !!!!! !!!!! ", + " !!!!! !!!!! ", + " !!!! !!!!! ", " ", " ! !!! !! !! !! ", " ! !! !!! ! !! ! ", diff --git a/tests/visual_tests/grids/group-symbolizer-1-512-512-2.0-grid-reference.json b/tests/visual_tests/grids/group-symbolizer-1-512-512-2.0-grid-reference.json index dc6d066a2..14f363667 100644 --- a/tests/visual_tests/grids/group-symbolizer-1-512-512-2.0-grid-reference.json +++ b/tests/visual_tests/grids/group-symbolizer-1-512-512-2.0-grid-reference.json @@ -65,14 +65,14 @@ " ! ! ", " ! ! ", " ", + " !! !! ", + " !!!!!!!! !!!!!!!! ", " !!!!!!!!!! !!!!!!!!!! ", " !!!!!!!!!! !!!!!!!!!! ", " !!!!!!!!!! !!!!!!!!!! ", " !!!!!!!!!! !!!!!!!!!! ", - " !!!!!!!!!! !!!!!!!!!! ", - " !!!!!!!!!! !!!!!!!!!! ", - " !!!!!!!!!! !!!!!!!!!! ", - " !!!!!!!!!! !!!!!!!!!! ", + " !!!!!!!!! !!!!!!!!! ", + " !!!!!! !!!!!! ", " ", " !!!! !!!!!! ", " ! !! ! ", diff --git a/tests/visual_tests/images/group-symbolizer-1-512-512-1.0-agg-reference.png b/tests/visual_tests/images/group-symbolizer-1-512-512-1.0-agg-reference.png index c0199000e07ab27948c424c6a672729713376f6b..8fe8382b4ef55b77c3cf010eabfc603279ec2835 100644 GIT binary patch literal 2335 zcmeHJX;Tvh5Pb!J(1dR$4t-w&hh(`!QLRz&{Kw7a5 z(I6?cfCm^3OHjfgP@qtcmO}+Gh(_*!2jLJ*qd&pVeA&0NyR&cS&HJ!tnZBNedNe%% zhF;sY>;Q<`ln7lNEmUV))@$Jc(|f0f7C{EIgR=l*zyzQHbie|z0oDQ=05?E8=nYt} zfW0})9bjvPmCF$TSgpop6R-eFN4U*{*=ATcW4keYXCWA119N;43WNip6hs1102knE z>5f7O=zkAg5eScfZa|{}Bo8GEio>1)x}IKJ+;;NP2cO0Iw{6F!H-?Lqk@ViIV%Z9l zC)uw54QYB+6ecmzw>#zAzt?qB^#@c2S0>%fjoo!a_BS^ekv7>9mUVpWY*;NH@z0m} zV3-8I=`gLq7x_T?0u7q>y_y-pW!XB{6s*&^3vJcb&7rR{ooL0?SY@hmzZLQMn+7_y%8S+@^1@o_;R(}-c@%` z^^48)D*b0?NR|jK{9s2W8ii@%Ce-6iAKvYjFe^-kr>4^Ea_AM0Ysp7mMLMx3NBc(x zgIY$EbxLkkbuyhU=*X?*2n1tqczpk>5XA>^Is#;A3c7VfXiZc9;8=&Ws6}ziQRQ0q&xQ^796rZLXdjGJl?xmBa^>d?fspIf%+7pbad6O#tNdBqWLR?Ny z5T+f#u;nn@03T^QdkPe~3^S6DL#8JZJN;}aK?3ywrhnU0p}6th`uMp$%1)VpC>6&W zz1=}VQn+hUg7vSvMpsE_g0dWST5}v41@(I}U0m!l4MvrIh82B9ALf6zLC8y07KlbO zo|VrPj>oy`HN9`zC8PwJgue`QI*@ZQg=m@-;(94>Yu7lh@JYIkcU3@CfJ@wo^VX|w z6xE1+ewT%m^1_}7SBkxt9l^n%?F!c{r!?t8Zu7r$c5sS6!l35)7q08L9lD2}Ccxk_2myZm!tO%vU`l0BXGhVmQ z2n+Zjj4r9|fN5F&H3Dx;G-gt1liXCUm|vXG^3CrIcblr+@C;_{3+d=Ho%A{}rXc>5 z7u^zjD(ViId3#T|f-bu;q`QYot-7eat8k(l zxvA$9RQYKt{m%N>@tf=yiaG7aq256hE(LEoOl$C^J}_-4jO*`aa{^gE8j&jV3^at% Xk}lfeL&*uBJ{>O)-z~S?*+2XbT|Oa~ literal 2084 zcmeHIZBJVT6h3X~3WOF(3?r2n6I7xjE665n^aYd!8PLIk!jwVh3kV1;c7e<2+C~i( zt2Du6-BP4mP|!f=X66dJE!30+BX-r0(9S~XK#M}@%O=q7w!PkcFn;t8@Z~(`oacOb zPEMZFU&Sw_$1~#rfL``$$!P#Gk&+>nLV$VnnI8$LuBxaxK_E~8h(QKG5K}K>Zf-zdza%^eC=c>2d_-C{L$D06w7=v0;t$MB;vHe-r=RgdvZX6ItY92ZOf4ZV>w3 zS9Ins<1hM~-s04=e930Fai{rAoXLAmf9!w&Jq!>m$Z!#He57tZa=2REVCXN@Qt%HL7r1`JsLhqvQPN> z{&@Vxv|F&UB z43e5uxv~fb7$90B`Kuu{4P0{+*9a5BZ7%d#2;$(Yh3hL58C^blg=!UBiG?hufuheh zBe~fx`4TG3drPy9u#S5hSKLiEc^9Uf+Zj3;Dr+2og>&n%qT$NbRnIhPxZLfJbm<#7 z?Dl)@ua9pp95uBfc3!$PjPMfM6SMH14kOj|yJlC-B35Tn$X7(@RDHsD$h*6Me4kRQ zgG&k(b!tfH5we=&l!4aNd>Fd0*oE}ySIwe)O3Fs_o~3|i(arp9^`Z9zG&vS(E6jG= zr0R#Cveb@hueWLvOZ!8G zgh)vY(ld*%FD40g&bQ_H9&Bl*m5vP9wb?L@1MAc?Z(%!rq%O}%7OhpHfk&aGCTB=U zTINJnTqy@SM*@;{{xoHPhCuM9pW`M16Kf zIq(fFctJy2%miZ$uLV@8Q>Y{8_91!X&YkdbV?*kDY~jq8x+LDtuQ=;?FJKm=Q`~!W z+2bVJS5-;}stH)07s$j@^+*asm*iH;$I-12mk=_aL46AU$}Xl|Rgw3NaNqy`?-QDj nRB9tBf45XF<|M#*O&?A^xU)IlFrv;P{xp=G;FnCkEcoyr83^u< diff --git a/tests/visual_tests/images/group-symbolizer-1-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/group-symbolizer-1-512-512-1.0-cairo-reference.png index 28e070b55ba0e3133765b112094aa93f4fdca301..d969b6d9e84d1df5dc0d9b5cd630b1b24fc6fdbc 100644 GIT binary patch literal 2308 zcmeHJ`CAeO7=A%baF{(F8FqNpOr4AprU@F3%wlEftY(%6 z&9*GlG_6_lqR{Mctukrl0lG~#kP00Y6fpW1`q^LJ_j|tkd7tlx@6g7W)s_|x762@x z)?5RE1gBoiZv&dtAVq~jZ-<06d=Gk|Q&1FQi%fC|h7oPh;^J3s?`fKPxxAPiUw zxX|G4jyPb^Ld*_?>r!|x#H?`8fp983e6ijd3xcr~*ap~c!d4Qt8|`UG2fhKg##y_; z14yMXsRgkM5CbEC!2k$;7o1@x8J8l_q9Q`$*cHmb^i9v!B4lJeEWN@K$3GJ1|LlCO z|Fqt~$hL_fTVw`Q22Nit+uJC7e*cfB=GGx3=Mx8FJ;P_#_+#=#dm9JeWB1d1C@js7>iQ$5%&Wb9sTfm> zYf^I3xSpq#ukvZfMT~wFBAhMUFj=6@EYj=RtB3m9(sHKCmGI<_d(qa0bt<-9? z`=MI74o5vTPNy9iMrULDyBverF1d22G&8{B-%Qr=a;!@6tKVK_N|JUB1mEOm=_<)b zsqHG6IcTZhj)DRozqE@(d;Vs~l#tbsAX% z|5w4XlLIwGIwULg*BHf;p}cp$u(<2a;`WNc;ICS*=T$YHD(N&loYmQ$bG_qgC}IOgpm&yRr<{LJ|MB0`-yc zSN(64wU;}(m!K^N>}OKRHchKmHlco_%Sz=Irs5i>{YG|k4%0;Xr$WWQcgt9B)~FW= zTrs>%+~PkCRs{1@yqy1%Nx=%spjjq7FVndcqVQzCRU|=L9%?>{mr7}S3C1g>js;f& z2=Cm%8y~GJ|4Flt{I~RiYM)wpNr!W>*%d|A!`lr7ySLb7)jAT>Qnp<_a!h-_^Sfg@ z8!>&5Iwwi;D$$C0MMHZKS!N#@a9jJeSA7FZ6jRaLg3_qXw#{E822;=PTs#&vNd1!N zufAJ-JSaKwpxilcPPSWLO4(;`9R(X$`_ohur{YK2=1`ryEVks-YFXcvz67$g%X88@ zr|kqk#q7-R+iLod-#=pWgOmDKGro_@l~7l4mdN`V_HmZ16dKQ_At{*q$kVF-HO1*$t;hLAyr3$|;=^}14ihyadGYTXRX(bJ z?ejvsTFpZD(=i2RZ!j^Jsp`u3c}o-jlRI*PY=wv7)1}@?wD{)c^DA@%#Ige;K8*E! z(|CT5U+dW1HycFkAJn2SxK%Oi-qs{eXMWz1G@d)xe;`*eS=~J$957cNhOlTp*hHS& v6ijLGL3dz(w`s3Ja$~rziQ-J+(W!b9%^mqVTVLAX`*$WPGA80u7&HHWZ^#4M literal 2081 zcmeHI`%ha16h8O1th6%98nD0uwT^93DlBAR?GP9*VOgOWt;l$86CsSYAPRRC+KMRK z7|pV2#|EKbHo#3Du8t9yFzJc}t)Na&%HZ-4*79hV*#&J&z5WaPnP1NL<(x0)BwxPd zoD-zHwUg#g1Av{$N%6-3P=cc1P9i|p7Bou0aluhx0)gNLKqYhl3;-VhKY#!LHo#th zR|rlA4nP<{1i&ExcOJw7903plWCEN5CaZA6!x+jFm0$?&hzTgm?>2lPQWV_plS>r^^64A&mY?6V z7d09NjHD4hCwL(ds1csxw^O8B`+}u(?rWvr3?7QMU83|<**Oy-2X%r@qbRDo%~_td zlwXESsKt)b)~{<@>r(0btIWm}=$_?zOD&Fw2WgHdO@Nut9eGrl!J5i=inNU1G-(gt z!VG8My;httmGBD{*YCFXycuoQ?L!+TIbI>&CTqVW0wnT#TXt$+Wn}o}`H8I4> zF_5hb^-t6r->RL({Wlfh`(oW)gbAzp@(U{;iz0bHwevMnLZf$^smV45F#r6(UV)T& zH1=A|W?GET!bghH)GMx6*9Ig${=_l4XidwYlyr$D&cMxQT8oWu#|wFE_`^wtRIqNB sZ4aI=2g6*|oYQ~J=>LOPHT2cb=NepQw=;g#mj8c!azaXcS8QJOf90R6Q~&?~ diff --git a/tests/visual_tests/images/group-symbolizer-1-512-512-2.0-agg-reference.png b/tests/visual_tests/images/group-symbolizer-1-512-512-2.0-agg-reference.png index 77e7754e74cbe136c309515c4c484731e573314c..12093e2ec10def1a5afee34e975693a476c58eba 100644 GIT binary patch literal 3535 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 Gss9I20=wY= literal 2912 zcmeHJ`9B-j7C(uUmRg3VI;I+(@#uV%E|$<1QEIED)2di%9i1sH5h@9>WTJhkrRdYD zsS-Y@4ppI@#>84iYkA76hnk35M$V6` zRee z12_U;4PXmk2jB?c0^knd1#k`^03aA365tX50U!||1%Rp$mCFGbgA7YOP6>c&v%9mS zFZrH;%L$xu1DJkWMl+-t8Z!SSZJ#63QQy$2bB3SSuy+R^%1o0LSY}>2aa}-ixs2{Z zb$G%@6x0JVZ*J4&fKSxClMvszWDH~^)#TIge|!hxTEykT?CzObH3u_eRtBdxLW*gx zVBq=@^UH5`zdgZu84s?XIO$wg&^P95P zt67t!X=YS9eS|0$U4V+j^>J&D52?v~!TT}fe#sFkj_;ou#jkUNh1d#o=j@%QlUb;b zLTl8=45!KcZvrVVNC|BOtyQO1px4iksp30PcuKe05Ky#B#wXw3<;kZTZAv$X^OL3r;{nj~M zMfSPojQ*cOyN;N@MjI?gPx%Ozv<`Gd>G`}p4@`2ym7+8vU*HZuYpRv~-D)q*rTsTE z>imwfC}htsE9iWPkCmy2vf-*GiA_t*nA?_bhp-gj5Niug!O9=U|IEEWy-*LkiW;&+ zSo(*+xDIw0H58VFi1Yz39qeBub@i!1hJ!S9gIC+HW=KI^ybGwIw_BX;WdmD&TG(O* zaR`W|+qJ0>SORyAsmlL@>K{1xXH^%OEzoE}y}zUE*%Gp+RGx70FRwudt$$l0exHzN zx`8cgQ%Pb5e#47#Hl@LB%`d8S=k<80qTEGfPlzolJI%_WIhm)K!l(-iwdkctCPss} zcwl;^Yuj9r$h;-w#qSnYOtrAJr<|BxByzi1tf0XYbEBPnhxMDTFP$pYO5TeM#Oc!r zdqhbqSc%1g-ex0Srds2eva?)%yN=bms^pfgE16!u=}w;YaT0_R86(j-jwJ|kk>9cW@hgFoCSi6ZehK~E?`p=-o{XA0 zR@x62$yg@ zN&j6}iOZutpHZ%jh*dxcd=Y6vMGx6~Ayf{c`L~^lzEdiRAT|jNsxv?9Dtn#o&@I*w zTR~~f%8e7%Dbx7AU`O^%QDQ?}lIuQ1B%a|S63%_w6|bESw=ij;z7=en7U9|Akaw4( zjen3WZGWXUD-0jWrg=2@Jcu<))$6*Y(e~(Icg0$a#Kv}S7m4HjZWrS`&UGz# z@kr?y>_+Dr@*nW5Z!9g|$j%a#4sc?fX|BTz}s zJhRdkmUNVRzLJ{*jVuSdS9cQoEi$ZN#-GSG84(~f`s=cyHf;bXtNiuyNVhyK^ZZr zM?8E<)Kf_BY)9vP^?oD%p62m~wft;?`H-DCiE%$m@&B|HiNxMSgilHIQmB$)D}|EO z&@PNPy)l!>WB#)??$|LTzodoU;%%yU!ZTXGHXI$V$E&z%TEVNujk#M58rTV0ULR|d zRDSGuNbnv9{C=UwtANUO*=*zk8Dtf#jtHJ%GCp` ztglJP+^B?eSVi4g``mab6mkDba?+UH`W*ErTq}GQ@t9+8W+EfoJW$Hl_}d)8Avhp; zvb|EBTTdz$nO={=d_|o%_{UWF^2TTzWsfKjn%8^BLLmR8nXfdHKOBnjaLtd4PYr-^ zQ~K2VM{Hrb{5bld3Nt9r1IeA9>BOT3Itgr&e2L`DqlY>Ob1)`B_{12Mp(ievdSt`$ z8-W@fcRzI#pPDHkhco(Q!TyD>hUmAT$iO8OUZdb3Vh!#3SrBDz*G<$`tL%Q#+xgLn HFxr0sE6#1$ diff --git a/tests/visual_tests/images/group-symbolizer-1-512-512-2.0-cairo-reference.png b/tests/visual_tests/images/group-symbolizer-1-512-512-2.0-cairo-reference.png index 9eacb7d3f2b5be643c474c9e549bbcb65ec316b0..e86cfee6f762fb6e2472d6c8b02d38712cd1ff4b 100644 GIT binary patch literal 3644 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 DU#Hv7 delta 1981 zcmZuyc~sJg7QUc}WSV9~MJkS_ofelGmzN7Rmf7^wX0p;u(I#zjUveGv$7l^sjAdE* z#+BDznpSFVh?HqP%e`_-MG2R{5Ya(F;L&^MyuaT4?|$d|zWbeX?>U#XnN7$wN8%6v z-FH8z3j=@y&;>A1H->-**a%<*U<$AWUS2-I+f8@ z)>dJR_a=%QHpK;-n;g)OD9DG$P@Ab?1`ltE{qPp^wQ>;)sE6N=SD3oOi!BBFS?r3l0WDtLyJ4X z5YwGX(F?ZI9-kcek8*iIw&VO@Pk_iBogx_YI+@Ynk|s#^gc#@gjr7E+jzYivvXaxePm}}te1&d~=1>3JKpAVp?e?mLjq268A?0%&g8~$He zu@<+V_frYkRk=+`qPZrmrBPJQF8t-bKJo=XEj-BsXIF)?c&Zs8yWAzK=is>SG}T1J zl6J(92C^dX&RNar;}{WXgv_K^aI(hexIvRQ+_Rv`u7KRkO|O!pd8?g*vBDoir$Gq&BeOB5vS324({O4?0dS7^3MG&Y`2VwgEROkSC3PBo!UZk=<+6;ZEtdczo#wNyGn?{Y7>LsU@1FzD&TGp^3dBIrdX8%U=kd=53OR#=Mz&B-Sd}xkl z!2!xkGdT;xiLwiE)X5iLV4tNJzOWWN^+y&TEIiSH}#nwKWijFf!UM)I^+Eb}3ALcT~Y&zEm zRA^i~url!;IretZW6NzX$u0BRvs$LK&No$U8SF^%_JMD$a7QiU1xVn6Nj0i&o1Q7* z?6`k{(}yWcnb!Rg_X5J#JWJoCE3=RNu(=@KVGK<&viYrJ2-YQJ&60M;7ADCSum5^f zvWfT9F@uWmDYGhH5$f8Rgq#WiAzW@8yfQ%_hSM|j8?AAt^CthOn%bS+Q}N`*18A`J zvF`0&+2C1Fnx8*=0#4_ohSX% zt5}1j>#M=@7F89G*$ES_pOQ`(OQ%BWhD4{3ww#%^{X-64L&v`?C2Kz2By_1pWs|AO zQ-p3UQs*~eS@U%!UB+SZL)iYV1BLVRS?ZhAeg5s2enFYj8u7_=-zJB5TBJjAMiY(S zfag3*X}s^4_xfVqh0j8ysaaTbUF3*kN_zDpEoKzOh40f6iOFxr%h`T?TEVq{AX$#= zz?j-X{;8{0lQrqaq^1zx4t#Gz*JqQ1s-)BG(J(1*{^n!#(l%rYZ^ng_2Px$dn8QM| zzl{+~1T*XMFZjO4{gYLnxvBas02(7c3&MxmE;U>~(s+ z$u1T#pV4Wb^GMpj)|h@)p~A`#W{Jk*Bma9yE;?`c@z)a-0e*zgGRGxTpF~BOAK_7N nH+{etUf*b))`3Fc;z5bEMUq!Nz}l(bFTlb5-uo)P3(ovEwBNT1 From 864426ae54c47e5975e598ea8a462860f25f11ae Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Wed, 22 Oct 2014 14:54:44 -0400 Subject: [PATCH 7/8] Add reference images for new visual test group-symbolizer-4. --- ...mbolizer-4-512-256-1.0-grid-reference.json | 73 ++++++++++++++++++ ...mbolizer-4-512-256-2.0-grid-reference.json | 73 ++++++++++++++++++ ...symbolizer-4-512-256-1.0-agg-reference.png | Bin 0 -> 4175 bytes ...mbolizer-4-512-256-1.0-cairo-reference.png | Bin 0 -> 3501 bytes ...symbolizer-4-512-256-2.0-agg-reference.png | Bin 0 -> 8700 bytes ...mbolizer-4-512-256-2.0-cairo-reference.png | Bin 0 -> 7343 bytes 6 files changed, 146 insertions(+) create mode 100644 tests/visual_tests/grids/group-symbolizer-4-512-256-1.0-grid-reference.json create mode 100644 tests/visual_tests/grids/group-symbolizer-4-512-256-2.0-grid-reference.json create mode 100644 tests/visual_tests/images/group-symbolizer-4-512-256-1.0-agg-reference.png create mode 100644 tests/visual_tests/images/group-symbolizer-4-512-256-1.0-cairo-reference.png create mode 100644 tests/visual_tests/images/group-symbolizer-4-512-256-2.0-agg-reference.png create mode 100644 tests/visual_tests/images/group-symbolizer-4-512-256-2.0-cairo-reference.png diff --git a/tests/visual_tests/grids/group-symbolizer-4-512-256-1.0-grid-reference.json b/tests/visual_tests/grids/group-symbolizer-4-512-256-1.0-grid-reference.json new file mode 100644 index 000000000..4371a770d --- /dev/null +++ b/tests/visual_tests/grids/group-symbolizer-4-512-256-1.0-grid-reference.json @@ -0,0 +1,73 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! ! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !! !!!! !!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!!!!!!!!!! ", + " !!!!!!!!! !!! !!!! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!!!!!!!!!! ", + " !!!!!!!!!!!!! !!!! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!!!!!!!!!! ", + " !!!! !!!! !! !!!! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!!!!!!!!!! ", + " !! !!! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !! ! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/group-symbolizer-4-512-256-2.0-grid-reference.json b/tests/visual_tests/grids/group-symbolizer-4-512-256-2.0-grid-reference.json new file mode 100644 index 000000000..26ada908c --- /dev/null +++ b/tests/visual_tests/grids/group-symbolizer-4-512-256-2.0-grid-reference.json @@ -0,0 +1,73 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!! ", + " !!!! !!! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!! ", + " !!!!! !!!!!!! !!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!! !!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!! !!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!! !!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!! ", + " !!!! !!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/images/group-symbolizer-4-512-256-1.0-agg-reference.png b/tests/visual_tests/images/group-symbolizer-4-512-256-1.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..84ab8d42089b145de2a56da6f29eaeaa0a94fecf GIT binary patch literal 4175 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 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/group-symbolizer-4-512-256-1.0-cairo-reference.png b/tests/visual_tests/images/group-symbolizer-4-512-256-1.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..1ecd9b335d6df3648962d3c3217eb2e17b6d1b42 GIT binary patch literal 3501 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

Xevw0b3q>w5vRJ{XM>;@*G>Wroa1M9M{2G zuF5{z!FtJEanEh?<=Z&0PSd}%GK=6{U!2svnHM^x!1s6&>;Ld4g@~%rl?g4fr&X{u z+v;B>>@&$FEerYYea`>b6#X)^kTtLEdz{en&ShX|DzJ?I!A9!5Gw{OE|dKv}C cZxu$uL~CE`+amh8(QOV&v$r5IZzYbb3@tF(xcsF(-YA|zQ#nUwO@MhjYv zkdPKyY-P}5OP1`+^L_OBe7=8u|M>l`-|xDG+hoRi?@VlO75 zC;|XtYaMLY0}yZ)0V)yy8*#Dl!Ua)oPM&sn6XXFF05Adk0ptLz0dT$J0O0_Xzw}>B z1OWaM`b%+!^dAPFk~2T|JpI=goc^ncOYk51m;N{Nujc03j)$(Lf33RYha~$O<4W23mM?5$NO85Hx52rubJ%6JRC4 z5-M2Wa%-^1sRNMLf(NMJ@@;t22VfWYf!11pVBA+B5QYm+{@Yg&1CRl`mx;!R0^1UN zt(NTv*y0FqT^f~^J}nInhXBeHk`w@{ZDMi77SMVK>d&>$X#<0|E(4czgHkQXegGH* z7zP*vz%cw#P;2iZz{q6tOXirUC`PAava$}>95$nyF=b`{_plq?jp^uk6?$PNCSk*H z96gS$UX5Z9i^d)(Ie@KQo5V>vkDkXiZp8fk}1}^nBfU6hmv!8Z18kpAY|h zq9 z>s>rxrM(e()8Y_O`Lmk(SC^QV*{plzv88$E5C4NfNB@L{qtP*mNona>7cO1q=3Tp9 zc=Jy2y$2;_kDooScu`$lTi4L={{4qf&8=U)bas9F(c3pLI6N{oKIwAa{1zUz#r$;DJY|(R#&>i89p`k{JHq6-DVhEm(AAAWC9 z3eR1^RasGK|Fbhz z$;W3|BOTY@V(QyGH|o8X_S!790tv-cYpW_8mo;SWId%-Y|IgrHz(qnVLzJ`%lIz%A z>2s~&O;dIT(Znd0da9kw5SSJACM@}Nqo~6$ynN9b8o`Qf@@^qP73`O;2x^RYHvayk z|HO+JQJUe_z3yE3R~jPt5+6TQDU5e_eIC^R`BSt(I;z~6mWm`16PG0XRa_D@U}+pt z8D0{h+P_A9Dr+%=YDVkP<-5#V>g<%WS((SB-uHcEDVMaT=_j>8HmY2U z(&hV8k!Fym`);c$ZcyF9u5?U!t~R3A;zCM^=r-eO%eR+p=(=PXLJp;!IzPg{Yce=@ ztDrR^gp(Zn{Qi-Q4Ss$%NZZ911J$5Nl7Hl7b<$P3m<_z*6#G<NCgWPt%Q9tU>YV3xnvrUC&s3V(22ciazee6{j`>YGmUl=z^?^o4YZ1HR~ zMxT4qEZCGfRy$X+!8D@q-BI0Plm*m1ZWcW`Lfc^YQ4;opU3Ajrfmj?Be>tV9%$7^~zYR5|-Ha2E{a?Kv` z$Y10^$1xZanJiu)WV_VCihV^B!BLl=ZFXeNW4gRJaW?nk`^aL>%2wlc%I}Ilwdd}- zUs$DpV~HuwAmqtr*`0?HVlrtS@jJS@X5)q=>dPFMz>3AB{Q^^VGh{2OhZ~Kffmr z!?YMCcR|oJl3O?KnlX5FY~$9&R=ub7QNk&Z&w8EBVsN8aG(@-_@NJ#ulCuvU7YppM zpKg8LJh1$u}x@1z|%yU>46x2{hm5gfr2E(l6@PRiA*Ia>N#J~F0Z z!hP#yEYj&zvUZ&=;5v~^q&ICIa<$sY(jbQx&E1@n>-62l@fNVly=UvfO$9ZMNyrk0 zWR`&9J7S6{( z1A+;Bg4-Xgj^i%ac0|mOb5HHF#c|7I(~tr02wOUxi1NN?`i5y;L-a@sk$dzi6UKI( zdCjPVb1D#w-h+XGfmDIVbj^3;Jj+`V-v!~v2SFyvF*Ssw^`V)52!KWw5NmU58& z3v~iYgDfZjy5KEu_R!SbUpf;NlcMQa1U4$kWAOZ0((f!p>!DpDZ7q+OnyKiT+OzrUR{fo#{ghn7EMQW_wXdj6wyznOOOvmVinDW(s z65p$$lHf_;68META7FCluvWou``wzTKM11%sUlV%g@^X=UhMKhDXg_F)tXlH0|zD( zg@LZXkbzwUx)5U=8?cPUispVgX49yoc(mA-=epP4AstyM>_&CiER@5ATfcwR&wiR( zwIIAA?FUj2M5YQsHrOJ8LPAi_Ify+{UqoV3_Y#s!_^q;oq+KcnHoPK)U69)Tv}gCe zV`H~!0gZSlyjKVYAc+K1YO`{kYMJFB*on<#A_~_L24Bh!bs?-I#p^*SQRy2hEef+o zx}zro6y)WbAI*JT`lHD?(Pz)mqT}JRlIS|##elrka0kaPmw@(Lj{CM?&*B&2fOFG| zk6~mWdD3o28OsTMNvsS|UYDP49Pp1SJe-NRe+0(bjW>MW`qIsQ(j>fM+rt6i(s+J| zUx~XAg8(^@G|>@^Jt@#7oJIqsn1yK73Vs!l|K3;3;aSm$d*L`!aJjgT3{J4KX3gC4hUMx-RMZEp zhfNe~DpzcKi*Vl;o&nq}Q%T&KfW|kjg3v`- z*@&k^{0Vdea0RYYhgvWRS;8`8j{^Q+Pfe@pkkEC*>XdW%@KZM}WVO< z!HYkop(uR;X05YtS+%mIjeHKC8D>~GS06&JYO9~BDWFC5SBA{l>|sKJ`h_G-gxdd zwdh8wH%VTdl^K~uyk6S(jQjEoLrgpV&Hfx^m@GdgwMZR~J*TfOFqCk#VG1}?d%k)5 zSR|32ZqS82!tjK3md2*Q5`og763v02q0YEK9J*FyM2M9H{hi`{kIY+Ak5&ArG_Fx; z(DA0M+C+nWa$rpUu1znA+;W`>-h>N=s5pGXT7GU?dC-Z5+>>P1v9gK$E>@Wyqt=C& zAcVFHeVuw;aLy3KU!n49F|qOA80F*+VfpK%u{JE%?(tmiDr`z_t_;YGk5TokBMGZH#kZ` zEyQ_GppcYBZvZ_=#df~LuOTbeNYTX*Jxa43D$IM^L>zjtIimle7?|xVji4wYMGxbA zCI(epfM4jl*7yoEui1%C=sc0Q7#AF${PS(#wYo>oewPa-j9F^G=lV~$iXHq%8bY;o zuah4fhdO8{1cKRpRal0|LOZ2LgLjLd^h@X^VW@qzRbWl4*#1mP%5G8KCq_@$$^K7A zcet5vg-~(C`+3OdxVb63)ddTM5BRk%ZoI^W5bfF&-?3xHDtB;h%MZwMhC{^crCdFv zPY4KngZ!p7OOPy*E-6qv-jLAR6O5AC@p?>gG&6%z8lWvzvRj0Anc-bbQ5|@^x-8sx zA1o7V?5t2DgE3G3vhoKXHH-1FiZ6L|u0vqf<=H05AP2Rsc&u!q$(Z&`5RnY8f4%Ui z@FX@Sa2rUuU9Qk^WK$kDhj;L5TS2;%Dk#2dU)~SLSA60)75NP5iXYG>ts-=LBc@9M;wJ zd18+Q+D8aeOD%~E7LzwZ3}B5WT=hPUK3)Nd@I=g^o$?Zfx^7>2Wk~|Zxa3~?Ryo){ zqk8;-emYSKd8Z`7%$DdcmA7x-gTa+71na$d96zMQ{*i zf*!F5qw!vyb5Z<<%B8!NQr~$oa-?FF=_@sJ2&my0fk%g@rysG85#h2|e?;6mlDCHh zdS=e`MVnm-N=J>qyV_U(j@Muh-8Ozvr$cZ6PdRxZo-XoS8sVRu?Y?zxDY8MFr@;_M zbJgMgp0`&LE1QT#>Qo=)(Cuv*2j6N@_(aXNPZZV%*wXvHyW&gle)KW?8M8F}I=J^+ zfw4RkFenCZq^%(o9>j{K2D$UyAaA zH%K8hb&J&oB~&ivb=r;SMq<$_Z$V@1mg1&;WfHvO3a*c{^@{@JhHfzQpU%LubyN`jj>7pJ3jSNhIAn{qk~Km6g2DB^a5#KI0j)aaT% zI-S6$6oXSD!u`62MT1fyiPbVBeYMA$)POGm0-JDPeu@aN@bFXPw=A%FTd5z#@7(r# z7nOC$01l~r+(MMeC#Qr{m$FExF*)}hQ0<=wGMvPDXM$!}i?^|rLC&XO2TLAqQn?mP z8wmVmGud%?e_-6v@q8mF8!PEJd0iY%lyt=ha6)_sLD_8I^6U8&mLK~5=cQvWYx4w3 zL48xUytOt+pu0G<+id(AARg7R5Mh_M1c(Xok}tEXKdG3Pd{w#Cd|n-b7V+78cWO9` zOd5Nn6JGm`P}mEXqMB=x7=$;vGH6>A>iXpOQ^Qb(FyzMld@K%mQzw)&1<&K6+a|tk zChgdA{0}diioCqF-chohs*>Y2JvoEOm940-;>-fWBStR#*jo zRk(3ExbYu9ce&6`|Cq}(#pXK`$Y5BpI-K3cpN4oNwAJ#xIJx%;JZJ2>U%ZyAW2hl_ zstR%I5mIlsEN)TrT-BC>M!8UI7SLA>HRDI@mhMZu9;3i;VC$QC7YBU#(skFbBM8_> zl;P~U7hS+K60Xc_ohki1G5BR>`UEGu@N9lfXH+U3{F00&qv*v28QtcVvMW_&D6C+) zP%3nSY#|tnrX0C*KrSX(A#8fn&m2x?%+K5- zX5p%~zO)c!BT-`=*mTm=fCCpWcKp~QZUOdjj_n|; zCf=ZeN{?LKUi*!}GSMP2zSLAs)I_X$%7CchlYw=dRH3%k9pUF`^-O_!(Cq(8ZpUBK%sr19tTFA+a*2s z*!n#{@?7=7uA$QX;rln--8|;-Tf6&Fu%ZL6jxIj>Rwu9Dr0Lw7sh7LZq`lzlxA zvKJhKFP2qjcW4`3N&Ze`HI<%@>F`m(FHB#`5B$U83pV#{d{?vHe(aD;OWM>KjT*U# ztFKHQr@Asm9&a*@J?rzBSam#-b?EOXSHXtj6$Hj1IV`RFSJ&+hA7g7)-^RVO*KNKU zOe=Ek_t-iLVkCQgJ`2XQD(<~HB5o|bVX!o@bk=wzWVm|K-MdM}Yqs{+Y7x9U6f$N- zH5U?g3tq%`rGL&`vq^JMENW@zPh}tNydUKzKeo1={CqdbfAZmWFEY0z=%{OvL7Wkf zjb#HL8j3didJjv7EPZ!K6M{+gU!OA&)c;C zrSLPY-et;xJYn+5)ue@V4b~0B8dY$Uf7hMJ3%{pUf-z_Hu`Qky{FM_|K)4s6$LsxP zX@i7k*A~{+n@Yt(tN1mE1a}=q9khr5BE3tIO^QeCB29eDQpRr%S*m}tJO*14?VF${ z!h8AT6Tg@5yg%dHg9S-xCy=d_^*XSdl@3H?54yN4UNxCGkw3R%s!1R*?JC6ZAs=3S z2GVnmi5LXBeAZVO%QP^6c6o1G?txKZ9@`U$l~!d@X;S^6`$tSDmzBfOLveX`rP zr>0oi@QVl^L8foQTzLVOjy({nTEMs@wAUN)ltG;*>es!<7^}krfBi~NV^Ot<@az7( zw+U+ro4HEqRv^hD8(D3mDaLW~rUoop@4moxC1K4F+;fh#5-}AAFA}#`U!-Su+H9H^ zr4Ek?*OA@?B;+;m6dF%-ij=u<_t(bG+>!E5PNpMXd{dn9wE~m%)(|YkGhx_*EFqPw ztwA6YUsr^dsJ@<$;#NVH;OMNJz=l##0(dL=k16)Ca5;4neH-T-zVfGa3`ob9qyr>p9}%*l0fXl$bhnFAUGx ztann*KqLu23K(n#Ge({zLW`XGW>FPUJRLUmdCanRdIC41p{iOE{LyGoXP#GJQ6pC3 zN!TkBsgwT0qBC3C__R4$&K!SgyOYs(gW4WI$(vx^nY z!Gm{#>04&J0}Fnjb`MVzIbm-ECt&OOfUei_Me&YSjzkSAlW_aC28~IQBCZz=mH3hP z(0B(&zcuB(S_o(HtZ`ZGdyWKpbG?i5vS?Zt& zOGRhYrxOQU>(wSWPqxiYKpCDL52BT23-e6zbms`l;$FQPuKf~;Vz+u;>2D4zQf;Vt zDDlX**|o*j01Fefoz%e&x%@7t@Vx%fagpLWS{0JyBj0RN`IQ#A!GU7k^eR-nc*y@( zQ&${6<-M;FM;sIXYf40y0YO%sFv^e!{(?S4+1zvLSu2Qz)>_+F{E$aZIqeH%V^9%7 zJPe39kWbZL+FL5KO6Kk98~J}DE01U6H+EW134D)q>#nJ!gEo&wIK^AlxmRupgTbOb zSXpu0RPD>}7mcpBBA(5*VBcmq&dGRz!yec%g{ExHK+PpAI+OBwU3dNz-@+imMNk)k z8&ujbjMqwnx?~V#+`-kj@|}3FHaWZI*uoNIF^g`nUOr3XxBsuJGYYo^PA|`1j5UX41QT%v@u=;O z{Sy~`<`m9o>WFcGMxv2-nDy-GkD2PRXzTdXN13m`y|0Rlc?~v2-rL!U&vZtIcUmem z|HjXYJ<=O1&!0>bMuON57Wy1f?3}^C{3fYSxcUD0^Y0l<^5*G|o@4ie%IA$w(n(fe zGUBDDFJGCN!?*Ts%b)`X3}vG?J737n|10@!60|gJ%wxcEw+_A^M{>$GCyg98#@Raa zpkB|fL7^bx9#+$d=-Pf)iKB4o=Z`6?qSpTl9ri7Vy!Ohkqu#z+6rTQ}|6gU?{}g~V z9V1#EZ%iii+mozS(S7^eLVqI#MRyuS literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/group-symbolizer-4-512-256-2.0-cairo-reference.png b/tests/visual_tests/images/group-symbolizer-4-512-256-2.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..8801bd3c9b0e3b29c88be4cbd3eb19fcad14277a GIT binary patch literal 7343 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 XaM?8dCv1$^4uTEq9Bm$2v7`SBvIhBg literal 0 HcmV?d00001 From d524738ad935aea70cd1d7a20c35d4a390d956e6 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Mon, 27 Oct 2014 09:43:42 -0400 Subject: [PATCH 8/8] Remove point symbolizer support from group symbolizer. --- .../process_group_symbolizer.hpp | 24 +------------------ src/agg/process_group_symbolizer.cpp | 7 ------ src/cairo/process_group_symbolizer.cpp | 7 ------ src/grid/process_group_symbolizer.cpp | 6 ----- .../process_group_symbolizer.cpp | 22 ----------------- 5 files changed, 1 insertion(+), 65 deletions(-) diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index cc1be65c0..a5d72eaaf 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -103,25 +103,6 @@ struct virtual_renderer_common : private mapnik::noncopyable // stores all the arguments necessary to re-render this point // symbolizer at a later time. -struct point_render_thunk : noncopyable -{ - pixel_position pos_; - marker_ptr marker_; - agg::trans_affine tr_; - double opacity_; - composite_mode_e comp_op_; - - point_render_thunk(pixel_position const& pos, marker const& m, - agg::trans_affine const& tr, double opacity, - composite_mode_e comp_op); - point_render_thunk(point_render_thunk && rhs) - : pos_(std::move(rhs.pos_)), - marker_(std::move(rhs.marker_)), - tr_(std::move(rhs.tr_)), - opacity_(std::move(rhs.opacity_)), - comp_op_(std::move(rhs.comp_op_)) {} -}; - struct vector_marker_render_thunk { svg_path_ptr src_; @@ -197,8 +178,7 @@ struct text_render_thunk : noncopyable // Variant type for render thunks to allow us to re-render them // via a static visitor later. -using render_thunk = util::variant; using render_thunk_ptr = std::unique_ptr; @@ -220,8 +200,6 @@ struct render_thunk_extractor : public util::static_visitor<> virtual_renderer_common & common, box2d const& clipping_extent); - void operator()(point_symbolizer const& sym) const; - void operator()(markers_symbolizer const& sym) const; void operator()(text_symbolizer const& sym) const; diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index 5a7e728ad..1d823288d 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -62,13 +62,6 @@ struct thunk_renderer : public util::static_visitor<> : ren_(ren), ras_ptr_(ras_ptr), buf_(buf), common_(common), offset_(offset) {} - void operator()(point_render_thunk const &thunk) const - { - pixel_position new_pos(thunk.pos_.x + offset_.x, thunk.pos_.y + offset_.y); - ren_.render_marker(new_pos, *thunk.marker_, thunk.tr_, thunk.opacity_, - thunk.comp_op_); - } - void operator()(vector_marker_render_thunk const &thunk) const { using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender diff --git a/src/cairo/process_group_symbolizer.cpp b/src/cairo/process_group_symbolizer.cpp index 666cb66d1..35817e417 100644 --- a/src/cairo/process_group_symbolizer.cpp +++ b/src/cairo/process_group_symbolizer.cpp @@ -59,13 +59,6 @@ struct thunk_renderer : public util::static_visitor<> common_(common), offset_(offset) {} - void operator()(point_render_thunk const &thunk) const - { - pixel_position new_pos(thunk.pos_.x + offset_.x, thunk.pos_.y + offset_.y); - ren_.render_marker(new_pos, *thunk.marker_, thunk.tr_, thunk.opacity_, - thunk.comp_op_); - } - void operator()(vector_marker_render_thunk const &thunk) const { cairo_save_restore guard(context_); diff --git a/src/grid/process_group_symbolizer.cpp b/src/grid/process_group_symbolizer.cpp index e2cc6debe..252b8c267 100644 --- a/src/grid/process_group_symbolizer.cpp +++ b/src/grid/process_group_symbolizer.cpp @@ -74,12 +74,6 @@ struct thunk_renderer : public util::static_visitor<> common_(common), feature_(feature), offset_(offset) {} - void operator()(point_render_thunk const &thunk) const - { - ren_.render_marker(feature_, offset_ + thunk.pos_, - *thunk.marker_, thunk.tr_, thunk.opacity_, thunk.comp_op_); - } - void operator()(vector_marker_render_thunk const &thunk) const { using buf_type = grid_rendering_buffer; diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index 75cc4782c..0fae35166 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -29,13 +29,6 @@ namespace mapnik { -point_render_thunk::point_render_thunk(pixel_position const& pos, marker const& m, - agg::trans_affine const& tr, double opacity, - composite_mode_e comp_op) - : pos_(pos), marker_(std::make_shared(m)), - tr_(tr), opacity_(opacity), comp_op_(comp_op) -{} - vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src, svg_attribute_type const& attrs, agg::trans_affine const& marker_trans, @@ -145,21 +138,6 @@ render_thunk_extractor::render_thunk_extractor(box2d & box, common_(common), clipping_extent_(clipping_extent) {} -void render_thunk_extractor::operator()(point_symbolizer const& sym) const -{ - composite_mode_e comp_op = get(sym, keys::comp_op, feature_, common_.vars_, src_over); - - render_point_symbolizer( - sym, feature_, prj_trans_, common_, - [&](pixel_position const& pos, marker const& marker, - agg::trans_affine const& tr, double opacity) { - point_render_thunk thunk(pos, marker, tr, opacity, comp_op); - thunks_.push_back(std::make_unique(std::move(thunk))); - }); - - update_box(); -} - void render_thunk_extractor::operator()(markers_symbolizer const& sym) const { auto renderer_context = std::tie(thunks_);