diff --git a/bindings/python/mapnik_markers_symbolizer.cpp b/bindings/python/mapnik_markers_symbolizer.cpp index cc05b657d..698569378 100644 --- a/bindings/python/mapnik_markers_symbolizer.cpp +++ b/bindings/python/mapnik_markers_symbolizer.cpp @@ -97,7 +97,7 @@ void export_markers_symbolizer() ; class_("MarkersSymbolizer", - init<>("Default Markers Symbolizer - blue arrow")) + init<>("Default Markers Symbolizer - circle")) .def (init("")) //.def_pickle(markers_symbolizer_pickle_suite()) .add_property("filename", diff --git a/include/mapnik/marker_cache.hpp b/include/mapnik/marker_cache.hpp index 2e7f57699..b696a00b9 100644 --- a/include/mapnik/marker_cache.hpp +++ b/include/mapnik/marker_cache.hpp @@ -41,14 +41,21 @@ class marker; typedef boost::shared_ptr marker_ptr; -struct MAPNIK_DECL marker_cache : - public singleton , +class MAPNIK_DECL marker_cache : + public singleton , private boost::noncopyable { - - friend class CreateStatic; - static boost::unordered_map cache_; - static bool insert(std::string const& key, marker_ptr); + friend class CreateUsingNew; +private: + marker_cache(); + ~marker_cache(); + static bool insert_marker(std::string const& key, marker_ptr path); + static boost::unordered_map marker_cache_; + static bool insert_svg(std::string const& name, std::string const& svg_string); + static boost::unordered_map svg_cache_; +public: + static std::string known_svg_prefix_; + static bool is_uri(std::string const& path); static boost::optional find(std::string const& key, bool update_cache = false); static void clear(); }; diff --git a/src/load_map.cpp b/src/load_map.cpp index 29496b7f5..bc8d321da 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -56,6 +56,7 @@ #include #include #include +#include // boost #include @@ -987,15 +988,35 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node) } } - path_expression_ptr expr(boost::make_shared()); + optional marker_type = node.get_opt_attr("marker-type"); + if (marker_type) + { + MAPNIK_LOG_ERROR(markers_symbolizer) << "'marker-type' is deprecated and will be removed in Mapnik 3.x, use file='shape://' to specify known svg shapes"; + // back compatibility with Mapnik 2.0.0 + if (!marker_type->empty() && filename.empty()) + { + if (*marker_type == "ellipse") + { + filename = marker_cache::known_svg_prefix_ + "ellipse"; + } + else if (*marker_type == "arrow") + { + filename = marker_cache::known_svg_prefix_ + "arrow"; + } + } + } + + markers_symbolizer sym; + if (!filename.empty()) { + path_expression_ptr expr(boost::make_shared()); if (!parse_path_from_string(expr, filename, node.get_tree().path_expr_grammar)) { throw mapnik::config_error("Failed to parse path_expression '" + filename + "'"); } + sym.set_filename(expr); } - markers_symbolizer sym(expr); optional opacity = node.get_opt_attr("opacity"); if (opacity) sym.set_opacity(*opacity); @@ -1610,6 +1631,9 @@ void map_parser::ensure_font_face(std::string const& face_name) std::string map_parser::ensure_relative_to_xml(boost::optional opt_path) { + if (marker_cache::is_uri(*opt_path)) + return *opt_path; + if (relative_to_xml_) { boost::filesystem::path xml_path = filename_; diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 1c9e9799c..4caab454b 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -45,25 +45,73 @@ namespace mapnik { -boost::unordered_map marker_cache::cache_; +boost::unordered_map marker_cache::marker_cache_; +boost::unordered_map marker_cache::svg_cache_; +std::string marker_cache::known_svg_prefix_ = "shape://"; + +marker_cache::marker_cache() +{ + insert_svg("ellipse", + "" + "" + "" + ""); + insert_svg("arrow", + "" + "" + "" + ""); +} + +marker_cache::~marker_cache() {} void marker_cache::clear() { #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif - return cache_.clear(); + typedef boost::unordered_map::const_iterator iterator_type; + iterator_type itr = marker_cache_.begin(); + while(itr != marker_cache_.end()) + { + if (!is_uri(itr->first)) + { + marker_cache_.erase(itr++); + } + else + { + ++itr; + } + } } -bool marker_cache::insert(std::string const& uri, marker_ptr path) +bool marker_cache::is_uri(std::string const& path) +{ + return boost::algorithm::starts_with(path,known_svg_prefix_); +} + +bool marker_cache::insert_svg(std::string const& name, std::string const& svg_string) +{ + std::string key = known_svg_prefix_ + name; + typedef boost::unordered_map::const_iterator iterator_type; + iterator_type itr = svg_cache_.find(key); + if (itr == svg_cache_.end()) + { + return svg_cache_.insert(std::make_pair(key,svg_string)).second; + } + return false; +} + +bool marker_cache::insert_marker(std::string const& uri, marker_ptr path) { #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif - return cache_.insert(std::make_pair(uri,path)).second; + return marker_cache_.insert(std::make_pair(uri,path)).second; } -boost::optional marker_cache::find(std::string const& uri, bool update_cache) +boost::optional marker_cache::find(std::string const& uri, + bool update_cache) { boost::optional result; @@ -71,12 +119,13 @@ boost::optional marker_cache::find(std::string const& uri, bool upda { return result; } + #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif typedef boost::unordered_map::const_iterator iterator_type; - iterator_type itr = cache_.find(uri); - if (itr != cache_.end()) + iterator_type itr = marker_cache_.find(uri); + if (itr != marker_cache_.end()) { result.reset(itr->second); return result; @@ -84,14 +133,43 @@ boost::optional marker_cache::find(std::string const& uri, bool upda try { - // we can't find marker in cache, lets try to load it from filesystem - boost::filesystem::path path(uri); - if (!exists(path)) + // if uri references a built-in marker + if (is_uri(uri)) { - MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri; + boost::unordered_map::const_iterator mark_itr = svg_cache_.find(uri); + if (mark_itr == svg_cache_.end()) + { + MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri; + return result; + } + std::string known_svg_string = mark_itr->second; + using namespace mapnik::svg; + path_ptr marker_path(boost::make_shared()); + vertex_stl_adapter stl_storage(marker_path->source()); + svg_path_adapter svg_path(stl_storage); + svg_converter_type svg(svg_path, marker_path->attributes()); + svg_parser p(svg); + p.parse_from_string(known_svg_string); + //svg.arrange_orientations(); + double lox,loy,hix,hiy; + svg.bounding_rect(&lox, &loy, &hix, &hiy); + marker_path->set_bounding_box(lox,loy,hix,hiy); + marker_ptr mark(boost::make_shared(marker_path)); + result.reset(mark); + if (update_cache) + { + marker_cache_.insert(std::make_pair(uri,*result)); + } } + // otherwise assume file-based else { + boost::filesystem::path path(uri); + if (!exists(path)) + { + MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri; + return result; + } if (is_svg(uri)) { using namespace mapnik::svg; @@ -109,11 +187,12 @@ boost::optional marker_cache::find(std::string const& uri, bool upda result.reset(mark); if (update_cache) { - cache_.insert(std::make_pair(uri,*result)); + marker_cache_.insert(std::make_pair(uri,*result)); } } else { + // TODO - support reading images from string std::auto_ptr reader(mapnik::get_image_reader(uri)); if (reader.get()) { @@ -131,7 +210,7 @@ boost::optional marker_cache::find(std::string const& uri, bool upda result.reset(mark); if (update_cache) { - cache_.insert(std::make_pair(uri,*result)); + marker_cache_.insert(std::make_pair(uri,*result)); } } else diff --git a/src/markers_symbolizer.cpp b/src/markers_symbolizer.cpp index 0627ea70f..03554e03c 100644 --- a/src/markers_symbolizer.cpp +++ b/src/markers_symbolizer.cpp @@ -37,7 +37,7 @@ static const char * marker_placement_strings[] = { IMPLEMENT_ENUM( marker_placement_e, marker_placement_strings ) markers_symbolizer::markers_symbolizer() - : symbolizer_with_image(path_expression_ptr(new path_expression)), + : symbolizer_with_image(parse_path("shape://ellipse")), symbolizer_base(), width_(), height_(), @@ -45,7 +45,7 @@ markers_symbolizer::markers_symbolizer() allow_overlap_(false), spacing_(100.0), max_error_(0.2), - marker_p_(MARKER_LINE_PLACEMENT) {} + marker_p_(MARKER_POINT_PLACEMENT) {} markers_symbolizer::markers_symbolizer(path_expression_ptr const& filename) : symbolizer_with_image(filename), @@ -56,7 +56,7 @@ markers_symbolizer::markers_symbolizer(path_expression_ptr const& filename) allow_overlap_(false), spacing_(100.0), max_error_(0.2), - marker_p_(MARKER_LINE_PLACEMENT) {} + marker_p_(MARKER_POINT_PLACEMENT) {} markers_symbolizer::markers_symbolizer(markers_symbolizer const& rhs) : symbolizer_with_image(rhs),