Update symbolizer_helpers to support new placement finder.

This commit is contained in:
Hermann Kraus 2012-07-07 17:41:49 +02:00
parent dc9106d444
commit f0937451a2
8 changed files with 101 additions and 60 deletions

View file

@ -30,6 +30,7 @@
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/text_path.hpp>
#include <mapnik/text/placement_finder_ng.hpp>
//boost
#include <boost/shared_ptr.hpp>
@ -40,8 +41,6 @@ namespace mapnik {
typedef boost::ptr_vector<text_path> placements_type;
template <typename DetectorT> class placement_finder;
class text_layout;
typedef boost::shared_ptr<text_layout> text_layout_ptr;
/** Helper object that does all the TextSymbolizer placment finding
* work except actually rendering the object. */
@ -63,16 +62,15 @@ public:
/** Return next placement.
* If no more placements are found false is returned.
*/
bool next();
glyph_positions_ptr next();
/** Get current placement. next() has to be called before! */
placements_type & placements() const;
protected:
bool next_point_placement();
bool next_line_placement();
glyph_positions_ptr next_point_placement();
glyph_positions_ptr next_line_placement();
bool next_placement();
void initialize_geometries();
void initialize_points();
void update_detector(glyph_positions_ptr glyphs);
//Input
text_symbolizer const& sym_;
@ -107,7 +105,7 @@ protected:
bool points_on_line_;
text_placement_info_ptr placement_;
boost::shared_ptr<placement_finder<DetectorT> > finder_;
placement_finder_ng finder_;
};
template <typename FaceManagerT, typename DetectorT>
@ -175,6 +173,7 @@ protected:
using text_symbolizer_helper<FaceManagerT, DetectorT>::point_placement_;
using text_symbolizer_helper<FaceManagerT, DetectorT>::angle_;
using text_symbolizer_helper<FaceManagerT, DetectorT>::finder_;
using text_symbolizer_helper<FaceManagerT, DetectorT>::layout_;
};
} //namespace
#endif // SYMBOLIZER_HELPERS_HPP

View file

@ -41,11 +41,18 @@ namespace mapnik
/** This class stores all glyphs in a format run (i.e. conscutive glyphs with the same format). */
class format_run
{
char_properties_ptr properties;
public:
format_run(char_properties_ptr properties, double text_height);
std::vector<glyph_info> const& glyphs() const { return glyphs_; }
void add_glyph(glyph_info const& info);
double line_height() const { return line_height_; }
double text_height() const { return text_height_; }
private:
char_properties_ptr properties_;
std::vector<glyph_info> glyphs_;
double width_;
double text_height_;
double line_height_;
};
typedef boost::shared_ptr<format_run> format_run_ptr;
@ -61,13 +68,13 @@ typedef boost::shared_ptr<format_run> format_run_ptr;
class text_line
{
public:
double max_text_height; //Height of the largest format run in this run.
double max_line_height; //Includes line spacing
text_line();
std::vector<format_run_ptr> const& runs() const { return runs_; }
void add_run(format_run_ptr);
void add_run(format_run_ptr run);
private:
std::vector<format_run_ptr> runs_;
double max_line_height; //Includes line spacing
double max_text_height; //Height of the largest format run in this run.
};
typedef boost::shared_ptr<text_line> text_line_ptr;

View file

@ -25,6 +25,8 @@
//mapnik
#include <mapnik/box2d.hpp>
//stl
#include <list>
//boost
#include <boost/utility.hpp>
@ -42,10 +44,10 @@ typedef feature_impl Feature;
class text_layout;
typedef boost::shared_ptr<text_layout> text_layout_ptr;
class placement_positions
class glyph_positions
{
public:
placement_positions(text_layout_ptr layout);
glyph_positions(text_layout_ptr layout);
void point_placement(double x, double y);
private:
double x_;
@ -53,7 +55,9 @@ private:
bool point_;
text_layout_ptr layout_;
};
typedef boost::shared_ptr<placement_positions> placement_positions_ptr;
typedef boost::shared_ptr<glyph_positions> glyph_positions_ptr;
//typedef std::list<placement_positions_ptr> placement_positions_list;
class placement_finder_ng : boost::noncopyable
{
@ -63,7 +67,7 @@ public:
box2d<double> const& extent);
/** Try to place a single label at the given point. */
placement_positions_ptr find_point_placement(text_layout_ptr layout, double pos_x, double pos_y, double angle=0.0);
glyph_positions_ptr find_point_placement(text_layout_ptr layout, double pos_x, double pos_y, double angle=0.0);
private:
Feature const& feature_;
DetectorType const& detector_;

