store displacement logic in std::function and delay calc until dx/dy are evaluated (layout)

This commit is contained in:
artemp 2014-07-16 14:24:00 +01:00
parent 562058aff6
commit 4166fcdd5d
5 changed files with 85 additions and 32 deletions

View file

@ -36,7 +36,7 @@
#include <mapnik/symbolizer.hpp> #include <mapnik/symbolizer.hpp>
// stl // stl
#include <map> #include <map>
#include <functional>
// boost // boost
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/property_tree/ptree_fwd.hpp> #include <boost/property_tree/ptree_fwd.hpp>
@ -93,7 +93,7 @@ struct MAPNIK_DECL text_layout_properties
horizontal_alignment_e halign; horizontal_alignment_e halign;
justify_alignment_e jalign; justify_alignment_e jalign;
vertical_alignment_e valign; vertical_alignment_e valign;
std::function<pixel_position(feature_impl const& feature, attributes const& attrs)> displacement_evaluator_;
}; };
using text_layout_properties_ptr = std::shared_ptr<text_layout_properties>; using text_layout_properties_ptr = std::shared_ptr<text_layout_properties>;

View file

@ -92,6 +92,7 @@ void text_layout::layout()
init_alignment(); init_alignment();
// Find text origin. // Find text origin.
std::cerr << displacement_.x << "," << displacement_.y << " " << this << std::endl;
displacement_ = scale_factor_ * displacement_ + alignment_offset(); displacement_ = scale_factor_ * displacement_ + alignment_offset();
if (rotate_displacement_) displacement_ = displacement_.rotate(!orientation_); if (rotate_displacement_) displacement_ = displacement_.rotate(!orientation_);
// Find layout bounds, expanded for rotation // 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_); 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<value_double>(feature,attr), properties_.dx); // dx,dy
double dy = boost::apply_visitor(extract_value<value_double>(feature,attr), properties_.dy); displacement_ = properties_.displacement_evaluator_(feature, attrs);
displacement_ = {dx, dy};
wrap_width_ = boost::apply_visitor(extract_value<value_double>(feature,attr), properties_.wrap_width);
double angle = boost::apply_visitor(extract_value<value_double>(feature,attr), properties_.orientation);
wrap_width_ = boost::apply_visitor(extract_value<value_double>(feature,attrs), properties_.wrap_width);
double angle = boost::apply_visitor(extract_value<value_double>(feature,attrs), properties_.orientation);
orientation_.init(angle * M_PI/ 180.0); orientation_.init(angle * M_PI/ 180.0);
wrap_before_ = boost::apply_visitor(extract_value<value_bool>(feature,attr), properties_.wrap_before);
rotate_displacement_ = boost::apply_visitor(extract_value<value_bool>(feature,attr), properties_.rotate_displacement); wrap_before_ = boost::apply_visitor(extract_value<value_bool>(feature,attrs), properties_.wrap_before);
rotate_displacement_ = boost::apply_visitor(extract_value<value_bool>(feature,attrs), properties_.rotate_displacement);
} }
void text_layout::init_alignment() void text_layout::init_alignment()

View file

