Refactor markers dispatchers to use a common base class to share code.

This commit is contained in:
Jordan Hollinger 2014-10-06 19:05:19 -04:00 committed by Jordan Hollinger
parent c5d0c44de0
commit 1b15e53b63
12 changed files with 536 additions and 545 deletions

View file

@ -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 <mapnik/color.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/box2d.hpp>
// 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 <typename SvgRenderer, typename RasterizerType, typename RendererBaseType>
void render_vector_marker(SvgRenderer & svg_renderer, RasterizerType & ras, RendererBaseType & renb,
box2d<double> 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 <typename RendererType, typename RasterizerType>
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<pixfmt_pre>;
using interpolator_type = agg::span_interpolator_linear<>;
//using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type>;
using span_gen_type = agg::span_image_resample_rgba_affine<img_accessor_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<RendererType,
agg::span_allocator<color_type>,
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<color_type> 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);
}
}
}

View file

@ -37,10 +37,10 @@ struct pixel_position;
template <typename T> class box2d; template <typename T> class box2d;
namespace svg { struct path_attributes; } namespace svg { struct path_attributes; }
void render_vector_marker(cairo_context & context, pixel_position const& pos, void render_vector_marker(cairo_context & context, svg::svg_path_adapter & svg_path,
svg::svg_path_adapter & svg_path, box2d<double> const& bbox,
agg::pod_bvector<svg::path_attributes> const & attributes, agg::pod_bvector<svg::path_attributes> const & attributes,
agg::trans_affine const& tr, double opacity, bool recenter); box2d<double> const& bbox, agg::trans_affine const& tr,
double opacity);
} }

View file

