diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index 8c8e930dd..3a69f0be5 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -69,17 +69,17 @@ struct map_pickle_suite : boost::python::pickle_suite s.append(style_pair); } - return boost::python::make_tuple(m.get_current_extent(),m.background(),l,s); + return boost::python::make_tuple(m.get_current_extent(),m.background(),l,s,m.base_path()); } static void setstate (Map& m, boost::python::tuple state) { using namespace boost::python; - if (len(state) != 4) + if (len(state) != 5) { PyErr_SetObject(PyExc_ValueError, - ("expected 4-item tuple in call to __setstate__; got %s" + ("expected 5-item tuple in call to __setstate__; got %s" % state).ptr() ); throw_error_already_set(); @@ -107,6 +107,12 @@ struct map_pickle_suite : boost::python::pickle_suite mapnik::feature_type_style style = extract(style_pair[1]); m.insert_style(name, style); } + + if (state[4]) + { + std::string base_path = extract(state[4]); + m.set_base_path(base_path); + } } }; @@ -464,6 +470,16 @@ void export_map() "Usage:\n" ">>> m.background = Color('steelblue')\n" ) + + .add_property("base", + make_function(&Map::base_path,return_value_policy()), + &Map::set_base_path, + "The base path of the map where any files using relative \n" + "paths will be interpreted as relative to.\n" + "\n" + "Usage:\n" + ">>> m.base_path = '.'\n" + ) .add_property("buffer_size", &Map::buffer_size, diff --git a/include/mapnik/load_map.hpp b/include/mapnik/load_map.hpp index 95dc91e9a..84d35a19f 100644 --- a/include/mapnik/load_map.hpp +++ b/include/mapnik/load_map.hpp @@ -34,7 +34,7 @@ namespace mapnik { MAPNIK_DECL void load_map(Map & map, std::string const& filename, bool strict = false); -MAPNIK_DECL void load_map_string(Map & map, std::string const& str, bool strict = false, std::string const& base_url=""); +MAPNIK_DECL void load_map_string(Map & map, std::string const& str, bool strict = false, std::string const& base_path=""); } #endif // LOAD_MAP_HPP diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index cfd9ad516..9cc58116f 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -83,6 +83,7 @@ private: aspect_fix_mode aspectFixMode_; box2d current_extent_; boost::optional > maximum_extent_; + std::string base_path_; parameters extra_attr_; public: @@ -341,6 +342,15 @@ public: */ boost::optional > const& maximum_extent() const; + /*! \brief Get the map base path where paths should be relative to. + */ + std::string const& base_path() const; + + /*! \brief Set the map base path where paths should be releative to. + * @param srs Map base_path. + */ + void set_base_path(std::string const& base); + /*! \brief Zoom the map at the current position. * @param factor The factor how much the map is zoomed in or out. */ diff --git a/src/load_map.cpp b/src/load_map.cpp index c006883f3..11fb6370c 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -83,7 +83,7 @@ public: relative_to_xml_(true), font_manager_(font_engine_) {} - void parse_map(Map & map, ptree const & sty); + void parse_map(Map & map, ptree const & sty, std::string const& base_path=""); private: void parse_map_include( Map & map, ptree const & include); void parse_style(Map & map, ptree const & sty); @@ -146,15 +146,19 @@ void load_map(Map & map, std::string const& filename, bool strict) parser.parse_map(map, pt); } -void load_map_string(Map & map, std::string const& str, bool strict, std::string const& base_url) +void load_map_string(Map & map, std::string const& str, bool strict, std::string const& base_path) { ptree pt; #ifdef HAVE_LIBXML2 - read_xml2_string(str, pt, base_url); + if (!base_path.empty()) + read_xml2_string(str, pt, base_path); // accept base_path passed into function + else + read_xml2_string(str, pt, map.base_path()); // default to map base_path #else try { std::istringstream s(str); + // TODO - support base_path? read_xml(s,pt); } catch (const boost::property_tree::xml_parser_error & ex) @@ -163,11 +167,11 @@ void load_map_string(Map & map, std::string const& str, bool strict, std::string } #endif - map_parser parser( strict, base_url); - parser.parse_map(map, pt); + map_parser parser( strict, base_path); + parser.parse_map(map, pt, base_path); } -void map_parser::parse_map( Map & map, ptree const & pt ) +void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base_path ) { try { @@ -181,7 +185,8 @@ void map_parser::parse_map( Map & map, ptree const & pt ) << "paths-from-xml," << "minimum-version," << "font-directory," - << "maximum-extent"; + << "maximum-extent," + << "base"; ensure_attrs(map_node, "Map", s.str()); try @@ -196,6 +201,28 @@ void map_parser::parse_map( Map & map, ptree const & pt ) relative_to_xml_ = *paths_from_xml; } + optional base_path_from_xml = get_opt_attr(map_node, "base"); + if (!base_path.empty()) + { + map.set_base_path( base_path ); + } + else if (base_path_from_xml) + { + map.set_base_path( *base_path_from_xml ); + } + else + { + boost::filesystem::path xml_path(filename_); + // TODO - should we make this absolute? + #if (BOOST_FILESYSTEM_VERSION == 3) + std::string const& base = xml_path.parent_path().string(); + #else // v2 + std::string const& base = xml_path.branch_path().string(); + #endif + + map.set_base_path( base ); + } + optional bgcolor = get_opt_attr(map_node, "background-color"); if (bgcolor) { @@ -2093,7 +2120,8 @@ std::string map_parser::ensure_relative_to_xml( boost::optional opt if ( !rel_path.has_root_path() ) { #if (BOOST_FILESYSTEM_VERSION == 3) - boost::filesystem::path full = boost::filesystem::absolute(xml_path.branch_path()/rel_path).normalize(); + // TODO - normalize is now deprecated, use make_preferred? + boost::filesystem::path full = boost::filesystem::absolute(xml_path.parent_path()/rel_path); #else // v2 boost::filesystem::path full = boost::filesystem::complete(xml_path.branch_path()/rel_path).normalize(); #endif diff --git a/src/save_map.cpp b/src/save_map.cpp index c31c5d297..8800514c6 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -834,13 +834,18 @@ void serialize_map(ptree & pt, Map const & map, bool explicit_defaults) set_attr( map_node, "background-image", *image_filename ); } - unsigned buffer_size = map.buffer_size(); if ( buffer_size || explicit_defaults) { set_attr( map_node, "buffer-size", buffer_size ); } + std::string const& base_path = map.base_path(); + if ( !base_path.empty() || explicit_defaults) + { + set_attr( map_node, "base", base_path ); + } + optional > const& maximum_extent = map.maximum_extent(); if ( maximum_extent) {