View file

@ -41,13 +41,10 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
text_renderer<T> ren(*current_buffer_, font_manager_, *(font_manager_.get_stroker()), sym.comp_op());
while (helper.next())
glyph_positions_ptr glyphs;
while ((glyphs = helper.next()))
{
placements_type &placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)
{
ren.render(placements[ii].center);
}
ren.render(glyphs);
}
}

View file

@ -1203,6 +1203,7 @@ void cairo_renderer_base::start_map_processing(Map const& map)
cairo_context context(context_);
context.set_operator(sym.comp_op());
#if 0
while (helper.next())
{
placements_type &placements = helper.placements();
@ -1215,6 +1216,9 @@ void cairo_renderer_base::start_map_processing(Map const& map)
context.add_text(placements[ii], face_manager_, font_manager_);
}
}
#else
#warning CAIRO: Shield symbolizer rendering disabled!
#endif
}
void cairo_renderer_base::process(line_pattern_symbolizer const& sym,
@ -1629,6 +1633,7 @@ void cairo_renderer_base::start_map_processing(Map const& map)
cairo_context context(context_);
context.set_operator(sym.comp_op());
#if 0
while (helper.next()) {
placements_type &placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)
@ -1636,8 +1641,12 @@ void cairo_renderer_base::start_map_processing(Map const& map)
context.add_text(placements[ii], face_manager_, font_manager_);
}
}
#else
#warning CAIRO: Text rendering disabled
#endif
}
template class cairo_renderer<Cairo::Surface>;
template class cairo_renderer<Cairo::Context>;
}

View file

@ -45,7 +45,7 @@ text_symbolizer_helper<FaceManagerT, DetectorT>::text_symbolizer_helper(const te
angle_(0.0),
placement_valid_(false),
points_on_line_(false),
finder_()
finder_(feature, detector, dims_)
{
initialize_geometries();
if (!geometries_to_process_.size()) return;
@ -55,9 +55,9 @@ text_symbolizer_helper<FaceManagerT, DetectorT>::text_symbolizer_helper(const te
}
template <typename FaceManagerT, typename DetectorT>
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next()
glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next()
{
if (!placement_valid_) return false;
if (!placement_valid_) return glyph_positions_ptr();
if (point_placement_)
return next_point_placement();
else
@ -65,14 +65,14 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next()
}
template <typename FaceManagerT, typename DetectorT>
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
{
while (!geometries_to_process_.empty())
{
if (geo_itr_ == geometries_to_process_.end())
{
//Just processed the last geometry. Try next placement.
if (!next_placement()) return false; //No more placements
if (!next_placement()) return glyph_positions_ptr(); //No more placements
//Start again from begin of list
geo_itr_ = geometries_to_process_.begin();
continue; //Reexecute size check
@ -80,10 +80,11 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
clipped_geometry_type clipped(**geo_itr_);
clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
path_type path(t_, clipped, prj_trans_);
finder_->clear_placements();
#if 0
if (points_on_line_) {
finder_->find_point_placements(path);
} else {
@ -102,42 +103,44 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
feature_, t_, writer_.second);
return true;
}
#endif
//No placement for this geometry. Keep it in geometries_to_process_ for next try.
geo_itr_++;
}
return false;
return glyph_positions_ptr();
}
template <typename FaceManagerT, typename DetectorT>
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
{
while (!points_.empty())
{
if (point_itr_ == points_.end())
{
//Just processed the last point. Try next placement.
if (!next_placement()) return false; //No more placements
if (!next_placement()) return glyph_positions_ptr(); //No more placements
//Start again from begin of list
point_itr_ = points_.begin();
continue; //Reexecute size check
}
return false; //TODO
finder_->clear_placements();
finder_->find_point_placement(point_itr_->first, point_itr_->second, angle_);
if (!finder_->get_results().empty())
glyph_positions_ptr glyphs = finder_.find_point_placement(
layout_, point_itr_->first, point_itr_->second, angle_);
if (glyphs)
{
//Found a placement
point_itr_ = points_.erase(point_itr_);
#if 0
if (writer_.first) writer_.first->add_text(
finder_->get_results(), finder_->get_extents(),
feature_, t_, writer_.second);
finder_->update_detector();
return true;
#endif
update_detector(glyphs);
return glyphs;
}
//No placement for this point. Keep it in points_ for next try.
point_itr_++;
}
return false;
return glyph_positions_ptr();
}
struct largest_bbox_first
@ -265,21 +268,14 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
angle_ = 0.0;
}
// finder_ = boost::shared_ptr<placement_finder<DetectorT> >(new placement_finder<DetectorT>(feature_, *placement_, *info_, detector_, dims_));
#if 0
if (writer_.first) finder_->set_collect_extents(true);
#endif
placement_valid_ = true;
return true;
}
template <typename FaceManagerT, typename DetectorT>
placements_type &text_symbolizer_helper<FaceManagerT, DetectorT>::placements() const
{
return finder_->get_results();
}
/*****************************************************************************/
@ -323,26 +319,27 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
double label_x = point_itr_->first + shield_pos.first;
double label_y = point_itr_->second + shield_pos.second;
finder_->clear_placements();
finder_->find_point_placement(label_x, label_y, angle_);
if (finder_->get_results().empty())
glyph_positions_ptr glyphs = finder_.find_point_placement(layout_, label_x, label_y, angle_);
if (!glyphs)
{
//No placement for this point. Keep it in points_ for next try.
point_itr_++;
continue;
}
//Found a label placement but not necessarily also a marker placement
// check to see if image overlaps anything too, there is only ever 1 placement found for points and verticies
// check to see if image overlaps anything too
if (!sym_.get_unlock_image())
{
// center image at text center position
// remove displacement from image label
placements_type const& p = finder_->get_results();
//TODO
#if 0
double lx = p[0].center.x - text_disp.first;
double ly = p[0].center.y - text_disp.second;
marker_x_ = lx - 0.5 * marker_w_;
marker_y_ = ly - 0.5 * marker_h_;
marker_ext_.re_center(lx, ly);
#endif
}
else
{ // center image at reference location
@ -354,12 +351,14 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
if (placement_->properties.allow_overlap || detector_.has_placement(marker_ext_))
{
detector_.insert(marker_ext_);
finder_->update_detector();
this->update_detector(glyphs);
#if 0
if (writer_.first) {
writer_.first->add_box(marker_ext_, feature_, t_, writer_.second);
writer_.first->add_text(finder_->get_results(), finder_->get_extents(),
feature_, t_, writer_.second);
}
#endif
point_itr_ = points_.erase(point_itr_);
return true;
}
@ -374,6 +373,7 @@ template <typename FaceManagerT, typename DetectorT>
bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
{
position const& pos = placement_->properties.displacement;
#if 0
finder_->additional_boxes.clear();
//Markers are automatically centered
finder_->additional_boxes.push_back(
@ -381,6 +381,7 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
-0.5 * marker_ext_.height() - pos.second,
0.5 * marker_ext_.width() - pos.first,
0.5 * marker_ext_.height() - pos.second));
#endif
return text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement();
}

