Compare commits

...

40 commits

Author SHA1 Message Date
lightmare
89238f9559 Merge pull request #3465 from estadtherr/bypass_unconfigured_plugins
skip tests in save_map_test.py that use unavailable input plugins
2016-08-05 14:39:44 +02:00
Eric Stadtherr
7902591ac0 propagate unavailable input plugin check to other test cases 2016-08-02 12:55:53 -06:00
Eric Stadtherr
7f506ff5cf skip tests in save_map_test.py that use unavailable input plugins 2016-07-08 13:19:15 -06:00
Dane Springmeyer
e0616bd5ab tests for text 'orientation' property - refs mapnik/mapnik-support#34 2015-02-17 11:30:28 -08:00
Dane Springmeyer
0639d54db4 fix compile error with boost 1.49 - closes #2467 2015-01-08 20:57:33 -08:00
Dane Springmeyer
1b9ba41f96 travis updates 2014-10-03 17:49:31 -07:00
Dane Springmeyer
d8fd967c99 also test with gcc 2014-10-03 17:45:23 -07:00
Dane Springmeyer
1ffa0f2b94 travis: port fixes from 2.3.x branch 2014-09-22 23:39:06 -07:00
Dane Springmeyer
6a3b0634fe backport geojson plugin fixes from master - refs #2319 and 2367
Conflicts:
	plugins/input/geojson/geojson_datasource.cpp
2014-09-22 23:35:39 -07:00
Dane Springmeyer
29b717f9f6 adapt to new rtree interface in boost geometry >= 1.56 - refs #2367
Conflicts:
	plugins/input/geojson/geojson_datasource.cpp
2014-09-22 23:24:36 -07:00
Dane Springmeyer
8c4a5d53d3 boost 1.56 support 2014-09-22 23:22:05 -07:00
Dane Springmeyer
9c947232e9 adapt to ptree change in boost 1.56 - closes #2365 2014-09-22 14:28:41 -07:00
Dane Springmeyer
5dd79e88c0 fix css_grammar compile error with boost 1.56 - close #2366
Conflicts:
	SConstruct
2014-09-22 14:28:37 -07:00
Dane Springmeyer
08f651289d fix compile with boost 1.56 - refs #2368 2014-09-22 14:26:48 -07:00
Dane Springmeyer
3fc6e1282f fix skipping of empty text nodes in rapidxml parser (matches libxml2) - closes #2253 2014-06-17 21:48:10 -07:00
Dane Springmeyer
9e03ace209 rapidxml: validate closing tags like libxml2 parser (no overhead measurable seen) 2014-06-17 21:48:02 -07:00
Dane Springmeyer
ec089dcaea scons: fix curl linking when curl is static 2014-06-17 21:46:38 -07:00
Dane Springmeyer
f0821d897f improvements to GDAL 2.x handling - refs #2259 amends cbdd112223 2014-06-17 21:40:15 -07:00
Dane Springmeyer
f68291c5b4 support for GDAL >= 2.0 in ogr plugin - refs #2259 2014-06-17 21:40:02 -07:00
Dane Springmeyer
d269ce3bb3 scons: fix parsing of gdal libs when building against mapnik-packaging 2014-06-17 21:34:57 -07:00
Dane Springmeyer
8e8794790a Merge pull request #2192 from strk/2.2.x-no-terminate-pgis-dtor
Do not throw in postgis_datasource destruction if backend is down
2014-04-04 18:20:52 -07:00
Sandro Santilli
189d86ddd7 Do not throw in postgis_datasource destruction if backend is down
... and persist_connections is true!
Closes #2191
2014-03-26 15:32:09 +01:00
Dane Springmeyer
e3a456f846 postgis: use max float for no-op bbox token - closes #2158 2014-03-13 15:20:35 -07:00
Dane Springmeyer
c32b9b6788 Merge pull request #2175 from strk/2.2.x-segfault-on-execute
Do not attempt to PQclear a null PQresult*
2014-03-09 21:04:58 -07:00
Dane Springmeyer
44ef0324f0 Merge pull request #2174 from strk/2.2.x-handle-bad-connection
Make sure status() returns a message also on bad connection
2014-03-09 21:02:11 -07:00
Dane Springmeyer
d4662005fe Merge pull request #2178 from olt/proj48-double-free-fix
prevent double-free in mapnik::projection
2014-03-08 19:44:57 -08:00
Oliver Tonnhofer
5be238b2cd prevent double-free in mapnik::projection
A double-free can happen when init_proj4 is called outside of the
constructor (for projections with defer_proj_init=true) and when that
call fails. In this case proj_ctx_ is not set to NULL and then freed
again in the destructor. Set to null to avoid second pj_ctx_free call.

See #2170
2014-03-06 10:25:57 +01:00
Sandro Santilli
2b2aead8b3 Do not attempt to PQclear a null PQresult* 2014-03-06 09:59:18 +01:00
Sandro Santilli
5edc39555d Make sure status() returns a message also on bad connection
Closes #2173.
2014-03-06 09:56:13 +01:00
Dane Springmeyer
449e83fbf2 fix jpeg reading regression after #1805 - closes #2123 (patch from @clundgren) 2014-02-07 11:23:29 -08:00
Dane Springmeyer
482c4eb215 add missing attribute collector for markers symbolizer path expression - closes #1952 2013-11-22 18:02:21 -08:00
Dane Springmeyer
a295eea843 improve travis for 2.2.x branch 2013-11-17 15:43:29 -08:00
Dane Springmeyer
f9a09be2b1 fix osx/libc++/boost-1.55 compile error - refs #1973 2013-11-17 15:29:30 -08:00
Dane Springmeyer
09c919b3bd scons: avoid pollution of global compiler flags from python plugin - closes #2060 2013-10-31 13:38:55 -07:00
Dane Springmeyer
fe06c959c6 v2.2.x branch should declare itself as in development 2013-10-07 16:35:45 -07:00
Dane Springmeyer
b821c67cc5 Merge pull request #1958 from strk/2.2.x-fontset_runtime_test
Fix test expectance after adding layer name in error messages
2013-07-23 11:30:10 -07:00
Sandro Santilli
4b988a2c20 Fix test expectance after adding layer name in error messages 2013-07-23 20:22:39 +02:00
Artem Pavlenko
cde04dba4a Merge pull request #1936 from strk/2.2.x-layername-in-errormsg
2.2.x layername in errormsg
2013-07-02 13:08:58 -07:00
Sandro Santilli
dc7b943873 Comply to mapnik style 2013-06-26 11:20:35 +02:00
Sandro Santilli
ec2f03a6e0 Include layer name in error message from AGG renderer 2013-06-25 16:20:17 +02:00
46 changed files with 643 additions and 179 deletions

View file

@ -1,21 +1,44 @@
language: cpp language: cpp
compiler: clang compiler:
- clang
- gcc
env:
matrix:
- XMLPARSER="libxml2" DEBUG=False
- XMLPARSER="libxml2" DEBUG=True
- XMLPARSER="ptree" DEBUG=True
# travis + ubuntugis with gdal and postggis leads to many potential dead-end conflicts
# the below is thanks to https://github.com/CartoDB/Windshaft/blob/d82fe08b32fc7907bbe907ab290f8a082215ae26/.travis.yml#L1
before_install: before_install:
- echo 'yes' | sudo add-apt-repository ppa:mapnik/boost - export PGUSER=postgres
- sudo apt-get update -qq - sudo mv /etc/apt/sources.list.d/pgdg-source.list* /tmp
- sudo apt-get install -qq libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev - sudo apt-get -qq purge postgis* postgresql*
- sudo apt-add-repository -y ppa:cartodb/postgresql-9.3
- sudo apt-add-repository -y ppa:cartodb/gis
- sudo rm -Rf /var/lib/postgresql /etc/postgresql
- sudo apt-get update -qq
- sudo apt-get install -q libharfbuzz-dev postgresql-9.3-postgis-2.1 postgresql-contrib-9.3 gdal-bin libgdal-dev
- echo -e "local\tall\tall\ttrust\nhost\tall\tall\t127.0.0.1/32\ttrust\nhost\tall\tall\t::1/128\ttrust" |sudo tee /etc/postgresql/9.3/main/pg_hba.conf
- sudo service postgresql restart
install:
- sudo apt-get install -y libboost-python1.48-dev libboost-thread1.48-dev libboost-filesystem1.48-dev libboost-regex1.48-dev libboost-program-options1.48-dev
- sudo apt-get install -y make valgrind python-nose libicu-dev libproj-dev libcairo-dev python-cairo-dev libcairo-dev python-cairo-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libsqlite3-dev
# multi-face ttc font: https://github.com/mapnik/mapnik/issues/2274
- sudo apt-get install ttf-wqy-microhei
before_script:
- psql -U postgres -c 'create database template_postgis'
- psql -U postgres -c 'create extension postgis' -d template_postgis
- if [[ "${CXX}" == 'g++' ]]; then export JOBS=2; fi;
- if [[ "${CXX}" == 'clang++' ]]; then export JOBS=4; fi;
- if [[ "${DEBUG}" == True ]]; then export JOBS=$((JOBS/2)); fi;
script: script:
- ./configure DEMO=False BINDINGS='python' CPP_TESTS=False CAIRO=False INPUT_PLUGINS='' OPTIMIZATION=1 FAST=True && JOBS=2 make - ./configure CXX=${CXX} CC=${CC} XML_PARSER=$XML_PARSER DEBUG=${DEBUG} DEMO=True BENCHMARK=False BINDINGS='python' CPP_TESTS=True CAIRO=True FAST=True
- make
branches: - make test-local
only: - source localize.sh && make grind
- master
notifications:
irc:
channels:
- "irc.freenode.org#mapnik"
use_notice: true