@ -35,17 +35,17 @@ bool text_placement_info_list::next()
if (state == 0) { if (state == 0) {
properties = parent_->defaults; properties = parent_->defaults;
} else { } else {
if (state-1 >= parent_->list_.size()) return false; if (state >= parent_->list_.size() + 1) return false;
properties = parent_->list_[state-1]; properties = parent_->list_[state-1];
} }
state++; ++state;
return true; return true;
} }
text_symbolizer_properties & text_placements_list::add() text_symbolizer_properties & text_placements_list::add()
{ {
if (list_.size()) { if (list_.size()) {
text_symbolizer_properties &last = list_.back(); text_symbolizer_properties & last = list_.back();
list_.push_back(last); //Preinitialize with old values list_.push_back(last); //Preinitialize with old values
} else { } else {
list_.push_back(defaults); 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::text_placements_list()
: text_placements(), list_(0) {} : text_placements(),
list_(0) {}
void text_placements_list::add_expressions(expression_set & output) const 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) for( ;itr != end; ++itr)
{ {
if (itr->is_text() || !itr->is("Placement")) continue; 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<char_properties>(*(p.format)); //Make a deep copy p.format = std::make_shared<char_properties>(*(p.format)); //Make a deep copy
//p.layout_defaults = std::make_shared<text_layout_properties>(*(p.layout_defaults)); //p.layout_defaults = std::make_shared<text_layout_properties>(*(p.layout_defaults));
//TODO: This needs a real copy constructor for text_symbolizer_properties //TODO: This needs a real copy constructor for text_symbolizer_properties

View file

@ -63,37 +63,77 @@ bool text_placement_info_simple::next()
bool text_placement_info_simple::next_position_only() 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; if (position_state >= parent_->direction_.size()) return false;
directions_e dir = parent_->direction_[position_state]; directions_e dir = parent_->direction_[position_state];
switch (dir) { switch (dir)
{
case EXACT_POSITION: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
double dy = boost::apply_visitor(extract_value<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(dx,dy);
};
break; break;
case NORTH: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(0,-std::abs(dy));
};
break; break;
case EAST: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
return pixel_position(std::abs(dx),0);
};
break; break;
case SOUTH: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(0,std::abs(dy));
};
break; break;
case WEST: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
return pixel_position(-std::abs(dx),0);
};
break; break;
case NORTHEAST: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
double dy = boost::apply_visitor(extract_value<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(std::abs(dx),-std::abs(dy));
};
break; break;
case SOUTHEAST: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
double dy = boost::apply_visitor(extract_value<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(std::abs(dx),std::abs(dy));
};
break; break;
case NORTHWEST: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
double dy = boost::apply_visitor(extract_value<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(-std::abs(dx),-std::abs(dy));
};
break; break;
case SOUTHWEST: 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<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dx);
double dy = boost::apply_visitor(extract_value<value_double>(feature,attrs), this->parent_->defaults.layout_defaults.dy);
return pixel_position(-std::abs(dx),std::abs(dy));
};
break; break;
default: default:
MAPNIK_LOG_WARN(text_placements) << "Unknown placement"; 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(); std::string::const_iterator first = positions.begin(), last = positions.end();
qi::phrase_parse(first, last, qi::phrase_parse(first, last,
(direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> float_[push_back(phoenix::ref(text_sizes_), _1)]), (direction_name[push_back(phoenix::ref(direction_), _1)] % ',')
space >> *(',' >> float_[push_back(phoenix::ref(text_sizes_), _1)]),
); space);
if (first != last) if (first != last)
{ {
MAPNIK_LOG_WARN(text_placements) << "Could not parse text_placement_simple placement string ('" << positions << "')"; MAPNIK_LOG_WARN(text_placements) << "Could not parse text_placement_simple placement string ('" << positions << "')";

View file

@ -200,7 +200,7 @@ void set_property_from_xml(symbolizer_base::value_type & val, char const* name,
try try
{ {
optional<target_type> val_ = node.get_opt_attr<target_type>(name); optional<target_type> val_ = node.get_opt_attr<target_type>(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_; if (val_) val = *val_;
} }
catch (config_error const& ex) 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() text_layout_properties::text_layout_properties()
: halign(H_AUTO), : halign(H_AUTO),
jalign(J_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<value_double>(feature,attrs), this->dx);
double dy_ = boost::apply_visitor(extract_value<value_double>(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) 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 void text_layout_properties::add_expressions(expression_set& output) const
{ {
if (is_expression(dx)) output.insert(boost::get<expression_ptr>(dx));
if (is_expression(dy)) output.insert(boost::get<expression_ptr>(dy));
if (is_expression(orientation)) output.insert(boost::get<expression_ptr>(orientation)); if (is_expression(orientation)) output.insert(boost::get<expression_ptr>(orientation));
if (is_expression(wrap_width)) output.insert(boost::get<expression_ptr>(wrap_width)); if (is_expression(wrap_width)) output.insert(boost::get<expression_ptr>(wrap_width));
if (is_expression(wrap_before)) output.insert(boost::get<expression_ptr>(wrap_before)); if (is_expression(wrap_before)) output.insert(boost::get<expression_ptr>(wrap_before));