Merge branch 'master' into spirit-x3

This commit is contained in:
artemp 2016-01-29 11:15:19 +01:00
commit 3e866e63b2
60 changed files with 1361 additions and 1363 deletions

View file

@ -1,4 +1,3 @@
OS := $(shell uname -s)
PYTHON = python
@ -40,18 +39,15 @@ src/json/libmapnik-json.a:
# we first build memory intensive files with -j1
$(PYTHON) scons/scons.py -j1 \
--config=cache --implicit-cache --max-drift=1 \
src/renderer_common/process_group_symbolizer.os \
src/renderer_common/render_group_symbolizer.os \
src/renderer_common/render_markers_symbolizer.os \
src/renderer_common/render_thunk_extractor.os \
src/json/libmapnik-json.a \
src/wkt/libmapnik-wkt.a \
src/css_color_grammar.os \
src/expression_grammar_x3.os \
src/image_filter_types.os \
src/agg/process_markers_symbolizer.os \
src/agg/process_group_symbolizer.os \
src/grid/process_markers_symbolizer.os \
src/grid/process_group_symbolizer.os \
src/cairo/process_markers_symbolizer.os \
src/cairo/process_group_symbolizer.os \
src/expression_grammar.os \
src/transform_expression_grammar.os \
src/image_filter_grammar.os \
mapnik: src/json/libmapnik-json.a
# then install the rest with -j$(JOBS)

2
deps/mapbox/variant vendored

@ -1 +1 @@
Subproject commit 9afd6406065440e02b6bf42db4633b815846db0d
Subproject commit 7f7c667f870541c208c07d99a9f2c22dfa1f32de

View file

@ -45,27 +45,27 @@ struct evaluate
: feature_(f),
vars_(v) {}
value_integer operator() (value_integer val) const
value_type operator() (value_integer val) const
{
return val;
}
value_double operator() (value_double val) const
value_type operator() (value_double val) const
{
return val;
}
value_bool operator() (value_bool val) const
value_type operator() (value_bool val) const
{
return val;
}
value_null operator() (value_null val) const
value_type operator() (value_null val) const
{
return val;
}
value_unicode_string const& operator() (value_unicode_string const& str) const
value_type operator() (value_unicode_string const& str) const
{
return str;
}

View file

