Merge branch 'master' into spirit-x3
This commit is contained in:
commit
3e866e63b2
60 changed files with 1361 additions and 1363 deletions
16
Makefile
16
Makefile
|
@ -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
2
deps/mapbox/variant
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 9afd6406065440e02b6bf42db4633b815846db0d
|
||||
Subproject commit 7f7c667f870541c208c07d99a9f2c22dfa1f32de
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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
|
66
include/mapnik/renderer_common/render_group_symbolizer.hpp
Normal file
66
include/mapnik/renderer_common/render_group_symbolizer.hpp
Normal 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
|
76
include/mapnik/renderer_common/render_markers_symbolizer.hpp
Normal file
76
include/mapnik/renderer_common/render_markers_symbolizer.hpp
Normal 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
|
115
include/mapnik/renderer_common/render_thunk.hpp
Normal file
115
include/mapnik/renderer_common/render_thunk.hpp
Normal 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
|
97
include/mapnik/renderer_common/render_thunk_extractor.hpp
Normal file
97
include/mapnik/renderer_common/render_thunk_extractor.hpp
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
}}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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&,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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&,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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&,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
29
src/image_filter_grammar.cpp
Normal file
29
src/image_filter_grammar.cpp
Normal 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>>;
|
|
@ -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>
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
194
src/renderer_common/render_group_symbolizer.cpp
Normal file
194
src/renderer_common/render_group_symbolizer.cpp
Normal 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
|
|
@ -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
|
155
src/renderer_common/render_thunk_extractor.cpp
Normal file
155
src/renderer_common/render_thunk_extractor.cpp
Normal 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
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue