diff --git a/CHANGELOG b/CHANGELOG index eebfb533f..e85018ea2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,7 +11,14 @@ Developers: Please commit along with changes. For a complete change history, see the SVN log. -Mapnik Trunk +Mapnik 2.1.0 +------------ + +- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908) + + + +Mapnik 2.0.0 ------------ - Add minimum-path-length property to text_symbolizer to allow labels to be placed only on lines of a certain length (#865) diff --git a/include/mapnik/placement_finder.hpp b/include/mapnik/placement_finder.hpp index a2368ed93..2a605d15b 100644 --- a/include/mapnik/placement_finder.hpp +++ b/include/mapnik/placement_finder.hpp @@ -77,6 +77,10 @@ struct placement : boost::noncopyable std::pair dimensions; bool collect_extents; box2d extents; + + // additional boxes attached to the text labels which must also be + // placed in order for the text placement to succeed. e.g: shields. + std::vector > additional_boxes; }; diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index cb3591abc..2008939f0 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -229,12 +229,17 @@ void agg_renderer::process(shield_symbolizer const& sym, else if (geom.num_points() > 1 && how_placed == LINE_PLACEMENT) { - placement text_placement(info, sym, scale_factor_, label_ext.width(), label_ext.height(), true); - + placement text_placement(info, sym, scale_factor_, w, h, false); + position const& pos = sym.get_displacement(); + text_placement.avoid_edges = sym.get_avoid_edges(); + text_placement.additional_boxes.push_back( + box2d(-0.5 * label_ext.width() - boost::get<0>(pos), + -0.5 * label_ext.height() - boost::get<1>(pos), + 0.5 * label_ext.width() - boost::get<0>(pos), + 0.5 * label_ext.height() - boost::get<1>(pos))); finder.find_point_placements(text_placement, placement_options, path); - position const& pos = sym.get_displacement(); for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) { double x = floor(text_placement.placements[ii].starting_x); @@ -244,13 +249,13 @@ void agg_renderer::process(shield_symbolizer const& sym, double ly = y - boost::get<1>(pos); int px=int(floor(lx - (0.5*w))) + 1; int py=int(floor(ly - (0.5*h))) + 1; + label_ext.re_center(lx, ly); render_marker(px,py,**marker,tr,sym.get_opacity()); - if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second); - box2d dim = ren.prepare_glyphs(&text_placement.placements[ii]); ren.render(x,y); + if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second); } finder.update_detector(text_placement); if (writer.first) writer.first->add_text(text_placement, faces, feature, t_, writer.second); diff --git a/src/placement_finder.cpp b/src/placement_finder.cpp index a57da1222..9813dab04 100644 --- a/src/placement_finder.cpp +++ b/src/placement_finder.cpp @@ -38,6 +38,7 @@ #include #include #include +#include //stl #include @@ -482,6 +483,23 @@ void placement_finder::find_point_placement(placement & p, x += cwidth; // move position to next character } + // check the placement of any additional envelopes + if (!p.allow_overlap && !p.additional_boxes.empty()) + { + BOOST_FOREACH(box2d box, p.additional_boxes) + { + box2d pt(box.minx() + current_placement->starting_x, + box.miny() + current_placement->starting_y, + box.maxx() + current_placement->starting_x, + box.maxy() + current_placement->starting_y); + + // abort the whole placement if the additional envelopes can't be placed. + if (!detector_.has_point_placement(pt, p.minimum_distance)) return; + + c_envelopes.push(pt); + } + } + // since there was no early exit, add the character envelopes to the placements' envelopes while( !c_envelopes.empty() ) {