Refactor markers dispatchers to use a common base class to share code.
This commit is contained in:
parent
c5d0c44de0
commit
1b15e53b63
12 changed files with 536 additions and 545 deletions
148
include/mapnik/agg_render_marker.hpp
Normal file
148
include/mapnik/agg_render_marker.hpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2014 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/feature.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
#include <mapnik/svg/svg_path_attributes.hpp>
|
||||
#include <mapnik/svg/svg_converter.hpp>
|
||||
#include <mapnik/vertex_converters.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_renderer_base.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_image_filters.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_image_accessors.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_span_image_filter_rgba.h"
|
||||
#include "agg_span_interpolator_linear.h"
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename SvgRenderer, typename RasterizerType, typename RendererBaseType>
|
||||
void render_vector_marker(SvgRenderer & svg_renderer, RasterizerType & ras, RendererBaseType & renb,
|
||||
box2d<double> const& bbox, agg::trans_affine const& tr,
|
||||
double opacity, bool snap_to_pixels)
|
||||
{
|
||||
agg::scanline_u8 sl;
|
||||
if (snap_to_pixels)
|
||||
{
|
||||
// https://github.com/mapnik/mapnik/issues/1316
|
||||
agg::trans_affine snap_tr = tr;
|
||||
snap_tr.tx = std::floor(snap_tr.tx + .5);
|
||||
snap_tr.ty = std::floor(snap_tr.ty + .5);
|
||||
svg_renderer.render(ras, sl, renb, snap_tr, opacity, bbox);
|
||||
}
|
||||
else
|
||||
{
|
||||
svg_renderer.render(ras, sl, renb, tr, opacity, bbox);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RendererType, typename RasterizerType>
|
||||
void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_32 & src,
|
||||
agg::trans_affine const& tr, double opacity,
|
||||
float scale_factor, bool snap_to_pixels)
|
||||
{
|
||||
using color_type = agg::rgba8;
|
||||
using pixfmt_pre = agg::pixfmt_rgba32_pre;
|
||||
agg::scanline_u8 sl;
|
||||
double width = src.width();
|
||||
double height = src.height();
|
||||
if (std::fabs(1.0 - scale_factor) < 0.001
|
||||
&& (std::fabs(1.0 - tr.sx) < agg::affine_epsilon)
|
||||
&& (std::fabs(0.0 - tr.shy) < agg::affine_epsilon)
|
||||
&& (std::fabs(0.0 - tr.shx) < agg::affine_epsilon)
|
||||
&& (std::fabs(1.0 - tr.sy) < agg::affine_epsilon))
|
||||
{
|
||||
agg::rendering_buffer src_buffer((unsigned char *)src.getBytes(),src.width(),src.height(),src.width() * 4);
|
||||
pixfmt_pre pixf_mask(src_buffer);
|
||||
if (snap_to_pixels)
|
||||
{
|
||||
renb.blend_from(pixf_mask,
|
||||
0,
|
||||
std::floor(tr.tx + .5),
|
||||
std::floor(tr.ty + .5),
|
||||
unsigned(255*opacity));
|
||||
}
|
||||
else
|
||||
{
|
||||
renb.blend_from(pixf_mask,
|
||||
0,
|
||||
tr.tx,
|
||||
tr.ty,
|
||||
unsigned(255*opacity));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using img_accessor_type = agg::image_accessor_clone<pixfmt_pre>;
|
||||
using interpolator_type = agg::span_interpolator_linear<>;
|
||||
//using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type>;
|
||||
using span_gen_type = agg::span_image_resample_rgba_affine<img_accessor_type>;
|
||||
using renderer_type = agg::renderer_scanline_aa_alpha<RendererType,
|
||||
agg::span_allocator<color_type>,
|
||||
span_gen_type>;
|
||||
|
||||
double p[8];
|
||||
p[0] = 0; p[1] = 0;
|
||||
p[2] = width; p[3] = 0;
|
||||
p[4] = width; p[5] = height;
|
||||
p[6] = 0; p[7] = height;
|
||||
tr.transform(&p[0], &p[1]);
|
||||
tr.transform(&p[2], &p[3]);
|
||||
tr.transform(&p[4], &p[5]);
|
||||
tr.transform(&p[6], &p[7]);
|
||||
agg::span_allocator<color_type> sa;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bilinear(), true);
|
||||
agg::rendering_buffer marker_buf((unsigned char *)src.getBytes(),
|
||||
src.width(),
|
||||
src.height(),
|
||||
src.width()*4);
|
||||
pixfmt_pre pixf(marker_buf);
|
||||
img_accessor_type ia(pixf);
|
||||
agg::trans_affine final_tr(p, 0, 0, width, height);
|
||||
if (snap_to_pixels)
|
||||
{
|
||||
final_tr.tx = std::floor(final_tr.tx+.5);
|
||||
final_tr.ty = std::floor(final_tr.ty+.5);
|
||||
}
|
||||
interpolator_type interpolator(final_tr);
|
||||
span_gen_type sg(ia, interpolator, filter);
|
||||
renderer_type rp(renb, sa, sg, unsigned(opacity*255));
|
||||
ras.move_to_d(p[0],p[1]);
|
||||
ras.line_to_d(p[2],p[3]);
|
||||
ras.line_to_d(p[4],p[5]);
|
||||
ras.line_to_d(p[6],p[7]);
|
||||
agg::render_scanlines(ras, sl, rp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -37,10 +37,10 @@ struct pixel_position;
|
|||
template <typename T> class box2d;
|
||||
namespace svg { struct path_attributes; }
|
||||
|
||||
void render_vector_marker(cairo_context & context, pixel_position const& pos,
|
||||
svg::svg_path_adapter & svg_path, box2d<double> const& bbox,
|
||||
void render_vector_marker(cairo_context & context, svg::svg_path_adapter & svg_path,
|
||||
agg::pod_bvector<svg::path_attributes> const & attributes,
|
||||
agg::trans_affine const& tr, double opacity, bool recenter);
|
||||
box2d<double> const& bbox, agg::trans_affine const& tr,
|
||||
double opacity);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAPNIK_GRID_MARKER_HELPERS_HPP
|
||||
#define MAPNIK_GRID_MARKER_HELPERS_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/markers_placement.hpp>
|
||||
#include <mapnik/marker_helpers.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_bin.h"
|
||||
#include "agg_image_filters.h"
|
||||
#include "agg_trans_bilinear.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_image_accessors.h"
|
||||
#include "agg_span_image_filter_gray.h"
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename RendererBase, typename RendererType, typename Detector, typename RendererContext>
|
||||
struct raster_markers_rasterizer_dispatch_grid : public raster_markers_dispatch<Detector>
|
||||
{
|
||||
using pixfmt_type = typename RendererBase::pixfmt_type;
|
||||
using color_type = typename RendererBase::pixfmt_type::color_type;
|
||||
|
||||
using BufferType = typename std::tuple_element<0,RendererContext>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
using PixMapType = typename std::tuple_element<2,RendererContext>::type;
|
||||
|
||||
raster_markers_rasterizer_dispatch_grid(image_data_32 const& src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
markers_symbolizer const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
mapnik::feature_impl & feature,
|
||||
attributes const& vars,
|
||||
RendererContext const& renderer_context)
|
||||
: raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor,
|
||||
feature, vars, false),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
ras_(std::get<1>(renderer_context)),
|
||||
pixmap_(std::get<2>(renderer_context)),
|
||||
placed_(false)
|
||||
{}
|
||||
|
||||
void render_raster_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
agg::scanline_bin sl_;
|
||||
double width = src_.width();
|
||||
double height = src_.height();
|
||||
double p[8];
|
||||
p[0] = 0; p[1] = 0;
|
||||
p[2] = width; p[3] = 0;
|
||||
p[4] = width; p[5] = height;
|
||||
p[6] = 0; p[7] = height;
|
||||
marker_tr.transform(&p[0], &p[1]);
|
||||
marker_tr.transform(&p[2], &p[3]);
|
||||
marker_tr.transform(&p[4], &p[5]);
|
||||
marker_tr.transform(&p[6], &p[7]);
|
||||
ras_.move_to_d(p[0],p[1]);
|
||||
ras_.line_to_d(p[2],p[3]);
|
||||
ras_.line_to_d(p[4],p[5]);
|
||||
ras_.line_to_d(p[6],p[7]);
|
||||
RendererType ren(renb_);
|
||||
ren.color(color_type(feature_.id()));
|
||||
agg::render_scanlines(ras_, sl_, ren);
|
||||
if (!placed_)
|
||||
{
|
||||
pixmap_.add_feature(feature_);
|
||||
placed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_type pixf_;
|
||||
RendererBase renb_;
|
||||
RasterizerType & ras_;
|
||||
PixMapType & pixmap_;
|
||||
bool placed_;
|
||||
|
||||
using raster_markers_dispatch<Detector>::src_;
|
||||
using raster_markers_dispatch<Detector>::feature_;
|
||||
using raster_markers_dispatch<Detector>::snap_to_pixels_;
|
||||
};
|
||||
|
||||
|
||||
template <typename SvgRenderer, typename Detector, typename RendererContext>
|
||||
struct vector_markers_rasterizer_dispatch_grid : public vector_markers_dispatch<Detector>
|
||||
{
|
||||
using renderer_base = typename SvgRenderer::renderer_base ;
|
||||
using vertex_source_type = typename SvgRenderer::vertex_source_type ;
|
||||
using attribute_source_type = typename SvgRenderer::attribute_source_type;
|
||||
using pixfmt_type = typename renderer_base::pixfmt_type ;
|
||||
|
||||
using BufferType = typename std::tuple_element<0,RendererContext>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
using PixMapType = typename std::tuple_element<2,RendererContext>::type;
|
||||
|
||||
vector_markers_rasterizer_dispatch_grid(vertex_source_type & path,
|
||||
attribute_source_type const& attrs,
|
||||
box2d<double> const& bbox,
|
||||
agg::trans_affine const& marker_trans,
|
||||
markers_symbolizer const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
mapnik::feature_impl & feature,
|
||||
attributes const& vars,
|
||||
bool snap_to_pixels,
|
||||
RendererContext const& renderer_context)
|
||||
: vector_markers_dispatch<Detector>(bbox, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
svg_renderer_(path, attrs),
|
||||
ras_(std::get<1>(renderer_context)),
|
||||
pixmap_(std::get<2>(renderer_context)),
|
||||
placed_(false)
|
||||
{}
|
||||
|
||||
void render_vector_marker(agg::trans_affine & marker_tr, double opacity)
|
||||
{
|
||||
agg::scanline_bin sl_;
|
||||
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), marker_tr, opacity, bbox_);
|
||||
if (!placed_)
|
||||
{
|
||||
pixmap_.add_feature(feature_);
|
||||
placed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_type pixf_;
|
||||
renderer_base renb_;
|
||||
SvgRenderer svg_renderer_;
|
||||
RasterizerType & ras_;
|
||||
PixMapType & pixmap_;
|
||||
bool placed_;
|
||||
|
||||
using vector_markers_dispatch<Detector>::bbox_;
|
||||
using vector_markers_dispatch<Detector>::feature_;
|
||||
using vector_markers_dispatch<Detector>::snap_to_pixels_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
72
include/mapnik/grid/grid_render_marker.hpp
Normal file
72
include/mapnik/grid/grid_render_marker.hpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAPNIK_GRID_MARKER_HELPERS_HPP
|
||||
#define MAPNIK_GRID_MARKER_HELPERS_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/feature.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_bin.h"
|
||||
#include "agg_image_filters.h"
|
||||
#include "agg_trans_bilinear.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_image_accessors.h"
|
||||
#include "agg_span_image_filter_gray.h"
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename RendererType, typename RasterizerType>
|
||||
void render_raster_marker(RendererType ren,
|
||||
RasterizerType & ras,
|
||||
image_data_32 & src,
|
||||
mapnik::feature_impl const& feature,
|
||||
agg::trans_affine const& marker_tr,
|
||||
double opacity)
|
||||
{
|
||||
using color_type = typename RendererType::color_type;
|
||||
agg::scanline_bin sl;
|
||||
double width = src.width();
|
||||
double height = src.height();
|
||||
double p[8];
|
||||
p[0] = 0; p[1] = 0;
|
||||
p[2] = width; p[3] = 0;
|
||||
p[4] = width; p[5] = height;
|
||||
p[6] = 0; p[7] = height;
|
||||
marker_tr.transform(&p[0], &p[1]);
|
||||
marker_tr.transform(&p[2], &p[3]);
|
||||
marker_tr.transform(&p[4], &p[5]);
|
||||
marker_tr.transform(&p[6], &p[7]);
|
||||
ras.move_to_d(p[0],p[1]);
|
||||
ras.line_to_d(p[2],p[3]);
|
||||
ras.line_to_d(p[4],p[5]);
|
||||
ras.line_to_d(p[6],p[7]);
|
||||
ren.color(color_type(feature.id()));
|
||||
agg::render_scanlines(ras, sl, ren);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -40,19 +40,7 @@
|
|||
#include <mapnik/label_collision_detector.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_ellipse.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_renderer_base.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_image_filters.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_image_accessors.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_span_image_filter_rgba.h"
|
||||
#include "agg_span_interpolator_linear.h"
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
|
@ -71,22 +59,20 @@ using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
|
|||
template <typename Detector>
|
||||
struct vector_markers_dispatch : mapnik::noncopyable
|
||||
{
|
||||
vector_markers_dispatch(box2d<double> const& bbox,
|
||||
vector_markers_dispatch(svg_path_ptr const& src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
symbolizer_base const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl & feature,
|
||||
attributes const& vars,
|
||||
bool snap_to_pixels)
|
||||
: bbox_(bbox),
|
||||
attributes const& vars)
|
||||
: src_(src),
|
||||
marker_trans_(marker_trans),
|
||||
sym_(sym),
|
||||
detector_(detector),
|
||||
feature_(feature),
|
||||
vars_(vars),
|
||||
scale_factor_(scale_factor),
|
||||
snap_to_pixels_(snap_to_pixels)
|
||||
scale_factor_(scale_factor)
|
||||
{}
|
||||
|
||||
virtual ~vector_markers_dispatch() {}
|
||||
|
@ -101,10 +87,11 @@ struct vector_markers_dispatch : mapnik::noncopyable
|
|||
double opacity = get<double>(sym_,keys::opacity, feature_, vars_, 1.0);
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
coord2d center = bbox_.center();
|
||||
box2d<double> const& bbox = src_->bounding_box();
|
||||
coord2d center = bbox.center();
|
||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||
agg::trans_affine tr = recenter * marker_trans_;
|
||||
markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges };
|
||||
markers_placement_params params { bbox, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges };
|
||||
markers_placement_finder<T, Detector> placement_finder(
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
|
@ -113,42 +100,39 @@ struct vector_markers_dispatch : mapnik::noncopyable
|
|||
agg::trans_affine matrix = tr;
|
||||
matrix.rotate(angle);
|
||||
matrix.translate(x, y);
|
||||
render_vector_marker(matrix, opacity);
|
||||
render_marker(matrix, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void render_vector_marker(agg::trans_affine & marker_tr, double opacity) = 0;
|
||||
virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0;
|
||||
|
||||
protected:
|
||||
box2d<double> const& bbox_;
|
||||
svg_path_ptr const& src_;
|
||||
agg::trans_affine const& marker_trans_;
|
||||
symbolizer_base const& sym_;
|
||||
Detector & detector_;
|
||||
feature_impl & feature_;
|
||||
attributes const& vars_;
|
||||
double scale_factor_;
|
||||
bool snap_to_pixels_;
|
||||
};
|
||||
|
||||
template <typename Detector>
|
||||
struct raster_markers_dispatch : mapnik::noncopyable
|
||||
{
|
||||
raster_markers_dispatch(image_data_32 const& src,
|
||||
raster_markers_dispatch(image_data_32 & src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
symbolizer_base const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl & feature,
|
||||
attributes const& vars,
|
||||
bool snap_to_pixels = false)
|
||||
attributes const& vars)
|
||||
: src_(src),
|
||||
marker_trans_(marker_trans),
|
||||
sym_(sym),
|
||||
detector_(detector),
|
||||
feature_(feature),
|
||||
vars_(vars),
|
||||
scale_factor_(scale_factor),
|
||||
snap_to_pixels_(snap_to_pixels)
|
||||
scale_factor_(scale_factor)
|
||||
{}
|
||||
|
||||
virtual ~raster_markers_dispatch() {}
|
||||
|
@ -159,11 +143,11 @@ struct raster_markers_dispatch : mapnik::noncopyable
|
|||
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT);
|
||||
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
|
||||
bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false);
|
||||
box2d<double> bbox(0,0, src_.width(), src_.height());
|
||||
double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0);
|
||||
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
box2d<double> bbox(0,0, src_.width(), src_.height());
|
||||
markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method, path, detector_, params);
|
||||
|
@ -173,199 +157,20 @@ struct raster_markers_dispatch : mapnik::noncopyable
|
|||
agg::trans_affine matrix = marker_trans_;
|
||||
matrix.rotate(angle);
|
||||
matrix.translate(x, y);
|
||||
render_raster_marker(matrix, opacity);
|
||||
render_marker(matrix, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void render_raster_marker(agg::trans_affine const& marker_tr, double opacity) = 0;
|
||||
virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0;
|
||||
|
||||
protected:
|
||||
image_data_32 const& src_;
|
||||
image_data_32 & src_;
|
||||
agg::trans_affine const& marker_trans_;
|
||||
symbolizer_base const& sym_;
|
||||
Detector & detector_;
|
||||
feature_impl & feature_;
|
||||
attributes const& vars_;
|
||||
double scale_factor_;
|
||||
bool snap_to_pixels_;
|
||||
};
|
||||
|
||||
template <typename SvgRenderer, typename Detector, typename RendererContext>
|
||||
struct vector_markers_rasterizer_dispatch_agg : public vector_markers_dispatch<Detector>
|
||||
{
|
||||
using renderer_base = typename SvgRenderer::renderer_base ;
|
||||
using vertex_source_type = typename SvgRenderer::vertex_source_type ;
|
||||
using attribute_source_type = typename SvgRenderer::attribute_source_type;
|
||||
using pixfmt_type = typename renderer_base::pixfmt_type ;
|
||||
|
||||
using BufferType = typename std::tuple_element<0,RendererContext>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
|
||||
vector_markers_rasterizer_dispatch_agg(vertex_source_type & path,
|
||||
attribute_source_type const& attrs,
|
||||
box2d<double> const& bbox,
|
||||
agg::trans_affine const& marker_trans,
|
||||
symbolizer_base const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl & feature,
|
||||
attributes const& vars,
|
||||
bool snap_to_pixels,
|
||||
RendererContext const& renderer_context)
|
||||
: vector_markers_dispatch<Detector>(bbox, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
svg_renderer_(path, attrs),
|
||||
ras_(std::get<1>(renderer_context))
|
||||
{
|
||||
pixf_.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e>(sym, keys::comp_op, feature, vars, src_over)));
|
||||
}
|
||||
|
||||
~vector_markers_rasterizer_dispatch_agg() {}
|
||||
|
||||
void render_vector_marker(agg::trans_affine & marker_tr, double opacity)
|
||||
{
|
||||
agg::scanline_u8 sl_;
|
||||
|
||||
if (snap_to_pixels_)
|
||||
{
|
||||
// https://github.com/mapnik/mapnik/issues/1316
|
||||
marker_tr.tx = std::floor(marker_tr.tx + .5);
|
||||
marker_tr.ty = std::floor(marker_tr.ty + .5);
|
||||
}
|
||||
svg_renderer_.render(ras_, sl_, renb_, marker_tr, opacity, bbox_);
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_type pixf_;
|
||||
renderer_base renb_;
|
||||
SvgRenderer svg_renderer_;
|
||||
RasterizerType & ras_;
|
||||
|
||||
using vector_markers_dispatch<Detector>::bbox_;
|
||||
using vector_markers_dispatch<Detector>::snap_to_pixels_;
|
||||
};
|
||||
|
||||
template <typename Detector, typename RendererContext>
|
||||
struct raster_markers_rasterizer_dispatch_agg : public raster_markers_dispatch<Detector>
|
||||
{
|
||||
using BufferType = typename std::remove_reference<typename std::tuple_element<0,RendererContext>::type>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
|
||||
using color_type = agg::rgba8;
|
||||
using order_type = agg::order_rgba;
|
||||
using pixel_type = agg::pixel32_type;
|
||||
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
|
||||
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, BufferType>;
|
||||
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
|
||||
|
||||
raster_markers_rasterizer_dispatch_agg(image_data_32 const& src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
symbolizer_base const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl & feature,
|
||||
attributes const& vars,
|
||||
RendererContext const& renderer_context,
|
||||
bool snap_to_pixels = false)
|
||||
: raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor,
|
||||
feature, vars, snap_to_pixels),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
ras_(std::get<1>(renderer_context))
|
||||
{
|
||||
pixf_.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e>(sym, keys::comp_op, feature, vars, src_over)));
|
||||
}
|
||||
|
||||
~raster_markers_rasterizer_dispatch_agg() {}
|
||||
|
||||
void render_raster_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
using pixfmt_pre = agg::pixfmt_rgba32_pre;
|
||||
agg::scanline_u8 sl_;
|
||||
double width = this->src_.width();
|
||||
double height = this->src_.height();
|
||||
if (std::fabs(1.0 - this->scale_factor_) < 0.001
|
||||
&& (std::fabs(1.0 - marker_tr.sx) < agg::affine_epsilon)
|
||||
&& (std::fabs(0.0 - marker_tr.shy) < agg::affine_epsilon)
|
||||
&& (std::fabs(0.0 - marker_tr.shx) < agg::affine_epsilon)
|
||||
&& (std::fabs(1.0 - marker_tr.sy) < agg::affine_epsilon))
|
||||
{
|
||||
agg::rendering_buffer src_buffer((unsigned char *)src_.getBytes(),src_.width(),src_.height(),src_.width() * 4);
|
||||
pixfmt_pre pixf_mask(src_buffer);
|
||||
if (snap_to_pixels_)
|
||||
{
|
||||
renb_.blend_from(pixf_mask,
|
||||
0,
|
||||
std::floor(marker_tr.tx + .5),
|
||||
std::floor(marker_tr.ty + .5),
|
||||
unsigned(255*opacity));
|
||||
}
|
||||
else
|
||||
{
|
||||
renb_.blend_from(pixf_mask,
|
||||
0,
|
||||
marker_tr.tx,
|
||||
marker_tr.ty,
|
||||
unsigned(255*opacity));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using img_accessor_type = agg::image_accessor_clone<pixfmt_pre>;
|
||||
using interpolator_type = agg::span_interpolator_linear<>;
|
||||
//using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type>;
|
||||
using span_gen_type = agg::span_image_resample_rgba_affine<img_accessor_type>;
|
||||
using renderer_type = agg::renderer_scanline_aa_alpha<renderer_base,
|
||||
agg::span_allocator<color_type>,
|
||||
span_gen_type>;
|
||||
|
||||
double p[8];
|
||||
p[0] = 0; p[1] = 0;
|
||||
p[2] = width; p[3] = 0;
|
||||
p[4] = width; p[5] = height;
|
||||
p[6] = 0; p[7] = height;
|
||||
marker_tr.transform(&p[0], &p[1]);
|
||||
marker_tr.transform(&p[2], &p[3]);
|
||||
marker_tr.transform(&p[4], &p[5]);
|
||||
marker_tr.transform(&p[6], &p[7]);
|
||||
agg::span_allocator<color_type> sa;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bilinear(), true);
|
||||
agg::rendering_buffer marker_buf((unsigned char *)src_.getBytes(),
|
||||
src_.width(),
|
||||
src_.height(),
|
||||
src_.width()*4);
|
||||
pixfmt_pre pixf(marker_buf);
|
||||
img_accessor_type ia(pixf);
|
||||
agg::trans_affine final_tr(p, 0, 0, width, height);
|
||||
if (snap_to_pixels_)
|
||||
{
|
||||
final_tr.tx = std::floor(final_tr.tx+.5);
|
||||
final_tr.ty = std::floor(final_tr.ty+.5);
|
||||
}
|
||||
interpolator_type interpolator(final_tr);
|
||||
span_gen_type sg(ia, interpolator, filter);
|
||||
renderer_type rp(renb_,sa, sg, unsigned(opacity*255));
|
||||
ras_.move_to_d(p[0],p[1]);
|
||||
ras_.line_to_d(p[2],p[3]);
|
||||
ras_.line_to_d(p[4],p[5]);
|
||||
ras_.line_to_d(p[6],p[7]);
|
||||
agg::render_scanlines(ras_, sl_, rp);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_comp_type pixf_;
|
||||
renderer_base renb_;
|
||||
RasterizerType & ras_;
|
||||
|
||||
using raster_markers_dispatch<Detector>::src_;
|
||||
using raster_markers_dispatch<Detector>::snap_to_pixels_;
|
||||
};
|
||||
|
||||
void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path);
|
||||
|
|
|
@ -32,17 +32,17 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T0, typename T1, typename T2>
|
||||
template <typename VD, typename RD, typename RendererType, typename ContextType>
|
||||
void render_markers_symbolizer(markers_symbolizer const& sym,
|
||||
mapnik::feature_impl & feature,
|
||||
proj_transform const& prj_trans,
|
||||
renderer_common const& common,
|
||||
RendererType const& common,
|
||||
box2d<double> const& clip_box,
|
||||
T2 const& renderer_context)
|
||||
ContextType const& renderer_context)
|
||||
{
|
||||
using namespace mapnik::svg;
|
||||
using vector_dispatch_type = T0;
|
||||
using raster_dispatch_type = T1;
|
||||
using vector_dispatch_type = VD;
|
||||
using raster_dispatch_type = RD;
|
||||
|
||||
std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse");
|
||||
bool clip = get<value_bool>(sym, keys::clip, feature, common.vars_, false);
|
||||
|
@ -71,18 +71,17 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
|
|||
if (filename == "shape://ellipse"
|
||||
&& (has_key<double>(sym,keys::width) || has_key<double>(sym,keys::height)))
|
||||
{
|
||||
svg_storage_type marker_ellipse;
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source());
|
||||
svg_path_ptr marker_ellipse = std::make_shared<svg_storage_type>();
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse->source());
|
||||
svg_path_adapter svg_path(stl_storage);
|
||||
build_ellipse(sym, feature, common.vars_, marker_ellipse, svg_path);
|
||||
build_ellipse(sym, feature, common.vars_, *marker_ellipse, svg_path);
|
||||
svg_attribute_type attributes;
|
||||
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_);
|
||||
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
|
||||
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
|
||||
box2d<double> bbox = marker_ellipse.bounding_box();
|
||||
vector_dispatch_type rasterizer_dispatch(svg_path,
|
||||
vector_dispatch_type rasterizer_dispatch(marker_ellipse,
|
||||
svg_path,
|
||||
result ? attributes : (*stock_vector_marker)->attributes(),
|
||||
bbox,
|
||||
image_tr,
|
||||
sym,
|
||||
*common.detector_,
|
||||
|
@ -124,9 +123,9 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
|
|||
svg_path_adapter svg_path(stl_storage);
|
||||
svg_attribute_type attributes;
|
||||
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_);
|
||||
vector_dispatch_type rasterizer_dispatch(svg_path,
|
||||
vector_dispatch_type rasterizer_dispatch(*stock_vector_marker,
|
||||
svg_path,
|
||||
result ? attributes : (*stock_vector_marker)->attributes(),
|
||||
bbox,
|
||||
image_tr,
|
||||
sym,
|
||||
*common.detector_,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#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>
|
||||
|
@ -59,6 +60,107 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename SvgRenderer, typename Detector, typename RendererContext>
|
||||
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector>
|
||||
{
|
||||
using renderer_base = typename SvgRenderer::renderer_base;
|
||||
using vertex_source_type = typename SvgRenderer::vertex_source_type;
|
||||
using attribute_source_type = typename SvgRenderer::attribute_source_type;
|
||||
using pixfmt_type = typename renderer_base::pixfmt_type;
|
||||
|
||||
using BufferType = typename std::tuple_element<0,RendererContext>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
|
||||
vector_markers_rasterizer_dispatch(svg_path_ptr const& src,
|
||||
vertex_source_type & path,
|
||||
svg_attribute_type const& attrs,
|
||||
agg::trans_affine const& marker_trans,
|
||||
symbolizer_base const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl & feature,
|
||||
attributes const& vars,
|
||||
bool snap_to_pixels,
|
||||
RendererContext const& renderer_context)
|
||||
: vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
svg_renderer_(path, attrs),
|
||||
ras_(std::get<1>(renderer_context)),
|
||||
snap_to_pixels_(snap_to_pixels)
|
||||
{
|
||||
pixf_.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e>(sym, keys::comp_op, feature, vars, src_over)));
|
||||
}
|
||||
|
||||
~vector_markers_rasterizer_dispatch() {}
|
||||
|
||||
void render_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
render_vector_marker(svg_renderer_, ras_, renb_, this->src_->bounding_box(),
|
||||
marker_tr, opacity, snap_to_pixels_);
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_type pixf_;
|
||||
renderer_base renb_;
|
||||
SvgRenderer svg_renderer_;
|
||||
RasterizerType & ras_;
|
||||
bool snap_to_pixels_;
|
||||
};
|
||||
|
||||
template <typename Detector, typename RendererContext>
|
||||
struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch<Detector>
|
||||
{
|
||||
using BufferType = typename std::remove_reference<typename std::tuple_element<0,RendererContext>::type>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
|
||||
using color_type = agg::rgba8;
|
||||
using order_type = agg::order_rgba;
|
||||
using pixel_type = agg::pixel32_type;
|
||||
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
|
||||
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, BufferType>;
|
||||
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
|
||||
|
||||
raster_markers_rasterizer_dispatch(image_data_32 & src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
symbolizer_base const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl & feature,
|
||||
attributes const& vars,
|
||||
RendererContext const& renderer_context,
|
||||
bool snap_to_pixels = false)
|
||||
: raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
ras_(std::get<1>(renderer_context)),
|
||||
snap_to_pixels_(snap_to_pixels)
|
||||
{
|
||||
pixf_.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e>(sym, keys::comp_op, feature, vars, src_over)));
|
||||
}
|
||||
|
||||
~raster_markers_rasterizer_dispatch() {}
|
||||
|
||||
void render_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
render_raster_marker(renb_, ras_, this->src_, marker_tr, opacity, this->scale_factor_, snap_to_pixels_);
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_comp_type pixf_;
|
||||
renderer_base renb_;
|
||||
RasterizerType & ras_;
|
||||
bool snap_to_pixels_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
|
||||
feature_impl & feature,
|
||||
|
@ -94,8 +196,8 @@ void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
|
|||
|
||||
auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_);
|
||||
using context_type = decltype(renderer_context);
|
||||
using vector_dispatch_type = vector_markers_rasterizer_dispatch_agg<svg_renderer_type, detector_type, context_type>;
|
||||
using raster_dispatch_type = raster_markers_rasterizer_dispatch_agg<detector_type, context_type>;
|
||||
using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type, detector_type, context_type>;
|
||||
using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<detector_type, context_type>;
|
||||
|
||||
render_markers_symbolizer<vector_dispatch_type, raster_dispatch_type>(
|
||||
sym, feature, prj_trans, common_, clip_box, renderer_context);
|
||||
|
|
|
@ -32,21 +32,12 @@
|
|||
namespace mapnik
|
||||
{
|
||||
|
||||
void render_vector_marker(cairo_context & context, pixel_position const& pos,
|
||||
svg::svg_path_adapter & svg_path, box2d<double> const& bbox,
|
||||
void render_vector_marker(cairo_context & context, svg::svg_path_adapter & svg_path,
|
||||
agg::pod_bvector<svg::path_attributes> const & attributes,
|
||||
agg::trans_affine const& tr, double opacity, bool recenter)
|
||||
box2d<double> const& bbox, agg::trans_affine const& tr,
|
||||
double opacity)
|
||||
{
|
||||
using namespace mapnik::svg;
|
||||
agg::trans_affine mtx = tr;
|
||||
if (recenter)
|
||||
{
|
||||
coord<double,2> c = bbox.center();
|
||||
mtx = agg::trans_affine_translation(-c.x,-c.y);
|
||||
mtx *= tr;
|
||||
mtx.translate(pos.x, pos.y);
|
||||
}
|
||||
|
||||
agg::trans_affine transform;
|
||||
|
||||
for(unsigned i = 0; i < attributes.size(); ++i)
|
||||
|
@ -56,7 +47,7 @@ void render_vector_marker(cairo_context & context, pixel_position const& pos,
|
|||
continue;
|
||||
cairo_save_restore guard(context);
|
||||
transform = attr.transform;
|
||||
transform *= mtx;
|
||||
transform *= tr;
|
||||
|
||||
// TODO - this 'is_valid' check is not used in the AGG renderer and also
|
||||
// appears to lead to bogus results with
|
||||
|
|
|
@ -201,13 +201,20 @@ void cairo_renderer<T>::render_marker(pixel_position const& pos,
|
|||
mapnik::svg_path_ptr vmarker = *marker.get_vector_data();
|
||||
if (vmarker)
|
||||
{
|
||||
agg::trans_affine marker_tr = tr;
|
||||
marker_tr *=agg::trans_affine_scaling(common_.scale_factor_);
|
||||
box2d<double> bbox = vmarker->bounding_box();
|
||||
agg::trans_affine marker_tr = tr;
|
||||
if (recenter)
|
||||
{
|
||||
coord<double,2> c = bbox.center();
|
||||
marker_tr = agg::trans_affine_translation(-c.x,-c.y);
|
||||
marker_tr *= tr;
|
||||
}
|
||||
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
|
||||
agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes();
|
||||
svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source());
|
||||
svg::svg_path_adapter svg_path(stl_storage);
|
||||
render_vector_marker(context_, pos, svg_path, bbox, attributes, marker_tr, opacity, recenter);
|
||||
marker_tr.translate(pos.x, pos.y);
|
||||
render_vector_marker(context_, svg_path, attributes, bbox, marker_tr, opacity);
|
||||
}
|
||||
}
|
||||
else if (marker.is_bitmap())
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#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
|
||||
|
@ -43,135 +44,67 @@ namespace mapnik
|
|||
|
||||
class feature_impl;
|
||||
class proj_transform;
|
||||
namespace svg { struct path_attributes; }
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename RendererContext, typename SvgPath, typename Attributes, typename Detector>
|
||||
struct markers_dispatch : mapnik::noncopyable
|
||||
template <typename RendererContext, typename Detector>
|
||||
struct vector_markers_dispatch_cairo : public vector_markers_dispatch<Detector>
|
||||
{
|
||||
markers_dispatch(SvgPath & marker,
|
||||
Attributes const& attributes,
|
||||
box2d<double> const& bbox,
|
||||
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 const& feature,
|
||||
feature_impl & feature,
|
||||
mapnik::attributes const& vars,
|
||||
bool snap_to_pixels,
|
||||
RendererContext const& renderer_context)
|
||||
:marker_(marker),
|
||||
attributes_(attributes),
|
||||
bbox_(bbox),
|
||||
marker_trans_(marker_trans),
|
||||
sym_(sym),
|
||||
detector_(detector),
|
||||
scale_factor_(scale_factor),
|
||||
feature_(feature),
|
||||
vars_(vars),
|
||||
: vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
|
||||
path_(path),
|
||||
attr_(attrs),
|
||||
ctx_(std::get<0>(renderer_context))
|
||||
{}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void add_path(T & path)
|
||||
void render_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
marker_placement_enum placement_method = get<marker_placement_enum>(
|
||||
sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT);
|
||||
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
|
||||
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
|
||||
bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false);
|
||||
double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0);
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
coord2d center = bbox_.center();
|
||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||
agg::trans_affine tr = recenter * marker_trans_;
|
||||
markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
agg::trans_affine matrix = tr;
|
||||
matrix.rotate(angle);
|
||||
matrix.translate(x, y);
|
||||
render_vector_marker(
|
||||
ctx_,
|
||||
pixel_position(x, y),
|
||||
marker_,
|
||||
bbox_,
|
||||
attributes_,
|
||||
matrix,
|
||||
opacity,
|
||||
false);
|
||||
}
|
||||
render_vector_marker(ctx_,
|
||||
path_,
|
||||
attr_,
|
||||
this->src_->bounding_box(),
|
||||
marker_tr,
|
||||
opacity);
|
||||
}
|
||||
|
||||
SvgPath & marker_;
|
||||
Attributes const& attributes_;
|
||||
box2d<double> const& bbox_;
|
||||
agg::trans_affine const& marker_trans_;
|
||||
markers_symbolizer const& sym_;
|
||||
Detector & detector_;
|
||||
double scale_factor_;
|
||||
feature_impl const& feature_;
|
||||
attributes const& vars_;
|
||||
private:
|
||||
svg::svg_path_adapter & path_;
|
||||
svg_attribute_type const& attr_;
|
||||
cairo_context & ctx_;
|
||||
};
|
||||
|
||||
template <typename RendererContext, typename Detector>
|
||||
struct raster_markers_dispatch : mapnik::noncopyable
|
||||
struct raster_markers_dispatch_cairo : public raster_markers_dispatch<Detector>
|
||||
{
|
||||
raster_markers_dispatch(mapnik::image_data_32 & src,
|
||||
raster_markers_dispatch_cairo(mapnik::image_data_32 & src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
markers_symbolizer const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
feature_impl const& feature,
|
||||
feature_impl & feature,
|
||||
mapnik::attributes const& vars,
|
||||
RendererContext const& renderer_context)
|
||||
: src_(src),
|
||||
detector_(detector),
|
||||
sym_(sym),
|
||||
marker_trans_(marker_trans),
|
||||
scale_factor_(scale_factor),
|
||||
feature_(feature),
|
||||
vars_(vars),
|
||||
: raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars),
|
||||
ctx_(std::get<0>(renderer_context)) {}
|
||||
|
||||
template <typename T>
|
||||
void add_path(T & path)
|
||||
~raster_markers_dispatch_cairo() {}
|
||||
|
||||
void render_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT);
|
||||
double opacity = get<double>(sym_, keys::opacity, feature_, vars_, 1.0);
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
|
||||
bool avoid_edges = get<bool>(sym_, keys::avoid_edges, feature_, vars_, false);
|
||||
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
|
||||
box2d<double> bbox_(0,0, src_.width(),src_.height());
|
||||
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
agg::trans_affine matrix = marker_trans_;
|
||||
matrix.rotate(angle);
|
||||
matrix.translate(x, y);
|
||||
ctx_.add_image(matrix, src_, opacity);
|
||||
}
|
||||
ctx_.add_image(marker_tr, this->src_, opacity);
|
||||
}
|
||||
|
||||
image_data_32 & src_;
|
||||
Detector & detector_;
|
||||
markers_symbolizer const& sym_;
|
||||
agg::trans_affine const& marker_trans_;
|
||||
double scale_factor_;
|
||||
feature_impl const& feature_;
|
||||
attributes const& vars_;
|
||||
private:
|
||||
cairo_context & ctx_;
|
||||
};
|
||||
|
||||
|
@ -182,8 +115,6 @@ void cairo_renderer<T>::process(markers_symbolizer const& sym,
|
|||
mapnik::feature_impl & feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
|
||||
|
||||
cairo_save_restore guard(context_);
|
||||
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, common_.vars_, src_over);
|
||||
context_.set_operator(comp_op);
|
||||
|
@ -192,11 +123,10 @@ void cairo_renderer<T>::process(markers_symbolizer const& sym,
|
|||
auto renderer_context = std::tie(context_);
|
||||
|
||||
using RendererContextType = decltype(renderer_context);
|
||||
using vector_dispatch_type = detail::markers_dispatch<RendererContextType,
|
||||
svg::path_adapter<svg::vertex_stl_adapter<svg::svg_path_storage> >,
|
||||
svg_attribute_type,label_collision_detector4>;
|
||||
using vector_dispatch_type = detail::vector_markers_dispatch_cairo<RendererContextType,
|
||||
label_collision_detector4>;
|
||||
|
||||
using raster_dispatch_type = detail::raster_markers_dispatch<RendererContextType,
|
||||
using raster_dispatch_type = detail::raster_markers_dispatch_cairo<RendererContextType,
|
||||
label_collision_detector4>;
|
||||
|
||||
|
||||
|
|
|
@ -45,11 +45,14 @@ porting notes -->
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/feature.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
#include <mapnik/marker_helpers.hpp>
|
||||
#include <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_renderer_base.hpp>
|
||||
#include <mapnik/grid/grid_render_marker.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/grid/grid_marker_helpers.hpp>
|
||||
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
|
@ -77,6 +80,111 @@ porting notes -->
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename SvgRenderer, typename Detector, typename RendererContext>
|
||||
struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch<Detector>
|
||||
{
|
||||
using renderer_base = typename SvgRenderer::renderer_base;
|
||||
using vertex_source_type = typename SvgRenderer::vertex_source_type;
|
||||
using attribute_source_type = typename SvgRenderer::attribute_source_type;
|
||||
using pixfmt_type = typename renderer_base::pixfmt_type;
|
||||
|
||||
using BufferType = typename std::tuple_element<0,RendererContext>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
using PixMapType = typename std::tuple_element<2,RendererContext>::type;
|
||||
|
||||
vector_markers_rasterizer_dispatch(svg_path_ptr const& src,
|
||||
vertex_source_type & path,
|
||||
svg_attribute_type const& attrs,
|
||||
agg::trans_affine const& marker_trans,
|
||||
markers_symbolizer const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
mapnik::feature_impl & feature,
|
||||
attributes const& vars,
|
||||
bool snap_to_pixels,
|
||||
RendererContext const& renderer_context)
|
||||
: vector_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor, feature, vars, snap_to_pixels),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
svg_renderer_(path, attrs),
|
||||
ras_(std::get<1>(renderer_context)),
|
||||
pixmap_(std::get<2>(renderer_context)),
|
||||
placed_(false)
|
||||
{}
|
||||
|
||||
void render_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
agg::scanline_bin sl_;
|
||||
svg_renderer_.render_id(ras_, sl_, renb_, this->feature_.id(), marker_tr, opacity, this->src_->bounding_box());
|
||||
if (!placed_)
|
||||
{
|
||||
pixmap_.add_feature(this->feature_);
|
||||
placed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_type pixf_;
|
||||
renderer_base renb_;
|
||||
SvgRenderer svg_renderer_;
|
||||
RasterizerType & ras_;
|
||||
PixMapType & pixmap_;
|
||||
bool placed_;
|
||||
};
|
||||
|
||||
template <typename RendererBase, typename RendererType, typename Detector, typename RendererContext>
|
||||
struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch<Detector>
|
||||
{
|
||||
using pixfmt_type = typename RendererBase::pixfmt_type;
|
||||
using color_type = typename RendererBase::pixfmt_type::color_type;
|
||||
|
||||
using BufferType = typename std::tuple_element<0,RendererContext>::type;
|
||||
using RasterizerType = typename std::tuple_element<1,RendererContext>::type;
|
||||
using PixMapType = typename std::tuple_element<2,RendererContext>::type;
|
||||
|
||||
raster_markers_rasterizer_dispatch(image_data_32 & src,
|
||||
agg::trans_affine const& marker_trans,
|
||||
markers_symbolizer const& sym,
|
||||
Detector & detector,
|
||||
double scale_factor,
|
||||
mapnik::feature_impl & feature,
|
||||
attributes const& vars,
|
||||
RendererContext const& renderer_context)
|
||||
: raster_markers_dispatch<Detector>(src, marker_trans, sym, detector, scale_factor,
|
||||
feature, vars, false),
|
||||
buf_(std::get<0>(renderer_context)),
|
||||
pixf_(buf_),
|
||||
renb_(pixf_),
|
||||
ras_(std::get<1>(renderer_context)),
|
||||
pixmap_(std::get<2>(renderer_context)),
|
||||
placed_(false)
|
||||
{}
|
||||
|
||||
void render_marker(agg::trans_affine const& marker_tr, double opacity)
|
||||
{
|
||||
render_raster_marker(RendererType(renb_), ras_, this->src_, this->feature_, marker_tr, opacity);
|
||||
if (!placed_)
|
||||
{
|
||||
pixmap_.add_feature(this->feature_);
|
||||
placed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BufferType & buf_;
|
||||
pixfmt_type pixf_;
|
||||
RendererBase renb_;
|
||||
RasterizerType & ras_;
|
||||
PixMapType & pixmap_;
|
||||
bool placed_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(markers_symbolizer const& sym,
|
||||
mapnik::feature_impl & feature,
|
||||
|
@ -100,10 +208,10 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
|
|||
|
||||
auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_);
|
||||
using context_type = decltype(renderer_context);
|
||||
using vector_dispatch_type = vector_markers_rasterizer_dispatch_grid<svg_renderer_type,
|
||||
using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch<svg_renderer_type,
|
||||
detector_type,
|
||||
context_type>;
|
||||
using raster_dispatch_type = raster_markers_rasterizer_dispatch_grid<grid_renderer_base_type,
|
||||
using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch<grid_renderer_base_type,
|
||||
renderer_type,
|
||||
detector_type,
|
||||
context_type>;
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
// mapnik
|
||||
#include <mapnik/marker_helpers.hpp>
|
||||
|
||||
#include "agg_ellipse.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path)
|
||||
|
|
Loading…
Reference in a new issue