@ -100,10 +100,8 @@ private:
static font_memory_cache_type global_memory_fonts_;
};
class MAPNIK_DECL face_manager : private util::noncopyable
class MAPNIK_DECL face_manager
{
using face_ptr_cache_type = std::map<std::string, face_ptr>;
public:
face_manager(font_library & library,
freetype_engine::font_file_mapping_type const& font_file_mapping,
@ -112,9 +110,13 @@ public:
face_set_ptr get_face_set(std::string const& name);
face_set_ptr get_face_set(font_set const& fset);
face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset);
inline stroker_ptr get_stroker() { return stroker_; }
stroker_ptr get_stroker() const { return stroker_; }
private:
face_ptr_cache_type face_ptr_cache_;
using face_cache = std::map<std::string, face_ptr>;
using face_cache_ptr = std::shared_ptr<face_cache>;
face_cache_ptr face_cache_;
font_library & library_;
freetype_engine::font_file_mapping_type const& font_file_mapping_;
freetype_engine::font_memory_cache_type const& font_memory_cache_;

View file

@ -178,12 +178,12 @@ struct geom_reproj_copy_visitor
: proj_trans_(proj_trans),
n_err_(n_err) {}
geometry<T> operator() (geometry_empty const&)
geometry<T> operator() (geometry_empty const&) const
{
return geometry_empty();
}
geometry<T> operator() (point<T> const& p)
geometry<T> operator() (point<T> const& p) const
{
geometry<T> geom; // default empty
unsigned int intial_err = n_err_;
@ -193,7 +193,7 @@ struct geom_reproj_copy_visitor
return geom;
}
geometry<T> operator() (line_string<T> const& ls)
geometry<T> operator() (line_string<T> const& ls) const
{
geometry<T> geom; // default empty
unsigned int intial_err = n_err_;
@ -203,7 +203,7 @@ struct geom_reproj_copy_visitor
return geom;
}
geometry<T> operator() (polygon<T> const& poly)
geometry<T> operator() (polygon<T> const& poly) const
{
geometry<T> geom; // default empty
polygon<T> new_poly = reproject_internal(poly, proj_trans_, n_err_);
@ -212,7 +212,7 @@ struct geom_reproj_copy_visitor
return geom;
}
geometry<T> operator() (multi_point<T> const& mp)
geometry<T> operator() (multi_point<T> const& mp) const
{
geometry<T> geom; // default empty
multi_point<T> new_mp = reproject_internal(mp, proj_trans_, n_err_);
@ -221,7 +221,7 @@ struct geom_reproj_copy_visitor
return geom;
}
geometry<T> operator() (multi_line_string<T> const& mls)
geometry<T> operator() (multi_line_string<T> const& mls) const
{
geometry<T> geom; // default empty
multi_line_string<T> new_mls = reproject_internal(mls, proj_trans_, n_err_);
@ -230,7 +230,7 @@ struct geom_reproj_copy_visitor
return geom;
}
geometry<T> operator() (multi_polygon<T> const& mpoly)
geometry<T> operator() (multi_polygon<T> const& mpoly) const
{
geometry<T> geom; // default empty
multi_polygon<T> new_mpoly = reproject_internal(mpoly, proj_trans_, n_err_);
@ -239,7 +239,7 @@ struct geom_reproj_copy_visitor
return geom;
}
geometry<T> operator() (geometry_collection<T> const& c)
geometry<T> operator() (geometry_collection<T> const& c) const
{
geometry<T> geom; // default empty
geometry_collection<T> new_c = reproject_internal(c, proj_trans_, n_err_);
@ -284,15 +284,15 @@ struct geom_reproj_visitor {
: proj_trans_(proj_trans) {}
template <typename T>
bool operator() (geometry<T> & geom)
bool operator() (geometry<T> & geom) const
{
return mapnik::util::apply_visitor((*this), geom);
}
bool operator() (geometry_empty &) { return true; }
bool operator() (geometry_empty &) const { return true; }
template <typename T>
bool operator() (point<T> & p)
bool operator() (point<T> & p) const
{
if (!proj_trans_.forward(p))
{
@ -302,7 +302,7 @@ struct geom_reproj_visitor {
}
template <typename T>
bool operator() (line_string<T> & ls)
bool operator() (line_string<T> & ls) const
{
if (proj_trans_.forward(ls) > 0)
{
@ -312,7 +312,7 @@ struct geom_reproj_visitor {
}
template <typename T>
bool operator() (polygon<T> & poly)
bool operator() (polygon<T> & poly) const
{
if (proj_trans_.forward(poly.exterior_ring) > 0)
{
@ -330,13 +330,13 @@ struct geom_reproj_visitor {
}
template <typename T>
bool operator() (multi_point<T> & mp)
bool operator() (multi_point<T> & mp) const
{
return (*this) (static_cast<line_string<T> &>(mp));
}
template <typename T>
bool operator() (multi_line_string<T> & mls)
bool operator() (multi_line_string<T> & mls) const
{
for (auto & ls : mls)
{
@ -349,7 +349,7 @@ struct geom_reproj_visitor {
}
template <typename T>
bool operator() (multi_polygon<T> & mpoly)
bool operator() (multi_polygon<T> & mpoly) const
{
for (auto & poly : mpoly)
{
@ -362,7 +362,7 @@ struct geom_reproj_visitor {
}
template <typename T>
bool operator() (geometry_collection<T> & c)
bool operator() (geometry_collection<T> & c) const
{
for (auto & g : c)
{

View file

@ -31,43 +31,51 @@
// stl
#include <vector>
using std::vector;
namespace mapnik
{
using bound_box = box2d<double>;
struct group_layout_manager
{
group_layout_manager(group_layout const& layout)
using bound_box = box2d<double>;
group_layout_manager()
: update_layout_(false)
{}
explicit group_layout_manager(group_layout const& layout)
: layout_(layout),
input_origin_(0, 0),
member_boxes_(vector<bound_box>()),
member_offsets_(vector<pixel_position>()),
update_layout_(true)
update_layout_(false)
{
}
group_layout_manager(group_layout const& layout, pixel_position const& input_origin)
: layout_(layout),
input_origin_(input_origin),
member_boxes_(vector<bound_box>()),
member_offsets_(vector<pixel_position>()),
update_layout_(true)
update_layout_(false)
{
}
group_layout_manager(group_layout const& layout, pixel_position const& input_origin,
vector<bound_box> const& item_boxes)
std::vector<bound_box> const& item_boxes)
: layout_(layout),
input_origin_(input_origin),
member_boxes_(item_boxes),
member_offsets_(vector<pixel_position>()),
update_layout_(true)
{
}
void set_input_origin(double x, double y)
{
input_origin_.set(x, y);
update_layout_ = true;
}
void set_input_origin(pixel_position const& input_origin)
{
input_origin_ = input_origin;
update_layout_ = true;
}
inline void set_layout(group_layout const& layout)
{
layout_ = layout;
@ -94,8 +102,8 @@ private:
group_layout layout_;
pixel_position input_origin_;
vector<bound_box> member_boxes_;
vector<pixel_position> member_offsets_;
std::vector<bound_box> member_boxes_;
std::vector<pixel_position> member_offsets_;
bool update_layout_;
};

View file

@ -683,7 +683,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
using namespace boost::gil;
rgba8_view_t src_view = rgba8_view(src);
bool premultiplied = src.get_premultiplied();
for (std::ptrdiff_t y = 0; y < src_view.height(); ++y)
{
rgba8_view_t::x_iterator src_it = src_view.row_begin(static_cast<long>(y));
@ -738,7 +738,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
X = deviate_x * Y / deviate_y;
Z = (1.0 - (deviate_x + deviate_y)) * Y / deviate_y;
// Neutral grey calculated from luminance (in D65)
double neutral_X = 0.312713 * Y / 0.329016;
double neutral_X = 0.312713 * Y / 0.329016;
double neutral_Z = 0.358271 * Y / 0.329016;
// Difference between simulated color and neutral grey
double diff_X = neutral_X - X;
@ -761,12 +761,12 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
// Convert to RGB color space
dr = X * 3.24071 + Y * -1.53726 + Z * -0.498571; // XYZ->RGB (sRGB:D65)
dg = X * -0.969258 + Y * 1.87599 + Z * 0.0415557;
db = X * 0.0556352 + Y * -0.203996 + Z * 1.05707;
db = X * 0.0556352 + Y * -0.203996 + Z * 1.05707;
// Compensate simulated color towards a neutral fit in RGB space
double fit_r = ((dr < 0.0 ? 0.0 : 1.0) - dr) / diff_r;
double fit_g = ((dg < 0.0 ? 0.0 : 1.0) - dg) / diff_g;
double fit_b = ((db < 0.0 ? 0.0 : 1.0) - db) / diff_b;
double adjust = std::max( (fit_r > 1.0 || fit_r < 0.0) ? 0.0 : fit_r,
double adjust = std::max( (fit_r > 1.0 || fit_r < 0.0) ? 0.0 : fit_r,
(fit_g > 1.0 || fit_g < 0.0) ? 0.0 : fit_g
);
adjust = std::max((fit_b > 1.0 || fit_b < 0.0) ? 0.0 : fit_b, adjust);
@ -777,7 +777,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
// Apply gamma correction
dr = std::pow(dr, 1.0 / 2.2);
dg = std::pow(dg, 1.0 / 2.2);
db = std::pow(db, 1.0 / 2.2);
db = std::pow(db, 1.0 / 2.2);
// premultiply
dr *= da;
dg *= da;
@ -917,7 +917,7 @@ struct filter_visitor
: src_(src) {}
template <typename T>
void operator () (T const& filter)
void operator () (T const& filter) const
{
apply_filter(src_, filter);
}
@ -931,9 +931,9 @@ struct filter_radius_visitor
filter_radius_visitor(int & radius)
: radius_(radius) {}
template <typename T>
void operator () (T const& /*filter*/) {}
void operator () (T const& /*filter*/) const {}
void operator () (agg_stack_blur const& op)
void operator () (agg_stack_blur const& op) const
{
if (static_cast<int>(op.rx) > radius_) radius_ = static_cast<int>(op.rx);
if (static_cast<int>(op.ry) > radius_) radius_ = static_cast<int>(op.ry);

View file

@ -41,8 +41,10 @@ namespace mapnik
struct image_any;
namespace svg { struct path_attributes; }
using attr_storage = agg::pod_bvector<mapnik::svg::path_attributes>;
using svg_storage_type = mapnik::svg::svg_storage<mapnik::svg::svg_path_storage,attr_storage>;
using svg::svg_path_adapter;
using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
using svg_storage_type = svg::svg_storage<svg::svg_path_storage, svg_attribute_type>;
using svg_path_ptr = std::shared_ptr<svg_storage_type>;
using image_ptr = std::shared_ptr<image_any>;

View file

@ -35,6 +35,7 @@
#include <mapnik/box2d.hpp>
#include <mapnik/vertex_processor.hpp>
#include <mapnik/renderer_common/apply_vertex_converter.hpp>
#include <mapnik/renderer_common/render_markers_symbolizer.hpp>
// agg
#include "agg_trans_affine.h"
@ -52,60 +53,53 @@ template <typename Detector>
struct vector_markers_dispatch : util::noncopyable
{
vector_markers_dispatch(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans,
symbolizer_base const& sym,
Detector & detector,
double scale_factor,
feature_impl const& feature,
attributes const& vars)
: src_(src),
marker_trans_(marker_trans),
sym_(sym),
detector_(detector),
feature_(feature),
vars_(vars),
scale_factor_(scale_factor)
attributes const& vars,
bool snap_to_pixels,
markers_renderer_context & renderer_context)
: params_(src->bounding_box(), recenter(src) * marker_trans,
sym, feature, vars, scale_factor, snap_to_pixels)
, renderer_context_(renderer_context)
, src_(src)
, path_(path)
, attrs_(attrs)
, detector_(detector)
{}
virtual ~vector_markers_dispatch() {}
template <typename T>
void add_path(T & path)
{
marker_placement_enum placement_method = get<marker_placement_enum, keys::markers_placement_type>(sym_, feature_, vars_);
value_bool ignore_placement = get<value_bool, keys::ignore_placement>(sym_, feature_, vars_);
value_bool allow_overlap = get<value_bool, keys::allow_overlap>(sym_, feature_, vars_);
value_bool avoid_edges = get<value_bool, keys::avoid_edges>(sym_, feature_, vars_);
value_double opacity = get<value_double,keys::opacity>(sym_, feature_, vars_);
value_double spacing = get<value_double, keys::spacing>(sym_, feature_, vars_);
value_double max_error = get<value_double, keys::max_error>(sym_, feature_, vars_);
coord2d center = src_->bounding_box().center();
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine tr = recenter * marker_trans_;
direction_enum direction = get<direction_enum, keys::direction>(sym_, feature_, vars_);
markers_placement_params params { src_->bounding_box(), tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges, direction };
markers_placement_finder<T, Detector> placement_finder(
placement_method, path, detector_, params);
params_.placement_method, path, detector_, params_.placement_params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
while (placement_finder.get_point(x, y, angle, params_.ignore_placement))
{
agg::trans_affine matrix = tr;
agg::trans_affine matrix = params_.placement_params.tr;
matrix.rotate(angle);
matrix.translate(x, y);
render_marker(matrix, opacity);
renderer_context_.render_marker(src_, path_, attrs_, params_, matrix);
}
}
virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0;
protected:
static agg::trans_affine recenter(svg_path_ptr const& src)
{
coord2d center = src->bounding_box().center();
return agg::trans_affine_translation(-center.x, -center.y);
}
markers_dispatch_params params_;
markers_renderer_context & renderer_context_;
svg_path_ptr const& src_;
agg::trans_affine const& marker_trans_;
symbolizer_base const& sym_;
svg_path_adapter & path_;
svg_attribute_type const& attrs_;
Detector & detector_;
feature_impl const& feature_;
attributes const& vars_;
double scale_factor_;
};
template <typename Detector>
@ -117,53 +111,35 @@ struct raster_markers_dispatch : util::noncopyable
Detector & detector,
double scale_factor,
feature_impl const& feature,
attributes const& vars)
: src_(src),
marker_trans_(marker_trans),
sym_(sym),
detector_(detector),
feature_(feature),
vars_(vars),
scale_factor_(scale_factor)
attributes const& vars,
markers_renderer_context & renderer_context)
: params_(box2d<double>(0, 0, src.width(), src.height()),
marker_trans, sym, feature, vars, scale_factor)
, renderer_context_(renderer_context)
, src_(src)
, detector_(detector)
{}
virtual ~raster_markers_dispatch() {}
template <typename T>
void add_path(T & path)
{
marker_placement_enum placement_method = get<marker_placement_enum, keys::markers_placement_type>(sym_, feature_, vars_);
value_bool allow_overlap = get<value_bool, keys::allow_overlap>(sym_, feature_, vars_);
value_bool avoid_edges = get<value_bool, keys::avoid_edges>(sym_, feature_, vars_);
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, vars_);
value_bool ignore_placement = get<value_bool, keys::ignore_placement>(sym_, feature_, vars_);
value_double spacing = get<value_double, keys::spacing>(sym_, feature_, vars_);
value_double max_error = get<value_double, keys::max_error>(sym_, feature_, vars_);
box2d<double> bbox(0,0, src_.width(),src_.height());
direction_enum direction = get<direction_enum, keys::direction>(sym_, feature_, vars_);
markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges, direction };
markers_placement_finder<T, Detector> placement_finder(
placement_method, path, detector_, params);
params_.placement_method, path, detector_, params_.placement_params);
double x, y, angle = .0;
while (placement_finder.get_point(x, y, angle, ignore_placement))
while (placement_finder.get_point(x, y, angle, params_.ignore_placement))
{
agg::trans_affine matrix = marker_trans_;
agg::trans_affine matrix = params_.placement_params.tr;
matrix.rotate(angle);
matrix.translate(x, y);
render_marker(matrix, opacity);
renderer_context_.render_marker(src_, params_, matrix);
}
}
virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0;
protected:
markers_dispatch_params params_;
markers_renderer_context & renderer_context_;
image_rgba8 const& src_;
agg::trans_affine const& marker_trans_;
symbolizer_base const& sym_;
Detector & detector_;
feature_impl const& feature_;
attributes const& vars_;
double scale_factor_;
};
void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars,

View file

@ -40,8 +40,8 @@ namespace mapnik {
struct markers_placement_params
{
box2d<double> const& size;
agg::trans_affine const& tr;
box2d<double> size;
agg::trans_affine tr;
double spacing;
double max_error;
bool allow_overlap;
@ -132,23 +132,8 @@ protected:
// Rotates the size_ box and translates the position.
box2d<double> perform_transform(double angle, double dx, double dy)
{
double x1 = params_.size.minx();
double x2 = params_.size.maxx();
double y1 = params_.size.miny();
double y2 = params_.size.maxy();
agg::trans_affine tr = params_.tr * agg::trans_affine_rotation(angle).translate(dx, dy);
double xA = x1, yA = y1,
xB = x2, yB = y1,
xC = x2, yC = y2,
xD = x1, yD = y2;
tr.transform(&xA, &yA);
tr.transform(&xB, &yB);
tr.transform(&xC, &yC);
tr.transform(&xD, &yD);
box2d<double> result(xA, yA, xC, yC);
result.expand_to_include(xB, yB);
result.expand_to_include(xD, yD);
return result;
return box2d<double>(params_.size, tr);
}
bool set_direction(double & angle)

View file

@ -42,13 +42,16 @@ namespace mapnik {
struct renderer_common : private util::noncopyable
{
using detector_ptr = std::shared_ptr<label_collision_detector4>;
renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor);
renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor,
std::shared_ptr<label_collision_detector4> detector);
detector_ptr detector);
renderer_common(Map const &m, request const &req, attributes const& vars, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor);
~renderer_common();
unsigned width_;
unsigned height_;
@ -60,11 +63,18 @@ struct renderer_common : private util::noncopyable
face_manager_freetype font_manager_;
box2d<double> query_extent_;
view_transform t_;
std::shared_ptr<label_collision_detector4> detector_;
detector_ptr detector_;
protected:
// it's desirable to keep this class implicitly noncopyable to prevent
// inadvertent copying from other places;
// this copy constructor is therefore protected and should only be used
// by virtual_renderer_common
renderer_common(renderer_common const& other);
private:
renderer_common(Map const &m, unsigned width, unsigned height, double scale_factor,
attributes const& vars, view_transform &&t, std::shared_ptr<label_collision_detector4> detector);
attributes const& vars, view_transform && t, detector_ptr detector);
};
}

View file

@ -31,7 +31,7 @@ struct apply_vertex_converter
apply_vertex_converter(VertexConverter & converter, Processor & proc)
: converter_(converter), proc_(proc) {}
template <typename Adapter>
void operator() (Adapter const& adapter) const
void operator() (Adapter const& adapter)
{
converter_.apply(adapter, proc_);
}

View file

@ -1,403 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP
// mapnik
#include <mapnik/pixel_position.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/group/group_layout_manager.hpp>
#include <mapnik/group/group_symbolizer_helper.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
#include <mapnik/text/glyph_positions.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
// agg
#include <agg_trans_affine.h>
namespace mapnik {
class text_symbolizer_helper;
using svg::svg_path_adapter;
using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
struct virtual_renderer_common : private util::noncopyable
{
virtual_renderer_common(renderer_common & common) :
width_(common.width_),
height_(common.height_),
scale_factor_(common.scale_factor_),
vars_(common.vars_),
shared_font_library_(common.shared_font_library_),
font_library_(*shared_font_library_),
font_manager_(common.font_manager_),
query_extent_(common.query_extent_),
t_(common.t_),
detector_(std::make_shared<label_collision_detector4>(common.detector_->extent())) {}
unsigned & width_;
unsigned & height_;
double & scale_factor_;
attributes & vars_;
// TODO: dirty hack for cairo renderer, figure out how to remove this
std::shared_ptr<font_library> & shared_font_library_;
font_library & font_library_;
face_manager_freetype & font_manager_;
box2d<double> & query_extent_;
view_transform & t_;
std::shared_ptr<label_collision_detector4> detector_;
};
// General:
// The approach here is to run the normal symbolizers, but in
// a 'virtual' blank environment where the changes that they
// make are recorded (the detector, the render_* calls).
//
// The recorded boxes are then used to lay out the items and
// the offsets from old to new positions can be used to perform
// the actual rendering calls.
// This should allow us to re-use as much as possible of the
// existing symbolizer layout and rendering code while still
// being able to interpose our own decisions about whether
// a collision has occurred or not.
// Thunk for rendering a particular instance of a point - this
// stores all the arguments necessary to re-render this point
// symbolizer at a later time.
struct vector_marker_render_thunk : util::noncopyable
{
svg_path_ptr src_;
svg_attribute_type attrs_;
agg::trans_affine tr_;
double opacity_;
composite_mode_e comp_op_;
bool snap_to_pixels_;
vector_marker_render_thunk(svg_path_ptr const& src,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,
bool snap_to_pixels);
vector_marker_render_thunk(vector_marker_render_thunk && rhs);
};
struct raster_marker_render_thunk : util::noncopyable
{
image_rgba8 const& src_;
agg::trans_affine tr_;
double opacity_;
composite_mode_e comp_op_;
bool snap_to_pixels_;
raster_marker_render_thunk(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,
bool snap_to_pixels);
raster_marker_render_thunk(raster_marker_render_thunk && rhs);
};
using helper_ptr = std::unique_ptr<text_symbolizer_helper>;
struct text_render_thunk : util::noncopyable
{
// helper is stored here in order
// to keep in scope the text rendering structures
helper_ptr helper_;
placements_list const& placements_;
double opacity_;
composite_mode_e comp_op_;
halo_rasterizer_enum halo_rasterizer_;
text_render_thunk(helper_ptr && helper,
double opacity, composite_mode_e comp_op,
halo_rasterizer_enum halo_rasterizer);
text_render_thunk(text_render_thunk && rhs);
};
// Variant type for render thunks to allow us to re-render them
// via a static visitor later.
using render_thunk = util::variant<vector_marker_render_thunk,
raster_marker_render_thunk,
text_render_thunk>;
using render_thunk_ptr = std::unique_ptr<render_thunk>;
using render_thunk_list = std::list<render_thunk_ptr>;
// Base class for extracting the bounding boxes associated with placing
// a symbolizer at a fake, virtual point - not real geometry.
//
// The bounding boxes can be used for layout, and the thunks are
// used to re-render at locations according to the group layout.
struct render_thunk_extractor
{
render_thunk_extractor(box2d<double> & box,
render_thunk_list & thunks,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
virtual_renderer_common & common,
box2d<double> const& clipping_extent);
void operator()(markers_symbolizer const& sym) const;
void operator()(text_symbolizer const& sym) const;
void operator()(shield_symbolizer const& sym) const;
template <typename T>
void operator()(T const& ) const
{
// TODO: warning if unimplemented?
}
private:
void extract_text_thunk(helper_ptr && helper, text_symbolizer const& sym) const;
box2d<double> & box_;
render_thunk_list & thunks_;
feature_impl & feature_;
attributes const& vars_;
proj_transform const& prj_trans_;
virtual_renderer_common & common_;
box2d<double> clipping_extent_;
void update_box() const;
};
template <typename F>
void render_offset_placements(placements_list const& placements,
pixel_position const& offset,
F render_text) {
for (auto const& glyphs : placements)
{
// move the glyphs to the correct offset
pixel_position base_point = glyphs->get_base_point();
glyphs->set_base_point(base_point + offset);
// update the position of any marker
marker_info_ptr marker_info = glyphs->get_marker();
pixel_position marker_pos = glyphs->marker_pos();
if (marker_info)
{
glyphs->set_marker(marker_info, marker_pos + offset);
}
render_text(glyphs);
// Need to put the base_point back how it was in case something else calls this again
// (don't want to add offset twice) or calls with a different offset.
glyphs->set_base_point(base_point);
if (marker_info)
{
glyphs->set_marker(marker_info, marker_pos);
}
}
}
template <typename F>
void render_group_symbolizer(group_symbolizer const& sym,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
box2d<double> const& clipping_extent,
renderer_common & common,
F render_thunks)
{
// find all column names referenced in the group rules and symbolizers
std::set<std::string> columns;
group_attribute_collector column_collector(columns, false);
column_collector(sym);
group_symbolizer_properties_ptr props = get<group_symbolizer_properties_ptr>(sym, keys::group_properties);
// create a new context for the sub features of this group
context_ptr sub_feature_ctx = std::make_shared<mapnik::context_type>();
// populate new context with column names referenced in the group rules and symbolizers
for (auto const& col_name : columns)
{
sub_feature_ctx->push(col_name);
}
// keep track of the sub features that we'll want to symbolize
// along with the group rules that they matched
std::vector< std::pair<group_rule_ptr, feature_ptr> > matches;
// create a copied 'virtual' common renderer for processing sub feature symbolizers
// create an empty detector for it, so we are sure we won't hit anything
virtual_renderer_common virtual_renderer(common);
// keep track of which lists of render thunks correspond to
// entries in the group_layout_manager.
std::vector<render_thunk_list> layout_thunks;
size_t num_layout_thunks = 0;
// layout manager to store and arrange bboxes of matched features
group_layout_manager layout_manager(props->get_layout(), pixel_position(common.width_ / 2.0, common.height_ / 2.0));
// run feature or sub feature through the group rules & symbolizers
// for each index value in the range
value_integer start = get<value_integer>(sym, keys::start_column);
value_integer end = start + get<value_integer>(sym, keys::num_columns);
for (value_integer col_idx = start; col_idx < end; ++col_idx)
{
// create sub feature with indexed column values
feature_ptr sub_feature = feature_factory::create(sub_feature_ctx, col_idx);
// copy the necessary columns to sub feature
for(auto const& col_name : columns)
{
if (col_name.find('%') != std::string::npos)
{
if (col_name.size() == 1)
{
// column name is '%' by itself, so give the index as the value
sub_feature->put(col_name, col_idx);
}
else
{
// indexed column
std::string col_idx_str;
if (mapnik::util::to_string(col_idx_str,col_idx))
{
std::string col_idx_name = col_name;
boost::replace_all(col_idx_name, "%", col_idx_str);
sub_feature->put(col_name, feature.get(col_idx_name));
}
}
}
else
{
// non-indexed column
sub_feature->put(col_name, feature.get(col_name));
}
}
// add a single point geometry at pixel origin
double x = common.width_ / 2.0, y = common.height_ / 2.0, z = 0.0;
common.t_.backward(&x, &y);
prj_trans.forward(x, y, z);
// note that we choose a point in the middle of the screen to
// try to ensure that we don't get edge artefacts due to any
// symbolizers with avoid-edges set: only the avoid-edges of
// the group symbolizer itself should matter.
geometry::point<double> origin_pt(x,y);
sub_feature->set_geometry(origin_pt);
// get the layout for this set of properties
for (auto const& rule : props->get_rules())
{
if (util::apply_visitor(evaluate<feature_impl,value_type,attributes>(*sub_feature,common.vars_),
*(rule->get_filter())).to_bool())
{
// add matched rule and feature to the list of things to draw
matches.emplace_back(rule, sub_feature);
// construct a bounding box around all symbolizers for the matched rule
bound_box bounds;
render_thunk_list thunks;
render_thunk_extractor extractor(bounds, thunks, *sub_feature, common.vars_, prj_trans,
virtual_renderer, clipping_extent);
for (auto const& _sym : *rule)
{
// TODO: construct layout and obtain bounding box
util::apply_visitor(extractor, _sym);
}
// add the bounding box to the layout manager
layout_manager.add_member_bound_box(bounds);
layout_thunks.emplace_back(std::move(thunks));
++num_layout_thunks;
break;
}
}
}
// create a symbolizer helper
group_symbolizer_helper helper(sym, feature, vars, prj_trans,
common.width_, common.height_,
common.scale_factor_, common.t_,
*common.detector_, clipping_extent);
for (size_t i = 0; i < matches.size(); ++i)
{
group_rule_ptr match_rule = matches[i].first;
feature_ptr match_feature = matches[i].second;
value_unicode_string rpt_key_value = "";
// get repeat key from matched group rule
expression_ptr rpt_key_expr = match_rule->get_repeat_key();
// if no repeat key was defined, use default from group symbolizer
if (!rpt_key_expr)
{
rpt_key_expr = get<expression_ptr>(sym, keys::repeat_key);
}
// evaluate the repeat key with the matched sub feature if we have one
if (rpt_key_expr)
{
rpt_key_value = util::apply_visitor(evaluate<feature_impl,value_type,attributes>(*match_feature,common.vars_),
*rpt_key_expr).to_unicode();
}
helper.add_box_element(layout_manager.offset_box_at(i), rpt_key_value);
}
pixel_position_list positions = helper.get();
for (pixel_position const& pos : positions)
{
for (size_t layout_i = 0; layout_i < num_layout_thunks; ++layout_i)
{
pixel_position const& offset = layout_manager.offset_at(layout_i);
pixel_position render_offset = pos + offset;
render_thunks(layout_thunks[layout_i], render_offset);
}
}
}
} // namespace mapnik
#endif // MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP

View file

@ -0,0 +1,66 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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_RENDERER_COMMON_RENDER_GROUP_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_RENDER_GROUP_SYMBOLIZER_HPP
// mapnik
#include <mapnik/pixel_position.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/renderer_common/render_thunk.hpp>
#include <mapnik/symbolizer_base.hpp>
#include <mapnik/text/glyph_positions.hpp>
namespace mapnik {
struct render_thunk_list_dispatch
{
virtual void operator()(vector_marker_render_thunk const& thunk) = 0;
virtual void operator()(raster_marker_render_thunk const& thunk) = 0;
virtual void operator()(text_render_thunk const& thunk) = 0;
void render_list(render_thunk_list const& thunks, pixel_position const& offset)
{
offset_ = offset;
for (render_thunk_ptr const& thunk : thunks)
{
util::apply_visitor(std::ref(*this), *thunk);
}
}
protected:
pixel_position offset_;
};
MAPNIK_DECL
void render_group_symbolizer(group_symbolizer const& sym,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
box2d<double> const& clipping_extent,
renderer_common & common,
render_thunk_list_dispatch & render_thunks);
} // namespace mapnik
#endif // MAPNIK_RENDERER_COMMON_RENDER_GROUP_SYMBOLIZER_HPP

View file

@ -0,0 +1,76 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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_RENDERER_COMMON_RENDER_MARKERS_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_RENDER_MARKERS_SYMBOLIZER_HPP
#include <mapnik/marker.hpp>
#include <mapnik/markers_placement.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/symbolizer_base.hpp>
namespace mapnik {
struct markers_dispatch_params
{
// placement
markers_placement_params placement_params;
marker_placement_enum placement_method;
value_bool ignore_placement;
// rendering
bool snap_to_pixels;
double scale_factor;
value_double opacity;
markers_dispatch_params(box2d<double> const& size,
agg::trans_affine const& tr,
symbolizer_base const& sym,
feature_impl const& feature,
attributes const& vars,
double scale_factor = 1.0,
bool snap_to_pixels = false);
};
struct markers_renderer_context : util::noncopyable
{
virtual void render_marker(image_rgba8 const& src,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr) = 0;
virtual void render_marker(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr) = 0;
};
MAPNIK_DECL
void render_markers_symbolizer(markers_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans,
renderer_common const& common,
box2d<double> const& clip_box,
markers_renderer_context & renderer_context);
} // namespace mapnik
#endif // MAPNIK_RENDERER_COMMON_RENDER_MARKERS_SYMBOLIZER_HPP

View file

@ -0,0 +1,115 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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_RENDERER_COMMON_RENDER_THUNK_HPP
#define MAPNIK_RENDERER_COMMON_RENDER_THUNK_HPP
// mapnik
#include <mapnik/image_compositing.hpp> // composite_mode_e
#include <mapnik/marker.hpp> // svg_attribute_type, svg_path_ptr
#include <mapnik/symbolizer_enumerations.hpp> // halo_rasterizer_enum
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/text/symbolizer_helpers.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// agg
#include <agg_trans_affine.h>
namespace mapnik {
// Thunk for rendering a particular instance of a point - this
// stores all the arguments necessary to re-render this point
// symbolizer at a later time.
struct vector_marker_render_thunk : util::movable
{
svg_path_ptr src_;
svg_attribute_type attrs_;
agg::trans_affine tr_;
double opacity_;
composite_mode_e comp_op_;
bool snap_to_pixels_;
vector_marker_render_thunk(svg_path_ptr const& src,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,
bool snap_to_pixels)
: src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity),
comp_op_(comp_op), snap_to_pixels_(snap_to_pixels)
{}
};
struct raster_marker_render_thunk : util::movable
{
image_rgba8 const& src_;
agg::trans_affine tr_;
double opacity_;
composite_mode_e comp_op_;
bool snap_to_pixels_;
raster_marker_render_thunk(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,
bool snap_to_pixels)
: src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op),
snap_to_pixels_(snap_to_pixels)
{}
};
struct text_render_thunk : util::movable
{
using helper_ptr = std::unique_ptr<text_symbolizer_helper>;
// helper is stored here in order
// to keep in scope the text rendering structures
helper_ptr helper_;
placements_list const& placements_;
double opacity_;
composite_mode_e comp_op_;
halo_rasterizer_enum halo_rasterizer_;
text_render_thunk(helper_ptr && helper,
double opacity, composite_mode_e comp_op,
halo_rasterizer_enum halo_rasterizer)
: helper_(std::move(helper)),
placements_(helper_->get()),
opacity_(opacity),
comp_op_(comp_op),
halo_rasterizer_(halo_rasterizer)
{}
};
// Variant type for render thunks to allow us to re-render them
// via a static visitor later.
using render_thunk = util::variant<vector_marker_render_thunk,
raster_marker_render_thunk,
text_render_thunk>;
using render_thunk_ptr = std::unique_ptr<render_thunk>;
using render_thunk_list = std::list<render_thunk_ptr>;
} // namespace mapnik
#endif // MAPNIK_RENDERER_COMMON_RENDER_THUNK_HPP

View file

@ -0,0 +1,97 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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_RENDERER_COMMON_RENDER_THUNK_EXTRACTOR_HPP
#define MAPNIK_RENDERER_COMMON_RENDER_THUNK_EXTRACTOR_HPP
// mapnik
#include <mapnik/renderer_common.hpp>
#include <mapnik/renderer_common/render_thunk.hpp>
#include <mapnik/symbolizer_base.hpp>
#include <mapnik/util/noncopyable.hpp>
namespace mapnik {
// The approach here is to run the normal symbolizers, but in
// a 'virtual' blank environment where the changes that they
// make are recorded (the detector, the render_* calls).
//
// The recorded boxes are then used to lay out the items and
// the offsets from old to new positions can be used to perform
// the actual rendering calls.
// This should allow us to re-use as much as possible of the
// existing symbolizer layout and rendering code while still
// being able to interpose our own decisions about whether
// a collision has occurred or not.
struct virtual_renderer_common : renderer_common
{
explicit virtual_renderer_common(renderer_common const& other);
};
// Base class for extracting the bounding boxes associated with placing
// a symbolizer at a fake, virtual point - not real geometry.
//
// The bounding boxes can be used for layout, and the thunks are
// used to re-render at locations according to the group layout.
struct render_thunk_extractor
{
render_thunk_extractor(box2d<double> & box,
render_thunk_list & thunks,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
virtual_renderer_common & common,
box2d<double> const& clipping_extent);
void operator()(markers_symbolizer const& sym) const;
void operator()(text_symbolizer const& sym) const;
void operator()(shield_symbolizer const& sym) const;
template <typename T>
void operator()(T const& ) const
{
// TODO: warning if unimplemented?
}
private:
void extract_text_thunk(text_render_thunk::helper_ptr && helper,
text_symbolizer const& sym) const;
box2d<double> & box_;
render_thunk_list & thunks_;
feature_impl & feature_;
attributes const& vars_;
proj_transform const& prj_trans_;
virtual_renderer_common & common_;
box2d<double> clipping_extent_;
void update_box() const;
};
} // namespace mapnik
#endif // MAPNIK_RENDERER_COMMON_RENDER_THUNK_EXTRACTOR_HPP

View file

@ -19,8 +19,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_PLACEMENTS_LIST_HPP
#define MAPNIK_PLACEMENTS_LIST_HPP
#ifndef MAPNIK_TEXT_GLYPH_POSITIONS_HPP
#define MAPNIK_TEXT_GLYPH_POSITIONS_HPP
//mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/pixel_position.hpp>
@ -79,7 +81,7 @@ public:
pixel_position const& get_base_point() const;
void set_base_point(pixel_position const& base_point);
void set_marker(marker_info_ptr marker, pixel_position const& marker_pos);
marker_info_ptr get_marker() const;
marker_info_ptr const& get_marker() const;
pixel_position const& marker_pos() const;
private:
std::vector<glyph_position> data_;
@ -88,8 +90,46 @@ private:
pixel_position marker_pos_;
box2d<double> bbox_;
};
using glyph_positions_ptr = std::unique_ptr<glyph_positions>;
using placements_list = std::list<glyph_positions_ptr>;
}
#endif // PLACEMENTS_LIST_HPP
struct scoped_glyph_positions_offset
{
scoped_glyph_positions_offset(glyph_positions & glyphs, pixel_position const& offset)
: glyphs_(glyphs)
, base_point_(glyphs.get_base_point())
, marker_pos_(glyphs.marker_pos())
{
// move the glyphs to the correct offset
glyphs_.set_base_point(base_point_ + offset);
// update the position of any marker
if (auto const& marker_info = glyphs_.get_marker())
{
glyphs_.set_marker(marker_info, marker_pos_ + offset);
}
}
~scoped_glyph_positions_offset()
{
// set the base_point back how it was
glyphs_.set_base_point(base_point_);
// restore marker as well, if there is any
if (auto const& marker_info = glyphs_.get_marker())
{
glyphs_.set_marker(marker_info, marker_pos_);
}
}
private:
glyph_positions & glyphs_;
pixel_position base_point_;
pixel_position marker_pos_;
};
} // namespace mapnik
#endif // MAPNIK_TEXT_GLYPH_POSITIONS_HPP

View file

@ -58,8 +58,35 @@ public:
composite_mode_e halo_comp_op = src_over,
double scale_factor = 1.0,
stroker_ptr stroker = stroker_ptr());
void set_comp_op(composite_mode_e comp_op)
{
comp_op_ = comp_op;
}
void set_halo_comp_op(composite_mode_e halo_comp_op)
{
halo_comp_op_ = halo_comp_op;
}
void set_halo_rasterizer(halo_rasterizer_e rasterizer)
{
rasterizer_ = rasterizer;
}
void set_scale_factor(double scale_factor)
{
scale_factor_ = scale_factor;
}
void set_stroker(stroker_ptr stroker)
{
stroker_ = stroker;
}
void set_transform(agg::trans_affine const& transform);
void set_halo_transform(agg::trans_affine const& halo_transform);
protected:
using glyph_vector = std::vector<glyph_t>;
void prepare_glyphs(glyph_positions const& positions);

View file

@ -111,11 +111,11 @@ struct transform_processor
vars_(v),
scale_factor_(scale_factor) {}
void operator() (identity_node const&)
void operator() (identity_node const&) const
{
}
void operator() (matrix_node const& node)
void operator() (matrix_node const& node) const
{
double a = eval(node.a_); // scale x;
double b = eval(node.b_);
@ -126,21 +126,21 @@ struct transform_processor
transform_.multiply(agg::trans_affine(a, b, c, d, e, f));
}
void operator() (translate_node const& node)
void operator() (translate_node const& node) const
{
double tx = eval(node.tx_) * scale_factor_;
double ty = eval(node.ty_, 0.0) * scale_factor_;
transform_.translate(tx, ty);
}
void operator() (scale_node const& node)
void operator() (scale_node const& node) const
{
double sx = eval(node.sx_);
double sy = eval(node.sy_, sx);
transform_.scale(sx, sy);
}
void operator() (rotate_node const& node)
void operator() (rotate_node const& node) const
{
double angle = deg2rad(eval(node.angle_));
double cx = eval(node.cx_, 0.0);
@ -150,7 +150,7 @@ struct transform_processor
transform_.translate(cx, cy);
}
void operator() (skewX_node const& node)
void operator() (skewX_node const& node) const
{
auto degrees = std::fmod(eval(node.angle_),90.0);
if (degrees < -89.0) degrees = -89.0;
@ -159,7 +159,7 @@ struct transform_processor
transform_.multiply(agg::trans_affine_skewing(angle, 0.0));
}
void operator() (skewY_node const& node)
void operator() (skewY_node const& node) const
{
auto degrees = std::fmod(eval(node.angle_),90.0);
if (degrees < -89.0) degrees = -89.0;

View file

@ -28,6 +28,15 @@ namespace mapnik { namespace util {
namespace non_copyable_
{
class movable
{
protected:
constexpr movable() = default;
~movable() = default;
movable( movable && ) = default;
movable& operator=(movable && ) = default;
};
class noncopyable
{
protected:
@ -36,8 +45,10 @@ protected:
noncopyable( noncopyable const& ) = delete;
noncopyable& operator=(noncopyable const& ) = delete;
};
}
using movable = non_copyable_::movable;
using noncopyable = non_copyable_::noncopyable;
}}

View file

@ -69,7 +69,7 @@ bool spatial_index<Value, Filter, InputStream>::check_header(InputStream& in)
template <typename Value, typename Filter, typename InputStream>
box2d<double> spatial_index<Value, Filter, InputStream>::bounding_box(InputStream& in)
{
if (!check_header(in)) throw std::runtime_error("Invalid index file");
if (!check_header(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)");
in.seekg(16 + 4, std::ios::beg);
box2d<double> box;
read_envelope(in, box);
@ -80,7 +80,7 @@ box2d<double> spatial_index<Value, Filter, InputStream>::bounding_box(InputStrea
template <typename Value, typename Filter, typename InputStream>
void spatial_index<Value, Filter, InputStream>::query(Filter const& filter, InputStream& in, std::vector<Value>& results)
{
if (!check_header(in)) throw std::runtime_error("Invalid index file");
if (!check_header(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)");
in.seekg(16, std::ios::beg);
query_node(filter, in, results);
}
@ -115,7 +115,7 @@ void spatial_index<Value, Filter, InputStream>::query_node(Filter const& filter,
template <typename Value, typename Filter, typename InputStream>
void spatial_index<Value, Filter, InputStream>::query_first_n(Filter const& filter, InputStream& in, std::vector<Value>& results, std::size_t count)
{
if (!check_header(in)) throw std::runtime_error("Invalid index file");
if (!check_header(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)");
in.seekg(16, std::ios::beg);
query_first_n_impl(filter, in, results, count);
}

View file

@ -46,30 +46,31 @@ public:
// unary visitor interface
// const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f))
template <typename F, typename V>
auto VARIANT_INLINE static apply_visitor(F && f, V const& v) -> decltype(V::visit(v, f))
{
return V::visit(v, f);
return V::visit(v, std::forward<F>(f));
}
// non-const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f))
template <typename F, typename V>
auto VARIANT_INLINE static apply_visitor(F && f, V & v) -> decltype(V::visit(v, f))
{
return V::visit(v, f);
return V::visit(v, std::forward<F>(f));
}
// binary visitor interface
// const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f))
template <typename F, typename V>
auto VARIANT_INLINE static apply_visitor(F && f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f))
{
return V::binary_visit(v0, v1, f);
return V::binary_visit(v0, v1, std::forward<F>(f));
}
// non-const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f))
template <typename F, typename V>
auto VARIANT_INLINE static apply_visitor(F && f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f))
{
return V::binary_visit(v0, v1, f);
return V::binary_visit(v0, v1, std::forward<F>(f));
}
// getter interface

View file

@ -35,38 +35,38 @@ struct vertex_processor
: proc_(proc) {}
template <typename Geometry>
void operator() (Geometry const& geom)
void operator() (Geometry const& geom) const
{
util::apply_visitor(*this, geom);
}
void operator() (geometry_empty const&)
void operator() (geometry_empty const&) const
{
// no-op
}
template <typename T1>
void operator() (point<T1> const& pt)
void operator() (point<T1> const& pt) const
{
point_vertex_adapter<T1> va(pt);
proc_(va);
}
template <typename T1>
void operator() (line_string<T1> const& line)
void operator() (line_string<T1> const& line) const
{
line_string_vertex_adapter<T1> va(line);
proc_(va);
}
template <typename T1>
void operator() (polygon<T1> const& poly)
void operator() (polygon<T1> const& poly) const
{
polygon_vertex_adapter<T1> va(poly);
proc_(va);
}
template <typename T1>
void operator() (multi_point<T1> const& multi_pt)
void operator() (multi_point<T1> const& multi_pt) const
{
for (auto const& pt : multi_pt)
{
@ -76,7 +76,7 @@ struct vertex_processor
}
template <typename T1>
void operator() (multi_line_string<T1> const& multi_line)
void operator() (multi_line_string<T1> const& multi_line) const
{
for (auto const& line : multi_line)
{
@ -86,7 +86,7 @@ struct vertex_processor
}
template <typename T1>
void operator() (multi_polygon<T1> const& multi_poly)
void operator() (multi_polygon<T1> const& multi_poly) const
{
for ( auto const& poly : multi_poly)
{
@ -96,7 +96,7 @@ struct vertex_processor
}
template <typename T1>
void operator() (geometry_collection<T1> const& collection)
void operator() (geometry_collection<T1> const& collection) const
{
for (auto const& geom : collection)
{

View file

@ -121,11 +121,11 @@ struct setup_agg_bg_visitor
mode_(mode),
opacity_(opacity) {}
void operator() (marker_null const&) {}
void operator() (marker_null const&) const {}
void operator() (marker_svg const&) {}
void operator() (marker_svg const&) const {}
void operator() (marker_rgba8 const& marker)
void operator() (marker_rgba8 const& marker) const
{
mapnik::image_rgba8 const& bg_image = marker.get_data();
std::size_t w = bg_image.width();
@ -361,9 +361,9 @@ struct agg_render_marker_visitor
opacity_(opacity),
comp_op_(comp_op) {}
void operator() (marker_null const&) {}
void operator() (marker_null const&) const {}
void operator() (marker_svg const& marker)
void operator() (marker_svg const& marker) const
{
using color_type = agg::rgba8;
using order_type = agg::order_rgba;
@ -414,7 +414,7 @@ struct agg_render_marker_visitor
svg_renderer.render(*ras_ptr_, sl, renb, mtx, opacity_, bbox);
}
void operator() (marker_rgba8 const& marker)
void operator() (marker_rgba8 const& marker) const
{
using color_type = agg::rgba8;
using order_type = agg::order_rgba;

View file

@ -165,12 +165,12 @@ struct RingRenderer {
};
template <typename BufferType>
struct render_ring_visitor {
struct render_ring_visitor
{
render_ring_visitor(RingRenderer<BufferType> & renderer)
: renderer_(renderer) {}
void operator()(mapnik::geometry::multi_polygon<double> const& geom)
void operator()(mapnik::geometry::multi_polygon<double> const& geom) const
{
for (auto const& poly : geom)
{
@ -178,7 +178,7 @@ struct render_ring_visitor {
}
}
void operator()(mapnik::geometry::polygon<double> const& geom)
void operator()(mapnik::geometry::polygon<double> const& geom) const
{
agg::rgba8 red(255,0,0,255);
agg::rgba8 green(0,255,255,255);
@ -199,7 +199,7 @@ struct render_ring_visitor {
}
template<typename GeomType>
void operator()(GeomType const&) {}
void operator()(GeomType const&) const {}
RingRenderer<BufferType> & renderer_;
};

View file

@ -25,20 +25,16 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/agg_render_marker.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/text/renderer.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/text/glyph_positions.hpp>
#include <mapnik/renderer_common/process_group_symbolizer.hpp>
#include <mapnik/renderer_common/clipping_extent.hpp>
#include <mapnik/renderer_common/render_group_symbolizer.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_converter.hpp>
// agg
#include "agg_trans_affine.h"
@ -55,7 +51,7 @@ template <typename T>
struct thunk_renderer;
template <>
struct thunk_renderer<image_rgba8>
struct thunk_renderer<image_rgba8> : render_thunk_list_dispatch
{
using renderer_type = agg_renderer<image_rgba8>;
using buffer_type = renderer_type::buffer_type;
@ -64,12 +60,13 @@ struct thunk_renderer<image_rgba8>
thunk_renderer(renderer_type &ren,
std::unique_ptr<rasterizer> const& ras_ptr,
buffer_type *buf,
renderer_common &common,
pixel_position const &offset)
: ren_(ren), ras_ptr_(ras_ptr), buf_(buf), common_(common), offset_(offset)
renderer_common &common)
: ren_(ren), ras_ptr_(ras_ptr), buf_(buf), common_(common),
tex_(*buf, HALO_RASTERIZER_FULL, src_over, src_over,
common.scale_factor_, common.font_manager_.get_stroker())
{}
void operator()(vector_marker_render_thunk const &thunk) const
virtual void operator()(vector_marker_render_thunk const& thunk)
{
using blender_type = agg::comp_op_adaptor_rgba_pre<agg::rgba8, agg::order_rgba>; // comp blender
using buf_type = agg::rendering_buffer;
@ -95,7 +92,7 @@ struct thunk_renderer<image_rgba8>
render_vector_marker(svg_renderer, *ras_ptr_, renb, thunk.src_->bounding_box(), offset_tr, thunk.opacity_, thunk.snap_to_pixels_);
}
void operator()(raster_marker_render_thunk const &thunk) const
virtual void operator()(raster_marker_render_thunk const& thunk)
{
using blender_type = agg::comp_op_adaptor_rgba_pre<agg::rgba8, agg::order_rgba>; // comp blender
using buf_type = agg::rendering_buffer;
@ -113,32 +110,25 @@ struct thunk_renderer<image_rgba8>
render_raster_marker(renb, *ras_ptr_, thunk.src_, offset_tr, thunk.opacity_, common_.scale_factor_, thunk.snap_to_pixels_);
}
void operator()(text_render_thunk const &thunk) const
virtual void operator()(text_render_thunk const& thunk)
{
text_renderer_type ren(*buf_, thunk.halo_rasterizer_, thunk.comp_op_, thunk.comp_op_,
common_.scale_factor_, common_.font_manager_.get_stroker());
tex_.set_comp_op(thunk.comp_op_);
tex_.set_halo_comp_op(thunk.comp_op_);
tex_.set_halo_rasterizer(thunk.halo_rasterizer_);
render_offset_placements(
thunk.placements_,
offset_,
[&] (glyph_positions_ptr const& glyphs)
for (auto const& glyphs : thunk.placements_)
{
scoped_glyph_positions_offset tmp_off(*glyphs, offset_);
if (auto const& mark = glyphs->get_marker())
{
marker_info_ptr mark = glyphs->get_marker();
if (mark)
{
ren_.render_marker(glyphs->marker_pos(),
*mark->marker_,
mark->transform_,
thunk.opacity_, thunk.comp_op_);
}
ren.render(*glyphs);
});
}
template <typename T>
void operator()(T const &) const
{
throw std::runtime_error("Rendering of this data type is not supported currently by the renderer");
ren_.render_marker(glyphs->marker_pos(),
*mark->marker_,
mark->transform_,
thunk.opacity_, thunk.comp_op_);
}
tex_.render(*glyphs);
}
}
private:
@ -146,7 +136,7 @@ private:
std::unique_ptr<rasterizer> const& ras_ptr_;
buffer_type *buf_;
renderer_common &common_;
pixel_position offset_;
text_renderer_type tex_;
};
template <typename T0, typename T1>
@ -154,16 +144,11 @@ void agg_renderer<T0,T1>::process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
thunk_renderer<buffer_type> ren(*this, ras_ptr, current_buffer_, common_);
render_group_symbolizer(
sym, feature, common_.vars_, prj_trans, clipping_extent(common_), common_,
[&](render_thunk_list const& thunks, pixel_position const& render_offset)
{
thunk_renderer<buffer_type> ren(*this, ras_ptr, current_buffer_, common_, render_offset);
for (render_thunk_ptr const& thunk : thunks)
{
util::apply_visitor(ren, *thunk);
}
});
ren);
}
template void agg_renderer<image_rgba8>::process(group_symbolizer const&,

View file

@ -71,9 +71,9 @@ struct agg_renderer_process_visitor_l
feature_(feature),
prj_trans_(prj_trans) {}
void operator() (marker_null const&) {}
void operator() (marker_null const&) const {}
void operator() (marker_svg const& marker)
void operator() (marker_svg const& marker) const
{
using color = agg::rgba8;
using order = agg::order_rgba;
@ -147,7 +147,7 @@ struct agg_renderer_process_visitor_l
mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
}
void operator() (marker_rgba8 const& marker)
void operator() (marker_rgba8 const& marker) const
{
using color = agg::rgba8;
using order = agg::order_rgba;
@ -214,7 +214,7 @@ struct agg_renderer_process_visitor_l
using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer_type>;
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
apply_vertex_converter_type apply(converter, ras);
mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
mapnik::util::apply_visitor(vertex_processor_type(apply), feature_.get_geometry());
}
private:

View file

@ -24,22 +24,15 @@
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/agg_render_marker.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp>
#include <mapnik/renderer_common/clipping_extent.hpp>
#include <mapnik/renderer_common/render_markers_symbolizer.hpp>
// agg
#include "agg_basics.h"
#include "agg_renderer_base.h"
@ -52,114 +45,62 @@
#include "agg_path_storage.h"
#include "agg_conv_transform.h"
// boost
#include <boost/optional.hpp>
namespace mapnik {
namespace detail {
template <typename SvgRenderer, typename Detector, typename RendererContext>
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector>
template <typename SvgRenderer, typename BufferType, typename RasterizerType>
struct agg_markers_renderer_context : markers_renderer_context
{
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)),
agg_markers_renderer_context(symbolizer_base const& sym,
feature_impl const& feature,
attributes const& vars,
BufferType & buf,
RasterizerType & ras)
: buf_(buf),
pixf_(buf_),
renb_(pixf_),
svg_renderer_(path, attrs),
ras_(std::get<1>(renderer_context)),
snap_to_pixels_(snap_to_pixels)
ras_(ras)
{
pixf_.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym, feature, vars)));
auto comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, vars);
pixf_.comp_op(static_cast<agg::comp_op_e>(comp_op));
}
~vector_markers_rasterizer_dispatch() {}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
virtual void render_marker(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
render_vector_marker(svg_renderer_, ras_, renb_, this->src_->bounding_box(),
marker_tr, opacity, snap_to_pixels_);
SvgRenderer svg_renderer(path, attrs);
render_vector_marker(svg_renderer, ras_, renb_, src->bounding_box(),
marker_tr, params.opacity, params.snap_to_pixels);
}
virtual void render_marker(image_rgba8 const& src,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
// In the long term this should be a visitor pattern based on the type of
// render src provided that converts the destination pixel type required.
render_raster_marker(renb_, ras_, src, marker_tr, params.opacity,
params.scale_factor, params.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_rgba8 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),
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, keys::comp_op>(sym, feature, vars)));
}
~raster_markers_rasterizer_dispatch() {}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
{
// In the long term this should be a visitor pattern based on the type of render this->src_ provided that converts
// the destination pixel type required.
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_;
};
}
} // namespace detail
template <typename T0, typename T1>
void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
@ -194,16 +135,16 @@ void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
buf_type render_buffer(current_buffer_->bytes(), current_buffer_->width(), current_buffer_->height(), current_buffer_->row_size());
box2d<double> clip_box = clipping_extent(common_);
auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_);
using markers_context_type = decltype(renderer_context);
using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type, detector_type, markers_context_type>;
using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<detector_type, markers_context_type>;
using context_type = detail::agg_markers_renderer_context<svg_renderer_type,
buf_type,
rasterizer>;
context_type renderer_context(sym, feature, common_.vars_, render_buffer, *ras_ptr);
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
render_markers_symbolizer(
sym, feature, prj_trans, common_, clip_box, renderer_context);
}
template void agg_renderer<image_rgba8>::process(markers_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);
}
} // namespace mapnik

View file

@ -30,7 +30,6 @@
#include <mapnik/symbolizer.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/renderer_common/process_point_symbolizer.hpp>

View file

@ -75,9 +75,9 @@ struct agg_renderer_process_visitor_p
feature_(feature),
prj_trans_(prj_trans) {}
void operator() (marker_null const&) {}
void operator() (marker_null const&) const {}
void operator() (marker_svg const& marker)
void operator() (marker_svg const& marker) const
{
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
@ -180,7 +180,7 @@ struct agg_renderer_process_visitor_p
agg::render_scanlines(*ras_ptr_, sl, rp);
}
void operator() (marker_rgba8 const& marker)
void operator() (marker_rgba8 const& marker) const
{
using color = agg::rgba8;
using order = agg::order_rgba;

View file

@ -154,6 +154,7 @@ source = Split(
well_known_srs.cpp
params.cpp
image_filter_types.cpp
image_filter_grammar.cpp
miniz_png.cpp
color.cpp
conversions.cpp
@ -252,8 +253,10 @@ source = Split(
config_error.cpp
color_factory.cpp
renderer_common.cpp
renderer_common/render_group_symbolizer.cpp
renderer_common/render_markers_symbolizer.cpp
renderer_common/render_pattern.cpp
renderer_common/process_group_symbolizer.cpp
renderer_common/render_thunk_extractor.cpp
math.cpp
"""
)

View file

@ -104,10 +104,10 @@ struct setup_marker_visitor
setup_marker_visitor(cairo_context & context, renderer_common const& common)
: context_(context), common_(common) {}
void operator() (marker_null const &) {}
void operator() (marker_svg const &) {}
void operator() (marker_null const &) const{}
void operator() (marker_svg const &) const {}
void operator() (marker_rgba8 const& marker)
void operator() (marker_rgba8 const& marker) const
{
mapnik::image_rgba8 const& bg_image = marker.get_data();
std::size_t w = bg_image.width();

View file

@ -25,13 +25,12 @@
// mapnik
#include <mapnik/marker.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/make_unique.hpp>
#include <mapnik/text/glyph_positions.hpp>
#include <mapnik/cairo/cairo_renderer.hpp>
#include <mapnik/cairo/cairo_render_vector.hpp>
// mapnik symbolizer generics
#include <mapnik/renderer_common/process_group_symbolizer.hpp>
#include <mapnik/renderer_common/render_group_symbolizer.hpp>
#include <memory>
@ -49,20 +48,19 @@ namespace {
// to render it, and the boxes themselves should already be
// in the detector from the placement_finder.
template <typename T>
struct thunk_renderer
struct thunk_renderer : render_thunk_list_dispatch
{
using renderer_type = cairo_renderer<T>;
thunk_renderer(renderer_type & ren,
cairo_context & context,
cairo_face_manager & face_manager,
renderer_common & common,
pixel_position const& offset)
renderer_common & common)
: ren_(ren), context_(context), face_manager_(face_manager),
common_(common), offset_(offset)
common_(common)
{}
void operator()(vector_marker_render_thunk const &thunk) const
virtual void operator()(vector_marker_render_thunk const& thunk)
{
cairo_save_restore guard(context_);
context_.set_operator(thunk.comp_op_);
@ -80,7 +78,7 @@ struct thunk_renderer
thunk.opacity_);
}
void operator()(raster_marker_render_thunk const& thunk) const
virtual void operator()(raster_marker_render_thunk const& thunk)
{
cairo_save_restore guard(context_);
context_.set_operator(thunk.comp_op_);
@ -90,32 +88,24 @@ struct thunk_renderer
context_.add_image(offset_tr, thunk.src_, thunk.opacity_);
}
void operator()(text_render_thunk const &thunk) const
virtual void operator()(text_render_thunk const& thunk)
{
cairo_save_restore guard(context_);
context_.set_operator(thunk.comp_op_);
render_offset_placements(
thunk.placements_,
offset_,
[&] (glyph_positions_ptr const& glyphs)
{
marker_info_ptr mark = glyphs->get_marker();
if (mark)
{
ren_.render_marker(glyphs->marker_pos(),
*mark->marker_,
mark->transform_,
thunk.opacity_, thunk.comp_op_);
}
context_.add_text(*glyphs, face_manager_, src_over, src_over, common_.scale_factor_);
});
}
for (auto const& glyphs : thunk.placements_)
{
scoped_glyph_positions_offset tmp_off(*glyphs, offset_);
template <typename T0>
void operator()(T0 const &) const
{
throw std::runtime_error("Rendering of this type is not supported by the cairo renderer.");
if (auto const& mark = glyphs->get_marker())
{
ren_.render_marker(glyphs->marker_pos(),
*mark->marker_,
mark->transform_,
thunk.opacity_, thunk.comp_op_);
}
context_.add_text(*glyphs, face_manager_, src_over, src_over, common_.scale_factor_);
}
}
private:
@ -123,7 +113,6 @@ private:
cairo_context & context_;
cairo_face_manager & face_manager_;
renderer_common & common_;
pixel_position offset_;
};
} // anonymous namespace
@ -133,16 +122,11 @@ void cairo_renderer<T>::process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
thunk_renderer<T> ren(*this, context_, face_manager_, common_);
render_group_symbolizer(
sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_,
[&](render_thunk_list const& thunks, pixel_position const& render_offset)
{
thunk_renderer<T> ren(*this, context_, face_manager_, common_, render_offset);
for (render_thunk_ptr const& thunk : thunks)
{
util::apply_visitor(ren, *thunk);
}
});
ren);
}
template void cairo_renderer<cairo_ptr>::process(group_symbolizer const&,

View file

@ -25,90 +25,46 @@
// mapnik
#include <mapnik/cairo/cairo_renderer.hpp>
#include <mapnik/cairo/cairo_render_vector.hpp>
#include <mapnik/markers_placement.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp>
// agg
#include "agg/include/agg_array.h" // for pod_bvector
#include "agg/include/agg_trans_affine.h" // for trans_affine, etc
#include <mapnik/renderer_common/render_markers_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
namespace mapnik
{
class feature_impl;
class proj_transform;
namespace detail {
template <typename RendererContext, typename Detector>
struct vector_markers_dispatch_cairo : public vector_markers_dispatch<Detector>
struct cairo_markers_renderer_context : markers_renderer_context
{
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 */, // only used in agg renderer currently
RendererContext const& renderer_context)
: vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
path_(path),
attr_(attrs),
ctx_(std::get<0>(renderer_context))
explicit cairo_markers_renderer_context(cairo_context & ctx)
: ctx_(ctx)
{}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
virtual void render_marker(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
render_vector_marker(ctx_,
path_,
attr_,
this->src_->bounding_box(),
path,
attrs,
src->bounding_box(),
marker_tr,
opacity);
params.opacity);
}
private:
svg::svg_path_adapter & path_;
svg_attribute_type const& attr_;
cairo_context & ctx_;
};
template <typename RendererContext, typename Detector>
struct raster_markers_dispatch_cairo : public raster_markers_dispatch<Detector>
{
raster_markers_dispatch_cairo(image_rgba8 const& 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<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
ctx_(std::get<0>(renderer_context)) {}
~raster_markers_dispatch_cairo() {}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
virtual void render_marker(image_rgba8 const& src,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
ctx_.add_image(marker_tr, this->src_, opacity);
ctx_.add_image(marker_tr, src, params.opacity);
}
private:
cairo_context & ctx_;
};
}
} // namespace detail
template <typename T>
void cairo_renderer<T>::process(markers_symbolizer const& sym,
@ -120,17 +76,10 @@ void cairo_renderer<T>::process(markers_symbolizer const& sym,
context_.set_operator(comp_op);
box2d<double> clip_box = common_.query_extent_;
auto renderer_context = std::tie(context_);
using context_type = detail::cairo_markers_renderer_context;
context_type renderer_context(context_);
using RendererContextType = decltype(renderer_context);
using vector_dispatch_type = detail::vector_markers_dispatch_cairo<RendererContextType,
label_collision_detector4>;
using raster_dispatch_type = detail::raster_markers_dispatch_cairo<RendererContextType,
label_collision_detector4>;
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
render_markers_symbolizer(
sym, feature, prj_trans, common_, clip_box,
renderer_context);
}
@ -139,6 +88,6 @@ template void cairo_renderer<cairo_ptr>::process(markers_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);
}
} // namespace mapnik
#endif // HAVE_CAIRO

View file

@ -362,7 +362,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name,
face_manager::face_manager(font_library & library,
freetype_engine::font_file_mapping_type const& font_file_mapping,
freetype_engine::font_memory_cache_type const& font_cache)
: face_ptr_cache_(),
: face_cache_(new face_cache()),
library_(library),
font_file_mapping_(font_file_mapping),
font_memory_cache_(font_cache)
@ -377,8 +377,8 @@ face_manager::face_manager(font_library & library,
face_ptr face_manager::get_face(std::string const& name)
{
auto itr = face_ptr_cache_.find(name);
if (itr != face_ptr_cache_.end())
auto itr = face_cache_->find(name);
if (itr != face_cache_->end())
{
return itr->second;
}
@ -392,7 +392,7 @@ face_ptr face_manager::get_face(std::string const& name)
freetype_engine::get_cache());
if (face)
{
face_ptr_cache_.emplace(name,face);
face_cache_->emplace(name, face);
}
return face;
}

View file

@ -29,25 +29,13 @@
#include <mapnik/grid/grid_renderer_base.hpp>
#include <mapnik/grid/grid.hpp>
#include <mapnik/grid/grid_render_marker.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/text/placement_finder.hpp>
#include <mapnik/text/symbolizer_helpers.hpp>
#include <mapnik/text/renderer.hpp>
#include <mapnik/text/glyph_positions.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/group/group_layout_manager.hpp>
#include <mapnik/group/group_symbolizer_helper.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/renderer_common/process_point_symbolizer.hpp>
#include <mapnik/renderer_common/process_group_symbolizer.hpp>
#include <mapnik/renderer_common/render_group_symbolizer.hpp>
// agg
#include "agg_trans_affine.h"
@ -61,7 +49,7 @@ namespace mapnik {
* in the detector from the placement_finder.
*/
template <typename T0>
struct thunk_renderer
struct thunk_renderer : render_thunk_list_dispatch
{
using renderer_type = grid_renderer<T0>;
using buffer_type = typename renderer_type::buffer_type;
@ -71,13 +59,13 @@ struct thunk_renderer
grid_rasterizer &ras,
buffer_type &pixmap,
renderer_common &common,
feature_impl &feature,
pixel_position const &offset)
feature_impl &feature)
: ren_(ren), ras_(ras), pixmap_(pixmap),
common_(common), feature_(feature), offset_(offset)
common_(common), feature_(feature),
tex_(pixmap, src_over, common.scale_factor_)
{}
void operator()(vector_marker_render_thunk const &thunk) const
virtual void operator()(vector_marker_render_thunk const& thunk)
{
using buf_type = grid_rendering_buffer;
using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
@ -106,7 +94,7 @@ struct thunk_renderer
pixmap_.add_feature(feature_);
}
void operator()(raster_marker_render_thunk const &thunk) const
virtual void operator()(raster_marker_render_thunk const& thunk)
{
using buf_type = grid_rendering_buffer;
using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
@ -122,34 +110,28 @@ struct thunk_renderer
pixmap_.add_feature(feature_);
}
void operator()(text_render_thunk const &thunk) const
virtual void operator()(text_render_thunk const &thunk)
{
text_renderer_type ren(pixmap_, thunk.comp_op_, common_.scale_factor_);
tex_.set_comp_op(thunk.comp_op_);
value_integer feature_id = feature_.id();
render_offset_placements(
thunk.placements_,
offset_,
[&] (glyph_positions_ptr const& glyphs)
{
marker_info_ptr mark = glyphs->get_marker();
if (mark)
{
ren_.render_marker(feature_,
glyphs->marker_pos(),
*mark->marker_,
mark->transform_,
thunk.opacity_, thunk.comp_op_);
}
ren.render(*glyphs, feature_id);
});
pixmap_.add_feature(feature_);
}
for (auto const& glyphs : thunk.placements_)
{
scoped_glyph_positions_offset tmp_off(*glyphs, offset_);
template <typename T1>
void operator()(T1 const &) const
{
// TODO: warning if unimplemented?
if (auto const& mark = glyphs->get_marker())
{
ren_.render_marker(feature_,
glyphs->marker_pos(),
*mark->marker_,
mark->transform_,
thunk.opacity_, thunk.comp_op_);
}
tex_.render(*glyphs, feature_id);
}
pixmap_.add_feature(feature_);
}
private:
@ -158,7 +140,7 @@ private:
buffer_type &pixmap_;
renderer_common &common_;
feature_impl &feature_;
pixel_position offset_;
text_renderer_type tex_;
};
template <typename T>
@ -166,16 +148,11 @@ void grid_renderer<T>::process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
thunk_renderer<T> ren(*this, *ras_ptr, pixmap_, common_, feature);
render_group_symbolizer(
sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_,
[&](render_thunk_list const& thunks, pixel_position const& render_offset)
{
thunk_renderer<T> ren(*this, *ras_ptr, pixmap_, common_, feature, render_offset);
for (render_thunk_ptr const& thunk : thunks)
{
util::apply_visitor(ren, *thunk);
}
});
ren);
}
template void grid_renderer<grid>::process(group_symbolizer const&,

View file

@ -44,146 +44,92 @@ porting notes -->
*/
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/grid/grid_rasterizer.hpp>
#include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/grid/grid_renderer_base.hpp>
#include <mapnik/grid/grid_render_marker.hpp>
#include <mapnik/grid/grid.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp>
#include <mapnik/renderer_common/render_markers_symbolizer.hpp>
// agg
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h"
// boost
#include <boost/optional.hpp>
// stl
#include <algorithm>
#include <tuple>
namespace mapnik {
namespace detail {
template <typename SvgRenderer, typename Detector, typename RendererContext>
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector>
template <typename SvgRenderer, typename ScanlineRenderer,
typename BufferType, typename RasterizerType, typename PixMapType>
struct grid_markers_renderer_context : markers_renderer_context
{
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),
buf_(std::get<0>(renderer_context)),
grid_markers_renderer_context(feature_impl const& feature,
BufferType & buf,
RasterizerType & ras,
PixMapType & pixmap)
: feature_(feature),
buf_(buf),
pixf_(buf_),
renb_(pixf_),
svg_renderer_(path, attrs),
ras_(std::get<1>(renderer_context)),
pixmap_(std::get<2>(renderer_context)),
ras_(ras),
pixmap_(pixmap),
placed_(false)
{}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
virtual void render_marker(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
SvgRenderer svg_renderer_(path, attrs);
agg::scanline_bin sl_;
svg_renderer_.render_id(ras_, sl_, renb_, this->feature_.id(), marker_tr, opacity, this->src_->bounding_box());
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), marker_tr,
params.opacity, src->bounding_box());
place_feature();
}
virtual void render_marker(image_rgba8 const& src,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
// In the long term this should be a visitor pattern based on the type of
// render src provided that converts the destination pixel type required.
render_raster_marker(ScanlineRenderer(renb_), ras_, src, feature_,
marker_tr, params.opacity);
place_feature();
}
void place_feature()
{
if (!placed_)
{
pixmap_.add_feature(this->feature_);
pixmap_.add_feature(feature_);
placed_ = true;
}
}
private:
feature_impl const& feature_;
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_rgba8 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),
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)
{
// In the long term this should be a visitor pattern based on the type of render this->src_ provided that converts
// the destination pixel type required.
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_;
};
}
} // namespace detail
template <typename T>
void grid_renderer<T>::process(markers_symbolizer const& sym,
@ -193,7 +139,6 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
using buf_type = grid_rendering_buffer;
using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
using detector_type = label_collision_detector4;
using namespace mapnik::svg;
using svg_attribute_type = agg::pod_bvector<path_attributes>;
@ -206,22 +151,20 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
ras_ptr->reset();
box2d<double> clip_box = common_.query_extent_;
auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_);
using grid_context_type = decltype(renderer_context);
using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type,
detector_type,
grid_context_type>;
using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<grid_renderer_base_type,
renderer_type,
detector_type,
grid_context_type>;
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
sym, feature, prj_trans, common_, clip_box,renderer_context);
using context_type = detail::grid_markers_renderer_context<svg_renderer_type,
renderer_type,
buf_type,
grid_rasterizer,
buffer_type>;
context_type renderer_context(feature, render_buf, *ras_ptr, pixmap_);
render_markers_symbolizer(
sym, feature, prj_trans, common_, clip_box, renderer_context);
}
template void grid_renderer<grid>::process(markers_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);
}
} // namespace mapnik
#endif

View file

@ -30,7 +30,6 @@
#include <mapnik/grid/grid.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/parse_path.hpp>

View file

@ -34,19 +34,21 @@ namespace mapnik
// This visitor will process offsets for the given layout
struct process_layout
{
using bound_box = box2d<double>;
// The vector containing the existing, centered item bounding boxes
vector<bound_box> const& member_boxes_;
std::vector<bound_box> const& member_boxes_;
// The vector to populate with item offsets
vector<pixel_position> & member_offsets_;
std::vector<pixel_position> & member_offsets_;
// The origin point of the member boxes
// i.e. The member boxes are positioned around input_origin,
// and the offset values should position them around (0,0)
pixel_position const& input_origin_;
process_layout(vector<bound_box> const& member_bboxes,
vector<pixel_position> &member_offsets,
process_layout(std::vector<bound_box> const& member_bboxes,
std::vector<pixel_position> &member_offsets,
pixel_position const& input_origin)
: member_boxes_(member_bboxes),
member_offsets_(member_offsets),
@ -54,9 +56,12 @@ struct process_layout
{
}
// arrange group memebers in centered, horizontal row
// arrange group members in centered, horizontal row
void operator()(simple_row_layout const& layout) const
{
member_offsets_.clear();
member_offsets_.reserve(member_boxes_.size());
double total_width = (member_boxes_.size() - 1) * layout.get_item_margin();
for (auto const& box : member_boxes_)
{
@ -66,7 +71,7 @@ struct process_layout
double x_offset = -(total_width / 2.0);
for (auto const& box : member_boxes_)
{
member_offsets_.push_back(pixel_position(x_offset - box.minx(), -input_origin_.y));
member_offsets_.emplace_back(x_offset - box.minx(), -input_origin_.y);
x_offset += box.width() + layout.get_item_margin();
}
}
@ -150,7 +155,7 @@ private:
}
};
bound_box group_layout_manager::offset_box_at(size_t i)
box2d<double> group_layout_manager::offset_box_at(size_t i)
{
handle_update();
pixel_position const& offset = member_offsets_.at(i);

View file

@ -190,7 +190,7 @@ struct composite_visitor
dy_(dy) {}
template <typename T>
void operator() (T & dst);
void operator() (T & dst) const;
private:
image_any const& src_;
@ -201,19 +201,19 @@ struct composite_visitor
};
template <typename T>
void composite_visitor::operator() (T & dst)
void composite_visitor::operator() (T & dst) const
{
throw std::runtime_error("Error: Composite with " + std::string(typeid(dst).name()) + " is not supported");
}
template <>
void composite_visitor::operator()<image_rgba8> (image_rgba8 & dst)
void composite_visitor::operator()<image_rgba8> (image_rgba8 & dst) const
{
composite(dst, util::get<image_rgba8>(src_), mode_, opacity_, dx_, dy_);
}
template <>
void composite_visitor::operator()<image_gray32f> (image_gray32f & dst)
void composite_visitor::operator()<image_gray32f> (image_gray32f & dst) const
{
composite(dst, util::get<image_gray32f>(src_), mode_, opacity_, dx_, dy_);
}

View file

@ -37,7 +37,7 @@ struct visitor_image_copy
{
using dst_type = typename T0::pixel_type;
T0 operator() (image_null const&)
T0 operator() (image_null const&) const
{
throw std::runtime_error("Can not cast a null image");
}
@ -48,7 +48,7 @@ struct visitor_image_copy
}
template <typename T1>
T0 operator() (T1 const& src)
T0 operator() (T1 const& src) const
{
T0 dst(safe_cast<int>(src.width()), safe_cast<int>(src.height()), false);
for (std::size_t y = 0; y < dst.height(); ++y)
@ -75,7 +75,7 @@ struct visitor_image_copy_so
throw std::runtime_error("Can not cast a null image");
}
T0 operator() (T0 const& src)
T0 operator() (T0 const& src) const
{
if (offset_ == src.get_offset() && scaling_ == src.get_scaling())
{
@ -91,7 +91,7 @@ struct visitor_image_copy_so
}
template <typename T1>
T0 operator() (T1 const& src)
T0 operator() (T1 const& src) const
{
double src_offset = src.get_offset();
double src_scaling = src.get_scaling();

View file

@ -0,0 +1,29 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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/image_filter_grammar.hpp>
#include <mapnik/image_filter_grammar_impl.hpp>
#include <mapnik/image_filter_types.hpp>
#include <string>
#include <vector>
template struct mapnik::image_filter_grammar<std::string::const_iterator,std::vector<mapnik::filter::filter_type>>;

View file

@ -22,7 +22,6 @@
// mapnik
#include <mapnik/image_filter_types.hpp>
#include <mapnik/image_filter_grammar.hpp>
#include <mapnik/image_filter_grammar_impl.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>

View file

@ -2087,7 +2087,7 @@ struct visitor_view_to_stream
: os_(os) {}
template <typename T>
void operator() (T const& view)
void operator() (T const& view) const
{
for (std::size_t i=0;i<view.height();i++)
{

View file

@ -118,19 +118,19 @@ namespace detail
struct visitor_create_marker
{
marker operator() (image_rgba8 & data)
marker operator() (image_rgba8 & data) const
{
mapnik::premultiply_alpha(data);
return mapnik::marker(mapnik::marker_rgba8(data));
}
marker operator() (image_null &)
marker operator() (image_null &) const
{
throw std::runtime_error("Can not make marker from null image data type");
}
template <typename T>
marker operator() (T &)
marker operator() (T &) const
{
throw std::runtime_error("Can not make marker from this data type");
}

View file

@ -29,10 +29,24 @@
namespace mapnik {
// copy constructor exclusively for virtual_renderer_common
renderer_common::renderer_common(renderer_common const& other)
: width_(other.width_),
height_(other.height_),
scale_factor_(other.scale_factor_),
vars_(other.vars_),
shared_font_library_(other.shared_font_library_),
font_library_(other.font_library_),
font_manager_(other.font_manager_),
query_extent_(other.query_extent_),
t_(other.t_),
detector_(other.detector_)
{}
renderer_common::renderer_common(Map const& map, unsigned width, unsigned height, double scale_factor,
attributes const& vars,
view_transform && t,
std::shared_ptr<label_collision_detector4> detector)
detector_ptr detector)
: width_(width),
height_(height),
scale_factor_(scale_factor),
@ -57,7 +71,7 @@ renderer_common::renderer_common(Map const &m, attributes const& vars, unsigned
renderer_common::renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor,
std::shared_ptr<label_collision_detector4> detector)
detector_ptr detector)
: renderer_common(m, width, height, scale_factor,
vars,
view_transform(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
@ -74,4 +88,10 @@ renderer_common::renderer_common(Map const &m, request const &req, attributes co
req.width() + req.buffer_size() ,req.height() + req.buffer_size())))
{}
renderer_common::~renderer_common()
{
// defined in .cpp to make this destructible elsewhere without
// having to #include <mapnik/label_collision_detector.hpp>
}
}

View file

@ -1,235 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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
*
*****************************************************************************/
// mapnik
#include <mapnik/renderer_common/process_group_symbolizer.hpp>
#include <mapnik/renderer_common/process_markers_symbolizer.hpp>
#include <mapnik/make_unique.hpp>
#include <memory>
namespace mapnik {
vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,
bool snap_to_pixels)
: src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity),
comp_op_(comp_op), snap_to_pixels_(snap_to_pixels)
{}
vector_marker_render_thunk::vector_marker_render_thunk(vector_marker_render_thunk && rhs)
: src_(std::move(rhs.src_)),
attrs_(std::move(rhs.attrs_)),
tr_(std::move(rhs.tr_)),
opacity_(std::move(rhs.opacity_)),
comp_op_(std::move(rhs.comp_op_)),
snap_to_pixels_(std::move(rhs.snap_to_pixels_)) {}
raster_marker_render_thunk::raster_marker_render_thunk(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,
bool snap_to_pixels)
: src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op),
snap_to_pixels_(snap_to_pixels)
{}
raster_marker_render_thunk::raster_marker_render_thunk(raster_marker_render_thunk && rhs)
: src_(rhs.src_),
tr_(std::move(rhs.tr_)),
opacity_(std::move(rhs.opacity_)),
comp_op_(std::move(rhs.comp_op_)),
snap_to_pixels_(std::move(rhs.snap_to_pixels_)) {}
text_render_thunk::text_render_thunk(helper_ptr && helper,
double opacity, composite_mode_e comp_op,
halo_rasterizer_enum halo_rasterizer)
: helper_(std::move(helper)),
placements_(helper_->get()),
opacity_(opacity),
comp_op_(comp_op),
halo_rasterizer_(halo_rasterizer)
{}
text_render_thunk::text_render_thunk(text_render_thunk && rhs)
: helper_(std::move(rhs.helper_)),
placements_(std::move(rhs.placements_)),
opacity_(std::move(rhs.opacity_)),
comp_op_(std::move(rhs.comp_op_)),
halo_rasterizer_(std::move(rhs.halo_rasterizer_)) {}
namespace detail {
template <typename Detector, typename RendererContext>
struct vector_marker_thunk_dispatch : public vector_markers_dispatch<Detector>
{
vector_marker_thunk_dispatch(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans,
symbolizer_base const& sym,
Detector & detector,
double scale_factor,
feature_impl & feature,
attributes const& vars,
bool snap_to_pixels,
RendererContext const& renderer_context)
: vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
attrs_(attrs), comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars)),
snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context))
{}
~vector_marker_thunk_dispatch() {}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
{
vector_marker_render_thunk thunk(this->src_, this->attrs_, marker_tr, opacity, comp_op_, snap_to_pixels_);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
}
private:
svg_attribute_type const& attrs_;
composite_mode_e comp_op_;
bool snap_to_pixels_;
render_thunk_list & thunks_;
};
template <typename Detector, typename RendererContext>
struct raster_marker_thunk_dispatch : public raster_markers_dispatch<Detector>
{
raster_marker_thunk_dispatch(image_rgba8 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),
comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars)),
snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context))
{}
~raster_marker_thunk_dispatch() {}
void render_marker(agg::trans_affine const& marker_tr, double opacity)
{
raster_marker_render_thunk thunk(this->src_, marker_tr, opacity, comp_op_, snap_to_pixels_);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
}
private:
composite_mode_e comp_op_;
bool snap_to_pixels_;
render_thunk_list & thunks_;
};
} // end detail ns
render_thunk_extractor::render_thunk_extractor(box2d<double> & box,
render_thunk_list & thunks,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
virtual_renderer_common & common,
box2d<double> const& clipping_extent)
: box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans),
common_(common), clipping_extent_(clipping_extent)
{}
void render_thunk_extractor::operator()(markers_symbolizer const& sym) const
{
auto renderer_context = std::tie(thunks_);
using thunk_context_type = decltype(renderer_context);
using vector_dispatch_type = detail::vector_marker_thunk_dispatch<label_collision_detector4, thunk_context_type>;
using raster_dispatch_type = detail::raster_marker_thunk_dispatch<label_collision_detector4, thunk_context_type>;
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context);
update_box();
}
void render_thunk_extractor::operator()(text_symbolizer const& sym) const
{
box2d<double> clip_box = clipping_extent_;
helper_ptr helper = std::make_unique<text_symbolizer_helper>(
sym, feature_, vars_, prj_trans_,
common_.width_, common_.height_,
common_.scale_factor_,
common_.t_, common_.font_manager_, *common_.detector_,
clip_box, agg::trans_affine());
extract_text_thunk(std::move(helper), sym);
}
void render_thunk_extractor::operator()(shield_symbolizer const& sym) const
{
box2d<double> clip_box = clipping_extent_;
helper_ptr helper = std::make_unique<text_symbolizer_helper>(
sym, feature_, vars_, prj_trans_,
common_.width_, common_.height_,
common_.scale_factor_,
common_.t_, common_.font_manager_, *common_.detector_,
clip_box, agg::trans_affine());
extract_text_thunk(std::move(helper), sym);
}
void render_thunk_extractor::extract_text_thunk(helper_ptr && helper, text_symbolizer const& sym) const
{
double opacity = get<double>(sym, keys::opacity, feature_, common_.vars_, 1.0);
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature_, common_.vars_, src_over);
halo_rasterizer_enum halo_rasterizer = get<halo_rasterizer_enum>(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL);
text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
update_box();
}
void render_thunk_extractor::update_box() const
{
label_collision_detector4 & detector = *common_.detector_;
for (auto const& label : detector)
{
if (box_.width() > 0 && box_.height() > 0)
{
box_.expand_to_include(label.get().box);
}
else
{
box_ = label.get().box;
}
}
detector.clear();
}
} // namespace mapnik

View file

@ -0,0 +1,194 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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
*
*****************************************************************************/
// mapnik
#include <mapnik/attribute_collector.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/group/group_layout_manager.hpp>
#include <mapnik/group/group_symbolizer_helper.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
#include <mapnik/renderer_common/render_group_symbolizer.hpp>
#include <mapnik/renderer_common/render_thunk_extractor.hpp>
#include <mapnik/util/conversions.hpp>
namespace mapnik {
void render_group_symbolizer(group_symbolizer const& sym,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
box2d<double> const& clipping_extent,
renderer_common & common,
render_thunk_list_dispatch & render_thunks)
{
// find all column names referenced in the group rules and symbolizers
std::set<std::string> columns;
group_attribute_collector column_collector(columns, false);
column_collector(sym);
auto props = get<group_symbolizer_properties_ptr>(sym, keys::group_properties);
// create a new context for the sub features of this group
context_ptr sub_feature_ctx = std::make_shared<mapnik::context_type>();
// populate new context with column names referenced in the group rules and symbolizers
for (auto const& col_name : columns)
{
sub_feature_ctx->push(col_name);
}
// keep track of the sub features that we'll want to symbolize
// along with the group rules that they matched
std::vector< std::pair<group_rule_ptr, feature_ptr> > matches;
// create a copied 'virtual' common renderer for processing sub feature symbolizers
// create an empty detector for it, so we are sure we won't hit anything
virtual_renderer_common virtual_renderer(common);
// keep track of which lists of render thunks correspond to
// entries in the group_layout_manager.
std::vector<render_thunk_list> layout_thunks;
// layout manager to store and arrange bboxes of matched features
group_layout_manager layout_manager(props->get_layout());
layout_manager.set_input_origin(common.width_ * 0.5, common.height_ * 0.5);
// run feature or sub feature through the group rules & symbolizers
// for each index value in the range
value_integer start = get<value_integer>(sym, keys::start_column);
value_integer end = start + get<value_integer>(sym, keys::num_columns);
for (value_integer col_idx = start; col_idx < end; ++col_idx)
{
// create sub feature with indexed column values
feature_ptr sub_feature = feature_factory::create(sub_feature_ctx, col_idx);
// copy the necessary columns to sub feature
for(auto const& col_name : columns)
{
if (col_name.find('%') != std::string::npos)
{
if (col_name.size() == 1)
{
// column name is '%' by itself, so give the index as the value
sub_feature->put(col_name, col_idx);
}
else
{
// indexed column
std::string col_idx_str;
if (mapnik::util::to_string(col_idx_str,col_idx))
{
std::string col_idx_name = col_name;
boost::replace_all(col_idx_name, "%", col_idx_str);
sub_feature->put(col_name, feature.get(col_idx_name));
}
}
}
else
{
// non-indexed column
sub_feature->put(col_name, feature.get(col_name));
}
}
// add a single point geometry at pixel origin
double x = common.width_ / 2.0, y = common.height_ / 2.0, z = 0.0;
common.t_.backward(&x, &y);
prj_trans.forward(x, y, z);
// note that we choose a point in the middle of the screen to
// try to ensure that we don't get edge artefacts due to any
// symbolizers with avoid-edges set: only the avoid-edges of
// the group symbolizer itself should matter.
geometry::point<double> origin_pt(x,y);
sub_feature->set_geometry(origin_pt);
// get the layout for this set of properties
for (auto const& rule : props->get_rules())
{
if (util::apply_visitor(evaluate<feature_impl,value_type,attributes>(*sub_feature,common.vars_),
*(rule->get_filter())).to_bool())
{
// add matched rule and feature to the list of things to draw
matches.emplace_back(rule, sub_feature);
// construct a bounding box around all symbolizers for the matched rule
box2d<double> bounds;
render_thunk_list thunks;
render_thunk_extractor extractor(bounds, thunks, *sub_feature, common.vars_, prj_trans,
virtual_renderer, clipping_extent);
for (auto const& _sym : *rule)
{
// TODO: construct layout and obtain bounding box
util::apply_visitor(extractor, _sym);
}
// add the bounding box to the layout manager
layout_manager.add_member_bound_box(bounds);
layout_thunks.emplace_back(std::move(thunks));
break;
}
}
}
// create a symbolizer helper
group_symbolizer_helper helper(sym, feature, vars, prj_trans,
common.width_, common.height_,
common.scale_factor_, common.t_,
*common.detector_, clipping_extent);
for (size_t i = 0; i < matches.size(); ++i)
{
group_rule_ptr match_rule = matches[i].first;
feature_ptr match_feature = matches[i].second;
value_unicode_string rpt_key_value = "";
// get repeat key from matched group rule
expression_ptr rpt_key_expr = match_rule->get_repeat_key();
// if no repeat key was defined, use default from group symbolizer
if (!rpt_key_expr)
{
rpt_key_expr = get<expression_ptr>(sym, keys::repeat_key);
}
// evaluate the repeat key with the matched sub feature if we have one
if (rpt_key_expr)
{
rpt_key_value = util::apply_visitor(evaluate<feature_impl,value_type,attributes>(*match_feature,common.vars_),
*rpt_key_expr).to_unicode();
}
helper.add_box_element(layout_manager.offset_box_at(i), rpt_key_value);
}
pixel_position_list const& positions = helper.get();
for (pixel_position const& pos : positions)
{
for (size_t layout_i = 0; layout_i < layout_thunks.size(); ++layout_i)
{
pixel_position const& offset = layout_manager.offset_at(layout_i);
pixel_position render_offset = pos + offset;
render_thunks.render_list(layout_thunks[layout_i], render_offset);
}
}
}
} // namespace mapnik

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 Artem Pavlenko
* Copyright (C) 2016 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,24 +20,24 @@
*
*****************************************************************************/
#ifndef MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/geometry_type.hpp>
#include <mapnik/renderer_common/render_markers_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
namespace mapnik {
template <typename VD, typename RD, typename RendererType, typename ContextType>
namespace detail {
template <typename Detector, typename RendererType, typename ContextType>
struct render_marker_symbolizer_visitor
{
using vector_dispatch_type = VD;
using raster_dispatch_type = RD;
using buffer_type = typename std::tuple_element<0,ContextType>::type;
using vector_dispatch_type = vector_markers_dispatch<Detector>;
using raster_dispatch_type = raster_markers_dispatch<Detector>;
using vertex_converter_type = vertex_converter<clip_line_tag,
clip_poly_tag,
@ -53,7 +53,7 @@ struct render_marker_symbolizer_visitor
proj_transform const& prj_trans,
RendererType const& common,
box2d<double> const& clip_box,
ContextType const& renderer_context)
ContextType & renderer_context)
: filename_(filename),
sym_(sym),
feature_(feature),
@ -62,9 +62,9 @@ struct render_marker_symbolizer_visitor
clip_box_(clip_box),
renderer_context_(renderer_context) {}
void operator() (marker_null const&) {}
void operator() (marker_null const&) const {}
void operator() (marker_svg const& mark)
void operator() (marker_svg const& mark) const
{
using namespace mapnik::svg;
bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
@ -179,7 +179,7 @@ struct render_marker_symbolizer_visitor
}
}
void operator() (marker_rgba8 const& mark)
void operator() (marker_rgba8 const& mark) const
{
using namespace mapnik::svg;
bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
@ -243,33 +243,57 @@ struct render_marker_symbolizer_visitor
proj_transform const& prj_trans_;
RendererType const& common_;
box2d<double> const& clip_box_;
ContextType const& renderer_context_;
ContextType & renderer_context_;
};
template <typename VD, typename RD, typename RendererType, typename ContextType>
} // namespace detail
markers_dispatch_params::markers_dispatch_params(box2d<double> const& size,
agg::trans_affine const& tr,
symbolizer_base const& sym,
feature_impl const& feature,
attributes const& vars,
double scale,
bool snap)
: placement_params{
.size = size,
.tr = tr,
.spacing = get<value_double, keys::spacing>(sym, feature, vars),
.max_error = get<value_double, keys::max_error>(sym, feature, vars),
.allow_overlap = get<value_bool, keys::allow_overlap>(sym, feature, vars),
.avoid_edges = get<value_bool, keys::avoid_edges>(sym, feature, vars),
.direction = get<direction_enum, keys::direction>(sym, feature, vars)}
, placement_method(get<marker_placement_enum, keys::markers_placement_type>(sym, feature, vars))
, ignore_placement(get<value_bool, keys::ignore_placement>(sym, feature, vars))
, snap_to_pixels(snap)
, scale_factor(scale)
, opacity(get<value_double, keys::opacity>(sym, feature, vars))
{
placement_params.spacing *= scale;
}
void render_markers_symbolizer(markers_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans,
RendererType const& common,
renderer_common const& common,
box2d<double> const& clip_box,
ContextType const& renderer_context)
markers_renderer_context & renderer_context)
{
using namespace mapnik::svg;
using Detector = decltype(*common.detector_);
using RendererType = renderer_common;
using ContextType = markers_renderer_context;
using VisitorType = detail::render_marker_symbolizer_visitor<Detector,
RendererType,
ContextType>;
std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse");
if (!filename.empty())
{
std::shared_ptr<mapnik::marker const> mark = mapnik::marker_cache::instance().find(filename, true);
render_marker_symbolizer_visitor<VD,RD,RendererType,ContextType> visitor(filename,
sym,
feature,
prj_trans,
common,
clip_box,
renderer_context);
auto mark = mapnik::marker_cache::instance().find(filename, true);
VisitorType visitor(filename, sym, feature, prj_trans, common, clip_box,
renderer_context);
util::apply_visitor(visitor, *mark);
}
}
} // namespace mapnik
#endif // MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP

View file

@ -0,0 +1,155 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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
*
*****************************************************************************/
// mapnik
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/make_unique.hpp>
#include <mapnik/renderer_common/render_markers_symbolizer.hpp>
#include <mapnik/renderer_common/render_thunk_extractor.hpp>
namespace mapnik {
virtual_renderer_common::virtual_renderer_common(renderer_common const& other)
: renderer_common(other)
{
// replace collision detector with my own so that I don't pollute the original
detector_ = std::make_shared<label_collision_detector4>(other.detector_->extent());
}
namespace detail {
struct thunk_markers_renderer_context : markers_renderer_context
{
thunk_markers_renderer_context(symbolizer_base const& sym,
feature_impl const& feature,
attributes const& vars,
render_thunk_list & thunks)
: comp_op_(get<composite_mode_e, keys::comp_op>(sym, feature, vars))
, thunks_(thunks)
{}
virtual void render_marker(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
vector_marker_render_thunk thunk(src, attrs, marker_tr, params.opacity,
comp_op_, params.snap_to_pixels);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
}
virtual void render_marker(image_rgba8 const& src,
markers_dispatch_params const& params,
agg::trans_affine const& marker_tr)
{
raster_marker_render_thunk thunk(src, marker_tr, params.opacity,
comp_op_, params.snap_to_pixels);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
}
private:
composite_mode_e comp_op_;
render_thunk_list & thunks_;
};
} // namespace detail
render_thunk_extractor::render_thunk_extractor(box2d<double> & box,
render_thunk_list & thunks,
feature_impl & feature,
attributes const& vars,
proj_transform const& prj_trans,
virtual_renderer_common & common,
box2d<double> const& clipping_extent)
: box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans),
common_(common), clipping_extent_(clipping_extent)
{}
void render_thunk_extractor::operator()(markers_symbolizer const& sym) const
{
using context_type = detail::thunk_markers_renderer_context;
context_type renderer_context(sym, feature_, vars_, thunks_);
render_markers_symbolizer(
sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context);
update_box();
}
void render_thunk_extractor::operator()(text_symbolizer const& sym) const
{
auto helper = std::make_unique<text_symbolizer_helper>(
sym, feature_, vars_, prj_trans_,
common_.width_, common_.height_,
common_.scale_factor_,
common_.t_, common_.font_manager_, *common_.detector_,
clipping_extent_, agg::trans_affine::identity);
extract_text_thunk(std::move(helper), sym);
}
void render_thunk_extractor::operator()(shield_symbolizer const& sym) const
{
auto helper = std::make_unique<text_symbolizer_helper>(
sym, feature_, vars_, prj_trans_,
common_.width_, common_.height_,
common_.scale_factor_,
common_.t_, common_.font_manager_, *common_.detector_,
clipping_extent_, agg::trans_affine::identity);
extract_text_thunk(std::move(helper), sym);
}
void render_thunk_extractor::extract_text_thunk(text_render_thunk::helper_ptr && helper,
text_symbolizer const& sym) const
{
double opacity = get<double>(sym, keys::opacity, feature_, common_.vars_, 1.0);
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature_, common_.vars_, src_over);
halo_rasterizer_enum halo_rasterizer = get<halo_rasterizer_enum>(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL);
text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
update_box();
}
void render_thunk_extractor::update_box() const
{
label_collision_detector4 & detector = *common_.detector_;
for (auto const& label : detector)
{
if (box_.width() > 0 && box_.height() > 0)
{
box_.expand_to_include(label.get().box);
}
else
{
box_ = label.get().box;
}
}
detector.clear();
}
} // namespace mapnik

View file

@ -27,7 +27,6 @@
#include <mapnik/svg/output/svg_renderer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/font_set.hpp>

View file

@ -74,7 +74,7 @@ void glyph_positions::set_marker(marker_info_ptr mark, pixel_position const& mar
marker_pos_ = marker_pos;
}
marker_info_ptr glyph_positions::get_marker() const
marker_info_ptr const& glyph_positions::get_marker() const
{
return marker_info_;
}

View file

@ -60,7 +60,9 @@ void text_renderer::prepare_glyphs(glyph_positions const& positions)
FT_Vector pen;
FT_Error error;
glyphs_.clear();
glyphs_.reserve(positions.size());
for (auto const& glyph_pos : positions)
{
glyph_info const& glyph = glyph_pos.glyph;
@ -121,7 +123,6 @@ agg_text_renderer<T>::agg_text_renderer (pixmap_type & pixmap,
template <typename T>
void agg_text_renderer<T>::render(glyph_positions const& pos)
{
glyphs_.clear();
prepare_glyphs(pos);
FT_Error error;
FT_Vector start;
@ -232,7 +233,6 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
template <typename T>
void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer feature_id)
{
glyphs_.clear();
prepare_glyphs(pos);
FT_Error error;
FT_Vector start;

View file

@ -181,10 +181,10 @@ struct warp_image_visitor
nodata_value_(nodata_value)
{}
void operator() (image_null const&) {}
void operator() (image_null const&) const {}
template <typename T>
void operator() (T const& source)
void operator() (T const& source) const
{
using image_type = T;
//source and target image data types must match

View file

@ -76,17 +76,19 @@ TEST_CASE("postgis") {
REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname));
}
mapnik::parameters params;
params["type"] = "postgis";
params["dbname"] = dbname;
mapnik::parameters base_params;
base_params["type"] = "postgis";
base_params["dbname"] = dbname;
SECTION("Postgis should throw without 'table' parameter")
{
mapnik::parameters params(base_params);
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'")
{
mapnik::parameters params(base_params);
params["table"] = "test";
params["max_async_connection"] = "2";
params["max_size"] = "1";
@ -95,12 +97,14 @@ TEST_CASE("postgis") {
SECTION("Postgis should throw with invalid metadata query")
{
mapnik::parameters params(base_params);
params["table"] = "does_not_exist";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with invalid key field")
{
mapnik::parameters params(base_params);
params["table"] = "test_invalid_id";
params["key_field"] = "id";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
@ -108,6 +112,7 @@ TEST_CASE("postgis") {
SECTION("Postgis should throw with multicolumn primary key")
{
mapnik::parameters params(base_params);
params["table"] = "test_invalid_multi_col_pk";
params["autodetect_key_field"] = "true";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
@ -115,6 +120,7 @@ TEST_CASE("postgis") {
SECTION("Postgis should throw without geom column")
{
mapnik::parameters params(base_params);
params["table"] = "test_no_geom_col";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -123,6 +129,7 @@ TEST_CASE("postgis") {
SECTION("Postgis should throw with invalid credentials")
{
mapnik::parameters params(base_params);
params["table"] = "test";
params["user"] = "not_a_valid_user";
params["password"] = "not_a_valid_pwd";
@ -131,6 +138,7 @@ TEST_CASE("postgis") {
SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit")
{
mapnik::parameters params(base_params);
params["persist_connection"] = "false";
params["table"] = "public.test";
params["geometry_field"] = "geom";
@ -143,6 +151,7 @@ TEST_CASE("postgis") {
SECTION("Postgis dataset geometry type")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM test WHERE gid=1) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -151,6 +160,7 @@ TEST_CASE("postgis") {
SECTION("Postgis query field names")
{
mapnik::parameters params(base_params);
params["table"] = "test";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -162,6 +172,7 @@ TEST_CASE("postgis") {
SECTION("Postgis iterate features")
{
mapnik::parameters params(base_params);
params["table"] = "test";
params["key_field"] = "gid";
params["max_async_connection"] = "2";
@ -192,6 +203,7 @@ TEST_CASE("postgis") {
SECTION("Postgis cursorresultest")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM test) as data";
params["cursor_size"] = "2";
auto ds = mapnik::datasource_cache::instance().create(params);
@ -218,6 +230,7 @@ TEST_CASE("postgis") {
SECTION("Postgis bbox query")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -233,6 +246,7 @@ TEST_CASE("postgis") {
SECTION("Postgis query extent: full dataset")
{
//include schema to increase coverage
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM public.test) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -247,6 +261,7 @@ TEST_CASE("postgis") {
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent from subquery")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM test where gid=4) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -261,6 +276,7 @@ TEST_CASE("postgis") {
*/
SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM test where gid=4) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
@ -276,6 +292,7 @@ TEST_CASE("postgis") {
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'")
{
mapnik::parameters params(base_params);
// !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000'
// https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617
params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data";

View file

@ -89,26 +89,26 @@ void assert_g_equal(geometry<T> const& g1, geometry<T> const& g2);
struct geometry_equal_visitor
{
template <typename T1, typename T2>
void operator() (T1 const&, T2 const&)
void operator() (T1 const&, T2 const&) const
{
// comparing two different types!
REQUIRE(false);
}
void operator() (geometry_empty const&, geometry_empty const&)
void operator() (geometry_empty const&, geometry_empty const&) const
{
REQUIRE(true);
}
template <typename T>
void operator() (point<T> const& p1, point<T> const& p2)
void operator() (point<T> const& p1, point<T> const& p2) const
{
REQUIRE(p1.x == Approx(p2.x));
REQUIRE(p1.y == Approx(p2.y));
}
template <typename T>
void operator() (line_string<T> const& ls1, line_string<T> const& ls2)
void operator() (line_string<T> const& ls1, line_string<T> const& ls2) const
{
if (ls1.size() != ls2.size())
{
@ -123,7 +123,7 @@ struct geometry_equal_visitor
}
template <typename T>
void operator() (polygon<T> const& p1, polygon<T> const& p2)
void operator() (polygon<T> const& p1, polygon<T> const& p2) const
{
(*this)(static_cast<line_string<T> const&>(p1.exterior_ring), static_cast<line_string<T> const&>(p2.exterior_ring));
@ -139,13 +139,13 @@ struct geometry_equal_visitor
}
template <typename T>
void operator() (multi_point<T> const& mp1, multi_point<T> const& mp2)
void operator() (multi_point<T> const& mp1, multi_point<T> const& mp2) const
{
(*this)(static_cast<line_string<T> const&>(mp1), static_cast<line_string<T> const&>(mp2));
}
template <typename T>
void operator() (multi_line_string<T> const& mls1, multi_line_string<T> const& mls2)
void operator() (multi_line_string<T> const& mls1, multi_line_string<T> const& mls2) const
{
if (mls1.size() != mls2.size())
{
@ -159,7 +159,7 @@ struct geometry_equal_visitor
}
template <typename T>
void operator() (multi_polygon<T> const& mpoly1, multi_polygon<T> const& mpoly2)
void operator() (multi_polygon<T> const& mpoly1, multi_polygon<T> const& mpoly2) const
{
if (mpoly1.size() != mpoly2.size())
{
@ -173,7 +173,7 @@ struct geometry_equal_visitor
}
template <typename T>
void operator() (mapnik::util::recursive_wrapper<geometry_collection<T> > const& c1_, mapnik::util::recursive_wrapper<geometry_collection<T> > const& c2_)
void operator() (mapnik::util::recursive_wrapper<geometry_collection<T> > const& c1_, mapnik::util::recursive_wrapper<geometry_collection<T> > const& c2_) const
{
geometry_collection<T> const& c1 = static_cast<geometry_collection<T> const&>(c1_);
geometry_collection<T> const& c2 = static_cast<geometry_collection<T> const&>(c2_);
@ -189,7 +189,7 @@ struct geometry_equal_visitor
}
template <typename T>
void operator() (geometry_collection<T> const& c1, geometry_collection<T> const& c2)
void operator() (geometry_collection<T> const& c1, geometry_collection<T> const& c2) const
{
if (c1.size() != c2.size())
{

View file

@ -43,6 +43,8 @@ SECTION("point -- geometry object") {
CHECK( failure == boost::geometry::no_failure );
}
#if BOOST_VERSION < 106000
SECTION("point unitialized") {
mapnik::geometry::point<double> pt2;
CHECK( mapnik::geometry::is_valid(pt2) );
@ -53,6 +55,7 @@ SECTION("point unitialized") {
CHECK( mapnik::geometry::is_valid(pt2, failure2) );
CHECK( failure2 == boost::geometry::no_failure );
}
#endif
#if BOOST_VERSION >= 106000
@ -120,7 +123,7 @@ SECTION("point Infinity") {
SECTION("multi point") {
mapnik::geometry::multi_point<double> mpt;
mpt.add_coord(0,0);
mpt.add_coord(0,0);
mpt.add_coord(1,1);
CHECK( mapnik::geometry::is_valid(mpt) );
std::string message;
@ -145,7 +148,7 @@ SECTION("multi point empty") {
SECTION("line_string") {
mapnik::geometry::line_string<double> line;
line.add_coord(0,0);
line.add_coord(0,0);
line.add_coord(1,1);
CHECK( mapnik::geometry::is_valid(line) );
std::string message;
@ -159,7 +162,7 @@ SECTION("line_string") {
// This shouldn't fail -- test added in case logic ever changes
SECTION("line_string repeated points") {
mapnik::geometry::line_string<double> line;
line.add_coord(0,0);
line.add_coord(0,0);
line.add_coord(1,1);
line.add_coord(1,1);
line.add_coord(2,2);
@ -185,10 +188,10 @@ SECTION("line_string empty") {
SECTION("multi_line_string") {
mapnik::geometry::line_string<double> line1;
line1.add_coord(0,0);
line1.add_coord(0,0);
line1.add_coord(1,1);
mapnik::geometry::line_string<double> line2;
line2.add_coord(0,1);
line2.add_coord(0,1);
line2.add_coord(1,2);
mapnik::geometry::multi_line_string<double> lines;
lines.emplace_back(line1);
@ -216,7 +219,7 @@ SECTION("multi_line_string empty") {
SECTION("polygon") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(1,0);
ring.add_coord(1,1);
ring.add_coord(0,1);
@ -234,7 +237,7 @@ SECTION("polygon") {
SECTION("polygon invalid winding order") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(0,1);
ring.add_coord(1,1);
ring.add_coord(1,0);
@ -253,7 +256,7 @@ SECTION("polygon invalid winding order") {
SECTION("polygon 2 repeated points") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(1,0);
ring.add_coord(1,1);
ring.add_coord(1,1);
@ -272,7 +275,7 @@ SECTION("polygon 2 repeated points") {
SECTION("polygon 3 repeated points") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(1,0);
ring.add_coord(1,1);
ring.add_coord(1,1);
@ -303,7 +306,7 @@ SECTION("polygon that is empty") {
SECTION("polygon with spike") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(1,0);
ring.add_coord(1,1);
ring.add_coord(2,2);
@ -323,14 +326,14 @@ SECTION("polygon with spike") {
SECTION("polygon with hole") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(3,0);
ring.add_coord(3,3);
ring.add_coord(0,3);
ring.add_coord(0,0);
poly.set_exterior_ring(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.add_coord(1,1);
hole.add_coord(1,1);
hole.add_coord(1,2);
hole.add_coord(2,2);
hole.add_coord(2,1);
@ -348,7 +351,7 @@ SECTION("polygon with hole") {
SECTION("polygon with empty hole") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(3,0);
ring.add_coord(3,3);
ring.add_coord(0,3);
@ -369,14 +372,14 @@ SECTION("polygon with empty hole") {
SECTION("polygon with hole with invalid winding order") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(3,0);
ring.add_coord(3,3);
ring.add_coord(0,3);
ring.add_coord(0,0);
poly.set_exterior_ring(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.add_coord(1,1);
hole.add_coord(1,1);
hole.add_coord(2,1);
hole.add_coord(2,2);
hole.add_coord(1,2);
@ -395,7 +398,7 @@ SECTION("multi polygon") {
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(1,0);
ring.add_coord(1,1);
ring.add_coord(0,1);
@ -403,7 +406,7 @@ SECTION("multi polygon") {
poly.set_exterior_ring(std::move(ring));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.add_coord(0,0);
ring2.add_coord(0,0);
ring2.add_coord(-1,0);
ring2.add_coord(-1,-1);
ring2.add_coord(0,-1);
@ -424,14 +427,14 @@ SECTION("multi polygon with hole") {
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.add_coord(0,0);
ring.add_coord(0,0);
ring.add_coord(3,0);
ring.add_coord(3,3);
ring.add_coord(0,3);
ring.add_coord(0,0);
poly.set_exterior_ring(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.add_coord(1,1);
hole.add_coord(1,1);
hole.add_coord(1,2);
hole.add_coord(2,2);
hole.add_coord(2,1);
@ -439,14 +442,14 @@ SECTION("multi polygon with hole") {
poly.add_hole(std::move(hole));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.add_coord(0,0);
ring2.add_coord(0,0);
ring2.add_coord(-3,0);
ring2.add_coord(-3,-3);
ring2.add_coord(0,-3);
ring2.add_coord(0,0);
poly2.set_exterior_ring(std::move(ring2));
mapnik::geometry::linear_ring<double> hole2;
hole2.add_coord(-1,-1);
hole2.add_coord(-1,-1);
hole2.add_coord(-1,-2);
hole2.add_coord(-2,-2);
hole2.add_coord(-2,-1);

View file

@ -57,13 +57,13 @@ public:
}
template <typename T, typename std::enable_if<T::renderer_type::support_tiles>::type* = nullptr>
void operator()(T const & renderer)
void operator()(T const& renderer) const
{
test(renderer);
}
template <typename T, typename std::enable_if<!T::renderer_type::support_tiles>::type* = nullptr>
void operator()(T const & renderer)
void operator()(T const & renderer) const
{
if (tiles_.width == 1 && tiles_.height == 1)
{
@ -73,7 +73,7 @@ public:
private:
template <typename T>
void test(T const & renderer)
void test(T const & renderer) const
{
map_size size { map_.width(), map_.height() };
std::chrono::high_resolution_clock::time_point start(std::chrono::high_resolution_clock::now());
@ -96,7 +96,7 @@ private:
}
template <typename T, typename std::enable_if<T::renderer_type::support_tiles>::type* = nullptr>
typename T::image_type render(T const & renderer)
typename T::image_type render(T const& renderer) const
{
if (tiles_.width == 1 && tiles_.height == 1)
{
@ -109,7 +109,7 @@ private:
}
template <typename T, typename std::enable_if<!T::renderer_type::support_tiles>::type* = nullptr>
typename T::image_type render(T const & renderer)
typename T::image_type render(T const & renderer) const
{
return renderer.render(map_, scale_factor_);
}
@ -364,4 +364,3 @@ void runner::parse_map_sizes(std::string const & str, std::vector<map_size> & si
}
}

View file

@ -56,7 +56,7 @@ struct main_marker_visitor
verbose_(verbose),
auto_open_(auto_open) {}
int operator() (mapnik::marker_svg const& marker)
int operator() (mapnik::marker_svg const& marker) const
{
using pixfmt = agg::pixfmt_rgba32_pre;
using renderer_base = agg::renderer_base<pixfmt>;
@ -122,14 +122,14 @@ struct main_marker_visitor
// default
template <typename T>
int operator() (T const&)
int operator() (T const&) const
{
std::clog << "svg2png error: '" << svg_name_ << "' is not a valid vector!\n";
return -1;
}
private:
std::string const& svg_name_;
std::string svg_name_;
bool verbose_;
bool auto_open_;
};