diff --git a/src/build.py b/src/build.py index 3e9b9ec9e..35f86e9a5 100644 --- a/src/build.py +++ b/src/build.py @@ -151,7 +151,6 @@ source = Split( markers_symbolizer.cpp metawriter.cpp raster_colorizer.cpp - text_placements.cpp wkt/wkt_factory.cpp metawriter_inmem.cpp metawriter_factory.cpp @@ -172,6 +171,11 @@ source = Split( formatting/format.cpp formatting/registry.cpp text_placements/registry.cpp + text_placements/base.cpp + text_placements/dummy.cpp + text_placements/list.cpp + text_placements/simple.cpp + text_properties.cpp """ ) diff --git a/src/text_placements/base.cpp b/src/text_placements/base.cpp new file mode 100644 index 000000000..f11a222cc --- /dev/null +++ b/src/text_placements/base.cpp @@ -0,0 +1,48 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +#include + +namespace mapnik { +text_placements::text_placements() : defaults() +{ +} + +void text_placements::add_expressions(expression_set &output) +{ + defaults.add_expressions(output); +} + + +/************************************************************************/ + +text_placement_info::text_placement_info(text_placements const* parent, + double scale_factor_, dimension_type dim, bool has_dimensions_) + : properties(parent->defaults), + scale_factor(scale_factor_), + has_dimensions(has_dimensions_), + dimensions(dim), + collect_extents(false) +{ + +} + +} //ns mapnik diff --git a/src/text_placements/dummy.cpp b/src/text_placements/dummy.cpp new file mode 100644 index 000000000..cf2d43f15 --- /dev/null +++ b/src/text_placements/dummy.cpp @@ -0,0 +1,39 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +#include +namespace mapnik +{ +bool text_placement_info_dummy::next() +{ + if (state) return false; + state++; + return true; +} + +text_placement_info_ptr text_placements_dummy::get_placement_info( + double scale_factor, dimension_type dim, bool has_dimensions) const +{ + return text_placement_info_ptr(new text_placement_info_dummy( + this, scale_factor, dim, has_dimensions)); +} + +} //ns mapnik diff --git a/src/text_placements/list.cpp b/src/text_placements/list.cpp new file mode 100644 index 000000000..47688ac90 --- /dev/null +++ b/src/text_placements/list.cpp @@ -0,0 +1,85 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +#include +namespace mapnik +{ + +bool text_placement_info_list::next() +{ + if (state == 0) { + properties = parent_->defaults; + } else { + if (state-1 >= parent_->list_.size()) return false; + properties = parent_->list_[state-1]; + } + state++; + return true; +} + +text_symbolizer_properties & text_placements_list::add() +{ + if (list_.size()) { + text_symbolizer_properties &last = list_.back(); + list_.push_back(last); //Preinitialize with old values + } else { + list_.push_back(defaults); + } + return list_.back(); +} + +text_symbolizer_properties & text_placements_list::get(unsigned i) +{ + return list_[i]; +} + +/***************************************************************************/ + +text_placement_info_ptr text_placements_list::get_placement_info( + double scale_factor, dimension_type dim, bool has_dimensions) const +{ + return text_placement_info_ptr(new text_placement_info_list(this, + scale_factor, dim, has_dimensions)); +} + +text_placements_list::text_placements_list() : text_placements(), list_(0) +{ + +} + +void text_placements_list::add_expressions(expression_set &output) +{ + defaults.add_expressions(output); + + std::vector::const_iterator it; + for (it=list_.begin(); it != list_.end(); it++) + { + it->add_expressions(output); + } +} + +unsigned text_placements_list::size() const +{ + return list_.size(); +} + +} //ns mapnik + diff --git a/src/text_placements/simple.cpp b/src/text_placements/simple.cpp new file mode 100644 index 000000000..9037389ae --- /dev/null +++ b/src/text_placements/simple.cpp @@ -0,0 +1,168 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include + +// boost +#include +#include +#include + +namespace mapnik +{ + +namespace qi = boost::spirit::qi; +namespace phoenix = boost::phoenix; +using phoenix::push_back; +using boost::spirit::ascii::space; +using phoenix::ref; +using qi::_1; + +bool text_placement_info_simple::next() +{ + while (1) { + if (state > 0) + { + if (state > parent_->text_sizes_.size()) return false; + properties.format.text_size = parent_->text_sizes_[state-1]; + } + if (!next_position_only()) { + state++; + position_state = 0; + } else { + break; + } + } + return true; +} + +bool text_placement_info_simple::next_position_only() +{ + const position &pdisp = parent_->defaults.displacement; + position &displacement = properties.displacement; + if (position_state >= parent_->direction_.size()) return false; + directions_t dir = parent_->direction_[position_state]; + switch (dir) { + case EXACT_POSITION: + displacement = pdisp; + break; + case NORTH: + displacement = std::make_pair(0, -abs(pdisp.second)); + break; + case EAST: + displacement = std::make_pair(abs(pdisp.first), 0); + break; + case SOUTH: + displacement = std::make_pair(0, abs(pdisp.second)); + break; + case WEST: + displacement = std::make_pair(-abs(pdisp.first), 0); + break; + case NORTHEAST: + displacement = std::make_pair(abs(pdisp.first), -abs(pdisp.second)); + break; + case SOUTHEAST: + displacement = std::make_pair(abs(pdisp.first), abs(pdisp.second)); + break; + case NORTHWEST: + displacement = std::make_pair(-abs(pdisp.first), -abs(pdisp.second)); + break; + case SOUTHWEST: + displacement = std::make_pair(-abs(pdisp.first), abs(pdisp.second)); + break; + default: + std::cerr << "WARNING: Unknown placement\n"; + } + position_state++; + return true; +} + +text_placement_info_ptr text_placements_simple::get_placement_info( + double scale_factor, dimension_type dim, bool has_dimensions) const +{ + return text_placement_info_ptr(new text_placement_info_simple(this, + scale_factor, dim, has_dimensions)); +} + +/** Position string: [POS][SIZE] + * [POS] is any combination of + * N, E, S, W, NE, SE, NW, SW, X (exact position) (separated by commas) + * [SIZE] is a list of font sizes, separated by commas. The first font size + * is always the one given in the TextSymbolizer's parameters. + * First all directions are tried, then font size is reduced + * and all directions are tried again. The process ends when a placement is + * found or the last fontsize is tried without success. + * Example: N,S,15,10,8 (tries placement above, then below and if + * that fails it tries the additional font sizes 15, 10 and 8. + */ +void text_placements_simple::set_positions(std::string positions) +{ + positions_ = positions; + struct direction_name_ : qi::symbols + { + direction_name_() + { + add + ("N" , NORTH) + ("E" , EAST) + ("S" , SOUTH) + ("W" , WEST) + ("NE", NORTHEAST) + ("SE", SOUTHEAST) + ("NW", NORTHWEST) + ("SW", SOUTHWEST) + ("X" , EXACT_POSITION) + ; + } + + } direction_name; + + std::string::iterator first = positions.begin(), last = positions.end(); + qi::phrase_parse(first, last, + (direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> qi::float_[push_back(phoenix::ref(text_sizes_), _1)]), + space + ); + if (first != last) { + std::cerr << "WARNING: Could not parse text_placement_simple placement string ('" << positions << "').\n"; + } + if (direction_.size() == 0) { + std::cerr << "WARNING: text_placements_simple with no valid placments! ('"<< positions<<"')\n"; + } +} + +text_placements_simple::text_placements_simple() +{ + set_positions("X"); +} + +text_placements_simple::text_placements_simple(std::string positions) +{ + set_positions(positions); +} + +std::string text_placements_simple::get_positions() +{ + return positions_; //TODO: Build string from data in direction_ and text_sizes_ +} + +} //ns mapnik diff --git a/src/text_placements.cpp b/src/text_properties.cpp similarity index 63% rename from src/text_placements.cpp rename to src/text_properties.cpp index 1261ec0d4..d54ec67d0 100644 --- a/src/text_placements.cpp +++ b/src/text_properties.cpp @@ -19,29 +19,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ - -#include -#include -#include -#include -#include -#include +// mapnik +#include #include +#include +#include +#include -#include -#include -#include -#include -#include - -namespace mapnik { - -namespace qi = boost::spirit::qi; -namespace phoenix = boost::phoenix; -using boost::spirit::ascii::space; -using phoenix::push_back; -using phoenix::ref; -using qi::_1; +namespace mapnik +{ using boost::optional; text_symbolizer_properties::text_symbolizer_properties() : @@ -350,233 +336,4 @@ void char_properties::to_xml(boost::property_tree::ptree &node, bool explicit_de } } -/************************************************************************/ - -text_placements::text_placements() : defaults() -{ -} - -void text_placements::add_expressions(expression_set &output) -{ - defaults.add_expressions(output); -} - - -/************************************************************************/ - -text_placement_info::text_placement_info(text_placements const* parent, - double scale_factor_, dimension_type dim, bool has_dimensions_) - : properties(parent->defaults), - scale_factor(scale_factor_), - has_dimensions(has_dimensions_), - dimensions(dim), - collect_extents(false) -{ - -} - -bool text_placement_info_dummy::next() -{ - if (state) return false; - state++; - return true; -} - -text_placement_info_ptr text_placements_dummy::get_placement_info( - double scale_factor, dimension_type dim, bool has_dimensions) const -{ - return text_placement_info_ptr(new text_placement_info_dummy( - this, scale_factor, dim, has_dimensions)); -} - -/************************************************************************/ - -bool text_placement_info_simple::next() -{ - while (1) { - if (state > 0) - { - if (state > parent_->text_sizes_.size()) return false; - properties.format.text_size = parent_->text_sizes_[state-1]; - } - if (!next_position_only()) { - state++; - position_state = 0; - } else { - break; - } - } - return true; -} - -bool text_placement_info_simple::next_position_only() -{ - const position &pdisp = parent_->defaults.displacement; - position &displacement = properties.displacement; - if (position_state >= parent_->direction_.size()) return false; - directions_t dir = parent_->direction_[position_state]; - switch (dir) { - case EXACT_POSITION: - displacement = pdisp; - break; - case NORTH: - displacement = std::make_pair(0, -abs(pdisp.second)); - break; - case EAST: - displacement = std::make_pair(abs(pdisp.first), 0); - break; - case SOUTH: - displacement = std::make_pair(0, abs(pdisp.second)); - break; - case WEST: - displacement = std::make_pair(-abs(pdisp.first), 0); - break; - case NORTHEAST: - displacement = std::make_pair(abs(pdisp.first), -abs(pdisp.second)); - break; - case SOUTHEAST: - displacement = std::make_pair(abs(pdisp.first), abs(pdisp.second)); - break; - case NORTHWEST: - displacement = std::make_pair(-abs(pdisp.first), -abs(pdisp.second)); - break; - case SOUTHWEST: - displacement = std::make_pair(-abs(pdisp.first), abs(pdisp.second)); - break; - default: - std::cerr << "WARNING: Unknown placement\n"; - } - position_state++; - return true; -} - -text_placement_info_ptr text_placements_simple::get_placement_info( - double scale_factor, dimension_type dim, bool has_dimensions) const -{ - return text_placement_info_ptr(new text_placement_info_simple(this, - scale_factor, dim, has_dimensions)); -} - -/** Position string: [POS][SIZE] - * [POS] is any combination of - * N, E, S, W, NE, SE, NW, SW, X (exact position) (separated by commas) - * [SIZE] is a list of font sizes, separated by commas. The first font size - * is always the one given in the TextSymbolizer's parameters. - * First all directions are tried, then font size is reduced - * and all directions are tried again. The process ends when a placement is - * found or the last fontsize is tried without success. - * Example: N,S,15,10,8 (tries placement above, then below and if - * that fails it tries the additional font sizes 15, 10 and 8. - */ -void text_placements_simple::set_positions(std::string positions) -{ - positions_ = positions; - struct direction_name_ : qi::symbols - { - direction_name_() - { - add - ("N" , NORTH) - ("E" , EAST) - ("S" , SOUTH) - ("W" , WEST) - ("NE", NORTHEAST) - ("SE", SOUTHEAST) - ("NW", NORTHWEST) - ("SW", SOUTHWEST) - ("X" , EXACT_POSITION) - ; - } - - } direction_name; - - std::string::iterator first = positions.begin(), last = positions.end(); - qi::phrase_parse(first, last, - (direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> qi::float_[push_back(phoenix::ref(text_sizes_), _1)]), - space - ); - if (first != last) { - std::cerr << "WARNING: Could not parse text_placement_simple placement string ('" << positions << "').\n"; - } - if (direction_.size() == 0) { - std::cerr << "WARNING: text_placements_simple with no valid placments! ('"<< positions<<"')\n"; - } -} - -text_placements_simple::text_placements_simple() -{ - set_positions("X"); -} - -text_placements_simple::text_placements_simple(std::string positions) -{ - set_positions(positions); -} - -std::string text_placements_simple::get_positions() -{ - return positions_; //TODO: Build string from data in direction_ and text_sizes_ -} - -/***************************************************************************/ - -bool text_placement_info_list::next() -{ - if (state == 0) { - properties = parent_->defaults; - } else { - if (state-1 >= parent_->list_.size()) return false; - properties = parent_->list_[state-1]; - } - state++; - return true; -} - -text_symbolizer_properties & text_placements_list::add() -{ - if (list_.size()) { - text_symbolizer_properties &last = list_.back(); - list_.push_back(last); //Preinitialize with old values - } else { - list_.push_back(defaults); - } - return list_.back(); -} - -text_symbolizer_properties & text_placements_list::get(unsigned i) -{ - return list_[i]; -} - -/***************************************************************************/ - -text_placement_info_ptr text_placements_list::get_placement_info( - double scale_factor, dimension_type dim, bool has_dimensions) const -{ - return text_placement_info_ptr(new text_placement_info_list(this, - scale_factor, dim, has_dimensions)); -} - -text_placements_list::text_placements_list() : text_placements(), list_(0) -{ - -} - -void text_placements_list::add_expressions(expression_set &output) -{ - defaults.add_expressions(output); - - std::vector::const_iterator it; - for (it=list_.begin(); it != list_.end(); it++) - { - it->add_expressions(output); - } -} - -unsigned text_placements_list::size() const -{ - return list_.size(); -} - - -} //namespace +} //ns mapnik