From 4166fcdd5dd2ad95e2f5c3bad1333e2d8a1a0032 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 16 Jul 2014 14:24:00 +0100 Subject: [PATCH] store displacement logic in std::function and delay calc until dx/dy are evaluated (layout) --- include/mapnik/text/text_properties.hpp | 4 +- src/text/layout.cpp | 18 ++++--- src/text/placements/list.cpp | 11 ++-- src/text/placements/simple.cpp | 70 +++++++++++++++++++------ src/text/text_properties.cpp | 14 ++++- 5 files changed, 85 insertions(+), 32 deletions(-) diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index 066a3951b..cb0ea6754 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -36,7 +36,7 @@ #include // stl #include - +#include // boost #include #include @@ -93,7 +93,7 @@ struct MAPNIK_DECL text_layout_properties horizontal_alignment_e halign; justify_alignment_e jalign; vertical_alignment_e valign; - + std::function displacement_evaluator_; }; using text_layout_properties_ptr = std::shared_ptr; diff --git a/src/text/layout.cpp b/src/text/layout.cpp index 9518884de..9d05e8fb5 100644 --- a/src/text/layout.cpp +++ b/src/text/layout.cpp @@ -92,6 +92,7 @@ void text_layout::layout() init_alignment(); // Find text origin. + std::cerr << displacement_.x << "," << displacement_.y << " " << this << std::endl; displacement_ = scale_factor_ * displacement_ + alignment_offset(); if (rotate_displacement_) displacement_ = displacement_.rotate(!orientation_); // Find layout bounds, expanded for rotation @@ -230,17 +231,18 @@ void text_layout::shape_text(text_line & line) shaper_type::shape_text(line, itemizer_, width_map_, font_manager_, scale_factor_); } -void text_layout::evaluate_properties(feature_impl const& feature, attributes const& attr) +void text_layout::evaluate_properties(feature_impl const& feature, attributes const& attrs) { - double dx = boost::apply_visitor(extract_value(feature,attr), properties_.dx); - double dy = boost::apply_visitor(extract_value(feature,attr), properties_.dy); - displacement_ = {dx, dy}; - wrap_width_ = boost::apply_visitor(extract_value(feature,attr), properties_.wrap_width); - double angle = boost::apply_visitor(extract_value(feature,attr), properties_.orientation); + // dx,dy + displacement_ = properties_.displacement_evaluator_(feature, attrs); + wrap_width_ = boost::apply_visitor(extract_value(feature,attrs), properties_.wrap_width); + + double angle = boost::apply_visitor(extract_value(feature,attrs), properties_.orientation); orientation_.init(angle * M_PI/ 180.0); - wrap_before_ = boost::apply_visitor(extract_value(feature,attr), properties_.wrap_before); - rotate_displacement_ = boost::apply_visitor(extract_value(feature,attr), properties_.rotate_displacement); + + wrap_before_ = boost::apply_visitor(extract_value(feature,attrs), properties_.wrap_before); + rotate_displacement_ = boost::apply_visitor(extract_value(feature,attrs), properties_.rotate_displacement); } void text_layout::init_alignment() diff --git a/src/text/placements/list.cpp b/src/text/placements/list.cpp index b66a0f38b..96475881a 100644 --- a/src/text/placements/list.cpp +++ b/src/text/placements/list.cpp @@ -35,17 +35,17 @@ bool text_placement_info_list::next() if (state == 0) { properties = parent_->defaults; } else { - if (state-1 >= parent_->list_.size()) return false; + if (state >= parent_->list_.size() + 1) return false; properties = parent_->list_[state-1]; } - state++; + ++state; return true; } text_symbolizer_properties & text_placements_list::add() { if (list_.size()) { - text_symbolizer_properties &last = list_.back(); + text_symbolizer_properties & last = list_.back(); list_.push_back(last); //Preinitialize with old values } else { list_.push_back(defaults); @@ -65,7 +65,8 @@ text_placement_info_ptr text_placements_list::get_placement_info(double scale_fa } text_placements_list::text_placements_list() - : text_placements(), list_(0) {} + : text_placements(), + list_(0) {} void text_placements_list::add_expressions(expression_set & output) const { @@ -94,7 +95,7 @@ text_placements_ptr text_placements_list::from_xml(xml_node const& xml, fontset_ for( ;itr != end; ++itr) { if (itr->is_text() || !itr->is("Placement")) continue; - text_symbolizer_properties &p = list->add(); + text_symbolizer_properties & p = list->add(); p.format = std::make_shared(*(p.format)); //Make a deep copy //p.layout_defaults = std::make_shared(*(p.layout_defaults)); //TODO: This needs a real copy constructor for text_symbolizer_properties diff --git a/src/text/placements/simple.cpp b/src/text/placements/simple.cpp index 0104b6e1b..0b4163bcb 100644 --- a/src/text/placements/simple.cpp +++ b/src/text/placements/simple.cpp @@ -63,37 +63,77 @@ bool text_placement_info_simple::next() bool text_placement_info_simple::next_position_only() { - pixel_position const& pdisp = {0,0};// FIXME parent_->defaults.layout_defaults.displacement; - pixel_position displacement = {0,0};// FIXME properties.layout_defaults.displacement; if (position_state >= parent_->direction_.size()) return false; directions_e dir = parent_->direction_[position_state]; - switch (dir) { + switch (dir) + { case EXACT_POSITION: - displacement = pdisp; + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(dx,dy); + }; break; case NORTH: - displacement.set(0, -std::abs(pdisp.y)); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(0,-std::abs(dy)); + }; break; case EAST: - displacement.set(std::abs(pdisp.x), 0); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + return pixel_position(std::abs(dx),0); + }; break; case SOUTH: - displacement.set(0, std::abs(pdisp.y)); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(0,std::abs(dy)); + }; break; case WEST: - displacement.set(-std::abs(pdisp.x), 0); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + return pixel_position(-std::abs(dx),0); + }; break; case NORTHEAST: - displacement.set(std::abs(pdisp.x), -std::abs(pdisp.y)); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(std::abs(dx),-std::abs(dy)); + }; break; case SOUTHEAST: - displacement.set(std::abs(pdisp.x), std::abs(pdisp.y)); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(std::abs(dx),std::abs(dy)); + }; break; case NORTHWEST: - displacement.set(-std::abs(pdisp.x), -std::abs(pdisp.y)); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(-std::abs(dx),-std::abs(dy)); + }; break; case SOUTHWEST: - displacement.set(-std::abs(pdisp.x), std::abs(pdisp.y)); + properties.layout_defaults.displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { + double dx = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dx); + double dy = boost::apply_visitor(extract_value(feature,attrs), this->parent_->defaults.layout_defaults.dy); + return pixel_position(-std::abs(dx),std::abs(dy)); + }; break; default: MAPNIK_LOG_WARN(text_placements) << "Unknown placement"; @@ -145,9 +185,9 @@ void text_placements_simple::set_positions(std::string const& positions) std::string::const_iterator first = positions.begin(), last = positions.end(); qi::phrase_parse(first, last, - (direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> float_[push_back(phoenix::ref(text_sizes_), _1)]), - space - ); + (direction_name[push_back(phoenix::ref(direction_), _1)] % ',') + >> *(',' >> float_[push_back(phoenix::ref(text_sizes_), _1)]), + space); if (first != last) { MAPNIK_LOG_WARN(text_placements) << "Could not parse text_placement_simple placement string ('" << positions << "')"; diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index a6e8fe502..3feae7af7 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -200,7 +200,7 @@ void set_property_from_xml(symbolizer_base::value_type & val, char const* name, try { optional val_ = node.get_opt_attr(name); - //if (val_) std::cerr << std::string(name) << " = " << *val_ << std::endl; + if (val_) std::cerr << std::string(name) << ":" << *val_ << std::endl; if (val_) val = *val_; } catch (config_error const& ex) @@ -217,7 +217,15 @@ void set_property_from_xml(symbolizer_base::value_type & val, char const* name, text_layout_properties::text_layout_properties() : halign(H_AUTO), jalign(J_AUTO), - valign(V_AUTO) {} + valign(V_AUTO) +{ + displacement_evaluator_ = [this](feature_impl const& feature, attributes const& attrs) + { double dx_ = boost::apply_visitor(extract_value(feature,attrs), this->dx); + double dy_ = boost::apply_visitor(extract_value(feature,attrs), this->dy); + std::cerr << dx_ << "," << dy_ << std::endl; + return pixel_position(dx_,dy_);}; + +} void text_layout_properties::from_xml(xml_node const &node) { @@ -289,6 +297,8 @@ void text_layout_properties::to_xml(boost::property_tree::ptree & node, void text_layout_properties::add_expressions(expression_set& output) const { + if (is_expression(dx)) output.insert(boost::get(dx)); + if (is_expression(dy)) output.insert(boost::get(dy)); if (is_expression(orientation)) output.insert(boost::get(orientation)); if (is_expression(wrap_width)) output.insert(boost::get(wrap_width)); if (is_expression(wrap_before)) output.insert(boost::get(wrap_before));