Update Cairo renderer so that it compiles.

This commit is contained in:
Matt Amos 2013-11-29 16:23:44 +00:00
parent 85dfd045ec
commit 1a22a19a95
3 changed files with 259 additions and 193 deletions

View file

@ -147,6 +147,7 @@ protected:
std::shared_ptr<freetype_engine> font_engine_;
face_manager<freetype_engine> font_manager_;
cairo_face_manager face_manager_;
box2d<double> clip_extent_;
std::shared_ptr<label_collision_detector4> detector_;
box2d<double> query_extent_;
void setup(Map const& m);

View file

@ -21,9 +21,9 @@
*****************************************************************************/
#include <mapnik/cairo_context.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/text_path.hpp>
#include <mapnik/text/text_properties.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/text/face.hpp>
#include <cairo-ft.h>
@ -403,99 +403,101 @@ void cairo_context::restore()
check_object_status_and_throw_exception(*this);
}
void cairo_context::show_glyph(unsigned long index, double x, double y)
void cairo_context::show_glyph(unsigned long index, pixel_position const &pos)
{
cairo_glyph_t glyph;
glyph.index = index;
glyph.x = x;
glyph.y = y;
glyph.x = pos.x;
glyph.y = pos.y;
cairo_show_glyphs(cairo_.get(), &glyph, 1);
check_object_status_and_throw_exception(*this);
}
void cairo_context::glyph_path(unsigned long index, double x, double y)
void cairo_context::glyph_path(unsigned long index, pixel_position const &pos)
{
cairo_glyph_t glyph;
glyph.index = index;
glyph.x = x;
glyph.y = y;
glyph.x = pos.x;
glyph.y = pos.y;
cairo_glyph_path(cairo_.get(), &glyph, 1);
check_object_status_and_throw_exception(*this);
}
void cairo_context::add_text(text_path const& path,
void cairo_context::add_text(glyph_positions_ptr path,
cairo_face_manager & manager,
face_manager<freetype_engine> & font_manager,
double scale_factor)
{
double sx = path.center.x;
double sy = path.center.y;
pixel_position const& base_point = path->get_base_point();
const double sx = base_point.x;
const double sy = base_point.y;
path.rewind();
for (std::size_t iii = 0; iii < path.num_nodes(); ++iii)
//render halo
double halo_radius = 0;
char_properties_ptr format;
for (auto const &glyph_pos : *path)
{
char_info_ptr c;
double x, y, angle;
glyph_info const& glyph = *(glyph_pos.glyph);
path.vertex(c, x, y, angle);
if (glyph.format)
{
format = glyph.format;
// Settings have changed.
halo_radius = format->halo_radius * scale_factor;
}
// make sure we've got reasonable values.
if (halo_radius <= 0.0 || halo_radius > 1024.0) continue;
face_set_ptr faces = font_manager.get_face_set(c->format->face_name, c->format->fontset);
double text_size = c->format->text_size * scale_factor;
face_set_ptr faces = font_manager.get_face_set(format->face_name, format->fontset);
double text_size = format->text_size * scale_factor;
faces->set_character_sizes(text_size);
glyph_ptr glyph = faces->get_glyph(c->c);
if (glyph)
{
cairo_matrix_t matrix;
matrix.xx = text_size * std::cos(angle);
matrix.xy = text_size * std::sin(angle);
matrix.yx = text_size * -std::sin(angle);
matrix.yy = text_size * std::cos(angle);
matrix.xx = text_size * glyph_pos.rot.cos;
matrix.xy = text_size * glyph_pos.rot.sin;
matrix.yx = text_size * -glyph_pos.rot.sin;
matrix.yy = text_size * glyph_pos.rot.cos;
matrix.x0 = 0;
matrix.y0 = 0;
set_font_matrix(matrix);
set_font_face(manager, glyph->get_face());
glyph_path(glyph->get_index(), sx + x, sy - y);
set_line_width(2.0 * c->format->halo_radius * scale_factor);
set_font_face(manager, glyph.face);
pixel_position pos = glyph_pos.pos + glyph.offset.rotate(glyph_pos.rot);
glyph_path(glyph.glyph_index, pixel_position(sx + pos.x, sy - pos.y));
set_line_width(2.0 * halo_radius);
set_line_join(ROUND_JOIN);
set_color(c->format->halo_fill);
set_color(format->halo_fill);
stroke();
}
for (auto const &glyph_pos : *path)
{
glyph_info const& glyph = *(glyph_pos.glyph);
if (glyph.format)
{
format = glyph.format;
// Settings have changed.
halo_radius = format->halo_radius * scale_factor;
}
path.rewind();
for (std::size_t iii = 0; iii < path.num_nodes(); ++iii)
{
char_info_ptr c;
double x, y, angle;
path.vertex(c, x, y, angle);
face_set_ptr faces = font_manager.get_face_set(c->format->face_name, c->format->fontset);
double text_size = c->format->text_size * scale_factor;
face_set_ptr faces = font_manager.get_face_set(format->face_name, format->fontset);
double text_size = format->text_size * scale_factor;
faces->set_character_sizes(text_size);
glyph_ptr glyph = faces->get_glyph(c->c);
if (glyph)
{
cairo_matrix_t matrix;
matrix.xx = text_size * std::cos(angle);
matrix.xy = text_size * std::sin(angle);
matrix.yx = text_size * -std::sin(angle);
matrix.yy = text_size * std::cos(angle);
matrix.xx = text_size * glyph_pos.rot.cos;
matrix.xy = text_size * glyph_pos.rot.sin;
matrix.yx = text_size * -glyph_pos.rot.sin;
matrix.yy = text_size * glyph_pos.rot.cos;
matrix.x0 = 0;
matrix.y0 = 0;
set_font_matrix(matrix);
set_font_face(manager, glyph->get_face());
set_color(c->format->fill);
show_glyph(glyph->get_index(), sx + x, sy - y);
}
set_font_face(manager, glyph.face);
pixel_position pos = glyph_pos.pos + glyph.offset.rotate(glyph_pos.rot);
set_color(format->fill);
show_glyph(glyph.glyph_index, pixel_position(sx + pos.x, sy - pos.y));
}
}

View file

@ -44,12 +44,11 @@
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/segment.hpp>
#include <mapnik/symbolizer_helpers.hpp>
#include <mapnik/text/symbolizer_helpers.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/warp.hpp>
#include <mapnik/config.hpp>
#include <mapnik/text_path.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/noncopyable.hpp>
@ -134,9 +133,9 @@ cairo_renderer_base::cairo_renderer_base(Map const& m,
font_engine_(std::make_shared<freetype_engine>()),
font_manager_(*font_engine_),
face_manager_(font_engine_),
detector_(std::make_shared<label_collision_detector4>(
box2d<double>(-m.buffer_size(), -m.buffer_size(),
m.width() + m.buffer_size(), m.height() + m.buffer_size())))
clip_extent_(-m.buffer_size(), -m.buffer_size(),
m.width() + m.buffer_size(), m.height() + m.buffer_size()),
detector_(std::make_shared<label_collision_detector4>(clip_extent_))
{
setup(m);
}
@ -156,9 +155,9 @@ cairo_renderer_base::cairo_renderer_base(Map const& m,
font_engine_(std::make_shared<freetype_engine>()),
font_manager_(*font_engine_),
face_manager_(font_engine_),
detector_(std::make_shared<label_collision_detector4>(
box2d<double>(-req.buffer_size(), -req.buffer_size(),
req.width() + req.buffer_size(), req.height() + req.buffer_size())))
clip_extent_(-m.buffer_size(), -m.buffer_size(),
m.width() + m.buffer_size(), m.height() + m.buffer_size()),
detector_(std::make_shared<label_collision_detector4>(clip_extent_))
{
setup(m);
}
@ -178,6 +177,8 @@ cairo_renderer_base::cairo_renderer_base(Map const& m,
font_engine_(std::make_shared<freetype_engine>()),
font_manager_(*font_engine_),
face_manager_(font_engine_),
clip_extent_(-m.buffer_size(), -m.buffer_size(),
m.width() + m.buffer_size(), m.height() + m.buffer_size()),
detector_(detector)
{
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << m.scale();
@ -310,22 +311,30 @@ void cairo_renderer_base::process(polygon_symbolizer const& sym,
proj_transform const& prj_trans)
{
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
context_.set_color(sym.get_fill(), sym.get_opacity());
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
mapnik::color fill = get<mapnik::color>(sym, keys::fill, feature, mapnik::color(128,128,128));
double opacity = get<double>(sym, keys::fill_opacity, feature, 1.0);
auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
bool clip = get<bool>(sym, keys::clip, feature, false);
double simplify_tolerance = get<double>(sym, keys::simplify_tolerance, feature, 0.0);
double smooth = get<double>(sym, keys::smooth, feature, 0.0);
context_.set_operator(comp_op);
context_.set_color(fill, opacity);
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
if (geom_transform) { evaluate_transform(tr, feature, *geom_transform); }
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, cairo_context, polygon_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_,context_,sym,t_,prj_trans,tr,1.0);
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>();
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for ( geometry_type & geom : feature.paths())
{
@ -345,15 +354,12 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
{
typedef coord_transform<CoordTransform,geometry_type> path_type;
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
color const& fill = sym.get_fill();
double height = 0.0;
expression_ptr height_expr = sym.height();
if (height_expr)
{
value_type result = boost::apply_visitor(evaluate<feature_impl,value_type>(feature), *height_expr);
height = result.to_double() * scale_factor_;
}
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
mapnik::color fill = get<mapnik::color>(sym, keys::fill, feature);
double opacity = get<double>(sym, keys::fill_opacity, feature, 1.0);
double height = get<double>(sym, keys::height, feature, 0.0);
context_.set_operator(comp_op);
for (std::size_t i = 0; i < feature.num_geometries(); ++i)
{
@ -400,7 +406,7 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
path_type faces_path(t_, *faces, prj_trans);
context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8 / 255.0,
fill.blue() * 0.8 / 255.0, fill.alpha() * sym.get_opacity() / 255.0);
fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0);
context_.add_path(faces_path);
context_.fill();
@ -431,13 +437,13 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
path_type path(t_, *frame, prj_trans);
context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8/255.0,
fill.blue() * 0.8 / 255.0, fill.alpha() * sym.get_opacity() / 255.0);
fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0);
context_.set_line_width(scale_factor_);
context_.add_path(path);
context_.stroke();
path_type roof_path(t_, *roof, prj_trans);
context_.set_color(fill, sym.get_opacity());
context_.set_color(fill, opacity);
context_.add_path(roof_path);
context_.fill();
}
@ -452,30 +458,45 @@ void cairo_renderer_base::process(line_symbolizer const& sym,
offset_transform_tag, affine_transform_tag,
simplify_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
cairo_save_restore guard(context_);
mapnik::stroke const& stroke_ = sym.get_stroke();
context_.set_operator(sym.comp_op());
context_.set_color(stroke_.get_color(), stroke_.get_opacity());
context_.set_line_join(stroke_.get_line_join());
context_.set_line_cap(stroke_.get_line_cap());
context_.set_miter_limit(stroke_.get_miterlimit());
context_.set_line_width(stroke_.get_width() * scale_factor_);
if (stroke_.has_dash())
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
bool clip = get<bool>(sym, keys::clip, feature, false);
double offset = get<double>(sym, keys::offset, feature, 0.0);
double simplify_tolerance = get<double>(sym, keys::simplify_tolerance, feature, 0.0);
double smooth = get<double>(sym, keys::smooth, feature, 0.0);
mapnik::color stroke = get<mapnik::color>(sym, keys::stroke, feature, mapnik::color(0,0,0));
double stroke_opacity = get<double>(sym, keys::stroke_opacity, feature, 1.0);
line_join_enum stroke_join = get<line_join_enum>(sym, keys::stroke_linejoin, MITER_JOIN);
line_cap_enum stroke_cap = get<line_cap_enum>(sym, keys::stroke_linecap, BUTT_CAP);
auto dash = get_optional<dash_array>(sym, keys::stroke_dasharray);
double miterlimit = get<double>(sym, keys::stroke_miterlimit, 4.0);
double width = get<double>(sym, keys::stroke_width, 1.0);
context_.set_operator(comp_op);
context_.set_color(stroke, stroke_opacity);
context_.set_line_join(stroke_join);
context_.set_line_cap(stroke_cap);
context_.set_miter_limit(miterlimit);
context_.set_line_width(width * scale_factor_);
if (dash)
{
context_.set_dash(stroke_.get_dash_array(), scale_factor_);
context_.set_dash(*dash, scale_factor_);
}
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
if (geom_transform) { evaluate_transform(tr, feature, *geom_transform); }
box2d<double> clipping_extent = query_extent_;
if (sym.clip())
if (clip)
{
double padding = (double)(query_extent_.width()/width_);
double half_stroke = stroke_.get_width()/2.0;
double half_stroke = width/2.0;
if (half_stroke > 1)
padding *= half_stroke;
if (std::fabs(sym.offset()) > 0)
padding *= std::fabs(sym.offset()) * 1.2;
if (std::fabs(offset) > 0)
padding *= std::fabs(offset) * 1.2;
padding *= scale_factor_;
clipping_extent.pad(padding);
}
@ -483,12 +504,12 @@ void cairo_renderer_base::process(line_symbolizer const& sym,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(clipping_extent,context_,sym,t_,prj_trans,tr,scale_factor_);
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
if (clip) converter.set<clip_line_tag>(); // optional clip (default: true)
converter.set<transform_tag>(); // always transform
if (std::fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
converter.set<affine_transform_tag>(); // optional affine transform
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for (geometry_type & geom : feature.paths())
{
@ -650,7 +671,16 @@ void cairo_renderer_base::process(point_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
std::string filename = get<std::string>(sym, keys::file, feature);
double opacity = get<double>(sym, keys::opacity, feature, 1.0);
point_placement_enum placement = get<point_placement_enum>(sym, keys::point_placement_type, feature, CENTROID_POINT_PLACEMENT);
bool allow_overlap = get<bool>(sym, keys::allow_overlap, feature, false);
bool ignore_placement = get<bool>(sym, keys::ignore_placement, feature, false);
auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
cairo_save_restore guard(context_);
context_.set_operator(comp_op);
boost::optional<marker_ptr> marker;
if ( !filename.empty() )
@ -669,7 +699,8 @@ void cairo_renderer_base::process(point_symbolizer const& sym,
coord2d center = bbox.center();
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_image_transform());
if (geom_transform) { evaluate_transform(tr, feature, *geom_transform); }
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine recenter_tr = recenter * tr;
box2d<double> label_ext = bbox * recenter_tr * agg::trans_affine_scaling(scale_factor_);
@ -681,7 +712,7 @@ void cairo_renderer_base::process(point_symbolizer const& sym,
double y;
double z = 0;
if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT)
if (placement == CENTROID_POINT_PLACEMENT)
{
if (!label::centroid(geom, x, y))
return;
@ -695,12 +726,12 @@ void cairo_renderer_base::process(point_symbolizer const& sym,
prj_trans.backward(x, y, z);
t_.forward(&x, &y);
label_ext.re_center(x,y);
if (sym.get_allow_overlap() ||
if (allow_overlap ||
detector_->has_placement(label_ext))
{
render_marker(pixel_position(x,y),**marker, tr, sym.get_opacity());
render_marker(pixel_position(x,y),**marker, tr, opacity);
if (!sym.get_ignore_placement())
if (!ignore_placement)
detector_->insert(label_ext);
}
}
@ -711,31 +742,31 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
shield_symbolizer_helper<face_manager<freetype_engine>,
label_collision_detector4> helper(
text_symbolizer_helper helper(
sym, feature, prj_trans,
width_, height_,
scale_factor_,
t_, font_manager_, *detector_, query_extent_);
t_, font_manager_, *detector_,
query_extent_);
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
double opacity = get<double>(sym,keys::opacity,feature, 1.0);
while (helper.next())
context_.set_operator(comp_op);
placements_list const &placements = helper.get();
for (glyph_positions_ptr glyphs : placements)
{
placements_type const& placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)
{
pixel_position pos = helper.get_marker_position(placements[ii]);
pos.x += 0.5 * helper.get_marker_width();
pos.y += 0.5 * helper.get_marker_height();
if (glyphs->marker()) {
pixel_position pos = glyphs->marker_pos();
render_marker(pos,
helper.get_marker(),
helper.get_image_transform(),
sym.get_opacity());
context_.add_text(placements[ii], face_manager_, font_manager_, scale_factor_);
*(glyphs->marker()->marker),
glyphs->marker()->transform,
opacity);
}
context_.add_text(glyphs, face_manager_, font_manager_, scale_factor_);
}
}
@ -746,15 +777,25 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym,
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance().find(filename,true);
std::string filename = get<std::string>(sym, keys::file, feature);
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
boost::optional<marker_ptr> marker;
if ( !filename.empty() )
{
marker = marker_cache::instance().find(filename, true);
}
else
{
marker.reset(std::make_shared<mapnik::marker>());
}
if (!marker && !(*marker)->is_bitmap()) return;
unsigned width((*marker)->width());
unsigned height((*marker)->height());
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
context_.set_operator(comp_op);
cairo_pattern pattern(**((*marker)->get_bitmap_data()));
pattern.set_extend(CAIRO_EXTEND_REPEAT);
@ -821,9 +862,15 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym,
//typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
std::string filename = get<std::string>(sym, keys::file, feature);
auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
bool clip = get<bool>(sym, keys::clip, feature, false);
double simplify_tolerance = get<double>(sym, keys::simplify_tolerance, feature, 0.0);
double smooth = get<double>(sym, keys::smooth, feature, 0.0);
context_.set_operator(comp_op);
std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance().find(filename,true);
if (!marker && !(*marker)->is_bitmap()) return;
@ -853,18 +900,18 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym,
//}
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
if (geom_transform) { evaluate_transform(tr, feature, *geom_transform); }
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, cairo_context, polygon_pattern_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_,context_,sym,t_,prj_trans,tr, scale_factor_);
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>();
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for ( geometry_type & geom : feature.paths())
{
@ -886,7 +933,14 @@ void cairo_renderer_base::process(raster_symbolizer const& sym,
if (source)
{
// If there's a colorizer defined, use it to color the raster in-place
raster_colorizer_ptr colorizer = sym.get_colorizer();
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym, keys::colorizer);
scaling_method_e scaling_method = get<scaling_method_e>(sym, keys::scaling, feature, SCALING_NEAR);
double filter_factor = get<double>(sym, keys::filter_factor, feature);
boost::optional<bool> is_premultiplied = get_optional<bool>(sym, keys::premultiplied, feature);
unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, 16));
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
double opacity = get<double>(sym, keys::opacity, feature, 1.0);
if (colorizer)
colorizer->colorize(source,feature);
@ -901,15 +955,11 @@ void cairo_renderer_base::process(raster_symbolizer const& sym,
int raster_height = end_y - start_y;
if (raster_width > 0 && raster_height > 0)
{
raster target(target_ext, raster_width,raster_height);
scaling_method_e scaling_method = sym.get_scaling_method();
double filter_radius = sym.calculate_filter_factor();
raster target(target_ext, raster_width, raster_height, filter_factor, true);
bool premultiply_source = !source->premultiplied_alpha_;
boost::optional<bool> is_premultiplied = sym.premultiplied();
if (is_premultiplied)
{
if (*is_premultiplied) premultiply_source = false;
else premultiply_source = true;
premultiply_source = !(*is_premultiplied);
}
if (premultiply_source)
{
@ -926,8 +976,7 @@ void cairo_renderer_base::process(raster_symbolizer const& sym,
double offset_y = ext.miny() - start_y;
reproject_and_scale_raster(target, *source, prj_trans,
offset_x, offset_y,
sym.get_mesh_size(),
filter_radius,
mesh_size,
scaling_method);
}
else
@ -950,12 +999,12 @@ void cairo_renderer_base::process(raster_symbolizer const& sym,
image_ratio_y,
0.0,
0.0,
filter_radius);
source->get_filter_factor());
}
}
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
context_.add_image(start_x, start_y, target.data_, sym.get_opacity());
context_.set_operator(comp_op);
context_.add_image(start_x, start_y, target.data_, opacity);
}
}
}
@ -986,7 +1035,13 @@ struct markers_dispatch
template <typename T>
void add_path(T & path)
{
marker_placement_e placement_method = sym_.get_marker_placement();
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, false);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, false);
double opacity = get<double>(sym_, keys::opacity, 1.0);
double spacing = get<double>(sym_, keys::spacing, 100.0);
double max_error = get<double>(sym_, keys::max_error, 0.2);
if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == geometry_type::types::Point)
@ -1015,12 +1070,12 @@ struct markers_dispatch
box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() ||
if (allow_overlap ||
detector_.has_placement(transformed_bbox))
{
render_vector_marker(ctx_, pixel_position(x,y), marker_, attributes_, marker_trans_, sym_.get_opacity(), true);
render_vector_marker(ctx_, pixel_position(x,y), marker_, attributes_, marker_trans_, opacity, true);
if (!sym_.get_ignore_placement())
if (!ignore_placement)
{
detector_.insert(transformed_bbox);
}
@ -1029,15 +1084,15 @@ struct markers_dispatch
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());
spacing * scale_factor_,
max_error,
allow_overlap);
double x, y, angle;
while (placement.get_point(x, y, angle, sym_.get_ignore_placement()))
while (placement.get_point(x, y, angle, ignore_placement))
{
agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle);
render_vector_marker(ctx_, pixel_position(x,y),marker_, attributes_, matrix, sym_.get_opacity(), true);
render_vector_marker(ctx_, pixel_position(x,y),marker_, attributes_, matrix, opacity, true);
}
}
@ -1075,7 +1130,12 @@ struct markers_dispatch_2
template <typename T>
void add_path(T & path)
{
marker_placement_e placement_method = sym_.get_marker_placement();
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
double opacity = get<double>(sym_, keys::opacity, 1.0);
double spacing = get<double>(sym_, keys::spacing, 100.0);
double max_error = get<double>(sym_, keys::max_error, 0.2);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, false);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, false);
if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == geometry_type::types::Point)
@ -1104,11 +1164,11 @@ struct markers_dispatch_2
box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() ||
if (allow_overlap ||
detector_.has_placement(transformed_bbox))
{
ctx_.add_image(matrix, *marker_, sym_.get_opacity());
if (!sym_.get_ignore_placement())
ctx_.add_image(matrix, *marker_, opacity);
if (!ignore_placement)
{
detector_.insert(transformed_bbox);
}
@ -1117,18 +1177,18 @@ struct markers_dispatch_2
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());
spacing * scale_factor_,
max_error,
allow_overlap);
double x, y, angle;
while (placement.get_point(x, y, angle, sym_.get_ignore_placement()))
while (placement.get_point(x, y, angle, ignore_placement))
{
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());
ctx_.add_image(matrix, *marker_, opacity);
}
}
}
@ -1150,22 +1210,29 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
typedef boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag> conv_types;
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
std::string filename = get<std::string>(sym, keys::file, feature, "shape://ellipse");
auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
auto img_transform = get_optional<transform_type>(sym, keys::image_transform);
auto width = get_optional<unsigned>(sym, keys::width);
auto height = get_optional<unsigned>(sym, keys::height);
bool clip = get<bool>(sym, keys::clip, feature, false);
double smooth = get<double>(sym, keys::smooth, feature, 0.0);
context_.set_operator(comp_op);
agg::trans_affine tr = agg::trans_affine_scaling(scale_factor_);
std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature);
if (!filename.empty())
{
boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true);
if (mark && *mark)
{
agg::trans_affine geom_tr;
evaluate_transform(geom_tr, feature, sym.get_transform());
if (geom_transform) { evaluate_transform(geom_tr, feature, *geom_transform); }
box2d<double> const& bbox = (*mark)->bounding_box();
setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym);
evaluate_transform(tr, feature, sym.get_image_transform());
if (img_transform) { evaluate_transform(tr, feature, *img_transform); }
if ((*mark)->is_vector())
{
@ -1176,13 +1243,10 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
boost::optional<svg_path_ptr> const& stock_vector_marker = (*mark)->get_vector_data();
expression_ptr const& width_expr = sym.get_width();
expression_ptr const& height_expr = sym.get_height();
// special case for simple ellipse markers
// to allow for full control over rx/ry dimensions
if (filename == "shape://ellipse"
&& (width_expr || height_expr))
&& (width || height))
{
svg_storage_type marker_ellipse;
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source());
@ -1191,7 +1255,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
svg_attributes_type attributes;
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());
if (img_transform) { evaluate_transform(marker_tr, feature, *img_transform); }
box2d<double> new_bbox = marker_ellipse.bounding_box();
dispatch_type dispatch(context_, marker_ellipse, result?attributes:(*stock_vector_marker)->attributes(),
@ -1200,7 +1264,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
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)
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
@ -1211,7 +1275,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
// don't clip if type==geometry_type::types::Point
}
converter.set<transform_tag>(); //always transform
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, converter, sym);
}
else
@ -1225,7 +1289,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
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)
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
@ -1236,7 +1300,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
// don't clip if type==geometry_type::types::Point
}
converter.set<transform_tag>(); //always transform
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, converter, sym);
}
}
@ -1255,7 +1319,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
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)
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
@ -1266,7 +1330,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
// don't clip if type==geometry_type::types::Point
}
converter.set<transform_tag>(); //always transform
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, converter, sym);
}
}
@ -1278,23 +1342,22 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
text_symbolizer_helper<face_manager<freetype_engine>,
label_collision_detector4> helper(
text_symbolizer_helper helper(
sym, feature, prj_trans,
width_, height_,
scale_factor_,
t_, font_manager_, *detector_, query_extent_);
t_, font_manager_, *detector_,
query_extent_);
cairo_save_restore guard(context_);
context_.set_operator(sym.comp_op());
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
while (helper.next())
context_.set_operator(comp_op);
placements_list const &placements = helper.get();
for (glyph_positions_ptr glyphs : placements)
{
placements_type const& placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)
{
context_.add_text(placements[ii], face_manager_, font_manager_, scale_factor_);
}
context_.add_text(glyphs, face_manager_, font_manager_, scale_factor_);
}
}