diff --git a/src/load_map.cpp b/src/load_map.cpp index c4c4ff396..b8589b5d0 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -91,8 +91,10 @@ namespace mapnik void parse_polygon_symbolizer( rule_type & rule, ptree const & sym); void parse_building_symbolizer( rule_type & rule, ptree const & sym ); void parse_raster_symbolizer( rule_type & rule, ptree const & sym ); - void parse_raster_colorizer(raster_colorizer_ptr const& rc, ptree const& node ); void parse_markers_symbolizer( rule_type & rule, ptree const & sym ); + void parse_glyph_symbolizer( rule_type & rule, ptree const & sym ); + + void parse_raster_colorizer(raster_colorizer_ptr const& rc, ptree const& node ); void ensure_font_face( const std::string & face_name ); @@ -626,6 +628,10 @@ namespace mapnik { rule.append(markers_symbolizer()); } + else if ( sym.first == "GlyphSymbolizer") + { + parse_glyph_symbolizer( rule, sym.second ); + } else if ( sym.first != "MinScaleDenominator" && sym.first != "MaxScaleDenominator" && @@ -1515,6 +1521,114 @@ namespace mapnik throw; } } + + void map_parser::parse_glyph_symbolizer(rule_type & rule, ptree const &sym) + { + try + { + // Parse required constructor args + std::string face_name = get_attr(sym, "face_name"); + std::string _char = get_attr(sym, "char"); + + glyph_symbolizer glyph_sym = glyph_symbolizer( + face_name, + parse_expression(_char, "utf8") + ); + + // + // parse and set optional attrs. + // + + // angle + optional angle = + get_opt_attr(sym, "angle"); + if (angle) + glyph_sym.set_angle(parse_expression(*angle, "utf8")); + + // value + optional value = + get_opt_attr(sym, "value"); + if (value) + glyph_sym.set_value(parse_expression(*value, "utf8")); + + // size + optional size = + get_opt_attr(sym, "size"); + if (size) + glyph_sym.set_size(parse_expression(*size, "utf8")); + + // color + optional _color = + get_opt_attr(sym, "color"); + if (_color) + glyph_sym.set_color(parse_expression(*_color, "utf8")); + + // halo_fill + optional halo_fill = get_opt_attr(sym, "halo_fill"); + if (halo_fill) + glyph_sym.set_halo_fill(*halo_fill); + + // halo_radius + optional halo_radius = get_opt_attr( + sym, + "halo_radius"); + if (halo_radius) + glyph_sym.set_halo_radius(*halo_radius); + + // allow_overlap + optional allow_overlap = get_opt_attr( + sym, + "allow_overlap" + ); + if (allow_overlap) + glyph_sym.set_allow_overlap(*allow_overlap); + + // avoid_edges + optional avoid_edges = get_opt_attr( + sym, + "avoid_edges" + ); + if (avoid_edges) + glyph_sym.set_avoid_edges(*avoid_edges); + + // displacement + optional dx = get_opt_attr(sym, "dx"); + optional dy = get_opt_attr(sym, "dy"); + if (dx && dy) + glyph_sym.set_displacement(*dx, *dy); + + // colorizer + ptree::const_iterator childIter = sym.begin(); + ptree::const_iterator endChild = sym.end(); + + for (; childIter != endChild; ++childIter) + { + ptree::value_type const& tag = *childIter; + + if (tag.first == "RasterColorizer") + { + raster_colorizer_ptr colorizer(new raster_colorizer()); + glyph_sym.set_colorizer(colorizer); + parse_raster_colorizer(colorizer, tag.second); + } + else if (tag.first!="" && tag.first!="" ) + { + throw config_error(std::string("Unknown child node. ") + + "Expected 'RasterColorizer' but got '" + + tag.first + "'"); + } + } + + + rule.append(glyph_sym); + } + catch (const config_error & ex) + { + ex.append_context("in GlyphSymbolizer"); + throw; + } + } + void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc, ptree const& node ) { diff --git a/src/save_map.cpp b/src/save_map.cpp index f90561f88..8091ce3a0 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -257,10 +257,72 @@ namespace mapnik // FIXME!!!!! } - void operator () ( glyph_symbolizer const& ) + void operator () ( glyph_symbolizer const& sym) { - // FIXME!!!!! + ptree &node = rule_.push_back( + ptree::value_type("GlyphSymbolizer", ptree()) + )->second; + + // face_name + set_attr( node, "face_name", sym.get_face_name() ); + + // char + if (sym.get_char()) { + const std::string &str = + to_expression_string(sym.get_char()); + set_attr( node, "char", str ); + } + + // angle + if (sym.get_angle()) { + const std::string &str = + to_expression_string(sym.get_angle()); + set_attr( node, "angle", str ); + } + + // value + if (sym.get_value()) { + const std::string &str = + to_expression_string(sym.get_value()); + set_attr( node, "value", str ); + } + + // size + if (sym.get_size()) { + const std::string &str = + to_expression_string(sym.get_size()); + set_attr( node, "size", str ); + } + + // color + if (sym.get_color()) { + const std::string &str = + to_expression_string(sym.get_color()); + set_attr( node, "color", str ); + } + + // colorizer + if (sym.get_colorizer()) { + serialize_raster_colorizer(node, sym.get_colorizer(), + explicit_defaults_); + } + + // allow_overlap + set_attr( node, "allow_overlap", sym.get_allow_overlap() ); + + // avoid_edges + set_attr( node, "avoid_edges", sym.get_avoid_edges() ); + + // displacement + position displacement = sym.get_displacement(); + set_attr( node, "dx", displacement.get<0>() ); + set_attr( node, "dy", displacement.get<1>() ); + + // halo fill & radius + set_attr( node, "halo_fill", sym.get_halo_fill() ); + set_attr( node, "halo_radius", sym.get_halo_radius() ); } + private: serialize_symbolizer(); void add_image_attributes(ptree & node, const symbolizer_with_image & sym) diff --git a/tests/data/good_maps/glyph_symbolizer.xml b/tests/data/good_maps/glyph_symbolizer.xml new file mode 100644 index 000000000..02efa2d47 --- /dev/null +++ b/tests/data/good_maps/glyph_symbolizer.xml @@ -0,0 +1,23 @@ + + + + diff --git a/tests/python_tests/glyph_symbolizer_test.py b/tests/python_tests/glyph_symbolizer_test.py index 8e6ad1767..c102eb084 100644 --- a/tests/python_tests/glyph_symbolizer_test.py +++ b/tests/python_tests/glyph_symbolizer_test.py @@ -2,7 +2,7 @@ #!/usr/bin/env python from nose.tools import * -from utilities import execution_path, save_data, Todo, contains_word +from utilities import execution_path, save_data, contains_word import os, mapnik2 @@ -39,16 +39,17 @@ def test_renders_with_cairo(): save_data('cairo_glyph_symbolizer.png', im.tostring('png')) assert contains_word('\xff\x00\x00\xff', im.tostring()) -def test_load_save_map(): - raise Todo("Implement XML de/serialization for GlyphSymbolizer") - +def test_load_save_load_map(): map = mapnik2.Map(256,256) in_map = "../data/good_maps/glyph_symbolizer.xml" mapnik2.load_map(map, in_map) - out_map = mapnik2.save_map_to_string(map) + out_map = mapnik2.save_map_to_string(map).decode('utf8') + map = mapnik2.Map(256,256) + mapnik2.load_map_from_string(map, out_map.encode('utf8')) assert 'GlyphSymbolizer' in out_map assert 'RasterColorizer' in out_map + assert u'í' in out_map, out_map # # Utilities and setup code