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)