Merge branch 'master' into python-textplacement

This commit is contained in:
Hermann Kraus 2012-02-11 11:25:28 +01:00
commit 67faac351b
23 changed files with 749 additions and 96 deletions

View file

@ -14,6 +14,8 @@ For a complete change history, see the SVN log.
Mapnik 2.1.0 Mapnik 2.1.0
------------ ------------
- Removed mutex locking during reprojection if using >= proj 4.7 (#1072)
- Removed PointDatasource - use more robust MemoryDatasource instead (#1032) - Removed PointDatasource - use more robust MemoryDatasource instead (#1032)
- SQLite - Added support for !intersects! token in sql subselects (#809) allow custom positioning of rtree spatial filter. - SQLite - Added support for !intersects! token in sql subselects (#809) allow custom positioning of rtree spatial filter.

View file

@ -254,13 +254,17 @@ public:
std::string to_string() const std::string to_string() const
{ {
std::stringstream ss; std::stringstream ss;
ss << "Feature (" << std::endl; ss << "Feature ( id=" << id_ << std::endl;
context_type::map_type::const_iterator itr = ctx_->mapping_.begin(); context_type::map_type::const_iterator itr = ctx_->mapping_.begin();
context_type::map_type::const_iterator end = ctx_->mapping_.end(); context_type::map_type::const_iterator end = ctx_->mapping_.end();
for ( ;itr!=end; ++itr) for ( ;itr!=end; ++itr)
{
std::size_t index = itr->second;
if (index < data_.size())
{ {
ss << " " << itr->first << ":" << data_[itr->second] << std::endl; ss << " " << itr->first << ":" << data_[itr->second] << std::endl;
} }
}
ss << ")" << std::endl; ss << ")" << std::endl;
return ss.str(); return ss.str();
} }

View file

@ -0,0 +1,126 @@
/*****************************************************************************
*
* 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_FEATURE_COLLECTION_GRAMMAR_HPP
#define MAPNIK_FEATURE_COLLECTION_GRAMMAR_HPP
// mapnik
#include <mapnik/json/feature_grammar.hpp>
// spirit::qi
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/variant.hpp>
// stl
#include <iostream>
namespace mapnik { namespace json {
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;
struct generate_id
{
typedef int result_type;
generate_id(int start)
: id_(start) {}
int operator() () const
{
return id_++;
}
mutable int id_;
};
template <typename Iterator, typename FeatureType>
struct feature_collection_grammar :
qi::grammar<Iterator, std::vector<feature_ptr>(), ascii::space_type>
{
feature_collection_grammar(context_ptr const& ctx, mapnik::transcoder const& tr)
: feature_collection_grammar::base_type(feature_collection,"feature-collection"),
ctx_(ctx),
feature_g(tr),
generate_id_(1)
{
using qi::lit;
using qi::eps;
using qi::_a;
using qi::_b;
using qi::_val;
using qi::_r1;
using phoenix::push_back;
using phoenix::construct;
using phoenix::new_;
using phoenix::val;
feature_collection = lit('{') >> (type | features) % lit(",") >> lit('}')
;
type = lit("\"type\"") > lit(":") > lit("\"FeatureCollection\"")
;
features = lit("\"features\"")
> lit(":")
> lit('[')
> feature(_val) % lit(',')
> lit(']')
;
feature = eps[_a = construct<feature_ptr>(new_<feature_impl>(ctx_,generate_id_()))]
>> feature_g(*_a)[push_back(_r1,_a)]
;
type.name("type");
features.name("features");
feature.name("feature");
feature_g.name("feature-grammar");
qi::on_error<qi::fail>
(
feature_collection
, std::clog
<< phoenix::val("Error parsing GeoJSON ")
<< qi::_4
<< phoenix::val(" here: \"")
<< construct<std::string>(qi::_3, qi::_2)
<< phoenix::val("\"")
<< std::endl
);
}
context_ptr ctx_;
qi::rule<Iterator, std::vector<feature_ptr>(), ascii::space_type> feature_collection; // START
qi::rule<Iterator, ascii::space_type> type;
qi::rule<Iterator, std::vector<feature_ptr>(), ascii::space_type> features;
qi::rule<Iterator, qi::locals<feature_ptr,int>, void(std::vector<feature_ptr>&), ascii::space_type> feature;
feature_grammar<Iterator,FeatureType> feature_g;
boost::phoenix::function<generate_id> generate_id_;
};
}}
#endif // MAPNIK_FEATURE_COLLECTION_GRAMMAR_HPP

View file

@ -0,0 +1,57 @@
/*****************************************************************************
*
* 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_FEATURE_COLLECTION_PARSER_HPP
#define MAPNIK_FEATURE_COLLECTION_PARSER_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
//#include <mapnik/json/feature_collection_grammar.hpp>
// boost
#include <boost/scoped_ptr.hpp>
#include <boost/utility.hpp>
// stl
#include <vector>
namespace mapnik { namespace json {
template <typename Iterator, typename FeatureType> struct feature_collection_grammar;
class feature_collection_parser //: private boost::noncopyable
{
typedef std::string::const_iterator iterator_type;
typedef mapnik::Feature feature_type;
public:
feature_collection_parser(mapnik::context_ptr const& ctx, mapnik::transcoder const& tr);
~feature_collection_parser();
bool parse(std::string const& json, std::vector<mapnik::feature_ptr> & features);
private:
boost::scoped_ptr<mapnik::json::feature_collection_grammar<iterator_type,feature_type> > grammar_;
};
}}
#endif //MAPNIK_FEATURE_COLLECTION_PARSER_HPP

View file

@ -0,0 +1,384 @@
/*****************************************************************************
*
* 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_FEATURE_GRAMMAR_HPP
#define MAPNIK_FEATURE_GRAMMAR_HPP
// mapnik
#include <mapnik/geometry.hpp>
// spirit::qi
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/variant.hpp>
// stl
#include <iostream>
namespace mapnik { namespace json {
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace fusion = boost::fusion;
namespace ascii = boost::spirit::ascii;
class attribute_value_visitor
: public boost::static_visitor<mapnik::value>
{
public:
attribute_value_visitor(mapnik::transcoder const& tr)
: tr_(tr) {}
mapnik::value operator()(std::string const& val) const
{
return mapnik::value(tr_.transcode(val.c_str()));
}
template <typename T>
mapnik::value operator()(T const& val) const
{
return mapnik::value(val);
}
mapnik::transcoder const& tr_;
};
struct put_property
{
template <typename T0,typename T1, typename T2>
struct result
{
typedef void type;
};
explicit put_property(mapnik::transcoder const& tr)
: tr_(tr) {}
template <typename T0,typename T1, typename T2>
void operator() (T0 & feature, T1 const& key, T2 const& val) const
{
mapnik::value v = boost::apply_visitor(attribute_value_visitor(tr_),val); // TODO: optimize
feature.put_new(key, v);
}
mapnik::transcoder const& tr_;
};
struct extract_geometry
{
template <typename T>
struct result
{
typedef boost::ptr_vector<mapnik::geometry_type>& type;
};
template <typename T>
boost::ptr_vector<mapnik::geometry_type>& operator() (T & feature) const
{
return feature.paths();
}
};
struct push_vertex
{
template <typename T0,typename T1, typename T2, typename T3>
struct result
{
typedef void type;
};
template <typename T0,typename T1, typename T2, typename T3>
void operator() (T0 c, T1 path, T2 x, T3 y) const
{
BOOST_ASSERT( path!=0 );
path->push_vertex(x,y,c);
}
};
struct cleanup
{
template <typename T0>
struct result
{
typedef void type;
};
template <typename T0>
void operator() (T0 & path) const
{
if (path) delete path, path=0;
}
};
template <typename Iterator, typename FeatureType>
struct feature_grammar :
qi::grammar<Iterator, void(FeatureType&),
ascii::space_type>
{
feature_grammar(mapnik::transcoder const& tr)
: feature_grammar::base_type(feature,"feature"),
put_property_(put_property(tr))
{
using qi::lit;
using qi::int_;
using qi::double_;
#if BOOST_VERSION > 104200
using qi::no_skip;
#else
using qi::lexeme;
#endif
using ascii::char_;
using qi::_val;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_a;
using qi::_b;
using qi::_r1;
using qi::_r2;
using qi::fail;
using qi::on_error;
using qi::_pass;
using qi::eps;
using qi::raw;
using phoenix::new_;
using phoenix::push_back;
using phoenix::construct;
// generic json types
value = object | array | string_
| number
;
pairs = key_value % lit(',')
;
key_value = (string_ >> lit(':') >> value)
;
object = lit('{')
>> *pairs
>> lit('}')
;
array = lit('[')
>> value >> *(lit(',') >> value)
>> lit(']')
;
number %= strict_double
| int_
| lit("true") [_val = true]
| lit ("false") [_val = false]
| lit("null")[_val = construct<value_null>()]
;
unesc_char.add
("\\\"", '\"') // quotation mark
("\\\\", '\\') // reverse solidus
("\\/", '/') // solidus
("\\b", '\b') // backspace
("\\f", '\f') // formfeed
("\\n", '\n') // newline
("\\r", '\r') // carrige return
("\\t", '\t') // tab
;
string_ %= lit('"') >> *(unesc_char | "\\u" >> hex4 | (char_ - lit('"'))) >> lit('"')
;
// geojson types
feature_type = lit("\"type\"")
>> lit(':')
>> lit("\"Feature\"")
;
feature = lit('{')
>> (feature_type | (lit("\"geometry\"") > lit(':') > geometry(_r1)) | properties(_r1) | key_value) % lit(',')
>> lit('}')
;
properties = lit("\"properties\"")
>> lit(':') >> (lit('{') >> attributes(_r1) >> lit('}')) | lit("null")
;
attributes = (string_ [_a = _1] >> lit(':') >> attribute_value [put_property_(_r1,_a,_1)]) % lit(',')
;
attribute_value %= number | string_ ;
// Nabialek trick - FIXME: how to bind argument to dispatch rule?
// geometry = lit("\"geometry\"")
// >> lit(':') >> lit('{')
// >> lit("\"type\"") >> lit(':') >> geometry_dispatch[_a = _1]
// >> lit(',') >> lit("\"coordinates\"") >> lit(':')
// >> qi::lazy(*_a)
// >> lit('}')
// ;
// geometry_dispatch.add
// ("\"Point\"",&point_coordinates)
// ("\"LineString\"",&linestring_coordinates)
// ("\"Polygon\"",&polygon_coordinates)
// ;
//////////////////////////////////////////////////////////////////
geometry = (lit('{')[_a = 0 ]
>> lit("\"type\"") >> lit(':') >> geometry_dispatch[_a = _1] // <---- should be Nabialek trick!
>> lit(',')
>> (lit("\"coordinates\"") > lit(':') > coordinates(_r1,_a)
|
lit("\"geometries\"") > lit(':')
>> lit('[') >> geometry_collection(_r1) >> lit(']'))
>> lit('}'))
| lit("null")
;
geometry_dispatch.add
("\"Point\"",1)
("\"LineString\"",2)
("\"Polygon\"",3)
("\"MultiPoint\"",4)
("\"MultiLineString\"",5)
("\"MultiPolygon\"",6)
("\"GeometryCollection\"",7)
//
;
coordinates = eps(_r2 == 1) > point_coordinates(extract_geometry_(_r1))
| eps(_r2 == 2) > linestring_coordinates(extract_geometry_(_r1))
| eps(_r2 == 3) > polygon_coordinates(extract_geometry_(_r1))
| eps(_r2 == 4) > multipoint_coordinates(extract_geometry_(_r1))
| eps(_r2 == 5) > multilinestring_coordinates(extract_geometry_(_r1))
| eps(_r2 == 6) > multipolygon_coordinates(extract_geometry_(_r1))
;
point_coordinates = eps[ _a = new_<geometry_type>(Point) ]
> ( point(SEG_MOVETO,_a) [push_back(_r1,_a)] | eps[cleanup_(_a)][_pass = false] )
;
linestring_coordinates = eps[ _a = new_<geometry_type>(LineString)]
> (points(_a) [push_back(_r1,_a)]
| eps[cleanup_(_a)][_pass = false])
;
polygon_coordinates = eps[ _a = new_<geometry_type>(Polygon) ]
> ((lit('[')
> points(_a) % lit(',')
> lit(']')) [push_back(_r1,_a)]
| eps[cleanup_(_a)][_pass = false])
;
multipoint_coordinates = lit('[')
> (point_coordinates(_r1) % lit(','))
> lit(']')
;
multilinestring_coordinates = lit('[')
> (linestring_coordinates(_r1) % lit(','))
> lit(']')
;
multipolygon_coordinates = lit('[')
> (polygon_coordinates(_r1) % lit(','))
> lit(']')
;
geometry_collection = *geometry(_r1) >> *(lit(',') >> geometry(_r1))
;
// point
point = (lit('[') > double_ > lit(',') > double_ > lit(']')) [push_vertex_(_r1,_r2,_1,_2)];
// points
points = lit('[')[_a = SEG_MOVETO] > point (_a,_r1) % lit(',') [_a = SEG_LINETO] > lit(']');
on_error<fail>
(
feature
, std::cerr
<< phoenix::val("Error! Expecting ")
<< _4 // what failed?
<< phoenix::val(" here: \"")
<< construct<std::string>(_3, _2) // iterators to error-pos, end
<< phoenix::val("\"")
<< std::endl
);
}
// start
// generic JSON
qi::rule<Iterator,ascii::space_type> value;
qi::symbols<char const, char const> unesc_char;
qi::uint_parser< unsigned, 16, 4, 4 > hex4 ;
qi::rule<Iterator,std::string(), ascii::space_type> string_;
qi::rule<Iterator,ascii::space_type> key_value;
qi::rule<Iterator,boost::variant<value_null,bool,int,double>(),ascii::space_type> number;
qi::rule<Iterator,ascii::space_type> object;
qi::rule<Iterator,ascii::space_type> array;
qi::rule<Iterator,ascii::space_type> pairs;
qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
// geoJSON
qi::rule<Iterator,void(FeatureType&),ascii::space_type> feature; // START
qi::rule<Iterator,ascii::space_type> feature_type;
// Nabialek trick //////////////////////////////////////
//typedef typename qi::rule<Iterator,void(FeatureType &), ascii::space_type> dispatch_rule;
//qi::rule<Iterator,qi::locals<dispatch_rule*>, void(FeatureType&),ascii::space_type> geometry;
//qi::symbols<char, dispatch_rule*> geometry_dispatch;
////////////////////////////////////////////////////////
qi::rule<Iterator,qi::locals<int>, void(FeatureType&),ascii::space_type> geometry;
qi::symbols<char, int> geometry_dispatch;
qi::rule<Iterator,void(CommandType,geometry_type*),ascii::space_type> point;
qi::rule<Iterator,qi::locals<CommandType>,void(geometry_type*),ascii::space_type> points;
qi::rule<Iterator,void(FeatureType &,int),ascii::space_type> coordinates;
//
qi::rule<Iterator,qi::locals<geometry_type*>,
void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> point_coordinates;
qi::rule<Iterator,qi::locals<geometry_type*>,
void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> linestring_coordinates;
qi::rule<Iterator,qi::locals<geometry_type*>,
void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> polygon_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> multipoint_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> multilinestring_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> multipolygon_coordinates;
qi::rule<Iterator,void(FeatureType&),ascii::space_type> geometry_collection;
qi::rule<Iterator,void(FeatureType &),ascii::space_type> properties;
qi::rule<Iterator,qi::locals<std::string>, void(FeatureType &),ascii::space_type> attributes;
qi::rule<Iterator,boost::variant<value_null,bool,int,double,std::string>(), ascii::space_type> attribute_value;
phoenix::function<put_property> put_property_;
phoenix::function<extract_geometry> extract_geometry_;
boost::phoenix::function<push_vertex> push_vertex_;
boost::phoenix::function<cleanup> cleanup_;
};
}}
#endif // MAPNIK_FEATURE_GRAMMAR_HPP

View file

@ -144,6 +144,7 @@ public:
void to_xml(boost::property_tree::ptree &xml) const; 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(boost::property_tree::ptree const& xml);
virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const; virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const;
virtual void add_expressions(expression_set &output) const;
void set_child(node_ptr child); void set_child(node_ptr child);
node_ptr get_child() const; node_ptr get_child() const;

View file

@ -26,6 +26,8 @@
// mapnik // mapnik
#include <mapnik/config.hpp> #include <mapnik/config.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp> #include <boost/ptr_container/ptr_vector.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
// stl // stl
@ -41,7 +43,7 @@ MAPNIK_DECL bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_typ
#if BOOST_VERSION >= 104700 #if BOOST_VERSION >= 104700
class wkt_parser class wkt_parser : boost::noncopyable
{ {
typedef std::string::const_iterator iterator_type; typedef std::string::const_iterator iterator_type;
public: public:

View file

@ -17,6 +17,7 @@ plugin_sources = Split(
libraries = [] libraries = []
libraries.append('mapnik') libraries.append('mapnik')
libraries.append('boost_system%s' % env['BOOST_APPEND'])
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])
TARGET = plugin_env.SharedLibrary( TARGET = plugin_env.SharedLibrary(

View file

@ -38,6 +38,7 @@ plugin_env['LIBS'] = [env['PLUGINS']['gdal']['lib']]
# Link Library to Dependencies # Link Library to Dependencies
plugin_env['LIBS'].append('mapnik') plugin_env['LIBS'].append('mapnik')
plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND'])
plugin_env['LIBS'].append(env['ICU_LIB_NAME']) plugin_env['LIBS'].append(env['ICU_LIB_NAME'])
if env['RUNTIME_LINK'] == 'static': if env['RUNTIME_LINK'] == 'static':

View file

@ -37,6 +37,7 @@ libraries = []
# Link Library to Dependencies # Link Library to Dependencies
libraries.append('mapnik') libraries.append('mapnik')
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])
libraries.append('boost_system%s' % env['BOOST_APPEND'])
if env['THREADING'] == 'multi': if env['THREADING'] == 'multi':
libraries.append('boost_thread%s' % env['BOOST_APPEND']) libraries.append('boost_thread%s' % env['BOOST_APPEND'])

View file

@ -38,6 +38,7 @@ occi_src = Split(
libraries = [ 'occi', 'ociei' ] libraries = [ 'occi', 'ociei' ]
libraries.append('mapnik') libraries.append('mapnik')
libraries.append('boost_system%s' % env['BOOST_APPEND'])
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])
input_plugin = plugin_env.SharedLibrary('../occi', source=occi_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) input_plugin = plugin_env.SharedLibrary('../occi', source=occi_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])

View file

@ -38,6 +38,7 @@ plugin_env['LIBS'] = ['pq']
# Link Library to Dependencies # Link Library to Dependencies
plugin_env['LIBS'].append('mapnik') plugin_env['LIBS'].append('mapnik')
plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND'])
plugin_env['LIBS'].append(env['ICU_LIB_NAME']) plugin_env['LIBS'].append(env['ICU_LIB_NAME'])
if env['THREADING'] == 'multi': if env['THREADING'] == 'multi':
plugin_env['LIBS'].append('boost_thread%s' % env['BOOST_APPEND']) plugin_env['LIBS'].append('boost_thread%s' % env['BOOST_APPEND'])

View file

@ -44,6 +44,7 @@ plugin_sources = Split(
libraries = [ '' ] # eg 'libfoo' libraries = [ '' ] # eg 'libfoo'
libraries.append('mapnik') libraries.append('mapnik')
libraries.append('boost_system%s' % env['BOOST_APPEND'])
# link libicuuc, but ICU_LIB_NAME is used custom builds of icu can # link libicuuc, but ICU_LIB_NAME is used custom builds of icu can
# have different library names like osx which offers /usr/lib/libicucore.dylib # have different library names like osx which offers /usr/lib/libicucore.dylib
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])

View file

@ -189,8 +189,8 @@ void agg_renderer<T>::start_map_processing(Map const& map)
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
std::clog << "start map processing bbox=" std::clog << "start map processing bbox="
<< map.get_current_extent() << "\n"; << map.get_current_extent() << "\n";
ras_ptr->clip_box(0,0,width_,height_);
#endif #endif
ras_ptr->clip_box(0,0,width_,height_);
} }
template <typename T> template <typename T>

View file

@ -163,6 +163,7 @@ source = Split(
svg_points_parser.cpp svg_points_parser.cpp
svg_transform_parser.cpp svg_transform_parser.cpp
warp.cpp warp.cpp
json/feature_collection_parser.cpp
""" """
) )
@ -355,12 +356,14 @@ includes = glob.glob('../include/mapnik/*.hpp')
svg_includes = glob.glob('../include/mapnik/svg/*.hpp') svg_includes = glob.glob('../include/mapnik/svg/*.hpp')
wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp') wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp')
grid_includes = glob.glob('../include/mapnik/grid/*.hpp') grid_includes = glob.glob('../include/mapnik/grid/*.hpp')
json_includes = glob.glob('../include/mapnik/json/*.hpp')
util_includes = glob.glob('../include/mapnik/util/*.hpp') util_includes = glob.glob('../include/mapnik/util/*.hpp')
inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik') inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik')
svg_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/svg') svg_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/svg')
wkt_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/wkt') wkt_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/wkt')
grid_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/grid') grid_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/grid')
json_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/json')
util_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/util') util_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/util')
if 'uninstall' not in COMMAND_LINE_TARGETS: if 'uninstall' not in COMMAND_LINE_TARGETS:
@ -368,10 +371,12 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
env.Alias(target='install', source=env.Install(svg_inc_target, svg_includes)) env.Alias(target='install', source=env.Install(svg_inc_target, svg_includes))
env.Alias(target='install', source=env.Install(wkt_inc_target, wkt_includes)) env.Alias(target='install', source=env.Install(wkt_inc_target, wkt_includes))
env.Alias(target='install', source=env.Install(grid_inc_target, grid_includes)) env.Alias(target='install', source=env.Install(grid_inc_target, grid_includes))
env.Alias(target='install', source=env.Install(json_inc_target, json_includes))
env.Alias(target='install', source=env.Install(util_inc_target, util_includes)) env.Alias(target='install', source=env.Install(util_inc_target, util_includes))
env['create_uninstall_target'](env, inc_target) env['create_uninstall_target'](env, inc_target)
env['create_uninstall_target'](env, svg_inc_target) env['create_uninstall_target'](env, svg_inc_target)
env['create_uninstall_target'](env, wkt_inc_target) env['create_uninstall_target'](env, wkt_inc_target)
env['create_uninstall_target'](env, grid_inc_target) env['create_uninstall_target'](env, grid_inc_target)
env['create_uninstall_target'](env, json_inc_target)
env['create_uninstall_target'](env, util_inc_target) env['create_uninstall_target'](env, util_inc_target)

View file

@ -38,7 +38,7 @@ extern "C"
#include <mapnik/map.hpp> #include <mapnik/map.hpp>
// boost // boost
#include <boost/lexical_cast.hpp> #include <boost/spirit/include/qi.hpp>
// jpeg // jpeg
#if defined(HAVE_JPEG) #if defined(HAVE_JPEG)
@ -73,6 +73,8 @@ extern "C"
#include "agg_trans_affine.h" #include "agg_trans_affine.h"
#include "agg_image_filters.h" #include "agg_image_filters.h"
using namespace boost::spirit;
namespace mapnik namespace mapnik
{ {
@ -156,85 +158,84 @@ void handle_png_options(std::string const& type,
{ {
*use_octree = true; *use_octree = true;
} }
else if (boost::algorithm::istarts_with(t,std::string("c="))) else if (boost::algorithm::starts_with(t, "c="))
{
try
{ {
if (*colors < 0) if (*colors < 0)
throw ImageWriterException("invalid color parameter: unavailable for true color images"); throw ImageWriterException("invalid color parameter: unavailable for true color images");
*colors = boost::lexical_cast<int>(t.substr(2));
if (*colors < 0 || *colors > 256) std::string const& val = t.substr(2);
throw ImageWriterException("invalid color parameter: " + t.substr(2) + " out of bounds"); std::string::const_iterator str_beg = val.begin();
std::string::const_iterator str_end = val.end();
bool r = qi::phrase_parse(str_beg,str_end,qi::int_,ascii::space,*colors);
if (!r || (str_beg != str_end) || *colors < 0 || *colors > 256)
throw ImageWriterException("invalid color parameter: " + val);
} }
catch(boost::bad_lexical_cast &) else if (boost::algorithm::starts_with(t, "t="))
{
throw ImageWriterException("invalid color parameter: " + t.substr(2));
}
}
else if (boost::algorithm::istarts_with(t, std::string("t=")))
{
try
{ {
if (*colors < 0) if (*colors < 0)
throw ImageWriterException("invalid trans_mode parameter: unavailable for true color images"); throw ImageWriterException("invalid trans_mode parameter: unavailable for true color images");
*trans_mode = boost::lexical_cast<int>(t.substr(2));
if (*trans_mode < 0 || *trans_mode > 2) std::string const& val = t.substr(2);
throw ImageWriterException("invalid trans_mode parameter: " + t.substr(2) + " out of bounds"); std::string::const_iterator str_beg = val.begin();
std::string::const_iterator str_end = val.end();
bool r = qi::phrase_parse(str_beg,str_end,qi::int_,ascii::space,*trans_mode);
if (!r || (str_beg != str_end) || *trans_mode < 0 || *trans_mode > 2)
throw ImageWriterException("invalid trans_mode parameter: " + val);
} }
catch(boost::bad_lexical_cast &) else if (boost::algorithm::starts_with(t, "g="))
{
throw ImageWriterException("invalid trans_mode parameter: " + t.substr(2));
}
}
else if (boost::algorithm::istarts_with(t, std::string("g=")))
{
try
{ {
if (*colors < 0) if (*colors < 0)
throw ImageWriterException("invalid gamma parameter: unavailable for true color images"); throw ImageWriterException("invalid gamma parameter: unavailable for true color images");
*gamma = boost::lexical_cast<double>(t.substr(2)); std::string const& val = t.substr(2);
if (*gamma < 0) std::string::const_iterator str_beg = val.begin();
throw ImageWriterException("invalid gamma parameter: " + t.substr(2) + " out of bounds"); std::string::const_iterator str_end = val.end();
} bool r = qi::phrase_parse(str_beg,str_end,qi::double_,ascii::space,*gamma);
catch(boost::bad_lexical_cast &) if (!r || (str_beg != str_end) || *gamma < 0)
{ {
throw ImageWriterException("invalid gamma parameter: " + t.substr(2)); throw ImageWriterException("invalid gamma parameter: " + val);
} }
} }
else if (boost::algorithm::istarts_with(t,std::string("z="))) else if (boost::algorithm::starts_with(t, "z="))
{ {
try
{
*compression = boost::lexical_cast<int>(t.substr(2));
/* /*
#define Z_NO_COMPRESSION 0 #define Z_NO_COMPRESSION 0
#define Z_BEST_SPEED 1 #define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9 #define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1) #define Z_DEFAULT_COMPRESSION (-1)
*/ */
if (*compression < Z_DEFAULT_COMPRESSION || *compression > Z_BEST_COMPRESSION) std::string const& val = t.substr(2);
throw ImageWriterException("invalid compression parameter: " + t.substr(2) + " out of bounds (only -1 through 9 are valid)"); std::string::const_iterator str_beg = val.begin();
} std::string::const_iterator str_end = val.end();
catch(boost::bad_lexical_cast &) bool r = qi::phrase_parse(str_beg,str_end,qi::int_,ascii::space,*compression);
if (!r || (str_beg != str_end)
|| *compression < Z_DEFAULT_COMPRESSION
|| *compression > Z_BEST_COMPRESSION)
{ {
throw ImageWriterException("invalid compression parameter: " + t.substr(2)); throw ImageWriterException("invalid compression parameter: " + val + " (only -1 through 9 are valid)");
} }
} }
else if (boost::algorithm::istarts_with(t,std::string("s="))) else if (boost::algorithm::starts_with(t, "s="))
{ {
try std::string const& s = t.substr(2);
if (s == "default")
{ {
std::string s = boost::lexical_cast<std::string>(t.substr(2)); *strategy = Z_DEFAULT_STRATEGY;
if (s == "default") *strategy = Z_DEFAULT_STRATEGY; }
else if (s == "filtered") *strategy = Z_FILTERED; else if (s == "filtered")
else if (s == "huff") *strategy = Z_HUFFMAN_ONLY; {
else if (s == "rle") *strategy = Z_RLE; *strategy = Z_FILTERED;
}
else if (s == "huff")
{
*strategy = Z_HUFFMAN_ONLY;
}
else if (s == "rle")
{
*strategy = Z_RLE;
}
else else
throw ImageWriterException("invalid compression strategy parameter: " + s);
}
catch(boost::bad_lexical_cast &)
{ {
throw ImageWriterException("invalid compression strategy parameter: " + t.substr(2)); throw ImageWriterException("invalid compression strategy parameter: " + s);
} }
} }
} }
@ -247,10 +248,11 @@ void save_to_stream(T const& image,
std::string const& type, std::string const& type,
rgba_palette const& palette) rgba_palette const& palette)
{ {
if (stream) if (stream && image.width() > 0 && image.height() > 0)
{ {
//all this should go into image_writer factory //all this should go into image_writer factory
if (type == "png" || boost::algorithm::istarts_with(type, std::string("png"))) std::string t = boost::algorithm::to_lower_copy(type);
if (t == "png" || boost::algorithm::starts_with(t, "png"))
{ {
int colors = 256; int colors = 256;
int compression = Z_DEFAULT_COMPRESSION; int compression = Z_DEFAULT_COMPRESSION;
@ -259,7 +261,7 @@ void save_to_stream(T const& image,
double gamma = -1; double gamma = -1;
bool use_octree = true; bool use_octree = true;
handle_png_options(type, handle_png_options(t,
&colors, &colors,
&compression, &compression,
&strategy, &strategy,
@ -276,12 +278,12 @@ void save_to_stream(T const& image,
else else
save_as_png8_hex(stream, image, colors, compression, strategy, trans_mode, gamma); save_as_png8_hex(stream, image, colors, compression, strategy, trans_mode, gamma);
} }
else if (boost::algorithm::istarts_with(type, std::string("tif"))) else if (boost::algorithm::starts_with(t, "tif"))
{ {
throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)"); throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)");
} }
#if defined(HAVE_JPEG) #if defined(HAVE_JPEG)
else if (boost::algorithm::istarts_with(type, std::string("jpeg"))) else if (boost::algorithm::starts_with(t, "jpeg"))
{ {
throw ImageWriterException("palettes are not currently supported when writing to jpeg format"); throw ImageWriterException("palettes are not currently supported when writing to jpeg format");
} }
@ -297,10 +299,11 @@ void save_to_stream(T const& image,
std::ostream & stream, std::ostream & stream,
std::string const& type) std::string const& type)
{ {
if (stream) if (stream && image.width() > 0 && image.height() > 0)
{ {
//all this should go into image_writer factory //all this should go into image_writer factory
if (type == "png" || boost::algorithm::istarts_with(type, std::string("png"))) std::string t = boost::algorithm::to_lower_copy(type);
if (t == "png" || boost::algorithm::starts_with(t, "png"))
{ {
int colors = 256; int colors = 256;
int compression = Z_DEFAULT_COMPRESSION; int compression = Z_DEFAULT_COMPRESSION;
@ -309,7 +312,7 @@ void save_to_stream(T const& image,
double gamma = -1; double gamma = -1;
bool use_octree = true; bool use_octree = true;
handle_png_options(type, handle_png_options(t,
&colors, &colors,
&compression, &compression,
&strategy, &strategy,
@ -324,29 +327,27 @@ void save_to_stream(T const& image,
else else
save_as_png8_hex(stream, image, colors, compression, strategy, trans_mode, gamma); save_as_png8_hex(stream, image, colors, compression, strategy, trans_mode, gamma);
} }
else if (boost::algorithm::istarts_with(type, std::string("tif"))) else if (boost::algorithm::starts_with(t, "tif"))
{ {
save_as_tiff(stream, image); save_as_tiff(stream, image);
} }
#if defined(HAVE_JPEG) #if defined(HAVE_JPEG)
else if (boost::algorithm::istarts_with(type, std::string("jpeg"))) else if (boost::algorithm::starts_with(t, "jpeg"))
{ {
int quality = 85; int quality = 85;
try std::string const& val = t.substr(4);
if(!val.empty())
{ {
if(type.substr(4).length() != 0) std::string::const_iterator str_beg = val.begin();
std::string::const_iterator str_end = val.end();
bool r = qi::phrase_parse(str_beg,str_end,qi::int_,ascii::space,quality);
if (!r || (str_beg != str_end) || quality < 0 || quality > 100)
{ {
quality = boost::lexical_cast<int>(type.substr(4)); throw ImageWriterException("invalid jpeg quality: " + val);
if(quality<0 || quality>100) }
throw ImageWriterException("invalid jpeg quality: " + type.substr(4) + " out of bounds");
} }
save_as_jpeg(stream, quality, image); save_as_jpeg(stream, quality, image);
} }
catch(boost::bad_lexical_cast &)
{
throw ImageWriterException("invalid jpeg quality: " + type.substr(4) + " not a number");
}
}
#endif #endif
else throw ImageWriterException("unknown file type: " + type); else throw ImageWriterException("unknown file type: " + type);
} }

View file

@ -0,0 +1,56 @@
/*****************************************************************************
*
* 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/json/feature_collection_parser.hpp>
#include <mapnik/json/feature_collection_grammar.hpp>
// boost
#include <boost/version.hpp>
#include <boost/spirit/include/qi.hpp>
namespace mapnik { namespace json {
#if BOOST_VERSION >= 104700
feature_collection_parser::feature_collection_parser(mapnik::context_ptr const& ctx, mapnik::transcoder const& tr)
: grammar_(new feature_collection_grammar<iterator_type,feature_type>(ctx,tr)) {}
feature_collection_parser::~feature_collection_parser() {}
#endif
bool feature_collection_parser::parse(std::string const& json, std::vector<mapnik::feature_ptr> & features)
{
#if BOOST_VERSION >= 104700
using namespace boost::spirit;
iterator_type first = json.begin();
iterator_type last = json.end();
return qi::phrase_parse(first, last, *grammar_, ascii::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;
#endif
}
}}

View file

@ -84,10 +84,10 @@ public:
if ( !doc ) if ( !doc )
{ {
xmlError * error = xmlCtxtGetLastError( ctx_ ); xmlError * error = xmlCtxtGetLastError( ctx_ );
std::ostringstream os;
os << "XML document not well formed";
if (error) if (error)
{ {
std::ostringstream os;
os << "XML document not well formed";
os << ": " << std::endl << error->message; os << ": " << std::endl << error->message;
// remove CR // remove CR
std::string msg = os.str().substr(0, os.str().size() - 1); std::string msg = os.str().substr(0, os.str().size() - 1);

View file

@ -102,7 +102,8 @@ bool proj_transform::forward (double * x, double * y , double * z, int point_cou
} }
do { do {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 // https://github.com/mapnik/mapnik/issues/1072
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
mutex::scoped_lock lock(projection::mutex_); mutex::scoped_lock lock(projection::mutex_);
#endif #endif
if (pj_transform( source_.proj_, dest_.proj_, point_count, if (pj_transform( source_.proj_, dest_.proj_, point_count,
@ -153,7 +154,8 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co
} }
do { do {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 // https://github.com/mapnik/mapnik/issues/1072
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
mutex::scoped_lock lock(projection::mutex_); mutex::scoped_lock lock(projection::mutex_);
#endif #endif

View file

@ -34,7 +34,7 @@
namespace mapnik { namespace mapnik {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
boost::mutex projection::mutex_; boost::mutex projection::mutex_;
#endif #endif
@ -84,7 +84,7 @@ std::string const& projection::params() const
void projection::forward(double & x, double &y ) const void projection::forward(double & x, double &y ) const
{ {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
mutex::scoped_lock lock(mutex_); mutex::scoped_lock lock(mutex_);
#endif #endif
projUV p; projUV p;
@ -102,7 +102,7 @@ void projection::forward(double & x, double &y ) const
void projection::inverse(double & x,double & y) const void projection::inverse(double & x,double & y) const
{ {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
mutex::scoped_lock lock(mutex_); mutex::scoped_lock lock(mutex_);
#endif #endif
if (is_geographic_) if (is_geographic_)
@ -120,7 +120,7 @@ void projection::inverse(double & x,double & y) const
projection::~projection() projection::~projection()
{ {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
mutex::scoped_lock lock(mutex_); mutex::scoped_lock lock(mutex_);
#endif #endif
if (proj_) pj_free(proj_); if (proj_) pj_free(proj_);
@ -131,7 +131,7 @@ projection::~projection()
void projection::init() void projection::init()
{ {
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 470
mutex::scoped_lock lock(mutex_); mutex::scoped_lock lock(mutex_);
#endif #endif
#if PJ_VERSION >= 480 #if PJ_VERSION >= 480

View file

@ -277,6 +277,11 @@ node_ptr format_node::get_child() const
return child_; return child_;
} }
void format_node::add_expressions(expression_set &output) const
{
if (child_) child_->add_expressions(output);
}
} //namespace formating } //namespace formating
/************************************************************/ /************************************************************/

View file

@ -54,7 +54,6 @@ bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths)
wkt_parser parser; wkt_parser parser;
return parser.parse(wkt,paths); return parser.parse(wkt,paths);
#else #else
// TODO - remove this after mapnik 2.0.0 release
std::ostringstream s; std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
throw std::runtime_error("mapnik::from_wkt() requires at least boost 1.47 while your build was compiled against boost " + s.str()); throw std::runtime_error("mapnik::from_wkt() requires at least boost 1.47 while your build was compiled against boost " + s.str());

View file

@ -165,6 +165,9 @@ int main (int argc,char** argv)
box2d<double> item_ext; box2d<double> item_ext;
if (shape_type==shape_io::shape_null) if (shape_type==shape_io::shape_null)
{ {
// still need to increment pos, or the pos counter
// won't indicate EOF until too late.
pos+=4+content_length;
continue; continue;
} }
else if (shape_type==shape_io::shape_point) else if (shape_type==shape_io::shape_point)