refactor render_markers_symbolizer

This commit is contained in:
Mickey Rose 2016-01-27 01:55:50 +01:00
parent 8a55eefbb5
commit f99c0e5a6f
7 changed files with 226 additions and 373 deletions

View file

@ -48,64 +48,106 @@ struct clip_poly_tag;
using svg_attribute_type = agg::pod_bvector<svg::path_attributes>; using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
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 = 1.0,
bool snap = false)
: 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;
}
};
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;
};
template <typename Detector> template <typename Detector>
struct vector_markers_dispatch : util::noncopyable struct vector_markers_dispatch : util::noncopyable
{ {
vector_markers_dispatch(svg_path_ptr const& src, vector_markers_dispatch(svg_path_ptr const& src,
svg_path_adapter & path,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans, agg::trans_affine const& marker_trans,
symbolizer_base const& sym, symbolizer_base const& sym,
Detector & detector, Detector & detector,
double scale_factor, double scale_factor,
feature_impl const& feature, feature_impl const& feature,
attributes const& vars) attributes const& vars,
: src_(src), bool snap_to_pixels,
marker_trans_(marker_trans), markers_renderer_context & renderer_context)
sym_(sym), : params_(src->bounding_box(), recenter(src) * marker_trans,
detector_(detector), sym, feature, vars, scale_factor, snap_to_pixels)
feature_(feature), , renderer_context_(renderer_context)
vars_(vars), , src_(src)
scale_factor_(scale_factor) , path_(path)
, attrs_(attrs)
, detector_(detector)
{} {}
virtual ~vector_markers_dispatch() {}
template <typename T> template <typename T>
void add_path(T & path) 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( 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; 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.rotate(angle);
matrix.translate(x, y); 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: 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_; svg_path_ptr const& src_;
agg::trans_affine const& marker_trans_; svg_path_adapter & path_;
symbolizer_base const& sym_; svg_attribute_type const& attrs_;
Detector & detector_; Detector & detector_;
feature_impl const& feature_;
attributes const& vars_;
double scale_factor_;
}; };
template <typename Detector> template <typename Detector>
@ -117,53 +159,35 @@ struct raster_markers_dispatch : util::noncopyable
Detector & detector, Detector & detector,
double scale_factor, double scale_factor,
feature_impl const& feature, feature_impl const& feature,
attributes const& vars) attributes const& vars,
: src_(src), markers_renderer_context & renderer_context)
marker_trans_(marker_trans), : params_(box2d<double>(0, 0, src.width(), src.height()),
sym_(sym), marker_trans, sym, feature, vars, scale_factor)
detector_(detector), , renderer_context_(renderer_context)
feature_(feature), , src_(src)
vars_(vars), , detector_(detector)
scale_factor_(scale_factor)
{} {}
virtual ~raster_markers_dispatch() {}
template <typename T> template <typename T>
void add_path(T & path) 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( 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; 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.rotate(angle);
matrix.translate(x, y); 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: protected:
markers_dispatch_params params_;
markers_renderer_context & renderer_context_;
image_rgba8 const& src_; image_rgba8 const& src_;
agg::trans_affine const& marker_trans_;
symbolizer_base const& sym_;
Detector & detector_; 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, void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars,

View file

@ -40,8 +40,8 @@ namespace mapnik {
struct markers_placement_params struct markers_placement_params
{ {
box2d<double> const& size; box2d<double> size;
agg::trans_affine const& tr; agg::trans_affine tr;
double spacing; double spacing;
double max_error; double max_error;
bool allow_overlap; bool allow_overlap;
@ -132,23 +132,8 @@ protected:
// Rotates the size_ box and translates the position. // Rotates the size_ box and translates the position.
box2d<double> perform_transform(double angle, double dx, double dy) 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); agg::trans_affine tr = params_.tr * agg::trans_affine_rotation(angle).translate(dx, dy);
double xA = x1, yA = y1, return box2d<double>(params_.size, tr);
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;
} }
bool set_direction(double & angle) bool set_direction(double & angle)

View file

@ -37,7 +37,6 @@ struct render_marker_symbolizer_visitor
{ {
using vector_dispatch_type = VD; using vector_dispatch_type = VD;
using raster_dispatch_type = RD; using raster_dispatch_type = RD;
using buffer_type = typename std::tuple_element<0,ContextType>::type;
using vertex_converter_type = vertex_converter<clip_line_tag, using vertex_converter_type = vertex_converter<clip_line_tag,
clip_poly_tag, clip_poly_tag,
@ -246,14 +245,19 @@ struct render_marker_symbolizer_visitor
ContextType const& renderer_context_; ContextType const& renderer_context_;
}; };
template <typename VD, typename RD, typename RendererType, typename ContextType> template <typename RendererType>
void render_markers_symbolizer(markers_symbolizer const& sym, void render_markers_symbolizer(markers_symbolizer const& sym,
mapnik::feature_impl & feature, mapnik::feature_impl & feature,
proj_transform const& prj_trans, proj_transform const& prj_trans,
RendererType const& common, RendererType const& common,
box2d<double> const& clip_box, box2d<double> const& clip_box,
ContextType const& renderer_context) markers_renderer_context & renderer_context)
{ {
using Detector = decltype(*common.detector_);
using VD = vector_markers_dispatch<Detector>;
using RD = raster_markers_dispatch<Detector>;
using ContextType = markers_renderer_context & ;
using namespace mapnik::svg; using namespace mapnik::svg;
std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse"); std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse");
if (!filename.empty()) if (!filename.empty())

View file

@ -60,106 +60,58 @@ namespace mapnik {
namespace detail { namespace detail {
template <typename SvgRenderer, typename Detector, typename RendererContext> template <typename SvgRenderer, typename BufferType, typename RasterizerType>
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector> struct agg_markers_renderer_context : markers_renderer_context
{ {
using renderer_base = typename SvgRenderer::renderer_base; using renderer_base = typename SvgRenderer::renderer_base;
using vertex_source_type = typename SvgRenderer::vertex_source_type; using vertex_source_type = typename SvgRenderer::vertex_source_type;
using attribute_source_type = typename SvgRenderer::attribute_source_type; using attribute_source_type = typename SvgRenderer::attribute_source_type;
using pixfmt_type = typename renderer_base::pixfmt_type; using pixfmt_type = typename renderer_base::pixfmt_type;
using BufferType = typename std::tuple_element<0,RendererContext>::type; agg_markers_renderer_context(symbolizer_base const& sym,
using RasterizerType = typename std::tuple_element<1,RendererContext>::type; feature_impl const& feature,
vector_markers_rasterizer_dispatch(svg_path_ptr const& src,
vertex_source_type & path,
svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans,
symbolizer_base const& sym,
Detector & detector,
double scale_factor,
feature_impl & feature,
attributes const& vars, attributes const& vars,
bool snap_to_pixels, BufferType & buf,
RendererContext const& renderer_context) RasterizerType & ras)
: vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars), : buf_(buf),
buf_(std::get<0>(renderer_context)),
pixf_(buf_), pixf_(buf_),
renb_(pixf_), renb_(pixf_),
svg_renderer_(path, attrs), ras_(ras)
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))); 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() {} virtual void render_marker(svg_path_ptr const& src,
svg_path_adapter & path,
void render_marker(agg::trans_affine const& marker_tr, double opacity) 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(), SvgRenderer svg_renderer(path, attrs);
marker_tr, opacity, snap_to_pixels_); 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: private:
BufferType & buf_; BufferType & buf_;
pixfmt_type pixf_; pixfmt_type pixf_;
renderer_base renb_; renderer_base renb_;
SvgRenderer svg_renderer_;
RasterizerType & ras_; RasterizerType & ras_;
bool snap_to_pixels_;
}; };
template <typename Detector, typename RendererContext> } // namespace detail
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_;
};
}
template <typename T0, typename T1> template <typename T0, typename T1>
void agg_renderer<T0,T1>::process(markers_symbolizer const& sym, void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
@ -194,16 +146,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()); buf_type render_buffer(current_buffer_->bytes(), current_buffer_->width(), current_buffer_->height(), current_buffer_->row_size());
box2d<double> clip_box = clipping_extent(common_); box2d<double> clip_box = clipping_extent(common_);
auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_); using context_type = detail::agg_markers_renderer_context<svg_renderer_type,
using markers_context_type = decltype(renderer_context); buf_type,
using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type, detector_type, markers_context_type>; rasterizer>;
using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<detector_type, markers_context_type>; 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); sym, feature, prj_trans, common_, clip_box, renderer_context);
} }
template void agg_renderer<image_rgba8>::process(markers_symbolizer const&, template void agg_renderer<image_rgba8>::process(markers_symbolizer const&,
mapnik::feature_impl &, mapnik::feature_impl &,
proj_transform const&); proj_transform const&);
} } // namespace mapnik

