From f0937451a2f87a059a8ce2bfeca8b0d027a9f547 Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Sat, 7 Jul 2012 17:41:49 +0200 Subject: [PATCH] Update symbolizer_helpers to support new placement finder. --- include/mapnik/symbolizer_helpers.hpp | 15 +++-- include/mapnik/text/layout.hpp | 17 ++++-- include/mapnik/text/placement_finder_ng.hpp | 12 ++-- src/agg/process_text_symbolizer.cpp | 9 +-- src/cairo_renderer.cpp | 9 +++ src/symbolizer_helpers.cpp | 63 +++++++++++---------- src/text/layout.cpp | 24 ++++++++ src/text/placement_finder_ng.cpp | 12 ++-- 8 files changed, 101 insertions(+), 60 deletions(-) diff --git a/include/mapnik/symbolizer_helpers.hpp b/include/mapnik/symbolizer_helpers.hpp index 70dd327e2..00f8175c7 100644 --- a/include/mapnik/symbolizer_helpers.hpp +++ b/include/mapnik/symbolizer_helpers.hpp @@ -30,6 +30,7 @@ #include #include #include +#include //boost #include @@ -40,8 +41,6 @@ namespace mapnik { typedef boost::ptr_vector placements_type; template class placement_finder; -class text_layout; -typedef boost::shared_ptr 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 > finder_; + placement_finder_ng finder_; }; template @@ -175,6 +173,7 @@ protected: using text_symbolizer_helper::point_placement_; using text_symbolizer_helper::angle_; using text_symbolizer_helper::finder_; + using text_symbolizer_helper::layout_; }; } //namespace #endif // SYMBOLIZER_HELPERS_HPP diff --git a/include/mapnik/text/layout.hpp b/include/mapnik/text/layout.hpp index 7447dbcf0..8e9b7d6e5 100644 --- a/include/mapnik/text/layout.hpp +++ b/include/mapnik/text/layout.hpp @@ -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 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 glyphs_; + double width_; + double text_height_; + double line_height_; }; typedef boost::shared_ptr format_run_ptr; @@ -61,13 +68,13 @@ typedef boost::shared_ptr 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 const& runs() const { return runs_; } - void add_run(format_run_ptr); - + void add_run(format_run_ptr run); private: std::vector 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_ptr; diff --git a/include/mapnik/text/placement_finder_ng.hpp b/include/mapnik/text/placement_finder_ng.hpp index a9f46ccc8..f958eaff7 100644 --- a/include/mapnik/text/placement_finder_ng.hpp +++ b/include/mapnik/text/placement_finder_ng.hpp @@ -25,6 +25,8 @@ //mapnik #include +//stl +#include //boost #include @@ -42,10 +44,10 @@ typedef feature_impl Feature; class text_layout; typedef boost::shared_ptr 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_ptr; +typedef boost::shared_ptr glyph_positions_ptr; + +//typedef std::list placement_positions_list; class placement_finder_ng : boost::noncopyable { @@ -63,7 +67,7 @@ public: box2d 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_; diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index 4e6bcee91..c087fb734 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -41,13 +41,10 @@ void agg_renderer::process(text_symbolizer const& sym, text_renderer 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); } } diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 3d3e881b3..76344841f 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -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; template class cairo_renderer; } diff --git a/src/symbolizer_helpers.cpp b/src/symbolizer_helpers.cpp index 3d60df674..3f6a9049d 100644 --- a/src/symbolizer_helpers.cpp +++ b/src/symbolizer_helpers.cpp @@ -45,7 +45,7 @@ text_symbolizer_helper::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::text_symbolizer_helper(const te } template -bool text_symbolizer_helper::next() +glyph_positions_ptr text_symbolizer_helper::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::next() } template -bool text_symbolizer_helper::next_line_placement() +glyph_positions_ptr text_symbolizer_helper::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::next_line_placement() typedef agg::conv_clip_polyline clipped_geometry_type; typedef coord_transform 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::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 -bool text_symbolizer_helper::next_point_placement() +glyph_positions_ptr text_symbolizer_helper::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::next_placement() angle_ = 0.0; } - -// finder_ = boost::shared_ptr >(new placement_finder(feature_, *placement_, *info_, detector_, dims_)); - +#if 0 if (writer_.first) finder_->set_collect_extents(true); +#endif placement_valid_ = true; return true; } -template -placements_type &text_symbolizer_helper::placements() const -{ - return finder_->get_results(); -} - /*****************************************************************************/ @@ -323,26 +319,27 @@ bool shield_symbolizer_helper::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::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 bool shield_symbolizer_helper::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::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::next_line_placement(); } diff --git a/src/text/layout.cpp b/src/text/layout.cpp index 62926b256..b65ac763f 100644 --- a/src/text/layout.cpp +++ b/src/text/layout.cpp @@ -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 diff --git a/src/text/placement_finder_ng.cpp b/src/text/placement_finder_ng.cpp index 0d821f03b..b0afc919a 100644 --- a/src/text/placement_finder_ng.cpp +++ b/src/text/placement_finder_ng.cpp @@ -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(layout); - ptr->point_placement(pos_x, pos_y); + glyph_positions_ptr glyphs = boost::make_shared(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;