View file

@ -610,6 +610,10 @@ def get_pkg_lib(context, config, lib):
if ret: if ret:
try: try:
value = call(cmd,silent=True) value = call(cmd,silent=True)
if ' ' in value:
parts = value.split(' ')
if len(parts) > 1:
value = parts[1]
libnames = re.findall(libpattern,value) libnames = re.findall(libpattern,value)
if libnames: if libnames:
libname = libnames[0] libname = libnames[0]
@ -1427,7 +1431,7 @@ if not preconfigured:
env["CAIRO_ALL_LIBS"] = ['cairo'] env["CAIRO_ALL_LIBS"] = ['cairo']
if env['RUNTIME_LINK'] == 'static': if env['RUNTIME_LINK'] == 'static':
env["CAIRO_ALL_LIBS"].extend( env["CAIRO_ALL_LIBS"].extend(
['pixman-1','expat','fontconfig','iconv'] ['pixman-1','expat','iconv']
) )
# todo - run actual checkLib? # todo - run actual checkLib?
env['HAS_CAIRO'] = True env['HAS_CAIRO'] = True
@ -1619,6 +1623,15 @@ if not preconfigured:
debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG'] debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG']
ndebug_defines = ['-DNDEBUG'] ndebug_defines = ['-DNDEBUG']
boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
if boost_version_from_header > 53 or 'c++11' in env['CUSTOM_CXXFLAGS']:
env.Append(CPPDEFINES = '-DBOOST_SPIRIT_USE_PHOENIX_V3=1')
# - workaround boost gil channel_algorithm.hpp narrowing error
# TODO - remove when building against >= 1.55
# https://github.com/mapnik/mapnik/issues/1970
if 'clang++' in env['CXX']:
env.Append(CXXFLAGS = '-Wno-c++11-narrowing')
# Enable logging in debug mode (always) and release mode (when specified) # Enable logging in debug mode (always) and release mode (when specified)
if env['DEFAULT_LOG_SEVERITY']: if env['DEFAULT_LOG_SEVERITY']:
if env['DEFAULT_LOG_SEVERITY'] not in severities: if env['DEFAULT_LOG_SEVERITY'] not in severities:

View file

@ -194,7 +194,11 @@ struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node>
ListNodeWrap(object l) : formatting::list_node(), wrapper<formatting::list_node>() ListNodeWrap(object l) : formatting::list_node(), wrapper<formatting::list_node>()
{ {
stl_input_iterator<formatting::node_ptr> begin(l), end; stl_input_iterator<formatting::node_ptr> begin(l), end;
children_.insert(children_.end(), begin, end); while (begin != end)
{
children_.push_back(*begin);
++begin;
}
} }
/* TODO: Add constructor taking variable number of arguments. /* TODO: Add constructor taking variable number of arguments.

View file

@ -199,6 +199,11 @@ struct symbolizer_attributes : public boost::static_visitor<>
{ {
boost::apply_visitor(f_attr,*width_expr); boost::apply_visitor(f_attr,*width_expr);
} }
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform()); collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform()); collect_transform(sym.get_transform());
} }

View file

@ -125,7 +125,11 @@ struct alpha_conv_impl
struct hsl_conv_impl struct hsl_conv_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template<typename T>
#else
template<typename T0,typename T1, typename T2, typename T3> template<typename T0,typename T1, typename T2, typename T3>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -413,7 +417,11 @@ struct alpha_conv_impl
struct hsl_conv_impl struct hsl_conv_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template<typename T>
#else
template<typename T0,typename T1, typename T2, typename T3> template<typename T0,typename T1, typename T2, typename T3>
#endif
struct result struct result
{ {
typedef void type; typedef void type;

View file

@ -65,7 +65,11 @@ struct unicode_impl
struct regex_match_impl struct regex_match_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef expr_node type; typedef expr_node type;
@ -82,7 +86,11 @@ struct regex_match_impl
struct regex_replace_impl struct regex_replace_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0, typename T1, typename T2> template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef expr_node type; typedef expr_node type;

View file

@ -145,7 +145,7 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
multiplicative_expr = unary_expr [_val = _1] multiplicative_expr = unary_expr [_val = _1]
>> *( '*' >> unary_expr [_val *= _1] >> *( '*' >> unary_expr [_val *= _1]
| '/' >> unary_expr [_val /= _1] | '/' >> unary_expr [_val /= _1]
| '%' >> unary_expr [_val %= _1] | '%' >> unary_expr [_val %= construct<mapnik::expr_node>(_1)] //needed by clang++ with -std=c++11
| regex_match_expr[_val = regex_match_(_val, _1)] | regex_match_expr[_val = regex_match_(_val, _1)]
| regex_replace_expr(_val) [_val = _1] | regex_replace_expr(_val) [_val = _1]
) )

View file

@ -232,6 +232,7 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
int buffer_size, int buffer_size,
std::set<std::string>& names) std::set<std::string>& names)
{ {
try {
std::vector<std::string> const& style_names = lay.styles(); std::vector<std::string> const& style_names = lay.styles();
unsigned int num_styles = style_names.size(); unsigned int num_styles = style_names.size();
@ -548,6 +549,13 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
#endif #endif
p.end_layer_processing(lay); p.end_layer_processing(lay);
} catch (std::exception const& e) {
std::ostringstream m;
m << lay.name() << ": " << e.what();
throw std::runtime_error(m.str().c_str());
}
} }

View file

@ -66,6 +66,30 @@ public:
mapnik::transcoder const& tr_; mapnik::transcoder const& tr_;
}; };
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct put_property
{
typedef void result_type;
explicit put_property(mapnik::transcoder const& tr)
: tr_(tr) {}
template <typename T0,typename T1, typename T2>
result_type operator() (T0 & feature, T1 const& key, T2 const& val) const
{
feature.put_new(key, boost::apply_visitor(attribute_value_visitor(tr_),val));
}
mapnik::transcoder const& tr_;
};
struct extract_geometry
{
typedef boost::ptr_vector<mapnik::geometry_type>& result_type;
template <typename T>
result_type operator() (T & feature) const
{
return feature.paths();
}
};
#else
struct put_property struct put_property
{ {
template <typename T0,typename T1, typename T2> template <typename T0,typename T1, typename T2>
@ -100,6 +124,7 @@ struct extract_geometry
return feature.paths(); return feature.paths();
} }
}; };
#endif
template <typename Iterator, typename FeatureType> template <typename Iterator, typename FeatureType>
struct feature_grammar : struct feature_grammar :

View file

@ -38,11 +38,8 @@
#include <boost/spirit/include/phoenix_fusion.hpp> #include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_function.hpp> #include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp> #include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/fusion/include/boost_tuple.hpp> #include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/math/special_functions/trunc.hpp> // trunc to avoid needing C++11 #include <boost/math/special_functions/trunc.hpp> // for vc++ and android whose c++11 libs lack std::trunct
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1
namespace boost { namespace spirit { namespace traits { namespace boost { namespace spirit { namespace traits {
@ -61,6 +58,68 @@ namespace phoenix = boost::phoenix;
namespace { namespace {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct get_type
{
typedef int result_type;
result_type operator() (geometry_type const& geom) const
{
return static_cast<int>(geom.type());
}
};
struct get_first
{
typedef geometry_type::value_type const result_type;
result_type operator() (geometry_type const& geom) const
{
geometry_type::value_type coord;
boost::get<0>(coord) = geom.vertex(0,&boost::get<1>(coord),&boost::get<2>(coord));
return coord;
}
};
struct multi_geometry_type
{
typedef boost::tuple<unsigned,bool> result_type;
result_type operator() (geometry_container const& geom) const
{
unsigned type = 0u;
bool collection = false;
geometry_container::const_iterator itr = geom.begin();
geometry_container::const_iterator end = geom.end();
for ( ; itr != end; ++itr)
{
if (type != 0u && itr->type() != type)
{
collection = true;
break;
}
type = itr->type();
}
if (geom.size() > 1) type +=3;
return boost::tuple<unsigned,bool>(type, collection);
}
};
struct not_empty
{
typedef bool result_type;
result_type operator() (geometry_container const& cont) const
{
geometry_container::const_iterator itr = cont.begin();
geometry_container::const_iterator end = cont.end();
for ( ; itr != end; ++itr)
{
if (itr->size() > 0) return true;
}
return false;
}
};
#else
struct get_type struct get_type
{ {
template <typename T> template <typename T>
@ -100,7 +159,7 @@ struct multi_geometry_type
for ( ; itr != end; ++itr) for ( ; itr != end; ++itr)
{ {
if (type != 0u && itr->type() != type) if (type != 0u && static_cast<unsigned>(itr->type()) != type)
{ {
collection = true; collection = true;
break; break;
@ -113,6 +172,28 @@ struct multi_geometry_type
}; };
struct not_empty
{
template <typename T>
struct result { typedef bool type; };
bool operator() (geometry_container const& cont) const
{
geometry_container::const_iterator itr = cont.begin();
geometry_container::const_iterator end = cont.end();
for (; itr!=end; ++itr)
{
if (itr->size() > 0) return true;
}
return false;
}
};
#endif
template <typename T> template <typename T>
struct json_coordinate_policy : karma::real_policies<T> struct json_coordinate_policy : karma::real_policies<T>
{ {
@ -123,7 +204,7 @@ struct json_coordinate_policy : karma::real_policies<T>
{ {
if (n == 0.0) return 0; if (n == 0.0) return 0;
using namespace boost::spirit; using namespace boost::spirit;
return static_cast<unsigned>(15 - boost::math::trunc(log10(traits::get_absolute_value(n)))); return static_cast<unsigned>(14 - boost::math::trunc(log10(traits::get_absolute_value(n))));
} }
template <typename OutputIterator> template <typename OutputIterator>
@ -135,7 +216,7 @@ struct json_coordinate_policy : karma::real_policies<T>
template <typename OutputIterator> template <typename OutputIterator>
static bool fraction_part(OutputIterator& sink, T n static bool fraction_part(OutputIterator& sink, T n
, unsigned adjprec, unsigned precision) , unsigned adjprec, unsigned precision)
{ {
if (n == 0) return true; if (n == 0) return true;
return base_type::fraction_part(sink, n, adjprec, precision); return base_type::fraction_part(sink, n, adjprec, precision);
@ -153,6 +234,7 @@ struct geometry_generator_grammar :
: geometry_generator_grammar::base_type(coordinates) : geometry_generator_grammar::base_type(coordinates)
{ {
using boost::spirit::karma::uint_; using boost::spirit::karma::uint_;
using boost::spirit::bool_;
using boost::spirit::karma::_val; using boost::spirit::karma::_val;
using boost::spirit::karma::_1; using boost::spirit::karma::_1;
using boost::spirit::karma::lit; using boost::spirit::karma::lit;
@ -182,15 +264,15 @@ struct geometry_generator_grammar :
point_coord = &uint_ point_coord = &uint_
<< lit('[') << lit('[')
<< coord_type << lit(',') << coord_type << coord_type << lit(',') << coord_type
<< lit("]") << lit(']')
; ;
polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1]
<< karma::string[ if_ (_r1 > 1) [_1 = "],["] << karma::string[ if_ (_r1 > 1u) [_1 = "],["]
.else_[_1 = '[' ]] | &uint_ << lit(',')) .else_[_1 = '[' ]]
<< lit('[') << coord_type |
<< lit(',') &uint_(mapnik::SEG_LINETO)
<< coord_type << lit(']') << lit(',')) << lit('[') << coord_type << lit(',') << coord_type << lit(']')
; ;
coords2 %= *polygon_coord(_a) coords2 %= *polygon_coord(_a)
@ -205,7 +287,6 @@ struct geometry_generator_grammar :
karma::rule<OutputIterator, geometry_type const& ()> point; karma::rule<OutputIterator, geometry_type const& ()> point;
karma::rule<OutputIterator, geometry_type const& ()> linestring; karma::rule<OutputIterator, geometry_type const& ()> linestring;
karma::rule<OutputIterator, geometry_type const& ()> polygon; karma::rule<OutputIterator, geometry_type const& ()> polygon;
karma::rule<OutputIterator, geometry_type const& ()> coords; karma::rule<OutputIterator, geometry_type const& ()> coords;
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2; karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2;
karma::rule<OutputIterator, geometry_type::value_type ()> point_coord; karma::rule<OutputIterator, geometry_type::value_type ()> point_coord;
@ -235,6 +316,7 @@ struct multi_geometry_generator_grammar :
using boost::spirit::karma::_1; using boost::spirit::karma::_1;
using boost::spirit::karma::_a; using boost::spirit::karma::_a;
using boost::spirit::karma::_r1; using boost::spirit::karma::_r1;
using boost::spirit::bool_;
geometry_types.add geometry_types.add
(mapnik::Point,"\"Point\"") (mapnik::Point,"\"Point\"")
@ -245,7 +327,7 @@ struct multi_geometry_generator_grammar :
(mapnik::Polygon + 3,"\"MultiPolygon\"") (mapnik::Polygon + 3,"\"MultiPolygon\"")
; ;
start %= ( eps(phoenix::at_c<1>(_a))[_a = _multi_type(_val)] start %= ( eps(phoenix::at_c<1>(_a))[_a = multi_type_(_val)]
<< lit("{\"type\":\"GeometryCollection\",\"geometries\":[") << lit("{\"type\":\"GeometryCollection\",\"geometries\":[")
<< geometry_collection << lit("]}") << geometry_collection << lit("]}")
| |
@ -255,13 +337,13 @@ struct multi_geometry_generator_grammar :
geometry_collection = -(geometry2 % lit(',')) geometry_collection = -(geometry2 % lit(','))
; ;
geometry = (lit("{\"type\":") geometry = ( &bool_(true)[_1 = not_empty_(_val)] << lit("{\"type\":")
<< geometry_types[_1 = phoenix::at_c<0>(_a)][_a = _multi_type(_val)] << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = multi_type_(_val)]
<< lit(",\"coordinates\":") << lit(",\"coordinates\":")
<< karma::string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = '[']] << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3u) [_1 = '['].else_[_1 = ""]]
<< coordinates << coordinates
<< karma::string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']']] << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3u) [_1 = ']'].else_[_1 = ""]]
<< lit('}')) | lit("null") << lit('}')) | lit("null")
; ;
geometry2 = lit("{\"type\":") geometry2 = lit("{\"type\":")
@ -287,8 +369,9 @@ struct multi_geometry_generator_grammar :
karma::rule<OutputIterator, geometry_container const&()> coordinates; karma::rule<OutputIterator, geometry_container const&()> coordinates;
geometry_generator_grammar<OutputIterator> path; geometry_generator_grammar<OutputIterator> path;
// phoenix // phoenix
phoenix::function<multi_geometry_type> _multi_type; phoenix::function<multi_geometry_type> multi_type_;
phoenix::function<get_type > type_; phoenix::function<get_type > type_;
phoenix::function<not_empty> not_empty_;
// symbols table // symbols table
karma::symbols<unsigned, char const*> geometry_types; karma::symbols<unsigned, char const*> geometry_types;
}; };

View file

@ -37,6 +37,58 @@ namespace qi = boost::spirit::qi;
namespace standard_wide = boost::spirit::standard_wide; namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type; using standard_wide::space_type;
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct push_vertex
{
typedef void result_type;
template <typename T0,typename T1, typename T2, typename T3>
result_type operator() (T0 c, T1 path, T2 x, T3 y) const
{
BOOST_ASSERT( path!=0 );
path->push_vertex(x,y,c);
}
};
struct close_path
{
typedef void result_type;
template <typename T>
result_type operator() (T path) const
{
BOOST_ASSERT( path!=0 );
if (path->size() > 2u) // to form a polygon ring we need at least 3 vertices
{
path->close_path();
}
}
};
struct cleanup
{
typedef void result_type;
template <typename T0>
void operator() (T0 & path) const
{
if (path) delete path, path=0;
}
};
struct where_message
{
typedef std::string result_type;
template <typename Iterator>
std::string operator() (Iterator first, Iterator last, std::size_t size) const
{
std::string str(first, last);
if (str.length() > size)
return str.substr(0, size) + "..." ;
return str;
}
};
#else
struct push_vertex struct push_vertex
{ {
template <typename T0,typename T1, typename T2, typename T3> template <typename T0,typename T1, typename T2, typename T3>
@ -65,8 +117,11 @@ struct close_path
void operator() (T path) const void operator() (T path) const
{ {
BOOST_ASSERT( path!=0 ); BOOST_ASSERT( path!=0 );
path->close_path(); if (path->size() > 2u) // to form a polygon ring we need at least 3 vertices
} {
path->close_path();
}
}
}; };
struct cleanup struct cleanup
@ -101,12 +156,13 @@ struct where_message
return str; return str;
} }
}; };
#endif
template <typename Iterator> template <typename Iterator>
struct geometry_grammar : struct geometry_grammar :
qi::grammar<Iterator,qi::locals<int>, void(boost::ptr_vector<mapnik::geometry_type>& ) qi::grammar<Iterator,qi::locals<int>, void(boost::ptr_vector<mapnik::geometry_type>& )
, space_type> , space_type>
{ {
geometry_grammar(); geometry_grammar();
qi::rule<Iterator, qi::locals<int>, void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> geometry; qi::rule<Iterator, qi::locals<int>, void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> geometry;

View file

@ -124,12 +124,12 @@ public:
inline bool is_bitmap() const inline bool is_bitmap() const
{ {
return bitmap_data_; return bitmap_data_ ? true : false;
} }
inline bool is_vector() const inline bool is_vector() const
{ {
return vector_data_; return vector_data_ ? true : false;
} }
boost::optional<mapnik::image_ptr> get_bitmap_data() const boost::optional<mapnik::image_ptr> get_bitmap_data() const

View file

@ -45,7 +45,12 @@ inline double deg2rad(double deg)
template <typename PathType> template <typename PathType>
struct move_to struct move_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -66,7 +71,11 @@ struct move_to
template <typename PathType> template <typename PathType>
struct hline_to struct hline_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -88,7 +97,11 @@ struct hline_to
template <typename PathType> template <typename PathType>
struct vline_to struct vline_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -109,7 +122,11 @@ struct vline_to
template <typename PathType> template <typename PathType>
struct line_to struct line_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -131,7 +148,11 @@ struct line_to
template <typename PathType> template <typename PathType>
struct curve4 struct curve4
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3> template <typename T0, typename T1, typename T2, typename T3>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -156,7 +177,11 @@ struct curve4
template <typename PathType> template <typename PathType>
struct curve4_smooth struct curve4_smooth
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2> template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -178,7 +203,11 @@ struct curve4_smooth
template <typename PathType> template <typename PathType>
struct curve3 struct curve3
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2> template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -201,7 +230,11 @@ struct curve3
template <typename PathType> template <typename PathType>
struct curve3_smooth struct curve3_smooth
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -223,7 +256,11 @@ struct curve3_smooth
template <typename PathType> template <typename PathType>
struct arc_to struct arc_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5> template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
#endif
struct result struct result
{ {
typedef void type; typedef void type;

View file

@ -50,7 +50,11 @@ namespace mapnik { namespace svg {
template <typename TransformType> template <typename TransformType>
struct process_matrix struct process_matrix
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5> template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -70,7 +74,11 @@ namespace mapnik { namespace svg {
template <typename TransformType> template <typename TransformType>
struct process_rotate struct process_rotate
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2> template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -101,7 +109,11 @@ namespace mapnik { namespace svg {
template <typename TransformType> template <typename TransformType>
struct process_translate struct process_translate
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -123,7 +135,11 @@ namespace mapnik { namespace svg {
template <typename TransformType> template <typename TransformType>
struct process_scale struct process_scale
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -146,7 +162,11 @@ namespace mapnik { namespace svg {
template <typename TransformType> template <typename TransformType>
struct process_skew struct process_skew
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1> template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;

View file

@ -23,6 +23,7 @@
#ifndef MAPNIK_GEOMETRY_SVG_GENERATOR_HPP #ifndef MAPNIK_GEOMETRY_SVG_GENERATOR_HPP
#define MAPNIK_GEOMETRY_SVG_GENERATOR_HPP #define MAPNIK_GEOMETRY_SVG_GENERATOR_HPP
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> // for container stuff #include <mapnik/geometry.hpp> // for container stuff
@ -41,13 +42,11 @@
#include <boost/fusion/include/boost_tuple.hpp> #include <boost/fusion/include/boost_tuple.hpp>
#include <boost/type_traits/remove_pointer.hpp> #include <boost/type_traits/remove_pointer.hpp>
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1
/*! // adapted to conform to the concepts
* adapted to conform to the concepts // required by Karma to be recognized as a container of
* required by Karma to be recognized as a container of // attributes for output generation.
* attributes for output generation.
*/
namespace boost { namespace spirit { namespace traits { namespace boost { namespace spirit { namespace traits {
// TODO - this needs to be made generic to any path type // TODO - this needs to be made generic to any path type
@ -76,7 +75,7 @@ template <>
struct end_container<path_type const> struct end_container<path_type const>
{ {
static mapnik::util::path_iterator<path_type> static mapnik::util::path_iterator<path_type>
call (path_type const& g) call (path_type const& /*g*/)
{ {
return mapnik::util::path_iterator<path_type>(); return mapnik::util::path_iterator<path_type>();
} }
@ -92,6 +91,31 @@ namespace mapnik { namespace util {
namespace svg_detail { namespace svg_detail {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename Geometry>
struct get_type
{
typedef int result_type;
result_type operator() (Geometry const& geom) const
{
return static_cast<int>(geom.type());
}
};
template <typename T>
struct get_first
{
typedef T geometry_type;
typedef typename geometry_type::value_type const result_type;
result_type operator() (geometry_type const& geom) const
{
typename geometry_type::value_type coord;
geom.rewind(0);
boost::get<0>(coord) = geom.vertex(&boost::get<1>(coord),&boost::get<2>(coord));
return coord;
}
};
#else
template <typename Geometry> template <typename Geometry>
struct get_type struct get_type
{ {
@ -112,7 +136,7 @@ namespace mapnik { namespace util {
template <typename U> template <typename U>
struct result { typedef typename geometry_type::value_type const type; }; struct result { typedef typename geometry_type::value_type const type; };
typename geometry_type::value_type const operator() (geometry_type const& geom) const typename geometry_type::value_type operator() (geometry_type const& geom) const
{ {
typename geometry_type::value_type coord; typename geometry_type::value_type coord;
geom.rewind(0); geom.rewind(0);
@ -121,12 +145,13 @@ namespace mapnik { namespace util {
} }
}; };
#endif
template <typename T> template <typename T>
struct coordinate_policy : karma::real_policies<T> struct coordinate_policy : karma::real_policies<T>
{ {
typedef boost::spirit::karma::real_policies<T> base_type; typedef boost::spirit::karma::real_policies<T> base_type;
static int floatfield(T n) { return base_type::fmtflags::fixed; } static int floatfield(T n) { return base_type::fmtflags::fixed; }
static unsigned precision(T n) { return 6u ;} static unsigned precision(T n) { return 4u ;}
}; };
} }
@ -161,15 +186,15 @@ namespace mapnik { namespace util {
; ;
linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] linestring = &uint_(mapnik::LineString)[_1 = _type(_val)]
<< svg_path << lit('\"') << lit("d=\"") << svg_path << lit("\"")
; ;
polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)] polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)]
<< svg_path << lit('\"') << lit("d=\"") << svg_path << lit("\"")
; ;
svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit("d=\"") << lit('M') svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit('M')
| &uint_(mapnik::SEG_LINETO) [_a +=1] << karma::string [if_(_a == 1) [_1 = "L" ] ]) | &uint_(mapnik::SEG_LINETO) [_a +=1] << karma::string [if_(_a == 1u) [_1 = "L" ].else_[_1 =""]])
<< lit(' ') << coordinate << lit(' ') << coordinate) % lit(' ') << lit(' ') << coordinate << lit(' ') << coordinate) % lit(' ')
; ;

View file

@ -40,7 +40,6 @@
#include <boost/type_traits/remove_pointer.hpp> #include <boost/type_traits/remove_pointer.hpp>
#include <boost/math/special_functions/trunc.hpp> // trunc to avoid needing C++11 #include <boost/math/special_functions/trunc.hpp> // trunc to avoid needing C++11
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1
namespace boost { namespace spirit { namespace traits { namespace boost { namespace spirit { namespace traits {
@ -205,8 +204,7 @@ template <typename OutputIterator, typename GeometryContainer>
struct wkt_multi_generator : struct wkt_multi_generator :
karma::grammar<OutputIterator, karma::locals< boost::tuple<unsigned,bool> >, GeometryContainer const& ()> karma::grammar<OutputIterator, karma::locals< boost::tuple<unsigned,bool> >, GeometryContainer const& ()>
{ {
typedef GeometryContainer geometry_contaner; typedef typename boost::remove_pointer<typename GeometryContainer::value_type>::type geometry_type;
typedef boost::remove_pointer<typename geometry_container::value_type>::type geometry_type;
wkt_multi_generator(); wkt_multi_generator();
// rules // rules

View file

@ -23,7 +23,7 @@
#ifndef MAPNIK_VERSION_HPP #ifndef MAPNIK_VERSION_HPP
#define MAPNIK_VERSION_HPP #define MAPNIK_VERSION_HPP
#define MAPNIK_VERSION_IS_RELEASE 1 #define MAPNIK_VERSION_IS_RELEASE 0
#define MAPNIK_MAJOR_VERSION 2 #define MAPNIK_MAJOR_VERSION 2
#define MAPNIK_MINOR_VERSION 2 #define MAPNIK_MINOR_VERSION 2

View file

@ -40,12 +40,15 @@
namespace mapnik { namespace wkt { namespace mapnik { namespace wkt {
using namespace boost::spirit; using namespace boost::spirit;
using namespace boost::fusion;
using namespace boost::phoenix; using namespace boost::phoenix;
struct push_vertex struct push_vertex
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0,typename T1, typename T2, typename T3> template <typename T0,typename T1, typename T2, typename T3>
#endif
struct result struct result
{ {
typedef void type; typedef void type;

13
localize.sh Executable file
View file

@ -0,0 +1,13 @@
#!/bin/bash
UNAME=$(uname -s)
export CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ ${UNAME} = 'Darwin' ]; then
export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/"
else
export LD_LIBRARY_PATH="${CURRENT_DIR}/src/"
fi
export PYTHONPATH="${CURRENT_DIR}/bindings/python/":${PYTHONPATH}
export MAPNIK_FONT_DIRECTORY="${CURRENT_DIR}/fonts/dejavu-fonts-ttf-2.33/ttf/"
export MAPNIK_INPUT_PLUGINS_DIRECTORY="${CURRENT_DIR}/plugins/input/"
export PATH="${CURRENT_DIR}/utils/mapnik-config/":${PATH}
export PATH="${CURRENT_DIR}/utils/nik2img":${PATH}

View file

@ -32,10 +32,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/spirit/include/support_multi_pass.hpp> #include <boost/spirit/include/support_multi_pass.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/extensions/index/rtree/rtree.hpp>
// mapnik // mapnik
#include <mapnik/unicode.hpp> #include <mapnik/unicode.hpp>
@ -101,7 +97,11 @@ geojson_datasource::geojson_datasource(parameters const& params)
extent_(), extent_(),
tr_(new mapnik::transcoder(*params.get<std::string>("encoding","utf-8"))), tr_(new mapnik::transcoder(*params.get<std::string>("encoding","utf-8"))),
features_(), features_(),
#if BOOST_VERSION >= 105600
tree_()
#else
tree_(16,1) tree_(16,1)
#endif
{ {
if (file_.empty()) throw mapnik::datasource_exception("GeoJSON Plugin: missing <file> parameter"); if (file_.empty()) throw mapnik::datasource_exception("GeoJSON Plugin: missing <file> parameter");
@ -137,15 +137,13 @@ geojson_datasource::geojson_datasource(parameters const& params)
throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file '" + file_ + "'"); throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file '" + file_ + "'");
} }
bool first = true; std::size_t geometry_index = 0;
std::size_t count=0; BOOST_FOREACH (mapnik::feature_ptr const& f, features_)
BOOST_FOREACH (mapnik::feature_ptr f, features_)
{ {
mapnik::box2d<double> const& box = f->envelope(); mapnik::box2d<double> box = f->envelope();
if (first) if (geometry_index == 0)
{ {
extent_ = box; extent_ = box;
first = false;
mapnik::feature_kv_iterator f_itr = f->begin(); mapnik::feature_kv_iterator f_itr = f->begin();
mapnik::feature_kv_iterator f_end = f->end(); mapnik::feature_kv_iterator f_end = f->end();
for ( ;f_itr!=f_end; ++f_itr) for ( ;f_itr!=f_end; ++f_itr)
@ -158,7 +156,12 @@ geojson_datasource::geojson_datasource(parameters const& params)
{ {
extent_.expand_to_include(box); extent_.expand_to_include(box);
} }
tree_.insert(box_type(point_type(box.minx(),box.miny()),point_type(box.maxx(),box.maxy())), count++); #if BOOST_VERSION >= 105600
tree_.insert(std::make_pair(box_type(point_type(box.minx(),box.miny()),point_type(box.maxx(),box.maxy())),geometry_index));
#else
tree_.insert(box_type(point_type(box.minx(),box.miny()),point_type(box.maxx(),box.maxy())),geometry_index);
#endif
++geometry_index;
} }
} }
@ -213,7 +216,11 @@ mapnik::featureset_ptr geojson_datasource::features(mapnik::query const& q) cons
if (extent_.intersects(b)) if (extent_.intersects(b))
{ {
box_type box(point_type(b.minx(),b.miny()),point_type(b.maxx(),b.maxy())); box_type box(point_type(b.minx(),b.miny()),point_type(b.maxx(),b.maxy()));
#if BOOST_VERSION >= 105600
tree_.query(boost::geometry::index::intersects(box),std::back_inserter(index_array_));
#else
index_array_ = tree_.find(box); index_array_ = tree_.find(box);
#endif
return boost::make_shared<geojson_featureset>(features_, index_array_.begin(), index_array_.end()); return boost::make_shared<geojson_featureset>(features_, index_array_.begin(), index_array_.end());
} }
// otherwise return an empty featureset pointer // otherwise return an empty featureset pointer

View file

@ -36,11 +36,16 @@
// boost // boost
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/algorithms/area.hpp> #include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/geometries.hpp> #include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION >= 105600
#include <boost/geometry/index/rtree.hpp>
#else
#include <boost/geometry/extensions/index/rtree/rtree.hpp> #include <boost/geometry/extensions/index/rtree/rtree.hpp>
#endif
// stl // stl
#include <vector> #include <vector>
@ -53,7 +58,14 @@ class geojson_datasource : public mapnik::datasource
public: public:
typedef boost::geometry::model::d2::point_xy<double> point_type; typedef boost::geometry::model::d2::point_xy<double> point_type;
typedef boost::geometry::model::box<point_type> box_type; typedef boost::geometry::model::box<point_type> box_type;
#if BOOST_VERSION >= 105600
typedef std::pair<box_type,std::size_t> item_type;
typedef boost::geometry::index::linear<16,1> linear_type;
typedef boost::geometry::index::rtree<item_type,linear_type> spatial_index_type;
#else
typedef std::size_t item_type;
typedef boost::geometry::index::rtree<box_type,std::size_t> spatial_index_type; typedef boost::geometry::index::rtree<box_type,std::size_t> spatial_index_type;
#endif
// constructor // constructor
geojson_datasource(mapnik::parameters const& params); geojson_datasource(mapnik::parameters const& params);
@ -74,7 +86,7 @@ private:
boost::shared_ptr<mapnik::transcoder> tr_; boost::shared_ptr<mapnik::transcoder> tr_;
std::vector<mapnik::feature_ptr> features_; std::vector<mapnik::feature_ptr> features_;
spatial_index_type tree_; spatial_index_type tree_;
mutable std::deque<std::size_t> index_array_; mutable std::deque<item_type> index_array_;
}; };

View file

@ -30,8 +30,8 @@
#include "geojson_featureset.hpp" #include "geojson_featureset.hpp"
geojson_featureset::geojson_featureset(std::vector<mapnik::feature_ptr> const& features, geojson_featureset::geojson_featureset(std::vector<mapnik::feature_ptr> const& features,
std::deque<std::size_t>::const_iterator index_itr, array_type::const_iterator index_itr,
std::deque<std::size_t>::const_iterator index_end) array_type::const_iterator index_end)
: features_(features), : features_(features),
index_itr_(index_itr), index_itr_(index_itr),
index_end_(index_end) {} index_end_(index_end) {}
@ -42,7 +42,12 @@ mapnik::feature_ptr geojson_featureset::next()
{ {
if (index_itr_ != index_end_) if (index_itr_ != index_end_)
{ {
std::size_t index = *index_itr_++; #if BOOST_VERSION >= 105600
geojson_datasource::item_type const& item = *index_itr_++;
std::size_t index = item.second;
#else
std::size_t index = *index_itr_++;
#endif
if ( index < features_.size()) if ( index < features_.size())
{ {
return features_.at(index); return features_.at(index);

View file

@ -11,17 +11,18 @@
class geojson_featureset : public mapnik::Featureset class geojson_featureset : public mapnik::Featureset
{ {
public: public:
typedef std::deque<geojson_datasource::item_type> array_type;
geojson_featureset(std::vector<mapnik::feature_ptr> const& features, geojson_featureset(std::vector<mapnik::feature_ptr> const& features,
std::deque<std::size_t>::const_iterator index_itr, array_type::const_iterator index_itr,
std::deque<std::size_t>::const_iterator index_end); array_type::const_iterator index_end);
virtual ~geojson_featureset(); virtual ~geojson_featureset();
mapnik::feature_ptr next(); mapnik::feature_ptr next();
private: private:
mapnik::box2d<double> box_; mapnik::box2d<double> box_;
std::vector<mapnik::feature_ptr> const& features_; std::vector<mapnik::feature_ptr> const& features_;
std::deque<std::size_t>::const_iterator index_itr_; array_type::const_iterator index_itr_;
std::deque<std::size_t>::const_iterator index_end_; array_type::const_iterator index_end_;
}; };
#endif // GEOJSON_FEATURESET_HPP #endif // GEOJSON_FEATURESET_HPP

View file

@ -72,7 +72,11 @@ ogr_datasource::~ogr_datasource()
{ {
// free layer before destroying the datasource // free layer before destroying the datasource
layer_.free_layer(); layer_.free_layer();
#if GDAL_VERSION_MAJOR >= 2
GDALClose(( GDALDatasetH) dataset_);
#else
OGRDataSource::DestroyDataSource (dataset_); OGRDataSource::DestroyDataSource (dataset_);
#endif
} }
void ogr_datasource::init(mapnik::parameters const& params) void ogr_datasource::init(mapnik::parameters const& params)
@ -82,6 +86,7 @@ void ogr_datasource::init(mapnik::parameters const& params)
#endif #endif
// initialize ogr formats // initialize ogr formats
// NOTE: in GDAL >= 2.0 this is the same as GDALAllRegister()
OGRRegisterAll(); OGRRegisterAll();
boost::optional<std::string> file = params.get<std::string>("file"); boost::optional<std::string> file = params.get<std::string>("file");
@ -112,17 +117,26 @@ void ogr_datasource::init(mapnik::parameters const& params)
if (! driver.empty()) if (! driver.empty())
{ {
#if GDAL_VERSION_MAJOR >= 2
unsigned int nOpenFlags = GDAL_OF_READONLY | GDAL_OF_VECTOR;
const char* papszAllowedDrivers[] = { driver.c_str(), NULL };
dataset_ = static_cast<gdal_dataset_type>(GDALOpenEx(dataset_name_.c_str(),nOpenFlags,papszAllowedDrivers,NULL,NULL));
#else
OGRSFDriver * ogr_driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver.c_str()); OGRSFDriver * ogr_driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver.c_str());
if (ogr_driver && ogr_driver != NULL) if (ogr_driver && ogr_driver != NULL)
{ {
dataset_ = ogr_driver->Open((dataset_name_).c_str(), FALSE); dataset_ = ogr_driver->Open((dataset_name_).c_str(), FALSE);
} }
#endif
} }
else else
{ {
// open ogr driver // open ogr driver
dataset_ = OGRSFDriverRegistrar::Open((dataset_name_).c_str(), FALSE); #if GDAL_VERSION_MAJOR >= 2
dataset_ = static_cast<gdal_dataset_type>(OGROpen(dataset_name_.c_str(), FALSE, NULL));
#else
dataset_ = OGRSFDriverRegistrar::Open(dataset_name_.c_str(), FALSE);
#endif
} }
if (! dataset_) if (! dataset_)

View file

@ -63,7 +63,7 @@ private:
mapnik::datasource::datasource_t type_; mapnik::datasource::datasource_t type_;
std::string dataset_name_; std::string dataset_name_;
std::string index_name_; std::string index_name_;
OGRDataSource* dataset_; gdal_dataset_type dataset_;
ogr_layer_ptr layer_; ogr_layer_ptr layer_;
std::string layer_name_; std::string layer_name_;
mapnik::layer_descriptor desc_; mapnik::layer_descriptor desc_;

View file

@ -29,9 +29,16 @@
// stl // stl
#include <stdexcept> #include <stdexcept>
// ogr // gdal
#include <gdal_version.h>
#include <ogrsf_frmts.h> #include <ogrsf_frmts.h>
#if GDAL_VERSION_MAJOR >= 2
typedef GDALDataset* gdal_dataset_type;
#else
typedef OGRDataSource* gdal_dataset_type;
#endif
class ogr_layer_ptr class ogr_layer_ptr
{ {
public: public:
@ -62,7 +69,7 @@ public:
is_valid_ = false; is_valid_ = false;
} }
void layer_by_name(OGRDataSource* const datasource, void layer_by_name(gdal_dataset_type const datasource,
std::string const& layer_name) std::string const& layer_name)
{ {
free_layer(); free_layer();
@ -84,7 +91,7 @@ public:
#endif #endif
} }
void layer_by_index(OGRDataSource* const datasource, void layer_by_index(gdal_dataset_type const datasource,
int layer_index) int layer_index)
{ {
free_layer(); free_layer();
@ -110,7 +117,7 @@ public:
#endif #endif
} }
void layer_by_sql(OGRDataSource* const datasource, void layer_by_sql(gdal_dataset_type const datasource,
std::string const& layer_sql) std::string const& layer_sql)
{ {
free_layer(); free_layer();
@ -179,7 +186,7 @@ private:
} }
#endif #endif
OGRDataSource* datasource_; gdal_dataset_type datasource_;
OGRLayer* layer_; OGRLayer* layer_;
std::string layer_name_; std::string layer_name_;
bool owns_layer_; bool owns_layer_;

View file

@ -38,8 +38,22 @@ plugin_sources = Split(
) )
# Link Library to Dependencies # Link Library to Dependencies
libraries = [ 'xml2' ] plugin_env['LIBS'] = []
libraries.append('curl') if env['RUNTIME_LINK'] == 'static':
# pkg-config is more reliable than pg_config across platforms
cmd = 'pkg-config libcurl --libs --static'
try:
plugin_env.ParseConfig(cmd)
except OSError, e:
# if this fails likely only system curl is available
# on OS X at least the system curl lacks a pkg-config file
# so static linking is not viable anyway
plugin_env.Append(LIBS='curl')
else:
plugin_env.Append(LIBS='curl')
libraries = plugin_env['LIBS']
libraries.append('xml2')
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])
libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_system%s' % env['BOOST_APPEND'])

View file

@ -85,7 +85,7 @@ public:
PGresult *result = PQexec(conn_, sql.c_str()); PGresult *result = PQexec(conn_, sql.c_str());
bool ok = (result && (PQresultStatus(result) == PGRES_COMMAND_OK)); bool ok = (result && (PQresultStatus(result) == PGRES_COMMAND_OK));
PQclear(result); if ( result ) PQclear(result);
return ok; return ok;
} }
@ -107,7 +107,8 @@ public:
if (! result || (PQresultStatus(result) != PGRES_TUPLES_OK)) if (! result || (PQresultStatus(result) != PGRES_TUPLES_OK))
{ {
std::string err_msg = status(); std::string err_msg = "Postgis Plugin: ";
err_msg += status();
err_msg += "\nFull sql was: '"; err_msg += "\nFull sql was: '";
err_msg += sql; err_msg += sql;
err_msg += "'\n"; err_msg += "'\n";
@ -127,7 +128,8 @@ public:
std::string status; std::string status;
if (conn_) if (conn_)
{ {
status = PQerrorMessage(conn_); if ( isOK() ) return PQerrorMessage(conn_);
else return "Bad connection";
} }
else else
{ {

View file

@ -48,7 +48,7 @@
DATASOURCE_PLUGIN(postgis_datasource) DATASOURCE_PLUGIN(postgis_datasource)
const double postgis_datasource::FMAX = std::numeric_limits<double>::max(); const double postgis_datasource::FMAX = std::numeric_limits<float>::max();
const std::string postgis_datasource::GEOMETRY_COLUMNS = "geometry_columns"; const std::string postgis_datasource::GEOMETRY_COLUMNS = "geometry_columns";
const std::string postgis_datasource::SPATIAL_REF_SYS = "spatial_ref_system"; const std::string postgis_datasource::SPATIAL_REF_SYS = "spatial_ref_system";
@ -424,10 +424,19 @@ postgis_datasource::~postgis_datasource()
shared_ptr< Pool<Connection,ConnectionCreator> > pool = ConnectionManager::instance().getPool(creator_.id()); shared_ptr< Pool<Connection,ConnectionCreator> > pool = ConnectionManager::instance().getPool(creator_.id());
if (pool) if (pool)
{ {
shared_ptr<Connection> conn = pool->borrowObject(); try {
if (conn) shared_ptr<Connection> conn = pool->borrowObject();
{ if (conn)
conn->close(); {
conn->close();
}
} catch (mapnik::datasource_exception const& ex) {
// happens when borrowObject tries to
// create a new connection and fails.
// In turn, new connection would be needed
// when our broke and was thus no good to
// be borrowed
// See https://github.com/mapnik/mapnik/issues/2191
} }
} }
} }

View file

@ -20,6 +20,7 @@
# #
import os import os
import copy
Import ('plugin_base') Import ('plugin_base')
Import ('env') Import ('env')
@ -42,7 +43,7 @@ libraries.append(env['BOOST_PYTHON_LIB'])
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])
python_cpppath = env['PYTHON_INCLUDES'] python_cpppath = env['PYTHON_INCLUDES']
allcpp_paths = env['CPPPATH'] allcpp_paths = copy.copy(env['CPPPATH'])
allcpp_paths.extend(python_cpppath) allcpp_paths.extend(python_cpppath)
# NOTE: explicit linking to libpython is uneeded on most linux version if the # NOTE: explicit linking to libpython is uneeded on most linux version if the
# python plugin is used by a app in python using mapnik's python bindings # python plugin is used by a app in python using mapnik's python bindings

View file

@ -8,7 +8,7 @@ failures=$((failures+$?))
echo "*** Running C++ tests..." echo "*** Running C++ tests..."
for FILE in tests/cpp_tests/*-bin; do for FILE in tests/cpp_tests/*-bin; do
${FILE} -q -d .; ${FILE} -q -d .;
failures=$((failures+$?)) failures=$((failures+$?))
done done

View file

@ -170,7 +170,7 @@ void jpeg_reader<T>::skip(j_decompress_ptr cinfo, long count)
} }
else else
{ {
wrap->stream->seekg(count, std::ios_base::cur); wrap->stream->seekg(count - wrap->manager.bytes_in_buffer, std::ios_base::cur);
// trigger buffer fill // trigger buffer fill
wrap->manager.next_input_byte = 0; wrap->manager.next_input_byte = 0;
wrap->manager.bytes_in_buffer = 0; //bytes_in_buffer may be zero on return. wrap->manager.bytes_in_buffer = 0; //bytes_in_buffer may be zero on return.

View file

@ -23,8 +23,10 @@
// TODO https://github.com/mapnik/mapnik/issues/1658 // TODO https://github.com/mapnik/mapnik/issues/1658
#include <boost/version.hpp> #include <boost/version.hpp>
#if BOOST_VERSION >= 105200 #if BOOST_VERSION >= 105200
#ifndef BOOST_SPIRIT_USE_PHOENIX_V3
#define BOOST_SPIRIT_USE_PHOENIX_V3 #define BOOST_SPIRIT_USE_PHOENIX_V3
#endif #endif
#endif
// mapnik // mapnik
#include <mapnik/json/feature_collection_parser.hpp> #include <mapnik/json/feature_collection_parser.hpp>

View file

@ -108,7 +108,10 @@ void projection::init_proj4() const
proj_ = pj_init_plus_ctx(proj_ctx_, params_.c_str()); proj_ = pj_init_plus_ctx(proj_ctx_, params_.c_str());
if (!proj_) if (!proj_)
{ {
if (proj_ctx_) pj_ctx_free(proj_ctx_); if (proj_ctx_) {
pj_ctx_free(proj_ctx_);
proj_ctx_ = 0;
}
throw proj_init_error(params_); throw proj_init_error(params_);
} }
#else #else

View file

@ -81,7 +81,7 @@ public:
// Parse using appropriate flags // Parse using appropriate flags
// https://github.com/mapnik/mapnik/issues/1856 // https://github.com/mapnik/mapnik/issues/1856
// const int f_tws = rapidxml::parse_normalize_whitespace; // const int f_tws = rapidxml::parse_normalize_whitespace;
const int f_tws = rapidxml::parse_trim_whitespace; const int f_tws = rapidxml::parse_trim_whitespace | rapidxml::parse_validate_closing_tags;
rapidxml::xml_document<> doc; rapidxml::xml_document<> doc;
doc.parse<f_tws>(&v.front()); doc.parse<f_tws>(&v.front());
@ -143,7 +143,10 @@ private:
case rapidxml::node_data: case rapidxml::node_data:
case rapidxml::node_cdata: case rapidxml::node_cdata:
{ {
node.add_child(cur_node->value(), 0, true); if (cur_node->value_size() > 0) // Don't add empty text nodes
{
node.add_child(cur_node->value(), 0, true);
}
} }
break; break;
default: default:

View file

@ -42,6 +42,7 @@
// boost // boost
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/version.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp> #include <boost/property_tree/xml_parser.hpp>
@ -869,7 +870,11 @@ void save_map(Map const & map, std::string const& filename, bool explicit_defaul
{ {
ptree pt; ptree pt;
serialize_map(pt,map,explicit_defaults); serialize_map(pt,map,explicit_defaults);
#if BOOST_VERSION >= 105600
write_xml(filename,pt,std::locale(),boost::property_tree::xml_writer_make_settings<ptree::key_type>(' ',4));
#else
write_xml(filename,pt,std::locale(),boost::property_tree::xml_writer_make_settings(' ',4)); write_xml(filename,pt,std::locale(),boost::property_tree::xml_writer_make_settings(' ',4));
#endif
} }
std::string save_map_to_string(Map const & map, bool explicit_defaults) std::string save_map_to_string(Map const & map, bool explicit_defaults)
@ -877,7 +882,11 @@ std::string save_map_to_string(Map const & map, bool explicit_defaults)
ptree pt; ptree pt;
serialize_map(pt,map,explicit_defaults); serialize_map(pt,map,explicit_defaults);
std::ostringstream ss; std::ostringstream ss;
#if BOOST_VERSION >= 105600
write_xml(ss,pt,boost::property_tree::xml_writer_make_settings<ptree::key_type>(' ',4));
#else
write_xml(ss,pt,boost::property_tree::xml_writer_make_settings(' ',4)); write_xml(ss,pt,boost::property_tree::xml_writer_make_settings(' ',4));
#endif
return ss.str(); return ss.str();
} }

View file

@ -53,7 +53,7 @@ int main(int argc, char** argv)
// NOTE: this is a valid font, but will fail because none are registered // NOTE: this is a valid font, but will fail because none are registered
fontset.add_face_name("DejaVu Sans Book"); fontset.add_face_name("DejaVu Sans Book");
m.insert_fontset("fontset", fontset); m.insert_fontset("fontset", fontset);
mapnik::layer lyr("layer"); mapnik::layer lyr("myLayerName");
lyr.set_datasource(memory_ds); lyr.set_datasource(memory_ds);
lyr.add_style("style"); lyr.add_style("style");
m.addLayer(lyr); m.addLayer(lyr);
@ -70,7 +70,7 @@ int main(int argc, char** argv)
mapnik::agg_renderer<mapnik::image_32> ren(m,buf); mapnik::agg_renderer<mapnik::image_32> ren(m,buf);
ren.apply(); ren.apply();
} catch (std::exception const& ex) { } catch (std::exception const& ex) {
BOOST_TEST_EQ(std::string(ex.what()),std::string("No valid font face could be loaded for font set: 'fontset'")); BOOST_TEST_EQ(std::string(ex.what()),std::string("myLayerName: No valid font face could be loaded for font set: 'fontset'"));
} }
if (!::boost::detail::test_errors()) { if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m"; if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";

View file

@ -0,0 +1,15 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="steelblue" minimum-version="0.7.2">
<Style name="labels">
<Rule>
<TextSymbolizer face-name="DejaVu Sans Book"></TextSymbolizer>
<TextSymbolizer face-name="DejaVu Sans Book">''</TextSymbolizer>
<TextSymbolizer face-name="DejaVu Sans Book"><![CDATA[]]></TextSymbolizer>
</Rule>
</Style>
<Layer name="point" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>labels</StyleName>
</Layer>
</Map>

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from nose.tools import * from nose.tools import *
from utilities import execution_path, run_all from utilities import execution_path, run_all, datasources_available
import os, mapnik import os, mapnik
def setup(): def setup():
@ -99,9 +99,10 @@ def test_hit_grid():
""" encode a list of strings with run-length compression """ """ encode a list of strings with run-length compression """
return ["%d:%s" % (len(list(group)), name) for name, group in groupby(l)] return ["%d:%s" % (len(list(group)), name) for name, group in groupby(l)]
m = mapnik.Map(256,256); xmlfile = '../data/good_maps/agg_poly_gamma_map.xml'
try: if datasources_available(xmlfile):
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml'); m = mapnik.Map(256, 256)
mapnik.load_map(m, xmlfile)
m.zoom_all() m.zoom_all()
join_field = 'NAME' join_field = 'NAME'
fg = [] # feature grid fg = [] # feature grid
@ -117,10 +118,6 @@ def test_hit_grid():
hit_list = '|'.join(rle_encode(fg)) hit_list = '|'.join(rle_encode(fg))
eq_(hit_list[:16],'730:|2:Greenland') eq_(hit_list[:16],'730:|2:Greenland')
eq_(hit_list[-12:],'1:Chile|812:') eq_(hit_list[-12:],'1:Chile|812:')
except RuntimeError, e:
# only test datasources that we have installed
if not 'Could not create datasource' in str(e):
raise RuntimeError(str(e))
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -28,9 +28,9 @@ def test_adding_datasource_to_layer():
</Map> </Map>
''' '''
m = mapnik.Map(256, 256) if 'shape' in mapnik.DatasourceCache.plugin_names():
m = mapnik.Map(256, 256)
try:
mapnik.load_map_from_string(m, map_string) mapnik.load_map_from_string(m, map_string)
# validate it loaded fine # validate it loaded fine
@ -65,10 +65,6 @@ def test_adding_datasource_to_layer():
# test that assignment # test that assignment
eq_(m.layers[0].srs,'+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs') eq_(m.layers[0].srs,'+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs')
eq_(lyr.srs,'+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs') eq_(lyr.srs,'+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs')
except RuntimeError, e:
# only test datasources that we have installed
if not 'Could not create datasource' in str(e):
raise RuntimeError(e)
if __name__ == "__main__": if __name__ == "__main__":
setup() setup()

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from nose.tools import * from nose.tools import *
from utilities import execution_path, run_all from utilities import execution_path, run_all, datasources_available
import os, sys, glob, mapnik import os, sys, glob, mapnik
@ -30,20 +30,27 @@ def test_broken_files():
mapnik.logger.set_severity(default_logging_severity) mapnik.logger.set_severity(default_logging_severity)
def test_good_files(): def test_good_files():
good_files = glob.glob("../data/good_maps/*.xml") all_files = glob.glob("../data/good_maps/*.xml")
failures = []; good_files = list()
for xmlfile in all_files:
missing_plugins = set()
have_inputs = datasources_available(xmlfile, missing_plugins)
if have_inputs:
good_files.append(xmlfile)
else:
print 'Notice: skipping load_map_test for %s due to unavailable input plugins: %s' % (os.path.basename(xmlfile), list(missing_plugins))
failures = []
strict = True
for filename in good_files: for filename in good_files:
try: try:
m = mapnik.Map(512, 512) m = mapnik.Map(512, 512)
strict = True
mapnik.load_map(m, filename, strict) mapnik.load_map(m, filename, strict)
base_path = os.path.dirname(filename) base_path = os.path.dirname(filename)
mapnik.load_map_from_string(m,open(filename,'rb').read(),strict,base_path) mapnik.load_map_from_string(m, open(filename, 'rb').read(), strict, base_path)
except RuntimeError, e: except RuntimeError, e:
# only test datasources that we have installed failures.append('Failed to load valid map %s (%s)!' % (filename, str(e)))
if not 'Could not create datasource' in str(e):
failures.append('Failed to load valid map (%s)!' % filename)
eq_(len(failures),0,'\n'+'\n'.join(failures)) eq_(len(failures),0,'\n'+'\n'.join(failures))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -69,8 +69,8 @@ def test_line_symbolizer():
def test_line_symbolizer_stroke_reference(): def test_line_symbolizer_stroke_reference():
l = mapnik.LineSymbolizer(mapnik.Color('green'),0.1) l = mapnik.LineSymbolizer(mapnik.Color('green'),0.1)
l.stroke.add_dash(.1,.1) l.stroke.add_dash(.1,.1)
l.stroke.add_dash(.1,.1) l.stroke.add_dash(4,4)
eq_(l.stroke.get_dashes(), [(.1,.1),(.1,.1)]) eq_(l.stroke.get_dashes(), [(.1,.1),(4,4)])
eq_(l.stroke.color,mapnik.Color('green')) eq_(l.stroke.color,mapnik.Color('green'))
eq_(l.stroke.opacity,1.0) eq_(l.stroke.opacity,1.0)
assert_almost_equal(l.stroke.width,0.1) assert_almost_equal(l.stroke.width,0.1)
@ -88,6 +88,9 @@ def test_stroke_dash_api():
def test_text_symbolizer(): def test_text_symbolizer():
s = mapnik.TextSymbolizer() s = mapnik.TextSymbolizer()
eq_(s.orientation,None)
s.orientation = mapnik.Expression('45');
eq_(str(s.orientation),str(mapnik.Expression('45')))
eq_(s.comp_op,mapnik.CompositeOp.src_over) eq_(s.comp_op,mapnik.CompositeOp.src_over)
eq_(s.clip,True) eq_(s.clip,True)
eq_(s.halo_rasterizer,mapnik.halo_rasterizer.FULL) eq_(s.halo_rasterizer,mapnik.halo_rasterizer.FULL)
@ -375,9 +378,9 @@ def test_map_init_from_string():
</Layer> </Layer>
</Map>''' </Map>'''
m = mapnik.Map(600, 300) if 'shape' in mapnik.DatasourceCache.plugin_names():
eq_(m.base, '') m = mapnik.Map(600, 300)
try: eq_(m.base, '')
mapnik.load_map_from_string(m, map_string) mapnik.load_map_from_string(m, map_string)
eq_(m.base, './') eq_(m.base, './')
mapnik.load_map_from_string(m, map_string, False, "") # this "" will have no effect mapnik.load_map_from_string(m, map_string, False, "") # this "" will have no effect
@ -392,10 +395,6 @@ def test_map_init_from_string():
m.base = 'foo' m.base = 'foo'
mapnik.load_map_from_string(m, map_string, True, ".") mapnik.load_map_from_string(m, map_string, True, ".")
eq_(m.base, '.') eq_(m.base, '.')
except RuntimeError, e:
# only test datasources that we have installed
if not 'Could not create datasource' in str(e):
raise RuntimeError(e)
# Color initialization # Color initialization
@raises(Exception) # Boost.Python.ArgumentError @raises(Exception) # Boost.Python.ArgumentError

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
from nose.tools import * from nose.tools import *
from utilities import execution_path, run_all, contains_word, get_unique_colors from utilities import execution_path, run_all, contains_word, get_unique_colors,\
datasources_available
import os, mapnik import os, mapnik
@ -89,27 +90,22 @@ def test_dataraster_query_point():
assert len(features) == 0 assert len(features) == 0
def test_load_save_map(): def test_load_save_map():
map = mapnik.Map(256,256) m = mapnik.Map(256,256)
in_map = "../data/good_maps/raster_symbolizer.xml" in_map = "../data/good_maps/raster_symbolizer.xml"
try: if datasources_available(in_map):
mapnik.load_map(map, in_map) mapnik.load_map(m, in_map)
out_map = mapnik.save_map_to_string(m)
out_map = mapnik.save_map_to_string(map)
assert 'RasterSymbolizer' in out_map assert 'RasterSymbolizer' in out_map
assert 'RasterColorizer' in out_map assert 'RasterColorizer' in out_map
assert 'stop' in out_map assert 'stop' in out_map
except RuntimeError, e:
# only test datasources that we have installed
if not 'Could not create datasource' in str(e):
raise RuntimeError(str(e))
def test_raster_with_alpha_blends_correctly_with_background(): def test_raster_with_alpha_blends_correctly_with_background():
WIDTH = 500 WIDTH = 500
HEIGHT = 500 HEIGHT = 500
map = mapnik.Map(WIDTH, HEIGHT) m = mapnik.Map(WIDTH, HEIGHT)
WHITE = mapnik.Color(255, 255, 255) WHITE = mapnik.Color(255, 255, 255)
map.background = WHITE m.background = WHITE
style = mapnik.Style() style = mapnik.Style()
rule = mapnik.Rule() rule = mapnik.Rule()
@ -119,20 +115,20 @@ def test_raster_with_alpha_blends_correctly_with_background():
rule.symbols.append(symbolizer) rule.symbols.append(symbolizer)
style.rules.append(rule) style.rules.append(rule)
map.append_style('raster_style', style) m.append_style('raster_style', style)
map_layer = mapnik.Layer('test_layer') map_layer = mapnik.Layer('test_layer')
filepath = '../data/raster/white-alpha.png' filepath = '../data/raster/white-alpha.png'
if 'gdal' in mapnik.DatasourceCache.plugin_names(): if 'gdal' in mapnik.DatasourceCache.plugin_names():
map_layer.datasource = mapnik.Gdal(file=filepath) map_layer.datasource = mapnik.Gdal(file=filepath)
map_layer.styles.append('raster_style') map_layer.styles.append('raster_style')
map.layers.append(map_layer) m.layers.append(map_layer)
map.zoom_all() m.zoom_all()
mim = mapnik.Image(WIDTH, HEIGHT) mim = mapnik.Image(WIDTH, HEIGHT)
mapnik.render(map, mim) mapnik.render(m, mim)
imdata = mim.tostring() imdata = mim.tostring()
# All white is expected # All white is expected
eq_(get_unique_colors(mim),['rgba(254,254,254,255)']) eq_(get_unique_colors(mim),['rgba(254,254,254,255)'])

View file

@ -5,7 +5,7 @@ from nose.tools import *
import tempfile import tempfile
import os, mapnik import os, mapnik
from nose.tools import * from nose.tools import *
from utilities import execution_path, run_all from utilities import execution_path, run_all, datasources_available
def setup(): def setup():
# All of the paths used are relative, if we run the tests # All of the paths used are relative, if we run the tests
@ -104,16 +104,15 @@ def get_paired_images(w,h,mapfile):
return im,im2 return im,im2
def test_render_from_serialization(): def test_render_from_serialization():
try: xmlfile = '../data/good_maps/building_symbolizer.xml'
im,im2 = get_paired_images(100,100,'../data/good_maps/building_symbolizer.xml') if datasources_available(xmlfile):
eq_(im.tostring(),im2.tostring()) im, im2 = get_paired_images(100, 100, xmlfile)
eq_(im.tostring(), im2.tostring())
im,im2 = get_paired_images(100,100,'../data/good_maps/polygon_symbolizer.xml') xmlfile = '../data/good_maps/polygon_symbolizer.xml'
eq_(im.tostring(),im2.tostring()) if datasources_available(xmlfile):
except RuntimeError, e: im, im2 = get_paired_images(100, 100, xmlfile)
# only test datasources that we have installed eq_(im.tostring(), im2.tostring())
if not 'Could not create datasource' in str(e):
raise RuntimeError(e)
def test_render_points(): def test_render_points():
if not mapnik.has_cairo(): return if not mapnik.has_cairo(): return

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from nose.tools import * from nose.tools import *
from utilities import execution_path, run_all from utilities import execution_path, run_all, datasources_available
import tempfile import tempfile
import os, sys, glob, mapnik import os, sys, glob, mapnik
@ -11,10 +11,16 @@ def setup():
# from another directory we need to chdir() # from another directory we need to chdir()
os.chdir(execution_path('.')) os.chdir(execution_path('.'))
def compare_map(xml): def compare_map(xmlfile):
missing_plugins = set()
have_inputs = datasources_available(xmlfile, missing_plugins)
if not have_inputs:
print 'Notice: skipping map comparison for %s due to unavailable input plugins: %s' % (os.path.basename(xmlfile), list(missing_plugins))
return False
m = mapnik.Map(256, 256) m = mapnik.Map(256, 256)
absolute_base = os.path.abspath(os.path.dirname(xml)) absolute_base = os.path.abspath(os.path.dirname(xmlfile))
mapnik.load_map(m, xml, False, absolute_base) mapnik.load_map(m, xmlfile, False, absolute_base)
(handle, test_map) = tempfile.mkstemp(suffix='.xml', prefix='mapnik-temp-map1-') (handle, test_map) = tempfile.mkstemp(suffix='.xml', prefix='mapnik-temp-map1-')
os.close(handle) os.close(handle)
(handle, test_map2) = tempfile.mkstemp(suffix='.xml', prefix='mapnik-temp-map2-') (handle, test_map2) = tempfile.mkstemp(suffix='.xml', prefix='mapnik-temp-map2-')
@ -23,13 +29,13 @@ def compare_map(xml):
os.remove(test_map) os.remove(test_map)
mapnik.save_map(m, test_map) mapnik.save_map(m, test_map)
new_map = mapnik.Map(256, 256) new_map = mapnik.Map(256, 256)
mapnik.load_map(new_map, test_map,False,absolute_base) mapnik.load_map(new_map, test_map, False, absolute_base)
open(test_map2,'w').write(mapnik.save_map_to_string(new_map)) open(test_map2, 'w').write(mapnik.save_map_to_string(new_map))
diff = ' diff %s %s' % (os.path.abspath(test_map),os.path.abspath(test_map2)) diff = ' diff %s %s' % (os.path.abspath(test_map), os.path.abspath(test_map2))
try: try:
eq_(open(test_map).read(),open(test_map2).read()) eq_(open(test_map).read(), open(test_map2).read())
except AssertionError, e: except AssertionError, e:
raise AssertionError('serialized map "%s" not the same after being reloaded, \ncompare with command:\n\n$%s' % (xml,diff)) raise AssertionError('serialized map "%s" not the same after being reloaded, \ncompare with command:\n\n$%s' % (xmlfile, diff))
if os.path.exists(test_map): if os.path.exists(test_map):
os.remove(test_map) os.remove(test_map)

View file

@ -4,6 +4,7 @@
from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
import os, sys, inspect, traceback import os, sys, inspect, traceback
from xml.etree import ElementTree
import mapnik import mapnik
def execution_path(filename): def execution_path(filename):
@ -54,7 +55,7 @@ def get_unique_colors(im):
for y in range(im.height()): for y in range(im.height()):
pixel = im.get_pixel(x,y) pixel = im.get_pixel(x,y)
if pixel not in pixels: if pixel not in pixels:
pixels.append(pixel) pixels.append(pixel)
pixels = sorted(pixels) pixels = sorted(pixels)
return map(pixel2rgba,pixels) return map(pixel2rgba,pixels)
@ -86,3 +87,33 @@ def side_by_side_image(left_im, right_im):
im.blend(0, 0, left_im, 1.0) im.blend(0, 0, left_im, 1.0)
im.blend(left_im.width() + 1, 0, right_im, 1.0) im.blend(left_im.width() + 1, 0, right_im, 1.0)
return im return im
def datasources_available(map_file, missing_datasources=None):
'''
datasources_available
Determine whether the map file contains only available data source types.
@param map_file: path of XML map file
@type map_file: string
@param missing_datasources: set of data source type names. if there
are unavailable data sources, and a collection
reference is provided, it will be populated with
the names of the unavailable data sources
@type missing_datasources: set
@return: True if all referenced data source types are available,
otherwise False
'''
have_inputs = True
map_xml = ElementTree.parse(map_file)
data_source_type_params = map_xml.findall(".//Datasource/Parameter[@name=\"type\"]")
if data_source_type_params is not None and len(data_source_type_params) > 0:
for p in data_source_type_params:
dstype = p.text
if dstype not in mapnik.DatasourceCache.plugin_names():
have_inputs = False
if missing_datasources is not None:
missing_datasources.add(dstype)
return have_inputs