Merge remote-tracking branch 'origin/master'

This commit is contained in:
Artem Pavlenko 2012-03-13 16:44:36 +00:00
commit 385ca5b5b5
87 changed files with 1982 additions and 1730 deletions

View file

@ -40,15 +40,15 @@
using namespace mapnik;
/* Notes:
Overriding functions in inherited classes:
boost.python documentation doesn't really tell you how to do it.
But this helps:
http://www.gamedev.net/topic/446225-inheritance-in-boostpython/
Overriding functions in inherited classes:
boost.python documentation doesn't really tell you how to do it.
But this helps:
http://www.gamedev.net/topic/446225-inheritance-in-boostpython/
register_ptr_to_python is required for wrapped classes, but not for unwrapped.
register_ptr_to_python is required for wrapped classes, but not for unwrapped.
Functions don't have to be members of the class, but can also be
normal functions taking a ref to the class as first parameter.
Functions don't have to be members of the class, but can also be
normal functions taking a ref to the class as first parameter.
*/
namespace {
@ -261,7 +261,7 @@ struct TextPlacementsWrap: text_placements, wrapper<text_placements>
struct TextPlacementInfoWrap: text_placement_info, wrapper<text_placement_info>
{
TextPlacementInfoWrap(text_placements const* parent,
double scale_factor_)
double scale_factor_)
: text_placement_info(parent, scale_factor_)
{
@ -339,7 +339,7 @@ void export_text_placement()
;
class_<text_symbolizer>("TextSymbolizer",
init<>())
init<>())
.def(init<expression_ptr, std::string const&, unsigned, color const&>())
.add_property("placements",
&text_symbolizer::get_placement_options,
@ -357,7 +357,7 @@ void export_text_placement()
class_with_converter<text_symbolizer_properties>
("TextSymbolizerProperties")
("TextSymbolizerProperties")
.def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement)
.def_readwrite_convert("horizontal_alignment", &text_symbolizer_properties::halign)
.def_readwrite_convert("justify_alignment", &text_symbolizer_properties::jalign)
@ -381,15 +381,15 @@ void export_text_placement()
.add_property ("format_tree",
&text_symbolizer_properties::format_tree,
&text_symbolizer_properties::set_format_tree);
/* from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python.
add_expressions isn't useful in python either. The result is only needed by
attribute_collector (which isn't exposed in python) and
it just calls add_expressions of the associated formatting tree.
set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */
;
/* from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python.
add_expressions isn't useful in python either. The result is only needed by
attribute_collector (which isn't exposed in python) and
it just calls add_expressions of the associated formatting tree.
set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */
;
class_<char_properties>
("CharProperties")
("CharProperties")
.def(init<char_properties const&>()) //Copy constructor
.def_readwrite("face_name", &char_properties::face_name)
.def_readwrite("fontset", &char_properties::fontset)
@ -407,9 +407,9 @@ void export_text_placement()
;
class_<TextPlacementsWrap,
boost::shared_ptr<TextPlacementsWrap>,
boost::noncopyable>
("TextPlacements")
boost::shared_ptr<TextPlacementsWrap>,
boost::noncopyable>
("TextPlacements")
.def_readwrite("defaults", &text_placements::defaults)
.def("get_placement_info", pure_virtual(&text_placements::get_placement_info))
/* TODO: add_expressions() */
@ -417,10 +417,10 @@ void export_text_placement()
register_ptr_to_python<boost::shared_ptr<text_placements> >();
class_<TextPlacementInfoWrap,
boost::shared_ptr<TextPlacementInfoWrap>,
boost::noncopyable>
("TextPlacementInfo",
init<text_placements const*, double>())
boost::shared_ptr<TextPlacementInfoWrap>,
boost::noncopyable>
("TextPlacementInfo",
init<text_placements const*, double>())
.def("next", pure_virtual(&text_placement_info::next))
.def("get_actual_label_spacing", &text_placement_info::get_actual_label_spacing)
.def("get_actual_minimum_distance", &text_placement_info::get_actual_minimum_distance)
@ -432,27 +432,27 @@ void export_text_placement()
class_<processed_text,
boost::shared_ptr<processed_text>,
boost::noncopyable>
("ProcessedText", no_init)
boost::shared_ptr<processed_text>,
boost::noncopyable>
("ProcessedText", no_init)
.def("push_back", &processed_text::push_back)
.def("clear", &processed_text::clear)
;
class_<expression_set,
boost::shared_ptr<expression_set>,
boost::noncopyable>
("ExpressionSet")
boost::shared_ptr<expression_set>,
boost::noncopyable>
("ExpressionSet")
.def("insert", &insert_expression);
;
;
//TODO: Python namespace
class_<NodeWrap,
boost::shared_ptr<NodeWrap>,
boost::noncopyable>
("FormattingNode")
boost::shared_ptr<NodeWrap>,
boost::noncopyable>
("FormattingNode")
.def("apply", pure_virtual(&formatting::node::apply))
.def("add_expressions",
&formatting::node::add_expressions,
@ -462,10 +462,10 @@ void export_text_placement()
class_<TextNodeWrap,
boost::shared_ptr<TextNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingText", init<expression_ptr>())
boost::shared_ptr<TextNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingText", init<expression_ptr>())
.def(init<std::string>())
.def("apply", &formatting::text_node::apply, &TextNodeWrap::default_apply)
.add_property("text",
@ -476,10 +476,10 @@ void export_text_placement()
class_with_converter<FormatNodeWrap,
boost::shared_ptr<FormatNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingFormat")
boost::shared_ptr<FormatNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingFormat")
.def_readwrite_convert("text_size", &formatting::format_node::text_size)
.def_readwrite_convert("face_name", &formatting::format_node::face_name)
.def_readwrite_convert("character_spacing", &formatting::format_node::character_spacing)
@ -499,10 +499,10 @@ void export_text_placement()
register_ptr_to_python<boost::shared_ptr<formatting::format_node> >();
class_<ListNodeWrap,
boost::shared_ptr<ListNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingList", init<>())
boost::shared_ptr<ListNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingList", init<>())
.def(init<list>())
.def("append", &formatting::list_node::push_back)
.def("apply", &formatting::list_node::apply, &ListNodeWrap::default_apply)
@ -510,15 +510,15 @@ void export_text_placement()
.def("__getitem__", &ListNodeWrap::get_item)
.def("__setitem__", &ListNodeWrap::set_item)
.def("append", &ListNodeWrap::append)
;
;
register_ptr_to_python<boost::shared_ptr<formatting::list_node> >();
class_<ExprFormatWrap,
boost::shared_ptr<ExprFormatWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingExpressionFormat")
boost::shared_ptr<ExprFormatWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingExpressionFormat")
.def_readwrite("text_size", &formatting::expression_format::text_size)
.def_readwrite("face_name", &formatting::expression_format::face_name)
.def_readwrite("character_spacing", &formatting::expression_format::character_spacing)

View file

@ -29,8 +29,8 @@ namespace mapnik {
class python_thread
{
/* Docs:
http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock
*/
http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock
*/
public:
static void unblock()
{
@ -38,8 +38,8 @@ public:
if (state.get())
{
std::cerr << "ERROR: Python threads are already unblocked. "
"Unblocking again will loose the current state and "
"might crash later. Aborting!\n";
"Unblocking again will loose the current state and "
"might crash later. Aborting!\n";
abort(); //This is a serious error and can't be handled in any other sane way
}
#endif
@ -59,9 +59,9 @@ public:
if (thread_support && !state.get())
{
std::cerr << "ERROR: Trying to restore python thread state, "
"but no state is saved. Can't continue and also "
"can't raise an exception because the python "
"interpreter might be non-function. Aborting!\n";
"but no state is saved. Can't continue and also "
"can't raise an exception because the python "
"interpreter might be non-function. Aborting!\n";
abort();
}
#endif

View file

@ -102,8 +102,8 @@ struct python_optional : public boost::noncopyable
/** This class works around a bug in boost python.
See http://osdir.com/ml/python.c++/2003-11/msg00158.html
*/
See http://osdir.com/ml/python.c++/2003-11/msg00158.html
*/
template <typename T, typename X1 = boost::python::detail::not_specified, typename X2 = boost::python::detail::not_specified, typename X3 = boost::python::detail::not_specified>
class class_with_converter : public boost::python::class_<T, X1, X2, X3>
{
@ -131,8 +131,8 @@ public:
self& def_readwrite_convert(char const* name, D const& d, char const* doc=0)
{
this->add_property(name,
boost::python::make_getter(d, boost::python::return_value_policy<boost::python::return_by_value>()),
boost::python::make_setter(d, boost::python::default_call_policies()));
boost::python::make_getter(d, boost::python::return_value_policy<boost::python::return_by_value>()),
boost::python::make_setter(d, boost::python::default_call_policies()));
return *this;
}
};

View file

@ -0,0 +1,90 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#ifndef MAPNIK_BOOLEAN_HPP
#define MAPNIK_BOOLEAN_HPP
#include <istream>
namespace mapnik
{
/** Helper for class bool */
class boolean {
public:
boolean(): b_(false) {}
boolean(bool b) : b_(b) {}
boolean(boolean const& b) : b_(b.b_) {}
operator bool() const
{
return b_;
}
boolean & operator = (boolean const& other)
{
b_ = other.b_;
return * this;
}
boolean & operator = (bool other)
{
b_ = other;
return * this;
}
private:
bool b_;
};
/** Special stream input operator for boolean values */
template <typename charT, typename traits>
std::basic_istream<charT, traits> &
operator >> ( std::basic_istream<charT, traits> & s, boolean & b )
{
std::string word;
s >> word;
if ( s )
{
if ( word == "true" || word == "yes" || word == "on" ||
word == "1")
{
b = true;
}
else if ( word == "false" || word == "no" || word == "off" ||
word == "0")
{
b = false;
}
else
{
s.setstate( std::ios::failbit );
}
}
return s;
}
template <typename charT, typename traits>
std::basic_ostream<charT, traits> &
operator << ( std::basic_ostream<charT, traits> & s, boolean const& b )
{
s << ( b ? "true" : "false" );
return s;
}
}
#endif // MAPNIK_BOOLEAN_HPP

View file

@ -137,6 +137,14 @@ public:
std::string to_hex_string() const;
};
template <typename charT, typename traits>
std::basic_ostream<charT, traits> &
operator << ( std::basic_ostream<charT, traits> & s, mapnik::color const& c )
{
std::string hex_string( c.to_string() );
s << hex_string;
return s;
}
}

View file

@ -25,134 +25,26 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/color.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/version.hpp>
// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane)
#if BOOST_VERSION >= 104500
#include <mapnik/css_color_grammar.hpp>
namespace mapnik {
class color;
template <typename Iterator> struct css_color_grammar;
class MAPNIK_DECL color_factory : boost::noncopyable
{
public:
static void init_from_string(color & c, std::string const& css_color)
{
typedef std::string::const_iterator iterator_type;
typedef mapnik::css_color_grammar<iterator_type> css_color_grammar;
css_color_grammar g;
iterator_type first = css_color.begin();
iterator_type last = css_color.end();
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
c);
if (!result)
{
throw config_error(std::string("Failed to parse color value: ") +
"Expected a CSS color, but got '" + css_color + "'");
}
}
static void init_from_string(color & c, std::string const& css_color);
static bool parse_from_string(color & c, std::string const& css_color,
mapnik::css_color_grammar<std::string::const_iterator> const& g)
{
std::string::const_iterator first = css_color.begin();
std::string::const_iterator last = css_color.end();
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
c);
return result && (first == last);
}
mapnik::css_color_grammar<std::string::const_iterator> const& g);
static color from_string(std::string const& css_color)
{
color c;
init_from_string(c,css_color);
return c;
}
static color from_string(std::string const& css_color);
};
}
#else
#include <mapnik/css_color_grammar_deprecated.hpp>
namespace mapnik {
class MAPNIK_DECL color_factory : boost::noncopyable
{
public:
static bool parse_from_string(color & c, std::string const& css_color,
mapnik::css_color_grammar<std::string::const_iterator> const& g)
{
std::string::const_iterator first = css_color.begin();
std::string::const_iterator last = css_color.end();
mapnik::css css_;
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
css_);
if (result && (first == last))
{
c.set_red(css_.r);
c.set_green(css_.g);
c.set_blue(css_.b);
c.set_alpha(css_.a);
return true;
}
return false;
}
static void init_from_string(color & c, std::string const& css_color)
{
typedef std::string::const_iterator iterator_type;
typedef mapnik::css_color_grammar<iterator_type> css_color_grammar;
css_color_grammar g;
iterator_type first = css_color.begin();
iterator_type last = css_color.end();
mapnik::css css_;
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
css_);
if (!result)
{
throw config_error(std::string("Failed to parse color value: ") +
"Expected a CSS color, but got '" + css_color + "'");
}
c.set_red(css_.r);
c.set_green(css_.g);
c.set_blue(css_.b);
c.set_alpha(css_.a);
}
static color from_string(std::string const& css_color)
{
color c;
init_from_string(c,css_color);
return c;
}
};
}
#endif
#endif // MAPNIK_COLOR_FACTORY_HPP

