/***************************************************************************** * * This file is part of Mapnik (c++ mapping toolkit) * * Copyright (C) 2011 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 #include #include #include #include namespace mapnik { using boost::optional; text_symbolizer_properties::text_symbolizer_properties() : label_placement(POINT_PLACEMENT), halign(H_AUTO), jalign(J_MIDDLE), valign(V_AUTO), label_spacing(0), label_position_tolerance(0), avoid_edges(false), minimum_distance(0.0), minimum_padding(0.0), max_char_angle_delta(22.5 * M_PI/180.0), force_odd_labels(false), allow_overlap(false), text_ratio(0), wrap_width(0), tree_() { } void text_symbolizer_properties::process(processed_text &output, Feature const& feature) const { output.clear(); if (tree_) { tree_->apply(format, feature, output); } else { #ifdef MAPNIK_DEBUG std::cerr << "Warning: text_symbolizer_properties can't produce text: No formatting tree!\n"; #endif } } void text_symbolizer_properties::set_format_tree(formatting::node_ptr tree) { tree_ = tree; } formatting::node_ptr text_symbolizer_properties::format_tree() const { return tree_; } void text_symbolizer_properties::from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets) { optional placement_ = get_opt_attr(sym, "placement"); if (placement_) label_placement = *placement_; optional valign_ = get_opt_attr(sym, "vertical-alignment"); if (valign_) valign = *valign_; optional text_ratio_ = get_opt_attr(sym, "text-ratio"); if (text_ratio_) text_ratio = *text_ratio_; optional wrap_width_ = get_opt_attr(sym, "wrap-width"); if (wrap_width_) wrap_width = *wrap_width_; optional label_position_tolerance_ = get_opt_attr(sym, "label-position-tolerance"); if (label_position_tolerance_) label_position_tolerance = *label_position_tolerance_; optional spacing_ = get_opt_attr(sym, "spacing"); if (spacing_) label_spacing = *spacing_; optional minimum_distance_ = get_opt_attr(sym, "minimum-distance"); if (minimum_distance_) minimum_distance = *minimum_distance_; optional min_padding_ = get_opt_attr(sym, "minimum-padding"); if (min_padding_) minimum_padding = *min_padding_; optional min_path_length_ = get_opt_attr(sym, "minimum-path-length"); if (min_path_length_) minimum_path_length = *min_path_length_; optional avoid_edges_ = get_opt_attr(sym, "avoid-edges"); if (avoid_edges_) avoid_edges = *avoid_edges_; optional allow_overlap_ = get_opt_attr(sym, "allow-overlap"); if (allow_overlap_) allow_overlap = *allow_overlap_; optional halign_ = get_opt_attr(sym, "horizontal-alignment"); if (halign_) halign = *halign_; optional jalign_ = get_opt_attr(sym, "justify-alignment"); if (jalign_) jalign = *jalign_; /* Attributes needing special care */ optional orientation_ = get_opt_attr(sym, "orientation"); if (orientation_) orientation = parse_expression(*orientation_, "utf8"); optional dx = get_opt_attr(sym, "dx"); if (dx) displacement.first = *dx; optional dy = get_opt_attr(sym, "dy"); if (dy) displacement.second = *dy; optional max_char_angle_delta_ = get_opt_attr(sym, "max-char-angle-delta"); if (max_char_angle_delta_) max_char_angle_delta=(*max_char_angle_delta_)*(M_PI/180); optional name_ = get_opt_attr(sym, "name"); if (name_) { std::clog << "### WARNING: Using 'name' in TextSymbolizer/ShieldSymbolizer is deprecated!\n"; set_old_style_expression(parse_expression(*name_, "utf8")); } format.from_xml(sym, fontsets); formatting::node_ptr n(formatting::node::from_xml(sym)); if (n) set_format_tree(n); } void text_symbolizer_properties::to_xml(boost::property_tree::ptree &node, bool explicit_defaults, text_symbolizer_properties const &dfl) const { if (orientation) { std::string const& orientationstr = to_expression_string(*orientation); if (!dfl.orientation || orientationstr != to_expression_string(*(dfl.orientation)) || explicit_defaults) { set_attr(node, "orientation", orientationstr); } } if (displacement.first != dfl.displacement.first || explicit_defaults) { set_attr(node, "dx", displacement.first); } if (displacement.second != dfl.displacement.second || explicit_defaults) { set_attr(node, "dy", displacement.second); } if (label_placement != dfl.label_placement || explicit_defaults) { set_attr(node, "placement", label_placement); } if (valign != dfl.valign || explicit_defaults) { set_attr(node, "vertical-alignment", valign); } if (text_ratio != dfl.text_ratio || explicit_defaults) { set_attr(node, "text-ratio", text_ratio); } if (wrap_width != dfl.wrap_width || explicit_defaults) { set_attr(node, "wrap-width", wrap_width); } if (label_position_tolerance != dfl.label_position_tolerance || explicit_defaults) { set_attr(node, "label-position-tolerance", label_position_tolerance); } if (label_spacing != dfl.label_spacing || explicit_defaults) { set_attr(node, "spacing", label_spacing); } if (minimum_distance != dfl.minimum_distance || explicit_defaults) { set_attr(node, "minimum-distance", minimum_distance); } if (minimum_padding != dfl.minimum_padding || explicit_defaults) { set_attr(node, "minimum-padding", minimum_padding); } if (minimum_path_length != dfl.minimum_path_length || explicit_defaults) { set_attr(node, "minimum-path-length", minimum_path_length); } if (allow_overlap != dfl.allow_overlap || explicit_defaults) { set_attr(node, "allow-overlap", allow_overlap); } if (avoid_edges != dfl.avoid_edges || explicit_defaults) { set_attr(node, "avoid-edges", avoid_edges); } if (max_char_angle_delta != dfl.max_char_angle_delta || explicit_defaults) { set_attr(node, "max-char-angle-delta", max_char_angle_delta); } if (halign != dfl.halign || explicit_defaults) { set_attr(node, "horizontal-alignment", halign); } if (jalign != dfl.jalign || explicit_defaults) { set_attr(node, "justify-alignment", jalign); } if (valign != dfl.valign || explicit_defaults) { set_attr(node, "vertical-alignment", valign); } format.to_xml(node, explicit_defaults, dfl.format); if (tree_) tree_->to_xml(node); } void text_symbolizer_properties::add_expressions(expression_set &output) const { output.insert(orientation); if (tree_) tree_->add_expressions(output); } void text_symbolizer_properties::set_old_style_expression(expression_ptr expr) { tree_ = formatting::node_ptr(new formatting::text_node(expr)); } char_properties::char_properties() : text_size(10.0), character_spacing(0), line_spacing(0), text_opacity(1.0), wrap_before(false), wrap_char(' '), text_transform(NONE), fill(color(0,0,0)), halo_fill(color(255,255,255)), halo_radius(0) { } void char_properties::from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets) { optional text_size_ = get_opt_attr(sym, "size"); if (text_size_) text_size = *text_size_; optional character_spacing_ = get_opt_attr(sym, "character-spacing"); if (character_spacing_) character_spacing = *character_spacing_; optional fill_ = get_opt_attr(sym, "fill"); if (fill_) fill = *fill_; optional halo_fill_ = get_opt_attr(sym, "halo-fill"); if (halo_fill_) halo_fill = *halo_fill_; optional halo_radius_ = get_opt_attr(sym, "halo-radius"); if (halo_radius_) halo_radius = *halo_radius_; optional wrap_before_ = get_opt_attr(sym, "wrap-before"); if (wrap_before_) wrap_before = *wrap_before_; optional tconvert_ = get_opt_attr(sym, "text-transform"); if (tconvert_) text_transform = *tconvert_; optional line_spacing_ = get_opt_attr(sym, "line-spacing"); if (line_spacing_) line_spacing = *line_spacing_; optional opacity_ = get_opt_attr(sym, "opacity"); if (opacity_) text_opacity = *opacity_; optional wrap_char_ = get_opt_attr(sym, "wrap-character"); if (wrap_char_ && (*wrap_char_).size() > 0) wrap_char = ((*wrap_char_)[0]); optional face_name_ = get_opt_attr(sym, "face-name"); if (face_name_) { face_name = *face_name_; } optional fontset_name_ = get_opt_attr(sym, "fontset-name"); if (fontset_name_) { std::map::const_iterator itr = fontsets.find(*fontset_name_); if (itr != fontsets.end()) { fontset = itr->second; } else { throw config_error("Unable to find any fontset named '" + *fontset_name_ + "'"); } } if (!face_name.empty() && !fontset.get_name().empty()) { throw config_error(std::string("Can't have both face-name and fontset-name")); } if (face_name.empty() && fontset.get_name().empty()) { throw config_error(std::string("Must have face-name or fontset-name")); } } void char_properties::to_xml(boost::property_tree::ptree &node, bool explicit_defaults, char_properties const &dfl) const { std::string const& fontset_name = fontset.get_name(); std::string const& dfl_fontset_name = dfl.fontset.get_name(); if (fontset_name != dfl_fontset_name || explicit_defaults) { set_attr(node, "fontset-name", fontset_name); } if (face_name != dfl.face_name || explicit_defaults) { set_attr(node, "face-name", face_name); } if (text_size != dfl.text_size || explicit_defaults) { set_attr(node, "size", text_size); } if (fill != dfl.fill || explicit_defaults) { set_attr(node, "fill", fill); } if (halo_radius != dfl.halo_radius || explicit_defaults) { set_attr(node, "halo-radius", halo_radius); } if (halo_fill != dfl.halo_fill || explicit_defaults) { set_attr(node, "halo-fill", halo_fill); } if (wrap_before != dfl.wrap_before || explicit_defaults) { set_attr(node, "wrap-before", wrap_before); } if (wrap_char != dfl.wrap_char || explicit_defaults) { set_attr(node, "wrap-character", std::string(1, wrap_char)); } if (text_transform != dfl.text_transform || explicit_defaults) { set_attr(node, "text-transform", text_transform); } if (line_spacing != dfl.line_spacing || explicit_defaults) { set_attr(node, "line-spacing", line_spacing); } if (character_spacing != dfl.character_spacing || explicit_defaults) { set_attr(node, "character-spacing", character_spacing); } // for shield_symbolizer this is later overridden if (text_opacity != dfl.text_opacity || explicit_defaults) { set_attr(node, "opacity", text_opacity); } } } //ns mapnik