Merge remote-tracking branch 'origin/master'

This commit is contained in:
Artem Pavlenko 2012-02-22 17:17:25 +00:00
commit 5b49d64a48
11 changed files with 159 additions and 116 deletions

View file

@ -1432,7 +1432,7 @@ if not preconfigured:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts %s' % (env['OPTIMIZATION'],ndebug_flags))
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fcatch-undefined-behavior') #-ftrapv -fwrapv
env.Append(CXXFLAGS = '-fcatch-undefined-behavior -ftrapv -fwrapv')
if 'python' in env['BINDINGS']:
if not os.access(env['PYTHON'], os.X_OK):

View file

@ -188,6 +188,9 @@ void export_shield_symbolizer()
.add_property("minimum_distance",
&shield_symbolizer::get_minimum_distance,
&shield_symbolizer::set_minimum_distance)
.add_property("minimum_padding",
&shield_symbolizer::get_minimum_padding,
&shield_symbolizer::set_minimum_padding)
.add_property("name",&shield_symbolizer::get_name,
&shield_symbolizer::set_name)
.add_property("opacity",

View file

@ -357,16 +357,16 @@ void export_text_placement()
;
class_<text_symbolizer_properties>
class_with_converter<text_symbolizer_properties>
("TextSymbolizerProperties")
.def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement)
.def_readwrite_convert("horizontal_alignment", &text_symbolizer_properties::halign)
.def_readwrite_convert("justify_alignment", &text_symbolizer_properties::jalign)
.def_readwrite_convert("vertical_alignment", &text_symbolizer_properties::valign)
.def_readwrite("orientation", &text_symbolizer_properties::orientation)
.add_property("displacement",
&get_displacement,
&set_displacement)
.def_readwrite("label_placement", &text_symbolizer_properties::label_placement)
.def_readwrite("horizontal_alignment", &text_symbolizer_properties::halign)
.def_readwrite("justify_alignment", &text_symbolizer_properties::jalign)
.def_readwrite("vertical_alignment", &text_symbolizer_properties::valign)
.def_readwrite("label_spacing", &text_symbolizer_properties::label_spacing)
.def_readwrite("label_position_tolerance", &text_symbolizer_properties::label_position_tolerance)
.def_readwrite("avoid_edges", &text_symbolizer_properties::avoid_edges)
@ -483,22 +483,22 @@ void export_text_placement()
register_ptr_to_python<boost::shared_ptr<formatting::text_node> >();
class_with_optional<FormatNodeWrap,
class_with_converter<FormatNodeWrap,
boost::shared_ptr<FormatNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingFormat")
.def_readwrite_optional("text_size", &formatting::format_node::text_size)
.def_readwrite_optional("face_name", &formatting::format_node::face_name)
.def_readwrite_optional("character_spacing", &formatting::format_node::character_spacing)
.def_readwrite_optional("line_spacing", &formatting::format_node::line_spacing)
.def_readwrite_optional("text_opacity", &formatting::format_node::text_opacity)
.def_readwrite_optional("wrap_char", &formatting::format_node::wrap_char)
.def_readwrite_optional("wrap_before", &formatting::format_node::wrap_before)
.def_readwrite_optional("text_transform", &formatting::format_node::text_transform)
.def_readwrite_optional("fill", &formatting::format_node::fill)
.def_readwrite_optional("halo_fill", &formatting::format_node::halo_fill)
.def_readwrite_optional("halo_radius", &formatting::format_node::halo_radius)
.def_readwrite_convert("text_size", &formatting::format_node::text_size)
.def_readwrite_convert("face_name", &formatting::format_node::face_name)
.def_readwrite_convert("character_spacing", &formatting::format_node::character_spacing)
.def_readwrite_convert("line_spacing", &formatting::format_node::line_spacing)
.def_readwrite_convert("text_opacity", &formatting::format_node::text_opacity)
.def_readwrite_convert("wrap_char", &formatting::format_node::wrap_char)
.def_readwrite_convert("wrap_before", &formatting::format_node::wrap_before)
.def_readwrite_convert("text_transform", &formatting::format_node::text_transform)
.def_readwrite_convert("fill", &formatting::format_node::fill)
.def_readwrite_convert("halo_fill", &formatting::format_node::halo_fill)
.def_readwrite_convert("halo_radius", &formatting::format_node::halo_radius)
.def("apply", &formatting::format_node::apply, &FormatNodeWrap::default_apply)
.add_property("child",
&formatting::format_node::get_child,

View file

@ -104,31 +104,31 @@ struct python_optional : public boost::noncopyable
See http://osdir.com/ml/python.c++/2003-11/msg00158.html
*/
template <typename T, typename X1, typename X2, typename X3>
class class_with_optional : public boost::python::class_<T, X1, X2, X3>
template <typename T, typename X1 = boost::python::detail::not_specified, typename X2 = boost::python::detail::not_specified, typename X3 = boost::python::detail::not_specified>
class class_with_converter : public boost::python::class_<T, X1, X2, X3>
{
public:
typedef class_with_optional<T,X1,X2,X3> self;
typedef class_with_converter<T,X1,X2,X3> self;
// Construct with the class name, with or without docstring, and default __init__() function
class_with_optional(char const* name, char const* doc = 0) : boost::python::class_<T, X1, X2, X3>(name, doc) { }
class_with_converter(char const* name, char const* doc = 0) : boost::python::class_<T, X1, X2, X3>(name, doc) { }
// Construct with class name, no docstring, and an uncallable __init__ function
class_with_optional(char const* name, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, y) { }
class_with_converter(char const* name, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, y) { }
// Construct with class name, docstring, and an uncallable __init__ function
class_with_optional(char const* name, char const* doc, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, doc, y) { }
class_with_converter(char const* name, char const* doc, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, doc, y) { }
// Construct with class name and init<> function
template <class DerivedT> class_with_optional(char const* name, boost::python::init_base<DerivedT> const& i)
template <class DerivedT> class_with_converter(char const* name, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, i) { }
// Construct with class name, docstring and init<> function
template <class DerivedT>
inline class_with_optional(char const* name, char const* doc, boost::python::init_base<DerivedT> const& i)
inline class_with_converter(char const* name, char const* doc, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, doc, i) { }
template <class D>
self& def_readwrite_optional(char const* name, D const& d, char const* doc=0)
self& def_readwrite_convert(char const* name, D const& d, char const* doc=0)
{
this->add_property(name,
boost::python::make_getter(d, boost::python::return_value_policy<boost::python::return_by_value>()),

View file

@ -394,8 +394,16 @@ private:
// clip extreme alfa values
void create_palette_rek(std::vector<rgba> & palette, node * itr) const
{
// actually, ignore ones with < 3 pixels
if (itr->count >= 3)
/*
NOTE: previous code did:
// actually, ignore ones with < 3 pixels
if (itr->count >= 3)
But this could lead to memory corruption
*/
if (itr->count > 0)
{
unsigned count = itr->count;
byte a = byte(itr->alphas/float(count));
@ -475,8 +483,10 @@ private:
}
tries = 0;
// ignore leaves and also nodes with small mean error and not excessive number of pixels
if (((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count))) > 15
&& (cur_node->children_count > 0))
if (cur_node->pixel_count > 0 &&
(cur_node->children_count > 0) &&
(((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count))) > 15)
)
{
colors_--;
cur_node->count = 0;

View file

@ -0,0 +1,61 @@
/*****************************************************************************
*
* 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_CONVERSIONS_UTIL_HPP
#define MAPNIK_CONVERSIONS_UTIL_HPP
// mapnik
// boost
#include <boost/spirit/include/qi.hpp>
// stl
#include <string>
namespace mapnik { namespace conversions {
using namespace boost::spirit;
static bool string2int(std::string const& value, int * result)
{
if (value.empty())
return false;
std::string::const_iterator str_beg = value.begin();
std::string::const_iterator str_end = value.end();
bool r = qi::phrase_parse(str_beg,str_end,qi::int_,ascii::space,*result);
return r && (str_beg == str_end);
}
static bool string2double(std::string const& value, double * result)
{
if (value.empty())
return false;
std::string::const_iterator str_beg = value.begin();
std::string::const_iterator str_end = value.end();
bool r = qi::phrase_parse(str_beg,str_end,qi::double_,ascii::space,*result);
return r && (str_beg == str_end);
}
}
}
#endif // MAPNIK_CONVERSIONS_UTIL_HPP

View file

@ -28,10 +28,10 @@
#include <mapnik/global.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/sql_utils.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp>
@ -50,10 +50,7 @@ DATASOURCE_PLUGIN(postgis_datasource)
const std::string postgis_datasource::GEOMETRY_COLUMNS="geometry_columns";
const std::string postgis_datasource::SPATIAL_REF_SYS="spatial_ref_system";
using boost::lexical_cast;
using boost::bad_lexical_cast;
using boost::shared_ptr;
using mapnik::PoolGuard;
using mapnik::attribute_descriptor;
@ -174,13 +171,12 @@ void postgis_datasource::bind() const
if (srid_ == 0)
{
try
const char * srid_c = rs->getValue("srid");
if (srid_c != NULL)
{
srid_ = lexical_cast<int>(rs->getValue("srid"));
}
catch (bad_lexical_cast &ex)
{
std::clog << "Postgis Plugin: SRID=" << rs->getValue("srid") << " " << ex.what() << std::endl;
int result;
if (mapnik::conversions::string2int(srid_c,&result))
srid_ = result;
}
}
}
@ -205,13 +201,12 @@ void postgis_datasource::bind() const
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next())
{
try
const char * srid_c = rs->getValue("srid");
if (srid_c != NULL)
{
srid_ = lexical_cast<int>(rs->getValue("srid"));
}
catch (bad_lexical_cast &ex)
{
std::clog << "Postgis Plugin: SRID=" << rs->getValue("srid") << " " << ex.what() << std::endl;
int result;
if (mapnik::conversions::string2int(srid_c,&result))
srid_ = result;
}
}
rs->close();
@ -384,8 +379,9 @@ std::string postgis_datasource::populate_tokens(const std::string& sql) const
}
if ( boost::algorithm::icontains(sql,scale_denom_token_) )
{
std::string max_denom = lexical_cast<std::string>(FMAX);
boost::algorithm::replace_all(populated_sql,scale_denom_token_,max_denom);
std::ostringstream ss;
ss << FMAX;
boost::algorithm::replace_all(populated_sql,scale_denom_token_,ss.str());
}
return populated_sql;
}
@ -397,8 +393,9 @@ std::string postgis_datasource::populate_tokens(const std::string& sql, double s
if ( boost::algorithm::icontains(populated_sql,scale_denom_token_) )
{
std::string max_denom = lexical_cast<std::string>(scale_denom);
boost::algorithm::replace_all(populated_sql,scale_denom_token_,max_denom);
std::ostringstream ss;
ss << scale_denom;
boost::algorithm::replace_all(populated_sql,scale_denom_token_,ss.str());
}
if ( boost::algorithm::icontains(populated_sql,bbox_token_) )
@ -684,19 +681,22 @@ box2d<double> postgis_datasource::envelope() const
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next() && !rs->isNull(0))
{
try
{
double lox = lexical_cast<double>(rs->getValue(0));
double loy = lexical_cast<double>(rs->getValue(1));
double hix = lexical_cast<double>(rs->getValue(2));
double hiy = lexical_cast<double>(rs->getValue(3));
extent_.init(lox,loy,hix,hiy);
extent_initialized_ = true;
}
catch (bad_lexical_cast &ex)
{
std::clog << boost::format("Postgis Plugin: warning: could not determine extent from query: %s\nError was: '%s'\n") % s.str() % ex.what() << std::endl;
}
double lox;
double loy;
double hix;
double hiy;
if (mapnik::conversions::string2double(rs->getValue(0),&lox) &&
mapnik::conversions::string2double(rs->getValue(1),&loy) &&
mapnik::conversions::string2double(rs->getValue(2),&hix) &&
mapnik::conversions::string2double(rs->getValue(3),&hiy))
{
extent_.init(lox,loy,hix,hiy);
extent_initialized_ = true;
}
else
{
std::clog << boost::format("Postgis Plugin: warning: could not determine extent from query: %s\n") % s.str() << std::endl;
}
}
rs->close();
}

View file

@ -31,7 +31,6 @@
#include <mapnik/feature_layer_desc.hpp>
// boost
#include <boost/lexical_cast.hpp>
#include <boost/scoped_ptr.hpp>
#include "connection_manager.hpp"

View file

@ -30,17 +30,16 @@
#include <mapnik/unicode.hpp>
#include <mapnik/sql_utils.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/spirit/include/qi.hpp>
// stl
#include <sstream>
#include <string>
using boost::lexical_cast;
using boost::bad_lexical_cast;
using boost::trim_copy;
using mapnik::geometry_type;
using mapnik::byte;
@ -162,15 +161,9 @@ feature_ptr postgis_featureset::next()
else if (oid == 1700) // numeric
{
std::string str = mapnik::sql_utils::numeric2string(buf);
try
{
double val = boost::lexical_cast<double>(str);
double val;
if (mapnik::conversions::string2double(str,&val))
feature->put(name,val);
}
catch (boost::bad_lexical_cast & ex)
{
std::clog << ex.what() << "\n";
}
}
else
{

View file

@ -36,9 +36,7 @@ extern "C"
#include <mapnik/image_view.hpp>
#include <mapnik/palette.hpp>
#include <mapnik/map.hpp>
// boost
#include <boost/spirit/include/qi.hpp>
#include <mapnik/util/conversions.hpp>
// jpeg
#if defined(HAVE_JPEG)
@ -73,9 +71,6 @@ extern "C"
#include "agg_trans_affine.h"
#include "agg_image_filters.h"
using namespace boost::spirit;
namespace mapnik
{
@ -163,36 +158,24 @@ void handle_png_options(std::string const& type,
if (*colors < 0)
throw ImageWriterException("invalid color parameter: unavailable for true color images");
std::string const& val = t.substr(2);
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);
if (!mapnik::conversions::string2int(t.substr(2),colors) || *colors < 0 || *colors > 256)
throw ImageWriterException("invalid color parameter: " + t.substr(2));
}
else if (boost::algorithm::starts_with(t, "t="))
{
if (*colors < 0)
throw ImageWriterException("invalid trans_mode parameter: unavailable for true color images");
std::string const& val = t.substr(2);
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);
if (!mapnik::conversions::string2int(t.substr(2),trans_mode) || *trans_mode < 0 || *trans_mode > 2)
throw ImageWriterException("invalid trans_mode parameter: " + t.substr(2));
}
else if (boost::algorithm::starts_with(t, "g="))
{
if (*colors < 0)
throw ImageWriterException("invalid gamma parameter: unavailable for true color images");
std::string const& val = t.substr(2);
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::double_,ascii::space,*gamma);
if (!r || (str_beg != str_end) || *gamma < 0)
if (!mapnik::conversions::string2double(t.substr(2),gamma) || *gamma < 0)
{
throw ImageWriterException("invalid gamma parameter: " + val);
throw ImageWriterException("invalid gamma parameter: " + t.substr(2));
}
}
else if (boost::algorithm::starts_with(t, "z="))
@ -203,15 +186,11 @@ void handle_png_options(std::string const& type,
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
*/
std::string const& val = t.substr(2);
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,*compression);
if (!r || (str_beg != str_end)
if (!mapnik::conversions::string2int(t.substr(2),compression)
|| *compression < Z_DEFAULT_COMPRESSION
|| *compression > Z_BEST_COMPRESSION)
{
throw ImageWriterException("invalid compression parameter: " + val + " (only -1 through 9 are valid)");
throw ImageWriterException("invalid compression parameter: " + t.substr(2) + " (only -1 through 9 are valid)");
}
}
else if (boost::algorithm::starts_with(t, "s="))
@ -336,14 +315,11 @@ void save_to_stream(T const& image,
{
int quality = 85;
std::string const& val = t.substr(4);
if(!val.empty())
if (!val.empty())
{
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)
if (!mapnik::conversions::string2int(val,&quality) || quality < 0 || quality > 100)
{
throw ImageWriterException("invalid jpeg quality: " + val);
throw ImageWriterException("invalid jpeg quality: '" + val + "'");
}
}
save_as_jpeg(stream, quality, image);

View file

@ -198,10 +198,11 @@ def test_textsymbolizer_init():
ts = mapnik.TextSymbolizer(mapnik.Expression('[Field_Name]'), 'Font Name', 8, mapnik.Color('black'))
# eq_(str(ts.name), str(mapnik2.Expression('[Field_Name]'))) name field is no longer supported
eq_(ts.face_name, 'Font Name')
eq_(ts.text_size, 8)
eq_(ts.fill, mapnik.Color('black'))
eq_(ts.label_placement, mapnik.label_placement.POINT_PLACEMENT)
eq_(ts.format.face_name, 'Font Name')
eq_(ts.format.text_size, 8)
eq_(ts.format.fill, mapnik.Color('black'))
eq_(ts.properties.label_placement, mapnik.label_placement.POINT_PLACEMENT)
eq_(ts.properties.horizontal_alignment, mapnik.horizontal_alignment.AUTO)
# Map initialization
def test_layer_init():