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>
// stl
#include <map>
#include <functional>
// boost
#include <boost/optional.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
@ -93,7 +93,7 @@ struct MAPNIK_DECL text_layout_properties
horizontal_alignment_e halign;
justify_alignment_e jalign;
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>;

View file

@ -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<value_double>(feature,attr), properties_.dx);
double dy = boost::apply_visitor(extract_value<value_double>(feature,attr), properties_.dy);
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);
// dx,dy
displacement_ = properties_.displacement_evaluator_(feature, attrs);
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);
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()

View file

@ -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<char_properties>(*(p.format)); //Make a deep copy
//p.layout_defaults = std::make_shared<text_layout_properties>(*(p.layout_defaults));
//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()
{
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<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;
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;
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;
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;
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;
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;
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;
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;
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;
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 << "')";

View file

@ -200,7 +200,7 @@ void set_property_from_xml(symbolizer_base::value_type & val, char const* name,
try
{
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_;
}
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<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)
{
@ -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<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(wrap_width)) output.insert(boost::get<expression_ptr>(wrap_width));
if (is_expression(wrap_before)) output.insert(boost::get<expression_ptr>(wrap_before));