@ -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 <mapnik/symbolizer.hpp>
#include <mapnik/markers_placement.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geom_util.hpp>
// 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 <typename RendererBase, typename RendererType, typename Detector, typename RendererContext>
struct raster_markers_rasterizer_dispatch_grid : public raster_markers_dispatch<Detector>
{
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<Detector>(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<Detector>::src_;
using raster_markers_dispatch<Detector>::feature_;
using raster_markers_dispatch<Detector>::snap_to_pixels_;
};
template <typename SvgRenderer, typename Detector, typename RendererContext>
struct vector_markers_rasterizer_dispatch_grid : public vector_markers_dispatch<Detector>
{
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<double> 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<Detector>(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<Detector>::bbox_;
using vector_markers_dispatch<Detector>::feature_;
using vector_markers_dispatch<Detector>::snap_to_pixels_;
};
}
#endif

View file

@ -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 <mapnik/feature.hpp>
// 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 <typename RendererType, typename RasterizerType>
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

View file

@ -40,19 +40,7 @@
#include <mapnik/label_collision_detector.hpp> #include <mapnik/label_collision_detector.hpp>
// agg // 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_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 // boost
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -71,22 +59,20 @@ using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
template <typename Detector> template <typename Detector>
struct vector_markers_dispatch : mapnik::noncopyable struct vector_markers_dispatch : mapnik::noncopyable
{ {
vector_markers_dispatch(box2d<double> const& bbox, vector_markers_dispatch(svg_path_ptr const& src,
agg::trans_affine const& marker_trans, agg::trans_affine const& marker_trans,
symbolizer_base const& sym, symbolizer_base const& sym,
Detector & detector, Detector & detector,
double scale_factor, double scale_factor,
feature_impl & feature, feature_impl & feature,
attributes const& vars, attributes const& vars)
bool snap_to_pixels) : src_(src),
: bbox_(bbox),
marker_trans_(marker_trans), marker_trans_(marker_trans),
sym_(sym), sym_(sym),
detector_(detector), detector_(detector),
feature_(feature), feature_(feature),
vars_(vars), vars_(vars),
scale_factor_(scale_factor), scale_factor_(scale_factor)
snap_to_pixels_(snap_to_pixels)
{} {}
virtual ~vector_markers_dispatch() {} virtual ~vector_markers_dispatch() {}
@ -101,10 +87,11 @@ struct vector_markers_dispatch : mapnik::noncopyable
double opacity = get<double>(sym_,keys::opacity, feature_, vars_, 1.0); double opacity = get<double>(sym_,keys::opacity, feature_, vars_, 1.0);
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0); double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2); double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
coord2d center = bbox_.center(); box2d<double> const& bbox = src_->bounding_box();
coord2d center = bbox.center();
agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine tr = recenter * marker_trans_; 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<T, Detector> placement_finder( markers_placement_finder<T, Detector> placement_finder(
placement_method, path, detector_, params); placement_method, path, detector_, params);
double x, y, angle = .0; double x, y, angle = .0;
@ -113,42 +100,39 @@ struct vector_markers_dispatch : mapnik::noncopyable
agg::trans_affine matrix = tr; agg::trans_affine matrix = tr;
matrix.rotate(angle); matrix.rotate(angle);
matrix.translate(x, y); 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: protected:
box2d<double> const& bbox_; svg_path_ptr const& src_;
agg::trans_affine const& marker_trans_; agg::trans_affine const& marker_trans_;
symbolizer_base const& sym_; symbolizer_base const& sym_;
Detector & detector_; Detector & detector_;
feature_impl & feature_; feature_impl & feature_;
attributes const& vars_; attributes const& vars_;
double scale_factor_; double scale_factor_;
bool snap_to_pixels_;
}; };
template <typename Detector> template <typename Detector>
struct raster_markers_dispatch : mapnik::noncopyable 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, agg::trans_affine const& marker_trans,
symbolizer_base const& sym, symbolizer_base const& sym,
Detector & detector, Detector & detector,
double scale_factor, double scale_factor,
feature_impl & feature, feature_impl & feature,
attributes const& vars, attributes const& vars)
bool snap_to_pixels = false)
: src_(src), : src_(src),
marker_trans_(marker_trans), marker_trans_(marker_trans),
sym_(sym), sym_(sym),
detector_(detector), detector_(detector),
feature_(feature), feature_(feature),
vars_(vars), vars_(vars),
scale_factor_(scale_factor), scale_factor_(scale_factor)
snap_to_pixels_(snap_to_pixels)
{} {}
virtual ~raster_markers_dispatch() {} virtual ~raster_markers_dispatch() {}
@ -159,11 +143,11 @@ struct raster_markers_dispatch : mapnik::noncopyable
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false); bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false); bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false);
box2d<double> bbox(0,0, src_.width(), src_.height());
double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0); double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false); bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0); double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2); double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
box2d<double> 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_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges };
markers_placement_finder<T, label_collision_detector4> placement_finder( markers_placement_finder<T, label_collision_detector4> placement_finder(
placement_method, path, detector_, params); placement_method, path, detector_, params);
@ -173,199 +157,20 @@ struct raster_markers_dispatch : mapnik::noncopyable
agg::trans_affine matrix = marker_trans_; agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle); matrix.rotate(angle);
matrix.translate(x, y); 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: protected:
image_data_32 const& src_; image_data_32 & src_;
agg::trans_affine const& marker_trans_; agg::trans_affine const& marker_trans_;
symbolizer_base const& sym_; symbolizer_base const& sym_;
Detector & detector_; Detector & detector_;
feature_impl & feature_; feature_impl & feature_;
attributes const& vars_; attributes const& vars_;
double scale_factor_; double scale_factor_;
bool snap_to_pixels_;
};
template <typename SvgRenderer, typename Detector, typename RendererContext>
struct vector_markers_rasterizer_dispatch_agg : public vector_markers_dispatch<Detector>
{
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<double> 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<Detector>(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<agg::comp_op_e>(get<composite_mode_e>(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<Detector>::bbox_;
using vector_markers_dispatch<Detector>::snap_to_pixels_;
};
template <typename Detector, typename RendererContext>
struct raster_markers_rasterizer_dispatch_agg : public raster_markers_dispatch<Detector>
{
using BufferType = typename std::remove_reference<typename std::tuple_element<0,RendererContext>::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<color_type, order_type>; // comp blender
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, BufferType>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
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<Detector>(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<agg::comp_op_e>(get<composite_mode_e>(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<pixfmt_pre>;
using interpolator_type = agg::span_interpolator_linear<>;
//using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type>;
using span_gen_type = agg::span_image_resample_rgba_affine<img_accessor_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<renderer_base,
agg::span_allocator<color_type>,
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<color_type> 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<Detector>::src_;
using raster_markers_dispatch<Detector>::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); 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);

View file

@ -32,17 +32,17 @@
namespace mapnik { namespace mapnik {
template <typename T0, typename T1, typename T2> template <typename VD, typename RD, typename RendererType, typename ContextType>
void render_markers_symbolizer(markers_symbolizer const& sym, void render_markers_symbolizer(markers_symbolizer const& sym,
mapnik::feature_impl & feature, mapnik::feature_impl & feature,
proj_transform const& prj_trans, proj_transform const& prj_trans,
renderer_common const& common, RendererType const& common,
box2d<double> const& clip_box, box2d<double> const& clip_box,
T2 const& renderer_context) ContextType const& renderer_context)
{ {
using namespace mapnik::svg; using namespace mapnik::svg;
using vector_dispatch_type = T0; using vector_dispatch_type = VD;
using raster_dispatch_type = T1; using raster_dispatch_type = RD;
std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse"); std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse");
bool clip = get<value_bool>(sym, keys::clip, feature, common.vars_, false); bool clip = get<value_bool>(sym, keys::clip, feature, common.vars_, false);
@ -71,18 +71,17 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
if (filename == "shape://ellipse" if (filename == "shape://ellipse"
&& (has_key<double>(sym,keys::width) || has_key<double>(sym,keys::height))) && (has_key<double>(sym,keys::width) || has_key<double>(sym,keys::height)))
{ {
svg_storage_type marker_ellipse; svg_path_ptr marker_ellipse = std::make_shared<svg_storage_type>();
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source()); vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse->source());
svg_path_adapter svg_path(stl_storage); 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; svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_); bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform); auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform); if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
box2d<double> bbox = marker_ellipse.bounding_box(); vector_dispatch_type rasterizer_dispatch(marker_ellipse,
vector_dispatch_type rasterizer_dispatch(svg_path, svg_path,
result ? attributes : (*stock_vector_marker)->attributes(), result ? attributes : (*stock_vector_marker)->attributes(),
bbox,
image_tr, image_tr,
sym, sym,
*common.detector_, *common.detector_,
@ -124,9 +123,9 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
svg_path_adapter svg_path(stl_storage); svg_path_adapter svg_path(stl_storage);
svg_attribute_type attributes; svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_); 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(), result ? attributes : (*stock_vector_marker)->attributes(),
bbox,
image_tr, image_tr,
sym, sym,
*common.detector_, *common.detector_,

View file

@ -32,6 +32,7 @@
#include <mapnik/marker_helpers.hpp> #include <mapnik/marker_helpers.hpp>
#include <mapnik/marker.hpp> #include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp> #include <mapnik/marker_cache.hpp>
#include <mapnik/agg_render_marker.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp> #include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_storage.hpp> #include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp> #include <mapnik/svg/svg_path_adapter.hpp>
@ -59,6 +60,107 @@
namespace mapnik { namespace mapnik {
namespace detail {
template <typename SvgRenderer, typename Detector, typename RendererContext>
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector>
{
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<Detector>(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<agg::comp_op_e>(get<composite_mode_e>(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 <typename Detector, typename RendererContext>
struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch<Detector>
{
using BufferType = typename std::remove_reference<typename std::tuple_element<0,RendererContext>::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<color_type, order_type>; // comp blender
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, BufferType>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
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<Detector>(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<agg::comp_op_e>(get<composite_mode_e>(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 <typename T0, typename T1> template <typename T0, typename T1>
void agg_renderer<T0,T1>::process(markers_symbolizer const& sym, void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
feature_impl & feature, feature_impl & feature,
@ -94,8 +196,8 @@ void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_); auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_);
using context_type = decltype(renderer_context); using context_type = decltype(renderer_context);
using vector_dispatch_type = vector_markers_rasterizer_dispatch_agg<svg_renderer_type, detector_type, context_type>; using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type, detector_type, context_type>;
using raster_dispatch_type = raster_markers_rasterizer_dispatch_agg<detector_type, context_type>; using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<detector_type, context_type>;
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>( render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
sym, feature, prj_trans, common_, clip_box, renderer_context); sym, feature, prj_trans, common_, clip_box, renderer_context);

View file

@ -32,21 +32,12 @@
namespace mapnik namespace mapnik
{ {
void render_vector_marker(cairo_context & context, pixel_position const& pos, void render_vector_marker(cairo_context & context, svg::svg_path_adapter & svg_path,
svg::svg_path_adapter & svg_path, box2d<double> const& bbox,
agg::pod_bvector<svg::path_attributes> const & attributes, agg::pod_bvector<svg::path_attributes> const & attributes,
agg::trans_affine const& tr, double opacity, bool recenter) box2d<double> const& bbox, agg::trans_affine const& tr,
double opacity)
{ {
using namespace mapnik::svg; using namespace mapnik::svg;
agg::trans_affine mtx = tr;
if (recenter)
{
coord<double,2> c = bbox.center();
mtx = agg::trans_affine_translation(-c.x,-c.y);
mtx *= tr;
mtx.translate(pos.x, pos.y);
}
agg::trans_affine transform; agg::trans_affine transform;
for(unsigned i = 0; i < attributes.size(); ++i) for(unsigned i = 0; i < attributes.size(); ++i)
@ -56,7 +47,7 @@ void render_vector_marker(cairo_context & context, pixel_position const& pos,
continue; continue;
cairo_save_restore guard(context); cairo_save_restore guard(context);
transform = attr.transform; transform = attr.transform;
transform *= mtx; transform *= tr;
// TODO - this 'is_valid' check is not used in the AGG renderer and also // TODO - this 'is_valid' check is not used in the AGG renderer and also
// appears to lead to bogus results with // appears to lead to bogus results with

View file

@ -201,13 +201,20 @@ void cairo_renderer<T>::render_marker(pixel_position const& pos,
mapnik::svg_path_ptr vmarker = *marker.get_vector_data(); mapnik::svg_path_ptr vmarker = *marker.get_vector_data();
if (vmarker) if (vmarker)
{ {
agg::trans_affine marker_tr = tr;
marker_tr *=agg::trans_affine_scaling(common_.scale_factor_);
box2d<double> bbox = vmarker->bounding_box(); box2d<double> bbox = vmarker->bounding_box();
agg::trans_affine marker_tr = tr;
if (recenter)
{
coord<double,2> c = bbox.center();
marker_tr = agg::trans_affine_translation(-c.x,-c.y);
marker_tr *= tr;
}
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes(); agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes();
svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source()); svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source());
svg::svg_path_adapter svg_path(stl_storage); 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()) else if (marker.is_bitmap())

View file

@ -32,6 +32,7 @@
#include <mapnik/attribute.hpp> #include <mapnik/attribute.hpp>
#include <mapnik/marker.hpp> #include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp> #include <mapnik/marker_cache.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp> #include <mapnik/renderer_common/process_markers_symbolizer.hpp>
// agg // agg
@ -43,135 +44,67 @@ namespace mapnik
class feature_impl; class feature_impl;
class proj_transform; class proj_transform;
namespace svg { struct path_attributes; }
namespace detail { namespace detail {
template <typename RendererContext, typename SvgPath, typename Attributes, typename Detector> template <typename RendererContext, typename Detector>
struct markers_dispatch : mapnik::noncopyable struct vector_markers_dispatch_cairo : public vector_markers_dispatch<Detector>
{ {
markers_dispatch(SvgPath & marker, vector_markers_dispatch_cairo(svg_path_ptr const& src,
Attributes const& attributes, svg::svg_path_adapter & path,
box2d<double> const& bbox, svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans, agg::trans_affine const& marker_trans,
markers_symbolizer const& sym, markers_symbolizer const& sym,
Detector & detector, Detector & detector,
double scale_factor, double scale_factor,
feature_impl const& feature, feature_impl & feature,
mapnik::attributes const& vars, mapnik::attributes const& vars,
bool snap_to_pixels, bool snap_to_pixels,
RendererContext const& renderer_context) RendererContext const& renderer_context)
:marker_(marker), : vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
attributes_(attributes), path_(path),
bbox_(bbox), attr_(attrs),
marker_trans_(marker_trans),
sym_(sym),
detector_(detector),
scale_factor_(scale_factor),
feature_(feature),
vars_(vars),
ctx_(std::get<0>(renderer_context)) ctx_(std::get<0>(renderer_context))
{} {}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
template <typename T>
void add_path(T & path)
{ {
marker_placement_enum placement_method = get<marker_placement_enum>( render_vector_marker(ctx_,
sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); path_,
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false); attr_,
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false); this->src_->bounding_box(),
bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false); marker_tr,
double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0); opacity);
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(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<T, label_collision_detector4> 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);
}
} }
SvgPath & marker_; private:
Attributes const& attributes_; svg::svg_path_adapter & path_;
box2d<double> const& bbox_; svg_attribute_type const& attr_;
agg::trans_affine const& marker_trans_;
markers_symbolizer const& sym_;
Detector & detector_;
double scale_factor_;
feature_impl const& feature_;
attributes const& vars_;
cairo_context & ctx_; cairo_context & ctx_;
}; };
template <typename RendererContext, typename Detector> template <typename RendererContext, typename Detector>
struct raster_markers_dispatch : mapnik::noncopyable struct raster_markers_dispatch_cairo : public raster_markers_dispatch<Detector>
{ {
raster_markers_dispatch(mapnik::image_data_32 & src, raster_markers_dispatch_cairo(mapnik::image_data_32 & src,
agg::trans_affine const& marker_trans, agg::trans_affine const& marker_trans,
markers_symbolizer const& sym, markers_symbolizer const& sym,
Detector & detector, Detector & detector,
double scale_factor, double scale_factor,
feature_impl const& feature, feature_impl & feature,
mapnik::attributes const& vars, mapnik::attributes const& vars,
RendererContext const& renderer_context) RendererContext const& renderer_context)
: src_(src), : raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
detector_(detector),
sym_(sym),
marker_trans_(marker_trans),
scale_factor_(scale_factor),
feature_(feature),
vars_(vars),
ctx_(std::get<0>(renderer_context)) {} ctx_(std::get<0>(renderer_context)) {}
template <typename T> ~raster_markers_dispatch_cairo() {}
void add_path(T & path)
void render_marker(agg::trans_affine const& marker_tr, double opacity)
{ {
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); ctx_.add_image(marker_tr, this->src_, opacity);
double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0);
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
box2d<double> 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<T, label_collision_detector4> 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);
}
} }
image_data_32 & src_; private:
Detector & detector_;
markers_symbolizer const& sym_;
agg::trans_affine const& marker_trans_;
double scale_factor_;
feature_impl const& feature_;
attributes const& vars_;
cairo_context & ctx_; cairo_context & ctx_;
}; };
@ -182,8 +115,6 @@ void cairo_renderer<T>::process(markers_symbolizer const& sym,
mapnik::feature_impl & feature, mapnik::feature_impl & feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
cairo_save_restore guard(context_); cairo_save_restore guard(context_);
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, common_.vars_, src_over); composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, common_.vars_, src_over);
context_.set_operator(comp_op); context_.set_operator(comp_op);
@ -192,11 +123,10 @@ void cairo_renderer<T>::process(markers_symbolizer const& sym,
auto renderer_context = std::tie(context_); auto renderer_context = std::tie(context_);
using RendererContextType = decltype(renderer_context); using RendererContextType = decltype(renderer_context);
using vector_dispatch_type = detail::markers_dispatch<RendererContextType, using vector_dispatch_type = detail::vector_markers_dispatch_cairo<RendererContextType,
svg::path_adapter<svg::vertex_stl_adapter<svg::svg_path_storage> >, label_collision_detector4>;
svg_attribute_type,label_collision_detector4>;
using raster_dispatch_type = detail::raster_markers_dispatch<RendererContextType, using raster_dispatch_type = detail::raster_markers_dispatch_cairo<RendererContextType,
label_collision_detector4>; label_collision_detector4>;

View file

@ -45,11 +45,14 @@ porting notes -->
// mapnik // mapnik
#include <mapnik/feature.hpp> #include <mapnik/feature.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/grid/grid_rasterizer.hpp> #include <mapnik/grid/grid_rasterizer.hpp>
#include <mapnik/grid/grid_renderer.hpp> #include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/grid/grid_renderer_base.hpp> #include <mapnik/grid/grid_renderer_base.hpp>
#include <mapnik/grid/grid_render_marker.hpp>
#include <mapnik/grid/grid.hpp> #include <mapnik/grid/grid.hpp>
#include <mapnik/grid/grid_marker_helpers.hpp>
#include <mapnik/debug.hpp> #include <mapnik/debug.hpp>
#include <mapnik/geom_util.hpp> #include <mapnik/geom_util.hpp>
@ -77,6 +80,111 @@ porting notes -->
namespace mapnik { namespace mapnik {
namespace detail {
template <typename SvgRenderer, typename Detector, typename RendererContext>
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector>
{
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<Detector>(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 <typename RendererBase, typename RendererType, typename Detector, typename RendererContext>
struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch<Detector>
{
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<Detector>(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 <typename T> template <typename T>
void grid_renderer<T>::process(markers_symbolizer const& sym, void grid_renderer<T>::process(markers_symbolizer const& sym,
mapnik::feature_impl & feature, mapnik::feature_impl & feature,
@ -100,10 +208,10 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_); auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_);
using context_type = decltype(renderer_context); using context_type = decltype(renderer_context);
using vector_dispatch_type = vector_markers_rasterizer_dispatch_grid<svg_renderer_type, using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type,
detector_type, detector_type,
context_type>; context_type>;
using raster_dispatch_type = raster_markers_rasterizer_dispatch_grid<grid_renderer_base_type, using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<grid_renderer_base_type,
renderer_type, renderer_type,
detector_type, detector_type,
context_type>; context_type>;

View file

@ -23,6 +23,9 @@
// mapnik // mapnik
#include <mapnik/marker_helpers.hpp> #include <mapnik/marker_helpers.hpp>
#include "agg_ellipse.h"
#include "agg_color_rgba.h"
namespace mapnik { 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) 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)