View file

@ -28,31 +28,28 @@
namespace mapnik {
class xml_node;
class config_error : public std::exception
{
public:
config_error():
what_() {}
config_error( std::string const& what ) :
what_( what )
{
}
config_error(std::string const& what);
config_error(std::string const& what, xml_node const& node);
config_error(std::string const& what, unsigned line_number, std::string const& filename);
virtual ~config_error() throw() {}
virtual const char * what() const throw()
{
return what_.c_str();
}
void append_context(std::string const& ctx) const
{
what_ += " " + ctx;
}
virtual const char * what() const throw();
void append_context(const std::string & ctx) const;
void append_context(const std::string & ctx, xml_node const& node) const;
void append_context(xml_node const& node) const;
protected:
mutable std::string what_;
mutable unsigned line_number_;
mutable std::string file_;
mutable std::string node_name_;
mutable std::string msg_;
};
}
#endif // MAPNIK_CONFIG_ERROR_HPP

View file

@ -26,7 +26,6 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/expression_grammar.hpp>
// stl
#include <string>
@ -35,6 +34,7 @@ namespace mapnik
{
typedef boost::shared_ptr<expr_node> expression_ptr;
template <typename Iterator> struct expression_grammar;
class expression_factory
{

View file

@ -99,11 +99,11 @@ public:
feature_impl(context_ptr const& ctx, int id)
: id_(id),
ctx_(ctx),
data_(ctx_->mapping_.size()),
geom_cont_(),
raster_()
{}
ctx_(ctx),
data_(ctx_->mapping_.size()),
geom_cont_(),
raster_()
{}
inline int id() const { return id_;}

View file

@ -153,7 +153,7 @@ class MAPNIK_DECL font_face_set : private boost::noncopyable
public:
font_face_set(void)
: faces_(),
dimension_cache_() {}
dimension_cache_() {}
void add(face_ptr face)
{

View file

@ -36,6 +36,7 @@ namespace mapnik {
typedef std::set<expression_ptr> expression_set;
class processed_text;
class xml_node;
struct char_properties;
namespace formatting {
@ -48,7 +49,7 @@ class node
public:
virtual ~node() {}
virtual void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(boost::property_tree::ptree const& xml);
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const = 0;
virtual void add_expressions(expression_set &output) const;
};

View file

@ -31,7 +31,7 @@ namespace formatting {
class expression_format: public node {
public:
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(boost::property_tree::ptree const& xml);
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const;
virtual void add_expressions(expression_set &output) const;
@ -51,7 +51,7 @@ public:
private:
node_ptr child_;
static expression_ptr get_expression(boost::property_tree::ptree const& xml, std::string name);
static expression_ptr get_expression(xml_node const& xml, std::string name);
};
} //ns formatting
} //ns mapnik

View file

@ -31,7 +31,7 @@ namespace formatting {
class format_node: public node {
public:
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(boost::property_tree::ptree const& xml);
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const;
virtual void add_expressions(expression_set &output) const;

View file

@ -38,16 +38,16 @@ namespace mapnik
namespace formatting
{
typedef node_ptr (*from_xml_function_ptr)(boost::property_tree::ptree const& xml);
typedef node_ptr (*from_xml_function_ptr)(xml_node const& xml);
class registry : public singleton<registry, CreateStatic>,
private boost::noncopyable
private boost::noncopyable
{
public:
registry();
~registry() {}
void register_name(std::string name, from_xml_function_ptr ptr, bool overwrite=false);
node_ptr from_xml(std::string name, boost::property_tree::ptree const& xml);
node_ptr from_xml(xml_node const& xml);
private:
std::map<std::string, from_xml_function_ptr> map_;
};

View file

@ -31,7 +31,7 @@ public:
text_node(expression_ptr text): node(), text_(text) {}
text_node(std::string text): node(), text_(parse_expression(text)) {}
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(boost::property_tree::ptree const& xml);
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const;
virtual void add_expressions(expression_set &output) const;

View file

@ -1,26 +1,34 @@
#ifndef DUMP_XML_HPP
#define DUMP_XML_HPP
#include <boost/property_tree/ptree.hpp>
#include <mapnik/xml_node.hpp>
/* Debug dump ptree XML representation.
*/
void dump_xml(boost::property_tree::ptree const& xml, unsigned level=0)
*/
void dump_xml(xml_node const& xml, unsigned level=0)
{
std::string indent;
int i;
unsigned i;
for (i=0; i<level; i++)
{
indent += " ";
}
if (xml.data().length()) std::cout << indent << "data: '" << xml.data() << "'\n";
boost::property_tree::ptree::const_iterator itr = xml.begin();
boost::property_tree::ptree::const_iterator end = xml.end();
xml_node::attribute_map const& attr = xml.get_attributes();
std::cerr << indent <<"[" << xml.name();
xml_node::attribute_map::const_iterator aitr = attr.begin();
xml_node::attribute_map::const_iterator aend = attr.end();
for (;aitr!=aend; aitr++)
{
std::cerr << " (" << aitr->first << ", " << aitr->second.value << ", " << aitr->second.processed << ")";
}
std::cerr << "]" << "\n";
if (xml.is_text()) std::cerr << indent << "text: '" << xml.text() << "'\n";
xml_node::const_iterator itr = xml.begin();
xml_node::const_iterator end = xml.end();
for (; itr!=end; itr++)
{
std::cout << indent <<"[" << itr->first << "]" << "\n";
dump_xml(itr->second, level+1);
std::cout << indent << "[/" << itr->first << "]" << "\n";
dump_xml(*itr, level+1);
}
std::cerr << indent << "[/" << xml.name() << "]" << "\n";
}

View file

@ -30,6 +30,7 @@
#include <boost/property_tree/ptree.hpp>
namespace mapnik {
class xml_node;
/**
* Creates a metawriter with the properties specified in the property
@ -37,7 +38,7 @@ namespace mapnik {
* metawriters, but should provide an easy point to make them a
* proper factory method if this is wanted in the future.
*/
metawriter_ptr metawriter_create(const boost::property_tree::ptree &pt);
metawriter_ptr metawriter_create(xml_node const& pt);
/**
* Writes properties into the given property tree representing the

View file

@ -26,7 +26,6 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/global.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/utility.hpp>

View file

@ -124,16 +124,16 @@ private:
text_symbolizer_properties const& p;
text_placement_info const& pi;
/** Length of the longest line after linebreaks.
* Before find_line_breaks() this is the total length of the string.
*/
* Before find_line_breaks() this is the total length of the string.
*/
double string_width_;
/** Height of the string after linebreaks.
* Before find_line_breaks() this is the total length of the string.
*/
* Before find_line_breaks() this is the total length of the string.
*/
double string_height_;
/** Height of the tallest font in the first line not including line spacing.
* Used to determine the correct offset for the first line.
*/
* Used to determine the correct offset for the first line.
*/
double first_line_space_;
vertical_alignment_e valign_;
horizontal_alignment_e halign_;

View file

@ -23,450 +23,17 @@
#ifndef MAPNIK_PTREE_HELPERS_HPP
#define MAPNIK_PTREE_HELPERS_HPP
// mapnik
#include <mapnik/enumeration.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/property_tree/ptree.hpp>
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
// stl
#include <iostream>
#include <sstream>
namespace mapnik {
template <typename T>
inline boost::optional<T> fast_cast(std::string const& value);
template <typename T>
T get(boost::property_tree::ptree const& node, std::string const& name, bool is_attribute,
T const& default_value);
template <typename T>
T get(boost::property_tree::ptree const& node, std::string const& name, bool is_attribute);
template <typename T>
T get_value(boost::property_tree::ptree const& node, std::string const& name);
template <typename T>
boost::optional<T> get_optional(boost::property_tree::ptree const& node, std::string const& name,
bool is_attribute);
template <typename T>
boost::optional<T> get_opt_attr( boost::property_tree::ptree const& node,
std::string const& name)
{
return get_optional<T>( node, name, true);
}
template <typename T>
boost::optional<T> get_opt_child( boost::property_tree::ptree const& node,
std::string const& name)
{
return get_optional<T>( node, name, false);
}
template <typename T>
T get_attr( boost::property_tree::ptree const& node, std::string const& name,
T const& default_value )
{
return get<T>( node, name, true, default_value);
}
template <typename T>
T get_attr( boost::property_tree::ptree const& node, std::string const& name )
{
return get<T>( node, name, true );
}
template <typename charT, typename traits>
std::basic_ostream<charT, traits> &
operator << ( std::basic_ostream<charT, traits> & s, mapnik::color const& c )
{
std::string hex_string( c.to_string() );
s << hex_string;
return s;
}
/** Helper for class bool */
class boolean {
public:
boolean() : b_(false) {}
boolean(bool b) : b_(b) {}
boolean(boolean const& b) : b_(b.b_) {}
operator bool() const
{
return b_;
}
boolean & operator = (boolean const& other)
{
b_ = other.b_;
return * this;
}
boolean & operator = (bool other)
{
b_ = other;
return * this;
}
private:
bool b_;
};
/** Special stream input operator for boolean values */
template <typename charT, typename traits>
std::basic_istream<charT, traits> &
operator >> ( std::basic_istream<charT, traits> & s, boolean & b )
{
std::string word;
s >> word;
if ( s )
{
if ( word == "true" || word == "yes" || word == "on" ||
word == "1")
{
b = true;
}
else if ( word == "false" || word == "no" || word == "off" ||
word == "0")
{
b = false;
}
else
{
s.setstate( std::ios::failbit );
}
}
return s;
}
template <typename charT, typename traits>
std::basic_ostream<charT, traits> &
operator << ( std::basic_ostream<charT, traits> & s, boolean const& b )
{
s << ( b ? "true" : "false" );
return s;
}
template <typename T>
void set_attr(boost::property_tree::ptree & pt, std::string const& name, T const& v)
{
pt.put("<xmlattr>." + name, v);
}
class boolean;
template <typename T>
struct name_trait
{
static std::string name()
{
return "<unknown>";
}
// missing name_trait for type ...
// if you get here you are probably using a new type
// in the XML file. Just add a name trait for the new
// type below.
BOOST_STATIC_ASSERT( sizeof(T) == 0 );
};
#define DEFINE_NAME_TRAIT( type, type_name ) \
template <> \
struct name_trait<type> \
{ \
static std::string name() { return std::string("type ") + type_name; } \
};
DEFINE_NAME_TRAIT( double, "double")
DEFINE_NAME_TRAIT( float, "float")
DEFINE_NAME_TRAIT( unsigned, "unsigned")
DEFINE_NAME_TRAIT( boolean, "boolean")
DEFINE_NAME_TRAIT( int, "integer" )
DEFINE_NAME_TRAIT( std::string, "string" )
DEFINE_NAME_TRAIT( color, "color" )
template <typename ENUM, int MAX>
struct name_trait< mapnik::enumeration<ENUM, MAX> >
{
typedef enumeration<ENUM, MAX> Enum;
static std::string name()
{
std::string value_list("one of [");
for (unsigned i = 0; i < Enum::MAX; ++i)
{
value_list += Enum::get_string( i );
if ( i + 1 < Enum::MAX ) value_list += ", ";
}
value_list += "]";
return value_list;
}
};
template <typename T>
inline boost::optional<T> fast_cast(std::string const& value)
{
try
{
return boost::lexical_cast<T>( value );
}
catch (boost::bad_lexical_cast const& ex)
{
return boost::optional<T>();
}
}
template <>
inline boost::optional<int> fast_cast(std::string const& value)
{
int result;
if (mapnik::conversions::string2int(value,result))
return boost::optional<int>(result);
return boost::optional<int>();
}
template <>
inline boost::optional<double> fast_cast(std::string const& value)
{
double result;
if (mapnik::conversions::string2double(value,result))
return boost::optional<double>(result);
return boost::optional<double>();
}
template <>
inline boost::optional<float> fast_cast(std::string const& value)
{
float result;
if (mapnik::conversions::string2float(value,result))
return boost::optional<float>(result);
return boost::optional<float>();
}
template <typename T>
T get(boost::property_tree::ptree const& node,
std::string const& name,
bool is_attribute,
T const& default_value)
{
boost::optional<std::string> str;
if (is_attribute)
{
str = node.get_optional<std::string>( std::string("<xmlattr>.") + name );
}
else
{
str = node.get_optional<std::string>(name + ".<xmltext>");
}
if ( str )
{
boost::optional<T> result = fast_cast<T>(*str);
if (result)
{
return *result;
}
else
{
throw config_error(std::string("Failed to parse ") +
(is_attribute ? "attribute" : "child node") + " '" +
name + "'. Expected " + name_trait<T>::name() +
" but got '" + *str + "'");
}
}
else
{
return default_value;
}
}
template <>
inline color get(boost::property_tree::ptree const& node,
std::string const& name,
bool is_attribute,
color const& default_value)
{
boost::optional<std::string> str;
if (is_attribute)
{
str = node.get_optional<std::string>( std::string("<xmlattr>.") + name );
}
else
{
str = node.get_optional<std::string>(name + ".<xmltext>");
}
if ( str )
{
try
{
return mapnik::color_factory::from_string((*str).c_str());
}
catch (...)
{
throw config_error(std::string("Failed to parse ") +
(is_attribute ? "attribute" : "child node") + " '" +
name + "'. Expected " + name_trait<color>::name() +
" but got '" + *str + "'");
}
}
else
{
return default_value;
}
}
template <typename T>
T get(boost::property_tree::ptree const& node, std::string const& name, bool is_attribute)
{
boost::optional<std::string> str;
if (is_attribute)
{
str = node.get_optional<std::string>( std::string("<xmlattr>.") + name);
}
else
{
str = node.get_optional<std::string>(name + ".<xmltext>");
}
if ( ! str )
{
throw config_error(std::string("Required ") +
(is_attribute ? "attribute " : "child node ") +
"'" + name + "' is missing");
}
boost::optional<T> result = fast_cast<T>(*str);
if (result)
{
return *result;
}
else
{
throw config_error(std::string("Failed to parse ") +
(is_attribute ? "attribute" : "child node") + " '" +
name + "'. Expected " + name_trait<T>::name() +
" but got '" + *str + "'");
}
}
template <typename T>
T get_value(boost::property_tree::ptree const& node, std::string const& name)
{
try
{
/* NOTE: get_child works as long as there is only one child with that name.
If this function is used this used this condition must always be satisfied.
*/
return node.get_child("<xmltext>").get_value<T>();
}
catch (boost::property_tree::ptree_bad_path)
{
/* If the XML parser did not find any non-empty data element the is no
<xmltext> node. But we don't want to fail here but simply return a
default constructed value of the requested type.
*/
return T();
}
catch (...)
{
throw config_error(std::string("Failed to parse ") +
name + ". Expected " + name_trait<T>::name() +
" but got '" + node.data() + "'");
}
}
template <typename T>
boost::optional<T> get_optional(boost::property_tree::ptree const& node,
std::string const& name,
bool is_attribute)
{
boost::optional<std::string> str;
if (is_attribute)
{
str = node.get_optional<std::string>( std::string("<xmlattr>.") + name);
}
else
{
str = node.get_optional<std::string>(name + ".<xmltext>");
}
boost::optional<T> result;
if ( str )
{
result = fast_cast<T>(*str);
if (!result)
{
throw config_error(std::string("Failed to parse ") +
(is_attribute ? "attribute" : "child node") + " '" +
name + "'. Expected " + name_trait<T>::name() +
" but got '" + *str + "'");
}
}
return result;
}
template <>
inline boost::optional<std::string> get_optional(boost::property_tree::ptree const& node,
std::string const& name,
bool is_attribute)
{
if (is_attribute)
{
return node.get_optional<std::string>( std::string("<xmlattr>.") + name);
}
else
{
return node.get_optional<std::string>(name + ".<xmltext>");
}
}
template <>
inline boost::optional<color> get_optional(boost::property_tree::ptree const& node,
std::string const& name,
bool is_attribute)
{
boost::optional<std::string> str;
if (is_attribute)
{
str = node.get_optional<std::string>( std::string("<xmlattr>.") + name);
}
else
{
str = node.get_optional<std::string>(name + ".<xmltext>");
}
boost::optional<color> result;
if ( str )
{
try
{
result = mapnik::color_factory::from_string((*str).c_str());
}
catch (...)
{
throw config_error(std::string("Failed to parse ") +
(is_attribute ? "attribute" : "child node") + " '" +
name + "'. Expected " + name_trait<color>::name() +
" but got '" + *str + "'");
}
}
return result;
}
static inline bool has_child(boost::property_tree::ptree const& node, std::string const& name)
{
boost::optional<std::string> str = node.get_optional<std::string>(name);
return str;
}
} // end of namespace mapnik
#endif // MAPNIK_PTREE_HELPERS_HPP

View file

@ -39,7 +39,6 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/color.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/enumeration.hpp>

View file

@ -65,11 +65,11 @@ public:
detector_(detector),
writer_(sym.get_metawriter()),
dims_(0, 0, width, height),
query_extent_(query_extent),
text_(font_manager, scale_factor),
angle_(0.0),
placement_valid_(false),
points_on_line_(false),
query_extent_(query_extent),
finder_()
{
initialize_geometries();

View file

@ -38,7 +38,7 @@ public:
text_symbolizer_properties & add();
text_symbolizer_properties & get(unsigned i);
unsigned size() const;
static text_placements_ptr from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets);
static text_placements_ptr from_xml(xml_node const &xml, fontset_map const & fontsets);
private:
std::vector<text_symbolizer_properties> list_;
friend class text_placement_info_list;

View file

@ -39,17 +39,17 @@ namespace placements
{
typedef text_placements_ptr (*from_xml_function_ptr)(
boost::property_tree::ptree const& xml, fontset_map const & fontsets);
xml_node const& xml, fontset_map const & fontsets);
class registry : public singleton<registry, CreateStatic>,
private boost::noncopyable
private boost::noncopyable
{
public:
registry();
~registry() {}
void register_name(std::string name, from_xml_function_ptr ptr, bool overwrite=false);
text_placements_ptr from_xml(std::string name,
boost::property_tree::ptree const& xml,
xml_node const& xml,
fontset_map const & fontsets);
private:
std::map<std::string, from_xml_function_ptr> map_;

View file

@ -52,7 +52,7 @@ public:
text_placement_info_ptr get_placement_info(double scale_factor) const;
void set_positions(std::string positions);
std::string get_positions();
static text_placements_ptr from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets);
static text_placements_ptr from_xml(xml_node const &xml, fontset_map const & fontsets);
private:
std::string positions_;
std::vector<directions_t> direction_;

View file

@ -54,7 +54,7 @@ struct char_properties
{
char_properties();
/** Construct object from XML. */
void from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets);
void from_xml(xml_node const &sym, fontset_map const & fontsets);
/** Write object to XML ptree. */
void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, char_properties const& dfl=char_properties()) const;
std::string face_name;
@ -124,7 +124,7 @@ struct text_symbolizer_properties
{
text_symbolizer_properties();
/** Load all values from XML ptree. */
void from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets);
void from_xml(xml_node const &sym, fontset_map const & fontsets);
/** Save all values to XML ptree (but does not create a new parent node!). */
void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, text_symbolizer_properties const &dfl=text_symbolizer_properties()) const;

View file

@ -30,16 +30,16 @@
namespace mapnik { namespace conversions {
bool string2int(const char * value, int & result);
bool string2int(std::string const& value, int & result);
bool string2int(const char * value, int & result);
bool string2int(std::string const& value, int & result);
bool string2double(std::string const& value, double & result);
bool string2double(const char * value, double & result);
bool string2double(std::string const& value, double & result);
bool string2double(const char * value, double & result);
bool string2float(std::string const& value, float & result);
bool string2float(const char * value, float & result);
bool string2float(std::string const& value, float & result);
bool string2float(const char * value, float & result);
}
}
}
#endif // MAPNIK_CONVERSIONS_UTIL_HPP

View file

@ -26,7 +26,6 @@
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/variant.hpp>

View file

@ -23,16 +23,14 @@
#ifndef MAPNIK_LIBXML2_LOADER_HPP
#define MAPNIK_LIBXML2_LOADER_HPP
// boost
#include <boost/property_tree/ptree.hpp>
// stl
#include <string>
namespace mapnik
{
void read_xml2( std::string const & filename, boost::property_tree::ptree & pt);
void read_xml2_string( std::string const & str, boost::property_tree::ptree & pt, std::string const & base_path="");
class xml_node;
void read_xml(std::string const & filename, xml_node &node);
void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path="");
}
#endif // MAPNIK_LIBXML2_LOADER_HPP

137
include/mapnik/xml_node.hpp Normal file
View file

@ -0,0 +1,137 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#ifndef MAPNIK_XML_NODE_H
#define MAPNIK_XML_NODE_H
//mapnik
#include <mapnik/boolean.hpp>
//boost
#include <boost/optional.hpp>
//stl
#include <list>
#include <string>
#include <map>
#include <exception>
namespace mapnik
{
class xml_tree;
class xml_attribute
{
public:
xml_attribute(std::string const& value);
std::string value;
mutable bool processed;
};
class node_not_found: public std::exception
{
public:
node_not_found(std::string node_name);
virtual const char* what() const throw();
~node_not_found() throw ();
private:
std::string node_name_;
};
class attribute_not_found: public std::exception
{
public:
attribute_not_found(std::string const& node_name, std::string const& attribute_name);
virtual const char* what() const throw();
~attribute_not_found() throw ();
private:
std::string node_name_;
std::string attribute_name_;
};
class more_than_one_child: public std::exception
{
public:
more_than_one_child(std::string const& node_name);
virtual const char* what() const throw();
~more_than_one_child() throw ();
private:
std::string node_name_;
};
class xml_node
{
public:
typedef std::list<xml_node>::const_iterator const_iterator;
typedef std::map<std::string, xml_attribute> attribute_map;
xml_node(xml_tree &tree, std::string name, unsigned line=0, bool text_node = false);
std::string const& name() const;
std::string const& text() const;
std::string const& filename() const;
bool is_text() const;
bool is(std::string const& name) const;
xml_node &add_child(std::string const& name, unsigned line=0, bool text_node = false);
void add_attribute(std::string const& name, std::string const& value);
attribute_map const& get_attributes() const;
bool processed() const;
void set_processed(bool processed) const;
unsigned line() const;
const_iterator begin() const;
const_iterator end() const;
xml_node & get_child(std::string const& name);
xml_node const& get_child(std::string const& name) const;
xml_node const* get_opt_child(std::string const& name) const;
bool has_child(std::string const& name) const;
template <typename T>
boost::optional<T> get_opt_attr(std::string const& name) const;
template <typename T>
T get_attr(std::string const& name, T const& default_value) const;
template <typename T>
T get_attr(std::string const& name) const;
std::string get_text() const;
template <typename T>
T get_value() const;
private:
xml_tree &tree_;
std::string name_;
std::list<xml_node> children_;
attribute_map attributes_;
bool text_node_;
unsigned line_;
mutable bool processed_;
static std::string xml_text;
};
} //ns mapnik
#endif // MAPNIK_XML_NODE_H

View file

@ -0,0 +1,54 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#ifndef MAPNIK_XML_TREE_H
#define MAPNIK_XML_TREE_H
//mapnik
#include <mapnik/xml_node.hpp>
#include <mapnik/expression_grammar.hpp>
#include <mapnik/css_color_grammar.hpp>
//stl
#include <string>
namespace mapnik
{
class xml_tree
{
public:
xml_tree(std::string const& encoding="utf8");
void set_filename(std::string fn);
std::string const& filename() const;
xml_node &root();
private:
xml_node node_;
std::string file_;
transcoder tr_;
public:
mapnik::css_color_grammar<std::string::const_iterator> color_grammar;
mapnik::expression_grammar<std::string::const_iterator> expr_grammar;
};
} //ns mapnik
#endif // MAPNIK_XML_TREE_H

View file

@ -6,6 +6,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
// mapnik
#include <mapnik/feature_layer_desc.hpp>
@ -14,7 +15,7 @@
#include <mapnik/memory_featureset.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/util/geometry_to_ds_type.hpp>
#include <mapnik/ptree_helpers.hpp> // mapnik::boolean
#include <mapnik/boolean.hpp>
// stl
#include <sstream>

View file

@ -25,7 +25,7 @@
#include "gdal_featureset.hpp"
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/geom_util.hpp>
#include <gdal_version.h>

View file

@ -30,7 +30,7 @@
#include <cstdarg>
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/geom_util.hpp>
// boost

View file

@ -33,7 +33,7 @@
#include <cstdio>
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
// boost
#include <boost/algorithm/string.hpp>

View file

@ -25,7 +25,7 @@
#include "occi_featureset.hpp"
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/sql_utils.hpp>
// boost

View file

@ -33,7 +33,7 @@
#include <gdal_version.h>
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/geom_util.hpp>
// boost

View file

@ -26,7 +26,7 @@
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/sql_utils.hpp>
#include <mapnik/util/conversions.hpp>
@ -681,22 +681,22 @@ box2d<double> postgis_datasource::envelope() const
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next() && !rs->isNull(0))
{
double lox;
double loy;
double hix;
double hiy;
if (mapnik::conversions::string2double(rs->getValue(0),lox) &&
mapnik::conversions::string2double(rs->getValue(1),loy) &&
mapnik::conversions::string2double(rs->getValue(2),hix) &&
mapnik::conversions::string2double(rs->getValue(3),hiy))
{
extent_.init(lox,loy,hix,hiy);
extent_initialized_ = true;
}
else
{
std::clog << boost::format("Postgis Plugin: warning: could not determine extent from query: %s\n") % s.str() << std::endl;
}
double lox;
double loy;
double hix;
double hiy;
if (mapnik::conversions::string2double(rs->getValue(0),lox) &&
mapnik::conversions::string2double(rs->getValue(1),loy) &&
mapnik::conversions::string2double(rs->getValue(2),hix) &&
mapnik::conversions::string2double(rs->getValue(3),hiy))
{
extent_.init(lox,loy,hix,hiy);
extent_initialized_ = true;
}
else
{
std::clog << boost::format("Postgis Plugin: warning: could not determine extent from query: %s\n") % s.str() << std::endl;
}
}
rs->close();
}

View file

@ -29,7 +29,7 @@
#include <boost/make_shared.hpp>
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/geom_util.hpp>
using mapnik::datasource;

View file

@ -26,7 +26,7 @@
#include "sqlite_utils.hpp"
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/sql_utils.hpp>
#include <mapnik/util/geometry_to_ds_type.hpp>
#include <mapnik/wkb.hpp>

View file

@ -27,7 +27,6 @@
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/map.hpp>

View file

@ -178,6 +178,8 @@ source = Split(
text_placements/list.cpp
text_placements/simple.cpp
text_properties.cpp
xml_tree.cpp
config_error.cpp
"""
)
@ -299,7 +301,7 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']:
env2 = lib_env.Clone()
env2.Append(CXXFLAGS = '-DHAVE_LIBXML2')
libmapnik_cxxflags.append('-DHAVE_LIBXML2')
fixup = ['load_map.cpp','libxml2_loader.cpp']
fixup = ['libxml2_loader.cpp']
for cpp in fixup:
if cpp in source:
source.remove(cpp)
@ -307,6 +309,12 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']:
source.insert(0,env2.StaticObject(cpp))
else:
source.insert(0,env2.SharedObject(cpp))
else:
source += Split(
"""
rapidxml_loader.cpp
"""
)
if env['CUSTOM_LDFLAGS']:
linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], mapnik_lib_link_flag)

View file

@ -29,7 +29,6 @@
#include <mapnik/unicode.hpp>
#include <mapnik/markers_placement.hpp>
#include <mapnik/arrow.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>

View file

@ -25,11 +25,23 @@
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/format.hpp>
#include <boost/version.hpp>
// stl
#include <sstream>
// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane)
#if BOOST_VERSION >= 104500
#include <mapnik/css_color_grammar.hpp>
#else
#include <mapnik/css_color_grammar_deprecated.hpp>
#endif
namespace mapnik {
color::color( std::string const& css_string)
@ -81,5 +93,89 @@ std::string color::to_hex_string() const
}
}
/****************************************************************************/
void color_factory::init_from_string(color & c, std::string const& css_color)
{
typedef std::string::const_iterator iterator_type;
typedef mapnik::css_color_grammar<iterator_type> css_color_grammar;
css_color_grammar g;
iterator_type first = css_color.begin();
iterator_type last = css_color.end();
// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane)
#if BOOST_VERSION >= 104500
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
c);
if (!result)
{
throw config_error(std::string("Failed to parse color value: ") +
"Expected a CSS color, but got '" + css_color + "'");
}
#else
mapnik::css css_;
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
css_);
if (!result)
{
throw config_error(std::string("Failed to parse color value: ") +
"Expected a CSS color, but got '" + css_color + "'");
}
c.set_red(css_.r);
c.set_green(css_.g);
c.set_blue(css_.b);
c.set_alpha(css_.a);
#endif
}
bool color_factory::parse_from_string(color & c, std::string const& css_color,
mapnik::css_color_grammar<std::string::const_iterator> const& g)
{
std::string::const_iterator first = css_color.begin();
std::string::const_iterator last = css_color.end();
// boost 1.41 -> 1.44 compatibility, to be removed in mapnik 2.1 (dane)
#if BOOST_VERSION >= 104500
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
c);
return result && (first == last);
#else
mapnik::css css_;
bool result =
boost::spirit::qi::phrase_parse(first,
last,
g,
boost::spirit::ascii::space,
css_);
if (result && (first == last))
{
c.set_red(css_.r);
c.set_green(css_.g);
c.set_blue(css_.b);
c.set_alpha(css_.a);
return true;
}
#endif
}
color color_factory::from_string(std::string const& css_color)
{
color c;
init_from_string(c, css_color);
return c;
}
}

55
src/config_error.cpp Normal file
View file

@ -0,0 +1,55 @@
#include <mapnik/config_error.hpp>
#include <mapnik/xml_tree.hpp>
namespace mapnik
{
config_error::config_error(std::string const& what)
: what_(what), line_number_(0), file_(), node_name_(), msg_()
{
}
config_error::config_error(std::string const& what, xml_node const& node)
: what_(what), line_number_(node.line()), file_(node.filename()), node_name_(node.name()), msg_()
{
}
config_error::config_error(std::string const& what, unsigned line_number, std::string const& filename)
: what_(what), line_number_(line_number), file_(filename), node_name_(), msg_()
{
}
char const* config_error::what() const throw()
{
std::stringstream s;
s << file_;
if (line_number_ > 0) s << " line " << line_number_;
if (!node_name_.empty()) s << " in node "<< node_name_;
if (line_number_ > 0 || !file_.empty()) s << ": ";
s << what_;
msg_ = s.str(); //Avoid returning pointer to dead object
return msg_.c_str();
}
void config_error::append_context(std::string const& ctx) const
{
what_ += " " + ctx;
}
void config_error::append_context(std::string const& ctx, xml_node const& node) const
{
append_context(ctx);
append_context(node);
}
void config_error::append_context(xml_node const& node) const
{
if (!line_number_) line_number_ = node.line();
if (node_name_.empty()) node_name_ = node.name();
if (file_.empty()) file_ = node.filename();
}
}

View file

@ -23,21 +23,21 @@
// boost
#include <boost/spirit/include/qi.hpp>
#define BOOST_SPIRIT_AUTO(domain_, name, expr) \
typedef boost::proto::result_of:: \
deep_copy<BOOST_TYPEOF(expr)>::type name##_expr_type; \
BOOST_SPIRIT_ASSERT_MATCH( \
boost::spirit::domain_::domain, name##_expr_type); \
BOOST_AUTO(name, boost::proto::deep_copy(expr)); \
#define BOOST_SPIRIT_AUTO(domain_, name, expr) \
typedef boost::proto::result_of:: \
deep_copy<BOOST_TYPEOF(expr)>::type name##_expr_type; \
BOOST_SPIRIT_ASSERT_MATCH( \
boost::spirit::domain_::domain, name##_expr_type); \
BOOST_AUTO(name, boost::proto::deep_copy(expr)); \
namespace mapnik { namespace conversions {
using namespace boost::spirit;
BOOST_SPIRIT_AUTO(qi, INTEGER, qi::int_);
BOOST_SPIRIT_AUTO(qi, FLOAT, qi::float_);
BOOST_SPIRIT_AUTO(qi, DOUBLE, qi::double_);
BOOST_SPIRIT_AUTO(qi, INTEGER, qi::int_)
BOOST_SPIRIT_AUTO(qi, FLOAT, qi::float_)
BOOST_SPIRIT_AUTO(qi, DOUBLE, qi::double_)
bool string2int(const char * value, int & result)
{

View file

@ -24,6 +24,7 @@
#include <mapnik/expression.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/expression_grammar.hpp>
// boost
#include <boost/algorithm/string.hpp>
@ -50,8 +51,8 @@ expression_ptr expression_factory::compile(std::string const& str,transcoder con
}
bool expression_factory::parse_from_string(expression_ptr const& expr,
std::string const& str,
mapnik::expression_grammar<std::string::const_iterator> const& g)
std::string const& str,
mapnik::expression_grammar<std::string::const_iterator> const& g)
{
std::string::const_iterator itr = str.begin();
std::string::const_iterator end = str.end();

View file

@ -23,6 +23,7 @@
#include <mapnik/formatting/base.hpp>
#include <mapnik/formatting/list.hpp>
#include <mapnik/formatting/registry.hpp>
#include <mapnik/xml_node.hpp>
// boost
#include <boost/property_tree/ptree.hpp>
@ -38,18 +39,18 @@ void node::to_xml(boost::property_tree::ptree &xml) const
#endif
}
node_ptr node::from_xml(boost::property_tree::ptree const& xml)
node_ptr node::from_xml(xml_node const& xml)
{
list_node *list = new list_node();
node_ptr list_ptr(list);
boost::property_tree::ptree::const_iterator itr = xml.begin();
boost::property_tree::ptree::const_iterator end = xml.end();
xml_node::const_iterator itr = xml.begin();
xml_node::const_iterator end = xml.end();
for (; itr != end; ++itr) {
if (itr->first == "<xmlcomment>" || itr->first == "<xmlattr>" || itr->first == "Placement")
if (itr->name() == "Placement")
{
continue;
}
node_ptr n = registry::instance()->from_xml(itr->first, itr->second);
node_ptr n = registry::instance()->from_xml(*itr);
if (n) list->push_back(n);
}
if (list->get_children().size() == 1) {

View file

@ -27,6 +27,7 @@
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/xml_node.hpp>
// boost
@ -37,7 +38,7 @@ namespace formatting
using boost::property_tree::ptree;
void expression_format::to_xml(boost::property_tree::ptree &xml) const
{
ptree &new_node = xml.push_back(ptree::value_type("Format", ptree()))->second;
ptree &new_node = xml.push_back(ptree::value_type("ExpressionFormat", ptree()))->second;
if (face_name) set_attr(new_node, "face-name", to_expression_string(*face_name));
if (text_size) set_attr(new_node, "size", to_expression_string(*text_size));
if (character_spacing) set_attr(new_node, "character-spacing", to_expression_string*character_spacing);
@ -51,7 +52,7 @@ void expression_format::to_xml(boost::property_tree::ptree &xml) const
if (child_) child_->to_xml(new_node);
}
node_ptr expression_format::from_xml(ptree const& xml)
node_ptr expression_format::from_xml(xml_node const& xml)
{
expression_format *n = new expression_format();
node_ptr np(n);
@ -72,9 +73,9 @@ node_ptr expression_format::from_xml(ptree const& xml)
return np;
}
expression_ptr expression_format::get_expression(ptree const& xml, std::string name)
expression_ptr expression_format::get_expression(xml_node const& xml, std::string name)
{
boost::optional<std::string> tmp = get_opt_attr<std::string>(xml, name);
boost::optional<std::string> tmp = xml.get_opt_attr<std::string>(name);
if (tmp) return parse_expression(*tmp);
return expression_ptr();
}
@ -84,25 +85,25 @@ void expression_format::apply(char_properties const& p, const Feature &feature,
{
char_properties new_properties = p;
if (face_name) new_properties.face_name =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *face_name).to_string();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *face_name).to_string();
if (text_size) new_properties.text_size =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *text_size).to_double();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *text_size).to_double();
if (character_spacing) new_properties.character_spacing =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *character_spacing).to_double();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *character_spacing).to_double();
if (line_spacing) new_properties.line_spacing =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *line_spacing).to_double();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *line_spacing).to_double();
if (text_opacity) new_properties.text_opacity =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *text_opacity).to_double();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *text_opacity).to_double();
if (wrap_before) new_properties.wrap_before =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *wrap_before).to_bool();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *wrap_before).to_bool();
if (wrap_char) new_properties.wrap_char =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *character_spacing).to_unicode()[0];
boost::apply_visitor(evaluate<Feature,value_type>(feature), *character_spacing).to_unicode()[0];
// if (fill) new_properties.fill =
// boost::apply_visitor(evaluate<Feature,value_type>(feature), *fill).to_color();
// if (halo_fill) new_properties.halo_fill =
// boost::apply_visitor(evaluate<Feature,value_type>(feature), *halo_fill).to_color();
if (halo_radius) new_properties.halo_radius =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *halo_radius).to_double();
boost::apply_visitor(evaluate<Feature,value_type>(feature), *halo_radius).to_double();
if (child_) {
child_->apply(new_properties, feature, output);

View file

@ -21,6 +21,7 @@
*****************************************************************************/
#include <mapnik/formatting/format.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/xml_node.hpp>
namespace mapnik {
using boost::property_tree::ptree;
@ -44,7 +45,7 @@ void format_node::to_xml(ptree &xml) const
}
node_ptr format_node::from_xml(ptree const& xml)
node_ptr format_node::from_xml(xml_node const& xml)
{
format_node *n = new format_node();
node_ptr np(n);
@ -52,19 +53,19 @@ node_ptr format_node::from_xml(ptree const& xml)
node_ptr child = node::from_xml(xml);
n->set_child(child);
n->face_name = get_opt_attr<std::string>(xml, "face-name");
n->face_name = xml.get_opt_attr<std::string>("face-name");
/*TODO: Fontset is problematic. We don't have the fontsets pointer here... */
n->text_size = get_opt_attr<unsigned>(xml, "size");
n->character_spacing = get_opt_attr<unsigned>(xml, "character-spacing");
n->line_spacing = get_opt_attr<unsigned>(xml, "line-spacing");
n->text_opacity = get_opt_attr<double>(xml, "opactity");
boost::optional<boolean> wrap = get_opt_attr<boolean>(xml, "wrap-before");
n->text_size = xml.get_opt_attr<unsigned>("size");
n->character_spacing = xml.get_opt_attr<unsigned>("character-spacing");
n->line_spacing = xml.get_opt_attr<unsigned>("line-spacing");
n->text_opacity = xml.get_opt_attr<double>("opactity");
boost::optional<boolean> wrap = xml.get_opt_attr<boolean>("wrap-before");
if (wrap) n->wrap_before = *wrap;
n->wrap_char = get_opt_attr<unsigned>(xml, "wrap-character");
n->text_transform = get_opt_attr<text_transform_e>(xml, "text-transform");
n->fill = get_opt_attr<color>(xml, "fill");
n->halo_fill = get_opt_attr<color>(xml, "halo-fill");
n->halo_radius = get_opt_attr<double>(xml, "halo-radius");
n->wrap_char = xml.get_opt_attr<unsigned>("wrap-character");
n->text_transform = xml.get_opt_attr<text_transform_e>("text-transform");
n->fill = xml.get_opt_attr<color>("fill");
n->halo_fill = xml.get_opt_attr<color>("halo-fill");
n->halo_radius = xml.get_opt_attr<double>("halo-radius");
return np;
}

View file

@ -24,6 +24,8 @@
#include <mapnik/formatting/text.hpp>
#include <mapnik/formatting/format.hpp>
#include <mapnik/formatting/expression.hpp>
#include <mapnik/xml_node.hpp>
#include <mapnik/config_error.hpp>
namespace mapnik
{
@ -46,10 +48,11 @@ void registry::register_name(std::string name, from_xml_function_ptr ptr, bool o
}
}
node_ptr registry::from_xml(std::string name, const boost::property_tree::ptree &xml)
node_ptr registry::from_xml(xml_node const& xml)
{
std::map<std::string, from_xml_function_ptr>::const_iterator itr = map_.find(name);
if (itr == map_.end()) throw config_error("Unknown element '" + name + "'");
std::map<std::string, from_xml_function_ptr>::const_iterator itr = map_.find(xml.name());
if (itr == map_.end()) throw config_error("Unknown element '" + xml.name() + "'", xml);
xml.set_processed(true);
return itr->second(xml);
}
} //ns formatting

View file

@ -26,10 +26,7 @@
#include <mapnik/feature.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/processed_text.hpp>
// boost
#include <boost/algorithm/string.hpp>
#include <boost/make_shared.hpp>
#include <mapnik/xml_node.hpp>
namespace mapnik
{
@ -46,10 +43,9 @@ void text_node::to_xml(ptree &xml) const
}
node_ptr text_node::from_xml(boost::property_tree::ptree const& xml)
node_ptr text_node::from_xml(xml_node const& xml)
{
std::string data = xml.data();
boost::trim(data);
std::string data = xml.text();
if (data.empty()) return node_ptr(); //No text
return boost::make_shared<text_node>(parse_expression(data, "utf8"));
}

View file

@ -32,7 +32,6 @@
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/map.hpp>

View file

@ -33,29 +33,29 @@ namespace mapnik { namespace json {
#if BOOST_VERSION >= 104700
template <typename Iterator>
feature_collection_parser<Iterator>::feature_collection_parser(mapnik::context_ptr const& ctx, mapnik::transcoder const& tr)
: grammar_(new feature_collection_grammar<iterator_type,feature_type>(ctx,tr)) {}
template <typename Iterator>
feature_collection_parser<Iterator>::feature_collection_parser(mapnik::context_ptr const& ctx, mapnik::transcoder const& tr)
: grammar_(new feature_collection_grammar<iterator_type,feature_type>(ctx,tr)) {}
template <typename Iterator>
feature_collection_parser<Iterator>::~feature_collection_parser() {}
template <typename Iterator>
feature_collection_parser<Iterator>::~feature_collection_parser() {}
#endif
template <typename Iterator>
bool feature_collection_parser<Iterator>::parse(iterator_type first, iterator_type last, std::vector<mapnik::feature_ptr> & features)
{
template <typename Iterator>
bool feature_collection_parser<Iterator>::parse(iterator_type first, iterator_type last, std::vector<mapnik::feature_ptr> & features)
{
#if BOOST_VERSION >= 104700
using namespace boost::spirit;
return qi::phrase_parse(first, last, *grammar_, standard_wide::space, features);
using namespace boost::spirit;
return qi::phrase_parse(first, last, *grammar_, standard_wide::space, features);
#else
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("mapnik::feature_collection_parser::parse() requires at least boost 1.47 while your build was compiled against boost " + s.str());
return false;
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("mapnik::feature_collection_parser::parse() requires at least boost 1.47 while your build was compiled against boost " + s.str());
return false;
#endif
}
}
template class feature_collection_parser<std::string::const_iterator> ;
template class feature_collection_parser<boost::spirit::multi_pass<std::istreambuf_iterator<char> > >;
}}
template class feature_collection_parser<std::string::const_iterator> ;
template class feature_collection_parser<boost::spirit::multi_pass<std::istreambuf_iterator<char> > >;
}}

View file

@ -32,30 +32,30 @@
namespace mapnik { namespace json {
feature_generator::feature_generator()
: grammar_(new feature_generator_grammar<sink_type>()) {}
feature_generator::feature_generator()
: grammar_(new feature_generator_grammar<sink_type>()) {}
feature_generator::~feature_generator() {}
feature_generator::~feature_generator() {}
bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f)
{
sink_type sink(geojson);
return karma::generate(sink, *grammar_,f);
}
bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f)
{
sink_type sink(geojson);
return karma::generate(sink, *grammar_,f);
}
geometry_generator::geometry_generator()
: grammar_(new multi_geometry_generator_grammar<sink_type>()) {}
geometry_generator::geometry_generator()
: grammar_(new multi_geometry_generator_grammar<sink_type>()) {}
geometry_generator::~geometry_generator() {}
geometry_generator::~geometry_generator() {}
bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g)
{
sink_type sink(geojson);
return karma::generate(sink, *grammar_,g);
}
bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g)
{
sink_type sink(geojson);
return karma::generate(sink, *grammar_,g);
}
}}
}}
#else
@ -65,22 +65,22 @@ bool geometry_generator::generate(std::string & geojson, mapnik::geometry_contai
namespace mapnik { namespace json {
bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f)
{
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("feature_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str());
return false;
}
bool feature_generator::generate(std::string & geojson, mapnik::Feature const& f)
{
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("feature_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str());
return false;
}
bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g)
{
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("geometry_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str());
return false;
}
bool geometry_generator::generate(std::string & geojson, mapnik::geometry_container const& g)
{
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("geometry_generator::generate() requires at least boost 1.47 while your build was compiled against boost " + s.str());
return false;
}
}}
}}
#endif

View file

@ -22,26 +22,27 @@
#ifdef HAVE_LIBXML2
#include <mapnik/libxml2_loader.hpp>
// mapnik
#include <mapnik/xml_loader.hpp>
#include <mapnik/xml_node.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string/trim.hpp>
// libxml
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/parserInternals.h>
#include <libxml/xinclude.h>
// stl
#include <iostream>
using boost::property_tree::ptree;
using namespace std;
//#define DEFAULT_OPTIONS (XML_PARSE_NOENT | XML_PARSE_NOBLANKS | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA)
#define DEFAULT_OPTIONS (XML_PARSE_NOERROR | XML_PARSE_NOENT | XML_PARSE_NOBLANKS | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA)
namespace mapnik
@ -50,14 +51,14 @@ class libxml2_loader : boost::noncopyable
{
public:
libxml2_loader(const char *encoding = NULL, int options = DEFAULT_OPTIONS, const char *url = NULL) :
ctx_( 0 ),
encoding_( encoding ),
options_( options ),
url_( url )
ctx_(0),
encoding_(encoding),
options_(options),
url_(url)
{
LIBXML_TEST_VERSION;
ctx_ = xmlNewParserCtxt();
if ( ! ctx_ )
if (!ctx_)
{
throw std::runtime_error("Failed to create parser context.");
}
@ -71,19 +72,19 @@ public:
}
}
void load( std::string const& filename, ptree & pt )
void load(std::string const& filename, xml_node &node)
{
boost::filesystem::path path(filename);
if ( !boost::filesystem::exists( path ) ) {
throw config_error(string("Could not load map file '") +
filename + "': File does not exist");
if (!boost::filesystem::exists(path))
{
throw config_error(string("Could not load map file: File does not exist"), 0, filename);
}
xmlDocPtr doc = xmlCtxtReadFile(ctx_, filename.c_str(), encoding_, options_);
if ( !doc )
if (!doc)
{
xmlError * error = xmlCtxtGetLastError( ctx_ );
xmlError * error = xmlCtxtGetLastError(ctx_);
if (error)
{
std::ostringstream os;
@ -91,15 +92,7 @@ public:
os << ": " << std::endl << error->message;
// remove CR
std::string msg = os.str().substr(0, os.str().size() - 1);
config_error ex( msg );
os.str("");
os << "(encountered in file '" << error->file << "' at line "
<< error->line << ")";
ex.append_context( os.str() );
throw ex;
throw config_error(msg, error->line, error->file);
}
}
@ -110,21 +103,21 @@ public:
<< std::endl;
}
*/
load(doc, pt);
load(doc, node);
}
void load( const int fd, ptree & pt )
void load(const int fd, xml_node &node)
{
xmlDocPtr doc = xmlCtxtReadFd(ctx_, fd, url_, encoding_, options_);
load(doc, pt);
load(doc, node);
}
void load_string( std::string const& buffer, ptree & pt, std::string const & base_path )
void load_string(std::string const& buffer, xml_node &node, std::string const & base_path)
{
if (!base_path.empty())
{
boost::filesystem::path path(base_path);
if ( ! boost::filesystem::exists( path ) ) {
if (!boost::filesystem::exists(path)) {
throw config_error(string("Could not locate base_path '") +
base_path + "': file or directory does not exist");
}
@ -132,12 +125,12 @@ public:
xmlDocPtr doc = xmlCtxtReadMemory(ctx_, buffer.data(), buffer.length(), base_path.c_str(), encoding_, options_);
load(doc, pt);
load(doc, node);
}
void load( const xmlDocPtr doc, ptree & pt )
void load(const xmlDocPtr doc, xml_node &node)
{
if ( !doc )
if (!doc)
{
xmlError * error = xmlCtxtGetLastError( ctx_ );
std::ostringstream os;
@ -146,10 +139,10 @@ public:
{
os << ": " << std::endl << error->message;
}
throw config_error(os.str());
throw config_error(os.str(), error->line, error->file);
}
int iXIncludeReturn = xmlXIncludeProcessFlags( doc, options_ );
int iXIncludeReturn = xmlXIncludeProcessFlags(doc, options_);
if (iXIncludeReturn < 0)
{
@ -157,64 +150,48 @@ public:
throw config_error("XML XInclude error. One or more files failed to load.");
}
xmlNode * root = xmlDocGetRootElement( doc );
if ( ! root ) {
xmlNode * root = xmlDocGetRootElement(doc);
if (!root) {
xmlFreeDoc(doc);
throw config_error("XML document is empty.");
}
populate_tree( root, pt );
populate_tree(root, node);
xmlFreeDoc(doc);
}
private:
void append_attributes( xmlAttr * attributes, ptree & pt)
void append_attributes(xmlAttr *attributes, xml_node &node)
{
if (attributes)
for (; attributes; attributes = attributes->next )
{
ptree::iterator it = pt.push_back( ptree::value_type( "<xmlattr>", ptree() ));
ptree & attr_list = it->second;
xmlAttr * cur_attr = attributes;
for (; cur_attr; cur_attr = cur_attr->next )
{
ptree::iterator it = attr_list.push_back(
ptree::value_type( (char*)cur_attr->name, ptree() ));
it->second.put_value( (char*) cur_attr->children->content );
}
node.add_attribute((char *)attributes->name, (char *)attributes->children->content);
}
}
void populate_tree( xmlNode * node, ptree & pt )
void populate_tree(xmlNode *cur_node, xml_node &node)
{
xmlNode * cur_node = node;
for (; cur_node; cur_node = cur_node->next )
{
switch (cur_node->type)
{
case XML_ELEMENT_NODE:
{
ptree::iterator it = pt.push_back( ptree::value_type(
(char*)cur_node->name, ptree() ));
append_attributes( cur_node->properties, it->second);
populate_tree( cur_node->children, it->second );
xml_node &new_node = node.add_child((char *)cur_node->name, cur_node->line, false);
append_attributes(cur_node->properties, new_node);
populate_tree(cur_node->children, new_node);
}
break;
case XML_TEXT_NODE:
{
std::string trimmed = boost::algorithm::trim_copy(std::string((char*)cur_node->content));
if (trimmed.empty()) break;
ptree::iterator it = pt.push_back(ptree::value_type("<xmltext>", ptree()));
it->second.put_value(trimmed);
if (trimmed.empty()) break; //Don't add empty text nodes
node.add_child(trimmed, cur_node->line, true);
}
break;
case XML_COMMENT_NODE:
{
ptree::iterator it = pt.push_back(
ptree::value_type( "<xmlcomment>", ptree() ));
it->second.put_value( (char*) cur_node->content );
}
break;
break;
default:
break;
@ -228,15 +205,15 @@ private:
const char *url_;
};
void read_xml2( std::string const & filename, boost::property_tree::ptree & pt)
void read_xml(std::string const & filename, xml_node &node)
{
libxml2_loader loader;
loader.load( filename, pt );
loader.load(filename, node);
}
void read_xml2_string( std::string const & str, boost::property_tree::ptree & pt, std::string const & base_path)
void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path)
{
libxml2_loader loader;
loader.load_string( str, pt, base_path );
loader.load_string(str, node, base_path);
}
} // end of namespace mapnik

File diff suppressed because it is too large Load diff

View file

@ -588,7 +588,7 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
if (fs)
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
hit_test_filter(x,y,tol));
hit_test_filter(x,y,tol));
}
}
catch (...)
@ -634,7 +634,7 @@ featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
if (fs)
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
hit_test_filter(x,y,tol));
hit_test_filter(x,y,tol));
}
}
catch (...)

View file

@ -22,15 +22,15 @@
//$Id$
#include <mapnik/metawriter_factory.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/metawriter_json.hpp>
#include <mapnik/metawriter_inmem.hpp>
#include <mapnik/xml_node.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/config_error.hpp>
#include <boost/make_shared.hpp>
#include <boost/optional.hpp>
using boost::property_tree::ptree;
using boost::optional;
using std::string;
@ -38,20 +38,21 @@ namespace mapnik
{
metawriter_ptr
metawriter_create(const boost::property_tree::ptree &pt) {
metawriter_create(xml_node const& pt)
{
metawriter_ptr writer;
string type = get_attr<string>(pt, "type");
string type = pt.get_attr<string>("type");
optional<string> properties = get_opt_attr<string>(pt, "default-output");
optional<string> properties = pt.get_opt_attr<string>("default-output");
if (type == "json") {
string file = get_attr<string>(pt, "file");
string file = pt.get_attr<string>("file");
metawriter_json_ptr json = boost::make_shared<metawriter_json>(properties, parse_path(file));
optional<boolean> output_empty = get_opt_attr<boolean>(pt, "output-empty");
optional<boolean> output_empty = pt.get_opt_attr<boolean>("output-empty");
if (output_empty) {
json->set_output_empty(*output_empty);
}
optional<boolean> pixel_coordinates = get_opt_attr<boolean>(pt, "pixel-coordinates");
optional<boolean> pixel_coordinates = pt.get_opt_attr<boolean>("pixel-coordinates");
if (pixel_coordinates) {
json->set_pixel_coordinates(*pixel_coordinates);
}
@ -61,14 +62,16 @@ metawriter_create(const boost::property_tree::ptree &pt) {
metawriter_inmem_ptr inmem = boost::make_shared<metawriter_inmem>(properties);
writer = inmem;
} else {
throw config_error(string("Unknown type '") + type + "'");
throw config_error(string("Unknown type '") + type + "'", pt);
}
return writer;
}
void
metawriter_save(const metawriter_ptr &metawriter, ptree &metawriter_node, bool explicit_defaults) {
metawriter_save(const metawriter_ptr &metawriter,
boost::property_tree::ptree &metawriter_node, bool explicit_defaults)
{
metawriter_json *json = dynamic_cast<metawriter_json *>(metawriter.get());
if (json) {

View file

@ -21,6 +21,7 @@
*****************************************************************************/
#include <mapnik/palette.hpp>
#include <mapnik/config_error.hpp>
namespace mapnik
{

View file

@ -269,9 +269,9 @@ void placement_finder<DetectorT>::find_line_breaks()
// wrap text at first wrap_char after (default) the wrap width or immediately before the current word
if ((c == '\n') ||
(line_width > 0 &&
((line_width > wrap_at && !ci.format->wrap_before) ||
((line_width > wrap_at && !ci.format->wrap_before) ||
((line_width + last_wrap_char_width + word_width) > wrap_at && ci.format->wrap_before)) )
)
)
{
add_line(line_width, line_height, first_line);
line_breaks_.push_back(last_wrap_char_pos);
@ -675,10 +675,10 @@ void placement_finder<DetectorT>::find_line_placements(PathT & shape_path)
template <typename DetectorT>
std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(std::vector<vertex2d> const& path_positions,
std::vector<double> const& path_distances,
int & orientation,
unsigned index,
double distance)
std::vector<double> const& path_distances,
int & orientation,
unsigned index,
double distance)
{
//Check that the given distance is on the given index and find the correct index and distance if not
while (distance < 0 && index > 1)
@ -718,10 +718,10 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(std::
}
std::auto_ptr<text_path> current_placement(
new text_path((old_x + dx*distance/segment_length),
(old_y + dy*distance/segment_length)
)
);
new text_path((old_x + dx*distance/segment_length),
(old_y + dy*distance/segment_length)
)
);
double angle = atan2(-dy, dx);
@ -830,7 +830,7 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(std::
render_angle += M_PI;
}
current_placement->add_node(&ci,
render_x - current_placement->center.x,
render_x - current_placement->center.x,
-render_y + current_placement->center.y,
render_angle);
@ -870,7 +870,7 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(std::
template <typename DetectorT>
bool placement_finder<DetectorT>::test_placement(std::auto_ptr<text_path> const& current_placement,
int orientation)
int orientation)
{
//Create and test envelopes
bool status = true;
@ -909,8 +909,8 @@ bool placement_finder<DetectorT>::test_placement(std::auto_ptr<text_path> const&
if (!detector_.extent().intersects(e) ||
(!p.allow_overlap &&
!detector_.has_placement(e, info_.get_string(), pi.get_actual_minimum_distance())
)
)
)
{
//std::clog << "No Intersects:" << !dimensions_.intersects(e) << ": " << e << " @ " << dimensions_ << std::endl;
//std::clog << "No Placements:" << !detector_.has_placement(e, info.get_string(), p.minimum_distance) << std::endl;

View file

@ -1,4 +1,28 @@
/*****************************************************************************
*
* 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 <mapnik/processed_text.hpp>
#include <mapnik/config_error.hpp>
namespace mapnik
{
@ -43,7 +67,7 @@ string_info &processed_text::get_string_info()
{
if (!p.fontset.get_name().empty())
{
throw config_error("Unable to find specified font set '" + p.face_name + "'");
throw config_error("Unable to find specified font set '" + p.fontset.get_name() + "'");
} else if (!p.face_name.empty()) {
throw config_error("Unable to find specified font face '" + p.face_name + "'");
} else {

171
src/rapidxml_loader.cpp Normal file
View file

@ -0,0 +1,171 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#ifdef HAVE_LIBXML2
#error HAVE_LIBXML2 defined but compiling rapidxml_loader.cpp!
#endif
// mapnik
#include <mapnik/xml_loader.hpp>
#include <boost/property_tree/detail/xml_parser_read_rapidxml.hpp>
#include <mapnik/xml_node.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/algorithm/string/trim.hpp>
// stl
#include <iostream>
#include <fstream>
using namespace std;
namespace rapidxml = boost::property_tree::detail::rapidxml;
namespace mapnik
{
class rapidxml_loader : boost::noncopyable
{
public:
rapidxml_loader(const char *encoding = NULL) :
filename_()
{
}
~rapidxml_loader()
{
}
void load(const std::string & filename, xml_node &node)
{
filename_ = filename;
std::basic_ifstream<char> stream(filename.c_str());
if (!stream)
{
throw config_error("Could not load map file", 0, filename);
}
// TODO: stream.imbue(loc);
load(stream, node);
}
void load(std::basic_istream<char> &stream, xml_node &node)
{
stream.unsetf(std::ios::skipws);
std::vector<char> v(std::istreambuf_iterator<char>(stream.rdbuf()),
std::istreambuf_iterator<char>());
if (!stream.good())
{
throw config_error("Could not load map file", 0, filename_);
}
v.push_back(0); // zero-terminate
try
{
// Parse using appropriate flags
const int f_tws = rapidxml::parse_normalize_whitespace
| rapidxml::parse_trim_whitespace;
rapidxml::xml_document<> doc;
doc.parse<f_tws>(&v.front());
for (rapidxml::xml_node<char> *child = doc.first_node();
child; child = child->next_sibling())
{
populate_tree(child, node);
}
}
catch (rapidxml::parse_error &e)
{
long line = static_cast<long>(
std::count(&v.front(), e.where<char>(), '\n') + 1);
throw config_error(e.what(), line, filename_);
}
}
void load_string(const std::string & buffer, xml_node &node, std::string const & base_path )
{
// if (!base_path.empty())
// {
// boost::filesystem::path path(base_path);
// if (!boost::filesystem::exists(path)) {
// throw config_error(string("Could not locate base_path '") +
// base_path + "': file or directory does not exist");
// }
// }
load(buffer, node);
}
private:
void populate_tree(rapidxml::xml_node<char> *cur_node, xml_node &node)
{
switch (cur_node->type())
{
case rapidxml::node_element:
{
xml_node &new_node = node.add_child((char *)cur_node->name(), 0, false);
// Copy attributes
for (rapidxml::xml_attribute<char> *attr = cur_node->first_attribute();
attr; attr = attr->next_attribute())
{
new_node.add_attribute(attr->name(), attr->value());
}
// Copy children
for (rapidxml::xml_node<char> *child = cur_node->first_node();
child; child = child->next_sibling())
{
populate_tree(child, new_node);
}
}
break;
// Data nodes
case rapidxml::node_data:
case rapidxml::node_cdata:
{
std::string trimmed = boost::algorithm::trim_copy(std::string(cur_node->value()));
if (trimmed.empty()) break; //Don't add empty text nodes
node.add_child(trimmed, 0, true);
}
break;
default:
break;
}
}
private:
std::string filename_;
};
void read_xml(std::string const & filename, xml_node &node)
{
rapidxml_loader loader;
loader.load(filename, node);
}
void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path)
{
rapidxml_loader loader;
loader.load_string(str, node, base_path);
}
} // end of namespace mapnik

View file

@ -24,6 +24,7 @@
#include <mapnik/svg/svg_parser.hpp>
#include <mapnik/svg/svg_path_parser.hpp>
#include <mapnik/config_error.hpp>
#include "agg_ellipse.h"
#include "agg_rounded_rect.h"

View file

@ -20,9 +20,14 @@
*
*****************************************************************************/
//mapnik
#include <mapnik/text_placements/list.hpp>
#include <mapnik/xml_node.hpp>
//boost
#include <boost/make_shared.hpp>
namespace mapnik
{
@ -58,8 +63,7 @@ text_symbolizer_properties & text_placements_list::get(unsigned i)
text_placement_info_ptr text_placements_list::get_placement_info(double scale_factor) const
{
return text_placement_info_ptr(
boost::make_shared<text_placement_info_list>(this, scale_factor));
return boost::make_shared<text_placement_info_list>(this, scale_factor);
}
text_placements_list::text_placements_list() : text_placements(), list_(0)
@ -83,20 +87,19 @@ unsigned text_placements_list::size() const
return list_.size();
}
text_placements_ptr text_placements_list::from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets)
text_placements_ptr text_placements_list::from_xml(xml_node const &xml, fontset_map const & fontsets)
{
using boost::property_tree::ptree;
text_placements_list *list = new text_placements_list;
text_placements_ptr ptr = text_placements_ptr(list);
list->defaults.from_xml(xml, fontsets);
ptree::const_iterator itr = xml.begin();
ptree::const_iterator end = xml.end();
xml_node::const_iterator itr = xml.begin();
xml_node::const_iterator end = xml.end();
for( ;itr != end; ++itr)
{
if ((itr->first.find('<') != std::string::npos) || (itr->first != "Placement")) continue;
//TODO: ensure_attrs(symIter->second, "TextSymbolizer/Placement", s_common.str());
if (itr->is_text() || !itr->is("Placement")) continue;
text_symbolizer_properties &p = list->add();
p.from_xml(itr->second, fontsets);
p.from_xml(*itr, fontsets);
//TODO: if (strict_ &&
// !p.format.fontset.size())
// ensure_font_face(p.format.face_name);

View file

@ -24,6 +24,7 @@
#include <mapnik/text_placements/simple.hpp>
#include <mapnik/text_placements/list.hpp>
#include <mapnik/text_placements/dummy.hpp>
#include <mapnik/config_error.hpp>
namespace mapnik
{
@ -46,10 +47,10 @@ void registry::register_name(std::string name, from_xml_function_ptr ptr, bool o
}
}
text_placements_ptr registry::from_xml(std::string name, const boost::property_tree::ptree &xml, fontset_map const& fontsets)
text_placements_ptr registry::from_xml(std::string name, xml_node const& xml, fontset_map const& fontsets)
{
std::map<std::string, from_xml_function_ptr>::const_iterator itr = map_.find(name);
if (itr == map_.end()) throw config_error("Unknown placement-type '" + name + "'");
if (itr == map_.end()) throw config_error("Unknown placement-type '" + name + "'", xml);
return itr->second(xml, fontsets);
}
} //ns formatting

View file

@ -23,6 +23,7 @@
// mapnik
#include <mapnik/text_placements/simple.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/xml_node.hpp>
// boost
#include <boost/spirit/include/qi.hpp>
@ -102,8 +103,7 @@ bool text_placement_info_simple::next_position_only()
text_placement_info_ptr text_placements_simple::get_placement_info(
double scale_factor) const
{
return text_placement_info_ptr(
boost::make_shared<text_placement_info_simple>(this, scale_factor));
return boost::make_shared<text_placement_info_simple>(this, scale_factor);
}
/** Position string: [POS][SIZE]
@ -144,10 +144,12 @@ void text_placements_simple::set_positions(std::string positions)
(direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> qi::float_[push_back(phoenix::ref(text_sizes_), _1)]),
space
);
if (first != last) {
if (first != last)
{
std::cerr << "WARNING: Could not parse text_placement_simple placement string ('" << positions << "').\n";
}
if (direction_.size() == 0) {
if (direction_.size() == 0)
{
std::cerr << "WARNING: text_placements_simple with no valid placements! ('"<< positions<<"')\n";
}
}
@ -167,10 +169,10 @@ std::string text_placements_simple::get_positions()
return positions_; //TODO: Build string from data in direction_ and text_sizes_
}
text_placements_ptr text_placements_simple::from_xml(boost::property_tree::ptree const &xml, fontset_map const & fontsets)
text_placements_ptr text_placements_simple::from_xml(xml_node const &xml, fontset_map const & fontsets)
{
text_placements_ptr ptr = boost::make_shared<text_placements_simple>(
get_attr<std::string>(xml, "placements", "X"));
xml.get_attr<std::string>("placements", "X"));
ptr->defaults.from_xml(xml, fontsets);
return ptr;
}

View file

@ -25,6 +25,8 @@
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/formatting/text.hpp>
#include <mapnik/xml_node.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/make_shared.hpp>
@ -79,45 +81,45 @@ 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)
void text_symbolizer_properties::from_xml(xml_node const &sym, fontset_map const & fontsets)
{
optional<label_placement_e> placement_ = get_opt_attr<label_placement_e>(sym, "placement");
optional<label_placement_e> placement_ = sym.get_opt_attr<label_placement_e>("placement");
if (placement_) label_placement = *placement_;
optional<vertical_alignment_e> valign_ = get_opt_attr<vertical_alignment_e>(sym, "vertical-alignment");
optional<vertical_alignment_e> valign_ = sym.get_opt_attr<vertical_alignment_e>("vertical-alignment");
if (valign_) valign = *valign_;
optional<unsigned> text_ratio_ = get_opt_attr<unsigned>(sym, "text-ratio");
optional<unsigned> text_ratio_ = sym.get_opt_attr<unsigned>("text-ratio");
if (text_ratio_) text_ratio = *text_ratio_;
optional<unsigned> wrap_width_ = get_opt_attr<unsigned>(sym, "wrap-width");
optional<unsigned> wrap_width_ = sym.get_opt_attr<unsigned>("wrap-width");
if (wrap_width_) wrap_width = *wrap_width_;
optional<unsigned> label_position_tolerance_ = get_opt_attr<unsigned>(sym, "label-position-tolerance");
optional<unsigned> label_position_tolerance_ = sym.get_opt_attr<unsigned>("label-position-tolerance");
if (label_position_tolerance_) label_position_tolerance = *label_position_tolerance_;
optional<unsigned> spacing_ = get_opt_attr<unsigned>(sym, "spacing");
optional<unsigned> spacing_ = sym.get_opt_attr<unsigned>("spacing");
if (spacing_) label_spacing = *spacing_;
optional<unsigned> minimum_distance_ = get_opt_attr<unsigned>(sym, "minimum-distance");
optional<unsigned> minimum_distance_ = sym.get_opt_attr<unsigned>("minimum-distance");
if (minimum_distance_) minimum_distance = *minimum_distance_;
optional<unsigned> min_padding_ = get_opt_attr<unsigned>(sym, "minimum-padding");
optional<unsigned> min_padding_ = sym.get_opt_attr<unsigned>("minimum-padding");
if (min_padding_) minimum_padding = *min_padding_;
optional<unsigned> min_path_length_ = get_opt_attr<unsigned>(sym, "minimum-path-length");
optional<unsigned> min_path_length_ = sym.get_opt_attr<unsigned>("minimum-path-length");
if (min_path_length_) minimum_path_length = *min_path_length_;
optional<boolean> avoid_edges_ = get_opt_attr<boolean>(sym, "avoid-edges");
optional<boolean> avoid_edges_ = sym.get_opt_attr<boolean>("avoid-edges");
if (avoid_edges_) avoid_edges = *avoid_edges_;
optional<boolean> allow_overlap_ = get_opt_attr<boolean>(sym, "allow-overlap");
optional<boolean> allow_overlap_ = sym.get_opt_attr<boolean>("allow-overlap");
if (allow_overlap_) allow_overlap = *allow_overlap_;
optional<horizontal_alignment_e> halign_ = get_opt_attr<horizontal_alignment_e>(sym, "horizontal-alignment");
optional<horizontal_alignment_e> halign_ = sym.get_opt_attr<horizontal_alignment_e>("horizontal-alignment");
if (halign_) halign = *halign_;
optional<justify_alignment_e> jalign_ = get_opt_attr<justify_alignment_e>(sym, "justify-alignment");
optional<justify_alignment_e> jalign_ = sym.get_opt_attr<justify_alignment_e>("justify-alignment");
if (jalign_) jalign = *jalign_;
/* Attributes needing special care */
optional<std::string> orientation_ = get_opt_attr<std::string>(sym, "orientation");
optional<std::string> orientation_ = sym.get_opt_attr<std::string>("orientation");
if (orientation_) orientation = parse_expression(*orientation_, "utf8");
optional<double> dx = get_opt_attr<double>(sym, "dx");
optional<double> dx = sym.get_opt_attr<double>("dx");
if (dx) displacement.first = *dx;
optional<double> dy = get_opt_attr<double>(sym, "dy");
optional<double> dy = sym.get_opt_attr<double>("dy");
if (dy) displacement.second = *dy;
optional<double> max_char_angle_delta_ = get_opt_attr<double>(sym, "max-char-angle-delta");
optional<double> max_char_angle_delta_ = sym.get_opt_attr<double>("max-char-angle-delta");
if (max_char_angle_delta_) max_char_angle_delta=(*max_char_angle_delta_)*(M_PI/180);
optional<std::string> name_ = get_opt_attr<std::string>(sym, "name");
optional<std::string> name_ = sym.get_opt_attr<std::string>("name");
if (name_) {
std::clog << "### WARNING: Using 'name' in TextSymbolizer/ShieldSymbolizer is deprecated!\n";
set_old_style_expression(parse_expression(*name_, "utf8"));
@ -241,34 +243,34 @@ char_properties::char_properties() :
}
void char_properties::from_xml(boost::property_tree::ptree const &sym, fontset_map const & fontsets)
void char_properties::from_xml(xml_node const& sym, fontset_map const& fontsets)
{
optional<double> text_size_ = get_opt_attr<double>(sym, "size");
optional<double> text_size_ = sym.get_opt_attr<double>("size");
if (text_size_) text_size = *text_size_;
optional<double> character_spacing_ = get_opt_attr<double>(sym, "character-spacing");
optional<double> character_spacing_ = sym.get_opt_attr<double>("character-spacing");
if (character_spacing_) character_spacing = *character_spacing_;
optional<color> fill_ = get_opt_attr<color>(sym, "fill");
optional<color> fill_ = sym.get_opt_attr<color>("fill");
if (fill_) fill = *fill_;
optional<color> halo_fill_ = get_opt_attr<color>(sym, "halo-fill");
optional<color> halo_fill_ = sym.get_opt_attr<color>("halo-fill");
if (halo_fill_) halo_fill = *halo_fill_;
optional<double> halo_radius_ = get_opt_attr<double>(sym, "halo-radius");
optional<double> halo_radius_ = sym.get_opt_attr<double>("halo-radius");
if (halo_radius_) halo_radius = *halo_radius_;
optional<boolean> wrap_before_ = get_opt_attr<boolean>(sym, "wrap-before");
optional<boolean> wrap_before_ = sym.get_opt_attr<boolean>("wrap-before");
if (wrap_before_) wrap_before = *wrap_before_;
optional<text_transform_e> tconvert_ = get_opt_attr<text_transform_e>(sym, "text-transform");
optional<text_transform_e> tconvert_ = sym.get_opt_attr<text_transform_e>("text-transform");
if (tconvert_) text_transform = *tconvert_;
optional<double> line_spacing_ = get_opt_attr<double>(sym, "line-spacing");
optional<double> line_spacing_ = sym.get_opt_attr<double>("line-spacing");
if (line_spacing_) line_spacing = *line_spacing_;
optional<double> opacity_ = get_opt_attr<double>(sym, "opacity");
optional<double> opacity_ = sym.get_opt_attr<double>("opacity");
if (opacity_) text_opacity = *opacity_;
optional<std::string> wrap_char_ = get_opt_attr<std::string>(sym, "wrap-character");
optional<std::string> wrap_char_ = sym.get_opt_attr<std::string>("wrap-character");
if (wrap_char_ && (*wrap_char_).size() > 0) wrap_char = ((*wrap_char_)[0]);
optional<std::string> face_name_ = get_opt_attr<std::string>(sym, "face-name");
optional<std::string> face_name_ = sym.get_opt_attr<std::string>("face-name");
if (face_name_)
{
face_name = *face_name_;
}
optional<std::string> fontset_name_ = get_opt_attr<std::string>(sym, "fontset-name");
optional<std::string> fontset_name_ = sym.get_opt_attr<std::string>("fontset-name");
if (fontset_name_) {
std::map<std::string,font_set>::const_iterator itr = fontsets.find(*fontset_name_);
if (itr != fontsets.end())
@ -277,16 +279,16 @@ void char_properties::from_xml(boost::property_tree::ptree const &sym, fontset_m
}
else
{
throw config_error("Unable to find any fontset named '" + *fontset_name_ + "'");
throw config_error("Unable to find any fontset named '" + *fontset_name_ + "'", sym);
}
}
if (!face_name.empty() && !fontset.get_name().empty())
{
throw config_error(std::string("Can't have both face-name and fontset-name"));
throw config_error("Can't have both face-name and fontset-name", sym);
}
if (face_name.empty() && fontset.get_name().empty())
{
throw config_error(std::string("Must have face-name or fontset-name"));
throw config_error("Must have face-name or fontset-name", sym);
}
}

483
src/xml_tree.cpp Normal file
View file

@ -0,0 +1,483 @@
/*****************************************************************************
*
* 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 <mapnik/xml_tree.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/gamma_method.hpp>
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/config_error.hpp>
//boost
#include <boost/lexical_cast.hpp>
namespace mapnik
{
template <typename T>
inline boost::optional<T> fast_cast(xml_tree const& tree, std::string const& value)
{
try
{
return boost::lexical_cast<T>(value);
}
catch (boost::bad_lexical_cast const& ex)
{
return boost::optional<T>();
}
}
template <>
inline boost::optional<int> fast_cast(xml_tree const& tree, std::string const& value)
{
int result;
if (mapnik::conversions::string2int(value, result))
return boost::optional<int>(result);
return boost::optional<int>();
}
template <>
inline boost::optional<double> fast_cast(xml_tree const& tree, std::string const& value)
{
double result;
if (mapnik::conversions::string2double(value, result))
return boost::optional<double>(result);
return boost::optional<double>();
}
template <>
inline boost::optional<float> fast_cast(xml_tree const& tree, std::string const& value)
{
float result;
if (mapnik::conversions::string2float(value, result))
return boost::optional<float>(result);
return boost::optional<float>();
}
template <>
inline boost::optional<std::string> fast_cast(xml_tree const& tree, std::string const& value)
{
return value;
}
template <>
inline boost::optional<color> fast_cast(xml_tree const& tree, std::string const& value)
{
mapnik::color c;
if (mapnik::color_factory::parse_from_string(c, value, tree.color_grammar))
{
return c;
}
else
{
throw config_error("Failed to parse color '"+value+"'");
}
}
template <>
inline boost::optional<expression_ptr> fast_cast(xml_tree const& tree, std::string const& value)
{
expression_ptr expr(boost::make_shared<expr_node>(true));
if (expression_factory::parse_from_string(expr, value, tree.expr_grammar))
{
return expr;
} else
{
throw mapnik::config_error("Failed to parse expression '" + value + "'");
}
}
/****************************************************************************/
class boolean;
template <typename T>
struct name_trait
{
static std::string name()
{
return "<unknown>";
}
// missing name_trait for type ...
// if you get here you are probably using a new type
// in the XML file. Just add a name trait for the new
// type below.
BOOST_STATIC_ASSERT( sizeof(T) == 0 );
};
#define DEFINE_NAME_TRAIT( type, type_name ) \
template <> \
struct name_trait<type> \
{ \
static std::string name() { return std::string("type ") + type_name; } \
};
DEFINE_NAME_TRAIT( double, "double")
DEFINE_NAME_TRAIT( float, "float")
DEFINE_NAME_TRAIT( unsigned, "unsigned")
DEFINE_NAME_TRAIT( boolean, "boolean")
DEFINE_NAME_TRAIT( int, "integer" )
DEFINE_NAME_TRAIT( std::string, "string" )
DEFINE_NAME_TRAIT( color, "color" )
DEFINE_NAME_TRAIT(expression_ptr, "expression_ptr" )
template <typename ENUM, int MAX>
struct name_trait< mapnik::enumeration<ENUM, MAX> >
{
typedef enumeration<ENUM, MAX> Enum;
static std::string name()
{
std::string value_list("one of [");
for (unsigned i = 0; i < Enum::MAX; ++i)
{
value_list += Enum::get_string( i );
if ( i + 1 < Enum::MAX ) value_list += ", ";
}
value_list += "]";
return value_list;
}
};
/****************************************************************************/
xml_tree::xml_tree(std::string const& encoding)
: node_(*this, "<root>"),
file_(),
tr_(encoding),
color_grammar(),
expr_grammar(tr_)
{
node_.set_processed(true); //root node is always processed
}
void xml_tree::set_filename(std::string fn)
{
file_ = fn;
}
std::string const& xml_tree::filename() const
{
return file_;
}
xml_node &xml_tree::root()
{
return node_;
}
/****************************************************************************/
xml_attribute::xml_attribute(std::string const& value_)
: value(value_), processed(false)
{
}
/****************************************************************************/
node_not_found::node_not_found(std::string node_name)
: node_name_(node_name)
{
}
const char* node_not_found::what() const throw()
{
return ("Node "+node_name_+ "not found").c_str();
}
node_not_found::~node_not_found() throw()
{
}
attribute_not_found::attribute_not_found(
std::string const& node_name,
std::string const& attribute_name)
:
node_name_(node_name),
attribute_name_(attribute_name)
{
}
const char* attribute_not_found::what() const throw()
{
return ("Attribute '" + attribute_name_ +"' not found in node '"+node_name_+ "'").c_str();
}
attribute_not_found::~attribute_not_found() throw()
{
}
more_than_one_child::more_than_one_child(std::string const& node_name)
: node_name_(node_name)
{
}
const char* more_than_one_child::what() const throw()
{
return ("More than one child node in node '" + node_name_ +"'").c_str();
}
more_than_one_child::~more_than_one_child() throw()
{
}
/****************************************************************************/
xml_node::xml_node(xml_tree &tree, std::string name, unsigned line, bool text_node)
: tree_(tree),
name_(name),
text_node_(text_node),
line_(line),
processed_(false)
{
}
std::string xml_node::xml_text = "<xmltext>";
std::string const& xml_node::name() const
{
if (!text_node_)
return name_;
else
return xml_text;
}
std::string const& xml_node::text() const
{
if (text_node_)
{
processed_ = true;
return name_;
} else
{
throw config_error("text() called on non-text node", *this);
}
}
std::string const& xml_node::filename() const
{
return tree_.filename();
}
bool xml_node::is_text() const
{
return text_node_;
}
bool xml_node::is(std::string const& name) const
{
if (name_ == name)
{
processed_ = true;
return true;
}
return false;
}
xml_node &xml_node::add_child(std::string const& name, unsigned line, bool text_node)
{
children_.push_back(xml_node(tree_, name, line, text_node));
return children_.back();
}
void xml_node::add_attribute(std::string const& name, std::string const& value)
{
attributes_.insert(std::make_pair(name,xml_attribute(value)));
}
xml_node::attribute_map const& xml_node::get_attributes() const
{
return attributes_;
}
void xml_node::set_processed(bool processed) const
{
processed_ = processed;
}
bool xml_node::processed() const
{
return processed_;
}
xml_node::const_iterator xml_node::begin() const
{
return children_.begin();
}
xml_node::const_iterator xml_node::end() const
{
return children_.end();
}
xml_node & xml_node::get_child(std::string const& name)
{
std::list<xml_node>::iterator itr = children_.begin();
std::list<xml_node>::iterator end = children_.end();
for (; itr != end; itr++)
{
if (!(itr->text_node_) && itr->name_ == name)
{
itr->set_processed(true);
return *itr;
}
}
throw node_not_found(name);
}
xml_node const& xml_node::get_child(std::string const& name) const
{
xml_node const* node = get_opt_child(name);
if (!node) throw node_not_found(name);
return *node;
}
xml_node const* xml_node::get_opt_child(std::string const& name) const
{
const_iterator itr = children_.begin();
const_iterator end = children_.end();
for (; itr != end; itr++)
{
if (!(itr->text_node_) && itr->name_ == name)
{
itr->set_processed(true);
return &(*itr);
}
}
return 0;
}
bool xml_node::has_child(std::string const& name) const
{
return get_opt_child(name) != 0;
}
template <typename T>
boost::optional<T> xml_node::get_opt_attr(std::string const& name) const
{
std::map<std::string, xml_attribute>::const_iterator itr = attributes_.find(name);
if (itr == attributes_.end()) return boost::optional<T>();
itr->second.processed = true;
boost::optional<T> result = fast_cast<T>(tree_, itr->second.value);
if (!result)
{
throw config_error(std::string("Failed to parse attribute '") +
name + "'. Expected " + name_trait<T>::name() +
" but got '" + itr->second.value + "'", *this);
}
return result;
}
template <typename T>
T xml_node::get_attr(std::string const& name, T const& default_value) const
{
boost::optional<T> value = get_opt_attr<T>(name);
if (value) return *value;
return default_value;
}
template <typename T>
T xml_node::get_attr(std::string const& name) const
{
boost::optional<T> value = get_opt_attr<T>(name);
if (value) return *value;
throw attribute_not_found(name_, name);
}
std::string xml_node::get_text() const
{
if (children_.size() == 0)
{
return "";
}
if (children_.size() == 1)
{
return children_.front().text();
}
throw more_than_one_child(name_);
}
template <typename T>
T xml_node::get_value() const
{
boost::optional<T> result = fast_cast<T>(tree_, get_text());
if (!result)
{
throw config_error(std::string("Failed to parse value. Expected ")
+ name_trait<T>::name() +
" but got '" + get_text() + "'", *this);
}
return *result;
}
unsigned xml_node::line() const
{
return line_;
}
#define compile_get_opt_attr(T) template boost::optional<T> xml_node::get_opt_attr<T>(std::string const&) const
#define compile_get_attr(T) template T xml_node::get_attr<T>(std::string const&) const; template T xml_node::get_attr<T>(std::string const&, T const&) const
#define compile_get_value(T) template T xml_node::get_value<T>() const
compile_get_opt_attr(boolean);
compile_get_opt_attr(std::string);
compile_get_opt_attr(unsigned);
compile_get_opt_attr(float);
compile_get_opt_attr(double);
compile_get_opt_attr(color);
compile_get_opt_attr(gamma_method_e);
compile_get_opt_attr(line_rasterizer_e);
compile_get_opt_attr(line_join_e);
compile_get_opt_attr(line_cap_e);
compile_get_opt_attr(text_transform_e);
compile_get_opt_attr(label_placement_e);
compile_get_opt_attr(vertical_alignment_e);
compile_get_opt_attr(horizontal_alignment_e);
compile_get_opt_attr(justify_alignment_e);
compile_get_opt_attr(expression_ptr);
compile_get_attr(std::string);
compile_get_attr(filter_mode_e);
compile_get_attr(point_placement_e);
compile_get_attr(marker_placement_e);
compile_get_attr(marker_type_e);
compile_get_attr(pattern_alignment_e);
compile_get_attr(line_rasterizer_e);
compile_get_attr(colorizer_mode);
compile_get_attr(double);
compile_get_value(int);
compile_get_value(double);
compile_get_value(expression_ptr);
} //ns mapnik

View file

@ -230,13 +230,8 @@ def test_map_init_from_string():
map_string = '''<Map background-color="steelblue" base="./" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="My Style">
<Rule>
<PolygonSymbolizer>
<CssParameter name="fill">#f2eff9</CssParameter>
</PolygonSymbolizer>
<LineSymbolizer>
<CssParameter name="stroke">rgb(50%,50%,50%)</CssParameter>
<CssParameter name="stroke-width">0.1</CssParameter>
</LineSymbolizer>
<PolygonSymbolizer fill="#f2eff9"/>
<LineSymbolizer stroke="rgb(50%,50%,50%)" stroke-width="0.1"/>
</Rule>
</Style>
<Layer name="boundaries">

View file

@ -1,4 +1,4 @@
import math, operator
#import math, operator
import Image
import sys
@ -27,6 +27,10 @@ def compare(fn1, fn2):
return -1
diff = 0
pixels = im1.size[0] * im1.size[1]
delta_pixels = im2.size[0] * im2.size[1] - pixels
if delta_pixels != 0:
errors.append((fn1, delta_pixels))
return delta_pixels
im1 = im1.getdata()
im2 = im2.getdata()
for i in range(3, pixels - 1, 3):

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<Map background-color="green" srs="+proj=latlong +datum=WGS84">
<Map background-color="green" srs="+proj=latlong +datum=WGS84" minimum-version="2.0.0">
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
<StyleName>My Style</StyleName>

View file

@ -50,7 +50,7 @@ def render(filename, width, height=100):
return m
if len(sys.argv) == 2:
files = [(sys.argv[1], 500)]
files = [(sys.argv[1], (500, 500))]
elif len(sys.argv) > 2:
files = [sys.argv[1:]]