View file

@ -103,4 +103,28 @@ void text_layout::clear()
glyphs_.clear();
}
format_run::format_run(char_properties_ptr properties, double text_height)
: properties_(properties), glyphs_(), width_(0), text_height_(text_height), line_height_(0)
{
}
void format_run::add_glyph(const glyph_info &info)
{
glyphs_.push_back(info);
width_ += info.width;
line_height_ = info.line_height; //Same value for all characters with the same format
}
text_line::text_line()
: max_line_height(0), max_text_height(0)
{
}
void text_line::add_run(format_run_ptr run)
{
max_line_height = std::max(max_line_height, run->line_height());
max_text_height = std::max(max_text_height, run->text_height());
runs_.push_back(run);
}
} //ns mapnik

View file

@ -33,22 +33,22 @@ placement_finder_ng::placement_finder_ng( Feature const& feature, DetectorType &
{
}
placement_positions_ptr placement_finder_ng::find_point_placement(text_layout_ptr layout, double pos_x, double pos_y, double angle)
glyph_positions_ptr placement_finder_ng::find_point_placement(text_layout_ptr layout, double pos_x, double pos_y, double angle)
{
placement_positions_ptr ptr = boost::make_shared<placement_positions>(layout);
ptr->point_placement(pos_x, pos_y);
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>(layout);
glyphs->point_placement(pos_x, pos_y);
//TODO: angle
//TODO: Check for placement
return ptr;
return glyphs;
}
placement_positions::placement_positions(text_layout_ptr layout)
glyph_positions::glyph_positions(text_layout_ptr layout)
: x_(0), y_(0), point_(true), layout_(layout)
{
}
void placement_positions::point_placement(double x, double y)
void glyph_positions::point_placement(double x, double y)
{
x_ = x;
y_ = y;