View file

@ -42,73 +42,40 @@
namespace mapnik namespace mapnik
{ {
class feature_impl;
class proj_transform;
namespace detail { namespace detail {
template <typename RendererContext, typename Detector> struct cairo_markers_renderer_context : markers_renderer_context
struct vector_markers_dispatch_cairo : public vector_markers_dispatch<Detector>
{ {
vector_markers_dispatch_cairo(svg_path_ptr const& src, explicit cairo_markers_renderer_context(cairo_context & ctx)
svg::svg_path_adapter & path, : ctx_(ctx)
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))
{} {}
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_, render_vector_marker(ctx_,
path_, path,
attr_, attrs,
this->src_->bounding_box(), src->bounding_box(),
marker_tr, marker_tr,
opacity); params.opacity);
} }
private: virtual void render_marker(image_rgba8 const& src,
svg::svg_path_adapter & path_; markers_dispatch_params const& params,
svg_attribute_type const& attr_; agg::trans_affine const& marker_tr)
cairo_context & ctx_;
};
template <typename RendererContext, typename Detector>
struct raster_markers_dispatch_cairo : public raster_markers_dispatch<Detector>
{ {
raster_markers_dispatch_cairo(image_rgba8 const& src, ctx_.add_image(marker_tr, src, params.opacity);
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);
} }
private: private:
cairo_context & ctx_; cairo_context & ctx_;
}; };
} } // namespace detail
template <typename T> template <typename T>
void cairo_renderer<T>::process(markers_symbolizer const& sym, void cairo_renderer<T>::process(markers_symbolizer const& sym,
@ -120,17 +87,10 @@ void cairo_renderer<T>::process(markers_symbolizer const& sym,
context_.set_operator(comp_op); context_.set_operator(comp_op);
box2d<double> clip_box = common_.query_extent_; 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); render_markers_symbolizer(
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>(
sym, feature, prj_trans, common_, clip_box, sym, feature, prj_trans, common_, clip_box,
renderer_context); renderer_context);
} }
@ -139,6 +99,6 @@ template void cairo_renderer<cairo_ptr>::process(markers_symbolizer const&,
mapnik::feature_impl &, mapnik::feature_impl &,
proj_transform const&); proj_transform const&);
} } // namespace mapnik
#endif // HAVE_CAIRO #endif // HAVE_CAIRO

View file

@ -81,109 +81,72 @@ namespace mapnik {
namespace detail { namespace detail {
template <typename SvgRenderer, typename Detector, typename RendererContext> template <typename SvgRenderer, typename ScanlineRenderer,
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector> typename BufferType, typename RasterizerType, typename PixMapType>
struct grid_markers_renderer_context : markers_renderer_context
{ {
using renderer_base = typename SvgRenderer::renderer_base; using renderer_base = typename SvgRenderer::renderer_base;
using vertex_source_type = typename SvgRenderer::vertex_source_type; using vertex_source_type = typename SvgRenderer::vertex_source_type;
using attribute_source_type = typename SvgRenderer::attribute_source_type; using attribute_source_type = typename SvgRenderer::attribute_source_type;
using pixfmt_type = typename renderer_base::pixfmt_type; using pixfmt_type = typename renderer_base::pixfmt_type;
using BufferType = typename std::tuple_element<0,RendererContext>::type; grid_markers_renderer_context(feature_impl const& feature,
using RasterizerType = typename std::tuple_element<1,RendererContext>::type; BufferType & buf,
using PixMapType = typename std::tuple_element<2,RendererContext>::type; RasterizerType & ras,
PixMapType & pixmap)
vector_markers_rasterizer_dispatch(svg_path_ptr const& src, : feature_(feature),
vertex_source_type & path, buf_(buf),
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)),
pixf_(buf_), pixf_(buf_),
renb_(pixf_), renb_(pixf_),
svg_renderer_(path, attrs), ras_(ras),
ras_(std::get<1>(renderer_context)), pixmap_(pixmap),
pixmap_(std::get<2>(renderer_context)),
placed_(false) 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_; 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_) if (!placed_)
{ {
pixmap_.add_feature(this->feature_); pixmap_.add_feature(feature_);
placed_ = true; placed_ = true;
} }
} }
private: private:
feature_impl const& feature_;
BufferType & buf_; BufferType & buf_;
pixfmt_type pixf_; pixfmt_type pixf_;
renderer_base renb_; renderer_base renb_;
SvgRenderer svg_renderer_;
RasterizerType & ras_; RasterizerType & ras_;
PixMapType & pixmap_; PixMapType & pixmap_;
bool placed_; bool placed_;
}; };
template <typename RendererBase, typename RendererType, typename Detector, typename RendererContext> } // namespace detail
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_;
};
}
template <typename T> template <typename T>
void grid_renderer<T>::process(markers_symbolizer const& sym, void grid_renderer<T>::process(markers_symbolizer const& sym,
@ -193,7 +156,6 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
using buf_type = grid_rendering_buffer; using buf_type = grid_rendering_buffer;
using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>; using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
using detector_type = label_collision_detector4;
using namespace mapnik::svg; using namespace mapnik::svg;
using svg_attribute_type = agg::pod_bvector<path_attributes>; using svg_attribute_type = agg::pod_bvector<path_attributes>;
@ -206,22 +168,20 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
ras_ptr->reset(); ras_ptr->reset();
box2d<double> clip_box = common_.query_extent_; box2d<double> clip_box = common_.query_extent_;
auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_); using context_type = detail::grid_markers_renderer_context<svg_renderer_type,
using grid_context_type = decltype(renderer_context);
using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type,
detector_type,
grid_context_type>;
using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<grid_renderer_base_type,
renderer_type, renderer_type,
detector_type, buf_type,
grid_context_type>; grid_rasterizer,
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>( buffer_type>;
context_type renderer_context(feature, render_buf, *ras_ptr, pixmap_);
render_markers_symbolizer(
sym, feature, prj_trans, common_, clip_box, renderer_context); sym, feature, prj_trans, common_, clip_box, renderer_context);
} }
template void grid_renderer<grid>::process(markers_symbolizer const&, template void grid_renderer<grid>::process(markers_symbolizer const&,
mapnik::feature_impl &, mapnik::feature_impl &,
proj_transform const&); proj_transform const&);
} } // namespace mapnik
#endif #endif

View file

@ -38,68 +38,38 @@ virtual_renderer_common::virtual_renderer_common(renderer_common const& other)
namespace detail { namespace detail {
template <typename Detector, typename RendererContext> struct thunk_markers_renderer_context : markers_renderer_context
struct vector_marker_thunk_dispatch : public vector_markers_dispatch<Detector>
{ {
vector_marker_thunk_dispatch(svg_path_ptr const& src, 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_path_adapter & path,
svg_attribute_type const& attrs, svg_attribute_type const& attrs,
agg::trans_affine const& marker_trans, markers_dispatch_params const& params,
symbolizer_base const& sym, agg::trans_affine const& marker_tr)
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_); 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))); thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
} }
private: virtual void render_marker(image_rgba8 const& src,
svg_attribute_type const& attrs_; markers_dispatch_params const& params,
composite_mode_e comp_op_; agg::trans_affine const& marker_tr)
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, raster_marker_render_thunk thunk(src, marker_tr, params.opacity,
agg::trans_affine const& marker_trans, comp_op_, params.snap_to_pixels);
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))); thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk)));
} }
private: private:
composite_mode_e comp_op_; composite_mode_e comp_op_;
bool snap_to_pixels_;
render_thunk_list & thunks_; render_thunk_list & thunks_;
}; };
@ -118,12 +88,10 @@ render_thunk_extractor::render_thunk_extractor(box2d<double> & box,
void render_thunk_extractor::operator()(markers_symbolizer const& sym) const void render_thunk_extractor::operator()(markers_symbolizer const& sym) const
{ {
auto renderer_context = std::tie(thunks_); using context_type = detail::thunk_markers_renderer_context;
using thunk_context_type = decltype(renderer_context); context_type renderer_context(sym, feature_, vars_, thunks_);
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>( render_markers_symbolizer(
sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context); sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context);
update_box(); update_box();