Merge pull request #3265 from lightmare/refactor-symbolizers
refactoring group, markers symbolizers to reduce compile time / memory usage
This commit is contained in:
commit
0b2775a5e1
33 changed files with 1152 additions and 1212 deletions
10
Makefile
10
Makefile
|
@ -40,19 +40,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.os \
|
||||
src/transform_expression_grammar.os \
|
||||
src/image_filter_grammar.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 \
|
||||
|
||||
mapnik: src/json/libmapnik-json.a
|
||||
# then install the rest with -j$(JOBS)
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
||||
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);
|
||||
}
|
||||
#endif // PLACEMENTS_LIST_HPP
|
||||
}
|
||||
|
||||
~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);
|
||||
|
|
|
@ -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_)
|
||||
{
|
||||
marker_info_ptr mark = glyphs->get_marker();
|
||||
if (mark)
|
||||
scoped_glyph_positions_offset tmp_off(*glyphs, offset_);
|
||||
|
||||
if (auto const& mark = glyphs->get_marker())
|
||||
{
|
||||
ren_.render_marker(glyphs->marker_pos(),
|
||||
*mark->marker_,
|
||||
mark->transform_,
|
||||
thunk.opacity_, thunk.comp_op_);
|
||||
}
|
||||
ren.render(*glyphs);
|
||||
});
|
||||
tex_.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");
|
||||
}
|
||||
|
||||
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&,
|
||||
|
|
|
@ -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,
|
||||
agg_markers_renderer_context(symbolizer_base const& sym,
|
||||
feature_impl const& 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)),
|
||||
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>
|
||||
|
|
|
@ -253,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
|
||||
"""
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -47,20 +46,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_);
|
||||
|
@ -78,7 +76,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_);
|
||||
|
@ -88,18 +86,16 @@ 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)
|
||||
for (auto const& glyphs : thunk.placements_)
|
||||
{
|
||||
marker_info_ptr mark = glyphs->get_marker();
|
||||
if (mark)
|
||||
scoped_glyph_positions_offset tmp_off(*glyphs, offset_);
|
||||
|
||||
if (auto const& mark = glyphs->get_marker())
|
||||
{
|
||||
ren_.render_marker(glyphs->marker_pos(),
|
||||
*mark->marker_,
|
||||
|
@ -107,13 +103,7 @@ struct thunk_renderer
|
|||
thunk.opacity_, thunk.comp_op_);
|
||||
}
|
||||
context_.add_text(*glyphs, face_manager_, src_over, src_over, common_.scale_factor_);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T0>
|
||||
void operator()(T0 const &) const
|
||||
{
|
||||
throw std::runtime_error("Rendering of this type is not supported by the cairo renderer.");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -121,7 +111,6 @@ private:
|
|||
cairo_context & context_;
|
||||
cairo_face_manager & face_manager_;
|
||||
renderer_common & common_;
|
||||
pixel_position offset_;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -131,16 +120,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>
|
||||
virtual void render_marker(image_rgba8 const& src,
|
||||
markers_dispatch_params const& params,
|
||||
agg::trans_affine const& marker_tr)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -361,7 +361,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)
|
||||
|
@ -376,8 +376,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;
|
||||
}
|
||||
|
@ -391,7 +391,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,18 +110,17 @@ 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)
|
||||
for (auto const& glyphs : thunk.placements_)
|
||||
{
|
||||
marker_info_ptr mark = glyphs->get_marker();
|
||||
if (mark)
|
||||
scoped_glyph_positions_offset tmp_off(*glyphs, offset_);
|
||||
|
||||
if (auto const& mark = glyphs->get_marker())
|
||||
{
|
||||
ren_.render_marker(feature_,
|
||||
glyphs->marker_pos(),
|
||||
|
@ -141,15 +128,10 @@ struct thunk_renderer
|
|||
mark->transform_,
|
||||
thunk.opacity_, thunk.comp_op_);
|
||||
}
|
||||
ren.render(*glyphs, feature_id);
|
||||
});
|
||||
pixmap_.add_feature(feature_);
|
||||
tex_.render(*glyphs, feature_id);
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void operator()(T1 const &) const
|
||||
{
|
||||
// TODO: warning if unimplemented?
|
||||
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,
|
||||
using context_type = detail::grid_markers_renderer_context<svg_renderer_type,
|
||||
renderer_type,
|
||||
detector_type,
|
||||
grid_context_type>;
|
||||
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_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);
|
||||
|
|
|
@ -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,233 +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>
|
||||
|
||||
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),
|
||||
|
@ -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,
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue