+ cairo : impl raster markers support
This commit is contained in:
parent
d8bb4050c5
commit
f35f394b30
1 changed files with 196 additions and 66 deletions
|
@ -623,6 +623,24 @@ public:
|
||||||
context_->restore();
|
context_->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_image(agg::trans_affine const& tr, image_data_32 & data, double opacity = 1.0)
|
||||||
|
{
|
||||||
|
cairo_pattern pattern(data);
|
||||||
|
if (!tr.is_identity())
|
||||||
|
{
|
||||||
|
double m[6];
|
||||||
|
tr.store_to(m);
|
||||||
|
Cairo::Matrix cairo_matrix(m[0],m[1],m[2],m[3],m[4],m[5]);
|
||||||
|
cairo_matrix.invert();
|
||||||
|
pattern.set_matrix(cairo_matrix);
|
||||||
|
}
|
||||||
|
context_->save();
|
||||||
|
context_->set_source(pattern.pattern());
|
||||||
|
context_->paint_with_alpha(opacity);
|
||||||
|
context_->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_font_face(cairo_face_manager & manager, face_ptr face)
|
void set_font_face(cairo_face_manager & manager, face_ptr face)
|
||||||
{
|
{
|
||||||
context_->set_font_face(manager.get_face(face)->face());
|
context_->set_font_face(manager.get_face(face)->face());
|
||||||
|
@ -1127,6 +1145,7 @@ void render_vector_marker(cairo_context & context, pixel_position const& pos, ma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cairo_renderer_base::render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & tr, double opacity, bool recenter)
|
void cairo_renderer_base::render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & tr, double opacity, bool recenter)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1488,6 +1507,87 @@ struct markers_dispatch
|
||||||
double scale_factor_;
|
double scale_factor_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Context, typename ImageMarker, typename Detector>
|
||||||
|
struct markers_dispatch_2
|
||||||
|
{
|
||||||
|
markers_dispatch_2(Context & ctx,
|
||||||
|
ImageMarker & marker,
|
||||||
|
Detector & detector,
|
||||||
|
markers_symbolizer const& sym,
|
||||||
|
box2d<double> const& bbox,
|
||||||
|
agg::trans_affine const& marker_trans,
|
||||||
|
double scale_factor)
|
||||||
|
:ctx_(ctx),
|
||||||
|
marker_(marker),
|
||||||
|
detector_(detector),
|
||||||
|
sym_(sym),
|
||||||
|
bbox_(bbox),
|
||||||
|
marker_trans_(marker_trans),
|
||||||
|
scale_factor_(scale_factor) {}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void add_path(T & path)
|
||||||
|
{
|
||||||
|
marker_placement_e placement_method = sym_.get_marker_placement();
|
||||||
|
|
||||||
|
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||||
|
{
|
||||||
|
double x,y;
|
||||||
|
path.rewind(0);
|
||||||
|
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||||
|
{
|
||||||
|
label::interior_position(path, x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label::centroid(path, x, y);
|
||||||
|
}
|
||||||
|
coord2d center = bbox_.center();
|
||||||
|
agg::trans_affine matrix = agg::trans_affine_translation(-center.x, -center.y);
|
||||||
|
matrix *= marker_trans_;
|
||||||
|
matrix *=agg::trans_affine_translation(x, y);
|
||||||
|
|
||||||
|
box2d<double> transformed_bbox = bbox_ * matrix;
|
||||||
|
|
||||||
|
if (sym_.get_allow_overlap() ||
|
||||||
|
detector_.has_placement(transformed_bbox))
|
||||||
|
{
|
||||||
|
ctx_.add_image(matrix, *marker_, sym_.get_opacity());
|
||||||
|
if (!sym_.get_ignore_placement())
|
||||||
|
{
|
||||||
|
detector_.insert(transformed_bbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
markers_placement<T, label_collision_detector4> placement(path, bbox_, marker_trans_, detector_,
|
||||||
|
sym_.get_spacing() * scale_factor_,
|
||||||
|
sym_.get_max_error(),
|
||||||
|
sym_.get_allow_overlap());
|
||||||
|
double x, y, angle;
|
||||||
|
while (placement.get_point(x, y, angle))
|
||||||
|
{
|
||||||
|
coord2d center = bbox_.center();
|
||||||
|
agg::trans_affine matrix = agg::trans_affine_translation(-center.x, -center.y);
|
||||||
|
matrix *= marker_trans_;
|
||||||
|
matrix *= agg::trans_affine_rotation(angle);
|
||||||
|
matrix *= agg::trans_affine_translation(x, y);
|
||||||
|
ctx_.add_image(matrix, *marker_, sym_.get_opacity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context & ctx_;
|
||||||
|
ImageMarker & marker_;
|
||||||
|
Detector & detector_;
|
||||||
|
markers_symbolizer const& sym_;
|
||||||
|
box2d<double> const& bbox_;
|
||||||
|
agg::trans_affine const& marker_trans_;
|
||||||
|
double scale_factor_;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
void cairo_renderer_base::process(markers_symbolizer const& sym,
|
void cairo_renderer_base::process(markers_symbolizer const& sym,
|
||||||
mapnik::feature_impl & feature,
|
mapnik::feature_impl & feature,
|
||||||
|
@ -1512,83 +1612,113 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
|
||||||
box2d<double> const& bbox = (*mark)->bounding_box();
|
box2d<double> const& bbox = (*mark)->bounding_box();
|
||||||
setup_label_transform(tr, bbox, feature, sym);
|
setup_label_transform(tr, bbox, feature, sym);
|
||||||
|
|
||||||
|
if ((*mark)->is_vector())
|
||||||
using namespace mapnik::svg;
|
{
|
||||||
typedef agg::pod_bvector<path_attributes> svg_attributes_type;
|
using namespace mapnik::svg;
|
||||||
typedef detail::markers_dispatch<cairo_context, mapnik::svg_storage_type,
|
typedef agg::pod_bvector<path_attributes> svg_attributes_type;
|
||||||
|
typedef detail::markers_dispatch<cairo_context, mapnik::svg_storage_type,
|
||||||
svg_attributes_type,label_collision_detector4> dispatch_type;
|
svg_attributes_type,label_collision_detector4> dispatch_type;
|
||||||
|
|
||||||
boost::optional<svg_path_ptr> const& stock_vector_marker = (*mark)->get_vector_data();
|
boost::optional<svg_path_ptr> const& stock_vector_marker = (*mark)->get_vector_data();
|
||||||
|
|
||||||
expression_ptr const& width_expr = sym.get_width();
|
expression_ptr const& width_expr = sym.get_width();
|
||||||
expression_ptr const& height_expr = sym.get_height();
|
expression_ptr const& height_expr = sym.get_height();
|
||||||
|
|
||||||
// special case for simple ellipse markers
|
// special case for simple ellipse markers
|
||||||
// to allow for full control over rx/ry dimensions
|
// to allow for full control over rx/ry dimensions
|
||||||
if (filename == "shape://ellipse"
|
if (filename == "shape://ellipse"
|
||||||
&& (width_expr || height_expr))
|
&& (width_expr || height_expr))
|
||||||
{
|
|
||||||
svg_storage_type marker_ellipse;
|
|
||||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source());
|
|
||||||
svg_path_adapter svg_path(stl_storage);
|
|
||||||
build_ellipse(sym, feature, marker_ellipse, svg_path);
|
|
||||||
svg_attributes_type attributes;
|
|
||||||
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
|
|
||||||
//svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes());
|
|
||||||
agg::trans_affine marker_tr = agg::trans_affine_scaling(scale_factor_);
|
|
||||||
evaluate_transform(marker_tr, feature, sym.get_image_transform());
|
|
||||||
box2d<double> bbox = marker_ellipse.bounding_box();
|
|
||||||
coord2d center = bbox.center();
|
|
||||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
|
||||||
agg::trans_affine marker_trans = recenter * tr;
|
|
||||||
|
|
||||||
dispatch_type dispatch(context, marker_ellipse, result?attributes:(*stock_vector_marker)->attributes(),
|
|
||||||
detector_, sym, bbox, marker_tr, scale_factor_);
|
|
||||||
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
|
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
|
||||||
converter(query_extent_, dispatch, sym, t_, prj_trans, marker_tr, scale_factor_);
|
|
||||||
|
|
||||||
if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
|
|
||||||
{
|
{
|
||||||
eGeomType type = feature.paths()[0].type();
|
svg_storage_type marker_ellipse;
|
||||||
if (type == Polygon)
|
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source());
|
||||||
converter.set<clip_poly_tag>();
|
svg_path_adapter svg_path(stl_storage);
|
||||||
else if (type == LineString)
|
build_ellipse(sym, feature, marker_ellipse, svg_path);
|
||||||
converter.set<clip_line_tag>();
|
svg_attributes_type attributes;
|
||||||
// don't clip if type==Point
|
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
|
||||||
|
agg::trans_affine marker_tr = agg::trans_affine_scaling(scale_factor_);
|
||||||
|
evaluate_transform(marker_tr, feature, sym.get_image_transform());
|
||||||
|
box2d<double> bbox = marker_ellipse.bounding_box();
|
||||||
|
|
||||||
|
dispatch_type dispatch(context, marker_ellipse, result?attributes:(*stock_vector_marker)->attributes(),
|
||||||
|
detector_, sym, bbox, marker_tr, scale_factor_);
|
||||||
|
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
|
||||||
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_, dispatch, sym, t_, prj_trans, marker_tr, scale_factor_);
|
||||||
|
|
||||||
|
if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
|
||||||
|
{
|
||||||
|
eGeomType type = feature.paths()[0].type();
|
||||||
|
if (type == Polygon)
|
||||||
|
converter.set<clip_poly_tag>();
|
||||||
|
else if (type == LineString)
|
||||||
|
converter.set<clip_line_tag>();
|
||||||
|
// don't clip if type==Point
|
||||||
|
}
|
||||||
|
converter.set<transform_tag>(); //always transform
|
||||||
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
||||||
|
{
|
||||||
|
converter.apply(geom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
converter.set<transform_tag>(); //always transform
|
else
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
|
||||||
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
|
||||||
{
|
{
|
||||||
converter.apply(geom);
|
svg_attributes_type attributes;
|
||||||
|
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
|
||||||
|
|
||||||
|
dispatch_type dispatch(context, **stock_vector_marker, result?attributes:(*stock_vector_marker)->attributes(),
|
||||||
|
detector_, sym, bbox, tr, scale_factor_);
|
||||||
|
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
|
||||||
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_, dispatch, sym, t_, prj_trans, tr, scale_factor_);
|
||||||
|
|
||||||
|
if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
|
||||||
|
{
|
||||||
|
eGeomType type = feature.paths()[0].type();
|
||||||
|
if (type == Polygon)
|
||||||
|
converter.set<clip_poly_tag>();
|
||||||
|
else if (type == LineString)
|
||||||
|
converter.set<clip_line_tag>();
|
||||||
|
// don't clip if type==Point
|
||||||
|
}
|
||||||
|
converter.set<transform_tag>(); //always transform
|
||||||
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
||||||
|
{
|
||||||
|
converter.apply(geom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // raster markers
|
||||||
{
|
{
|
||||||
svg_attributes_type attributes;
|
typedef detail::markers_dispatch_2<cairo_context,
|
||||||
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
|
mapnik::image_ptr,
|
||||||
|
label_collision_detector4> dispatch_type;
|
||||||
dispatch_type dispatch(context, **stock_vector_marker, result?attributes:(*stock_vector_marker)->attributes(),
|
boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data();
|
||||||
detector_, sym, bbox, tr, scale_factor_);
|
if ( marker )
|
||||||
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
|
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
|
||||||
converter(query_extent_, dispatch, sym, t_, prj_trans, tr, scale_factor_);
|
|
||||||
|
|
||||||
if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
|
|
||||||
{
|
{
|
||||||
eGeomType type = feature.paths()[0].type();
|
dispatch_type dispatch(context, *marker,
|
||||||
if (type == Polygon)
|
detector_, sym, bbox, tr, scale_factor_);
|
||||||
converter.set<clip_poly_tag>();
|
|
||||||
else if (type == LineString)
|
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
|
||||||
converter.set<clip_line_tag>();
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
// don't clip if type==Point
|
converter(query_extent_, dispatch, sym, t_, prj_trans, tr, scale_factor_);
|
||||||
}
|
|
||||||
converter.set<transform_tag>(); //always transform
|
if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true)
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
{
|
||||||
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
eGeomType type = feature.paths()[0].type();
|
||||||
{
|
if (type == Polygon)
|
||||||
converter.apply(geom);
|
converter.set<clip_poly_tag>();
|
||||||
|
else if (type == LineString)
|
||||||
|
converter.set<clip_line_tag>();
|
||||||
|
// don't clip if type==Point
|
||||||
|
}
|
||||||
|
converter.set<transform_tag>(); //always transform
|
||||||
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
||||||
|
{
|
||||||
|
converter.apply(geom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue