Merge branch 'master' into mapnik-geometry
This commit is contained in:
commit
317e9c497f
21 changed files with 251 additions and 77 deletions
|
@ -52,6 +52,7 @@ Mapnik is written by Artem Pavlenko with contributions from:
|
|||
* Igor Podolskiy
|
||||
* Reid Priedhorsky
|
||||
* Brian Quinion
|
||||
* Even Rouault
|
||||
* Marcin Rudowski
|
||||
* Sandro Santilli
|
||||
* Christopher Schmidt
|
||||
|
|
13
SConstruct
13
SConstruct
|
@ -1283,10 +1283,11 @@ if not preconfigured:
|
|||
else:
|
||||
env['MISSING_DEPS'].append('libxml2')
|
||||
|
||||
if conf.CheckHasDlfcn():
|
||||
env.Append(CPPDEFINES = '-DMAPNIK_HAS_DLCFN')
|
||||
else:
|
||||
env['SKIPPED_DEPS'].extend(['dlfcn'])
|
||||
if not env['HOST']:
|
||||
if conf.CheckHasDlfcn():
|
||||
env.Append(CPPDEFINES = '-DMAPNIK_HAS_DLCFN')
|
||||
else:
|
||||
env['SKIPPED_DEPS'].extend(['dlfcn'])
|
||||
|
||||
OPTIONAL_LIBSHEADERS = []
|
||||
|
||||
|
@ -1340,7 +1341,7 @@ if not preconfigured:
|
|||
conf.prioritize_paths(silent=True)
|
||||
|
||||
# test for C++11 support, which is required
|
||||
if not conf.supports_cxx11():
|
||||
if not env['HOST'] and not conf.supports_cxx11():
|
||||
color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler to at least g++ 4.7 (ideally 4.8)")
|
||||
Exit(1)
|
||||
|
||||
|
@ -1361,7 +1362,7 @@ if not preconfigured:
|
|||
env['MISSING_DEPS'].append(env['ICU_LIB_NAME'])
|
||||
elif libname == 'harfbuzz':
|
||||
if not conf.harfbuzz_version():
|
||||
env['MISSING_DEPS'].append('harfbuzz-min-version')
|
||||
env['SKIPPED_DEPS'].append('harfbuzz-min-version')
|
||||
|
||||
if env['BIGINT']:
|
||||
env.Append(CPPDEFINES = '-DBIGINT')
|
||||
|
|
|
@ -222,6 +222,11 @@ void set_pixel_int(mapnik::image_any & im, unsigned x, unsigned y, int val)
|
|||
mapnik::set_pixel(im, x, y, val);
|
||||
}
|
||||
|
||||
unsigned get_type(mapnik::image_any & im)
|
||||
{
|
||||
return im.get_dtype();
|
||||
}
|
||||
|
||||
std::shared_ptr<image_any> open_from_file(std::string const& filename)
|
||||
{
|
||||
boost::optional<std::string> type = type_from_filename(filename);
|
||||
|
@ -441,6 +446,7 @@ void export_image()
|
|||
arg("y"),
|
||||
arg("get_color")=false
|
||||
))
|
||||
.def("get_type",&get_type)
|
||||
.def("clear",&clear)
|
||||
//TODO(haoyu) The method name 'tostring' might be confusing since they actually return bytes in Python 3
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ class image
|
|||
public:
|
||||
using pixel = T;
|
||||
using pixel_type = typename T::type;
|
||||
static const image_dtype dtype = T::id;
|
||||
static constexpr std::size_t pixel_size = sizeof(pixel_type);
|
||||
private:
|
||||
detail::image_dimensions<max_size> dimensions_;
|
||||
|
@ -313,6 +314,11 @@ public:
|
|||
{
|
||||
return painted_;
|
||||
}
|
||||
|
||||
inline image_dtype get_dtype() const
|
||||
{
|
||||
return dtype;
|
||||
}
|
||||
};
|
||||
|
||||
using image_rgba8 = image<rgba8_t>;
|
||||
|
@ -327,22 +333,6 @@ using image_gray64 = image<gray64_t>;
|
|||
using image_gray64s = image<gray64s_t>;
|
||||
using image_gray64f = image<gray64f_t>;
|
||||
|
||||
enum image_dtype : std::uint8_t
|
||||
{
|
||||
image_dtype_rgba8 = 0,
|
||||
image_dtype_gray8,
|
||||
image_dtype_gray8s,
|
||||
image_dtype_gray16,
|
||||
image_dtype_gray16s,
|
||||
image_dtype_gray32,
|
||||
image_dtype_gray32s,
|
||||
image_dtype_gray32f,
|
||||
image_dtype_gray64,
|
||||
image_dtype_gray64s,
|
||||
image_dtype_gray64f,
|
||||
image_dtype_null
|
||||
};
|
||||
|
||||
} // end ns
|
||||
|
||||
#endif // MAPNIK_IMAGE_DATA_HPP
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace mapnik {
|
|||
struct image_null
|
||||
{
|
||||
using pixel_type = uint8_t;
|
||||
static const image_dtype dtype = image_dtype_null;
|
||||
unsigned char const* getBytes() const { return nullptr; }
|
||||
unsigned char* getBytes() { return nullptr;}
|
||||
unsigned getSize() const { return 0; }
|
||||
|
@ -40,6 +41,7 @@ struct image_null
|
|||
bool painted() const { return false; }
|
||||
double get_offset() const { return 0.0; }
|
||||
void set_offset(double) {}
|
||||
image_dtype get_dtype() const { return dtype; }
|
||||
double get_scaling() const { return 1.0; }
|
||||
void set_scaling(double) {}
|
||||
bool get_premultiplied() const { return false; }
|
||||
|
@ -88,6 +90,15 @@ struct get_bytes_visitor
|
|||
}
|
||||
};
|
||||
|
||||
struct get_dtype_visitor
|
||||
{
|
||||
template <typename T>
|
||||
image_dtype operator()(T & data)
|
||||
{
|
||||
return data.get_dtype();
|
||||
}
|
||||
};
|
||||
|
||||
struct get_bytes_visitor_const
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -263,6 +274,11 @@ struct image_any : image_base
|
|||
return util::apply_visitor(detail::get_scaling_visitor(),*this);
|
||||
}
|
||||
|
||||
image_dtype get_dtype() const
|
||||
{
|
||||
return util::apply_visitor(detail::get_dtype_visitor(),*this);
|
||||
}
|
||||
|
||||
void set_offset(double val)
|
||||
{
|
||||
util::apply_visitor(detail::set_offset_visitor(val),*this);
|
||||
|
@ -306,6 +322,7 @@ inline image_any create_image_any(int width,
|
|||
case image_dtype_null:
|
||||
return image_any(std::move(image_null()));
|
||||
case image_dtype_rgba8:
|
||||
case IMAGE_DTYPE_MAX:
|
||||
default:
|
||||
return image_any(std::move(image_rgba8(width, height, initialize, premultiplied, painted)));
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ class image_view
|
|||
public:
|
||||
using pixel = typename T::pixel;
|
||||
using pixel_type = typename T::pixel_type;
|
||||
static const image_dtype dtype = T::dtype;
|
||||
static constexpr std::size_t pixel_size = sizeof(pixel_type);
|
||||
|
||||
image_view(unsigned x, unsigned y, unsigned width, unsigned height, T const& data)
|
||||
|
@ -42,10 +43,10 @@ public:
|
|||
height_(height),
|
||||
data_(data)
|
||||
{
|
||||
if (x_ >= data_.width()) x_=data_.width()-1;
|
||||
if (y_ >= data_.height()) y_=data_.height()-1;
|
||||
if (x_ + width_ > data_.width()) width_= data_.width() - x_;
|
||||
if (y_ + height_ > data_.height()) height_= data_.height() - y_;
|
||||
if (x_ >= data_.width() && data_.width() > 0) x_ = data_.width() - 1;
|
||||
if (y_ >= data_.height() && data.height() > 0) y_ = data_.height() - 1;
|
||||
if (x_ + width_ > data_.width()) width_ = data_.width() - x_;
|
||||
if (y_ + height_ > data_.height()) height_ = data_.height() - y_;
|
||||
}
|
||||
|
||||
~image_view() {}
|
||||
|
@ -131,6 +132,11 @@ public:
|
|||
{
|
||||
return data_.get_scaling();
|
||||
}
|
||||
|
||||
inline image_dtype get_dtype() const
|
||||
{
|
||||
return dtype;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned x_;
|
||||
|
|
|
@ -69,6 +69,15 @@ struct get_view_size_visitor
|
|||
}
|
||||
};
|
||||
|
||||
struct get_view_dtype_visitor
|
||||
{
|
||||
template <typename T>
|
||||
image_dtype operator()(T const& data) const
|
||||
{
|
||||
return data.get_dtype();
|
||||
}
|
||||
};
|
||||
|
||||
struct get_view_row_size_visitor
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -148,6 +157,11 @@ struct image_view_any : image_view_base
|
|||
{
|
||||
return util::apply_visitor(detail::get_view_scaling_visitor(),*this);
|
||||
}
|
||||
|
||||
image_dtype get_dtype() const
|
||||
{
|
||||
return util::apply_visitor(detail::get_view_dtype_visitor(),*this);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -25,16 +25,36 @@
|
|||
|
||||
#include <mapnik/global.hpp>
|
||||
|
||||
struct rgba8_t { using type = std::uint32_t; };
|
||||
struct gray8_t { using type = std::uint8_t; };
|
||||
struct gray8s_t { using type = std::int8_t; };
|
||||
struct gray16_t { using type = std::uint16_t; };
|
||||
struct gray16s_t { using type = std::int16_t; };
|
||||
struct gray32_t { using type = std::uint32_t; };
|
||||
struct gray32s_t { using type = std::int32_t; };
|
||||
struct gray32f_t { using type = float; };
|
||||
struct gray64_t { using type = std::uint64_t; };
|
||||
struct gray64s_t { using type = std::int64_t; };
|
||||
struct gray64f_t { using type = double; };
|
||||
namespace mapnik {
|
||||
|
||||
enum image_dtype : std::uint8_t
|
||||
{
|
||||
image_dtype_rgba8 = 0,
|
||||
image_dtype_gray8,
|
||||
image_dtype_gray8s,
|
||||
image_dtype_gray16,
|
||||
image_dtype_gray16s,
|
||||
image_dtype_gray32,
|
||||
image_dtype_gray32s,
|
||||
image_dtype_gray32f,
|
||||
image_dtype_gray64,
|
||||
image_dtype_gray64s,
|
||||
image_dtype_gray64f,
|
||||
image_dtype_null,
|
||||
IMAGE_DTYPE_MAX
|
||||
};
|
||||
|
||||
struct rgba8_t { using type = std::uint32_t; static const image_dtype id = image_dtype_rgba8; };
|
||||
struct gray8_t { using type = std::uint8_t; static const image_dtype id = image_dtype_gray8; };
|
||||
struct gray8s_t { using type = std::int8_t; static const image_dtype id = image_dtype_gray8s; };
|
||||
struct gray16_t { using type = std::uint16_t; static const image_dtype id = image_dtype_gray16; };
|
||||
struct gray16s_t { using type = std::int16_t; static const image_dtype id = image_dtype_gray16s; };
|
||||
struct gray32_t { using type = std::uint32_t; static const image_dtype id = image_dtype_gray32; };
|
||||
struct gray32s_t { using type = std::int32_t; static const image_dtype id = image_dtype_gray32s; };
|
||||
struct gray32f_t { using type = float; static const image_dtype id = image_dtype_gray32f; };
|
||||
struct gray64_t { using type = std::uint64_t; static const image_dtype id = image_dtype_gray64; };
|
||||
struct gray64s_t { using type = std::int64_t; static const image_dtype id = image_dtype_gray64s; };
|
||||
struct gray64f_t { using type = double; static const image_dtype id = image_dtype_gray64f; };
|
||||
|
||||
} // end ns
|
||||
#endif // MAPNIK_PIXEL_TYPES_HPP
|
||||
|
|
|
@ -176,18 +176,19 @@ geojson_datasource::geojson_datasource(parameters const& params)
|
|||
|
||||
namespace {
|
||||
using base_iterator_type = char const*;
|
||||
const mapnik::transcoder tr("utf8");
|
||||
const mapnik::json::feature_collection_grammar<base_iterator_type,mapnik::feature_impl> fc_grammar(tr);
|
||||
const mapnik::transcoder geojson_datasource_static_tr("utf8");
|
||||
const mapnik::json::feature_collection_grammar<base_iterator_type,mapnik::feature_impl> geojson_datasource_static_fc_grammar(geojson_datasource_static_tr);
|
||||
const mapnik::json::feature_grammar<base_iterator_type, mapnik::feature_impl> geojson_datasource_static_feature_grammar(geojson_datasource_static_tr);
|
||||
const mapnik::json::extract_bounding_box_grammar<base_iterator_type> geojson_datasource_static_bbox_grammar;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void geojson_datasource::initialise_index(Iterator start, Iterator end)
|
||||
{
|
||||
mapnik::json::boxes boxes;
|
||||
mapnik::json::extract_bounding_box_grammar<Iterator> bbox_grammar;
|
||||
boost::spirit::ascii::space_type space;
|
||||
Iterator itr = start;
|
||||
if (!boost::spirit::qi::phrase_parse(itr, end, (bbox_grammar)(boost::phoenix::ref(boxes)) , space))
|
||||
if (!boost::spirit::qi::phrase_parse(itr, end, (geojson_datasource_static_bbox_grammar)(boost::phoenix::ref(boxes)) , space))
|
||||
{
|
||||
throw mapnik::datasource_exception("GeoJSON Plugin: could not parse: '" + filename_ + "'");
|
||||
}
|
||||
|
@ -207,10 +208,8 @@ void geojson_datasource::initialise_index(Iterator start, Iterator end)
|
|||
Iterator end = itr + geometry_index.second;
|
||||
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
|
||||
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
|
||||
static const mapnik::transcoder tr("utf8");
|
||||
static const mapnik::json::feature_grammar<Iterator, mapnik::feature_impl> grammar(tr);
|
||||
boost::spirit::ascii::space_type space;
|
||||
if (!boost::spirit::qi::phrase_parse(itr, end, (grammar)(boost::phoenix::ref(*feature)), space))
|
||||
if (!boost::spirit::qi::phrase_parse(itr, end, (geojson_datasource_static_feature_grammar)(boost::phoenix::ref(*feature)), space))
|
||||
{
|
||||
throw std::runtime_error("Failed to parse geojson feature");
|
||||
}
|
||||
|
@ -237,7 +236,7 @@ void geojson_datasource::parse_geojson(Iterator start, Iterator end)
|
|||
|
||||
mapnik::json::default_feature_callback callback(features_);
|
||||
|
||||
bool result = boost::spirit::qi::phrase_parse(start, end, (fc_grammar)
|
||||
bool result = boost::spirit::qi::phrase_parse(start, end, (geojson_datasource_static_fc_grammar)
|
||||
(boost::phoenix::ref(ctx),boost::phoenix::ref(start_id), boost::phoenix::ref(callback)),
|
||||
space);
|
||||
if (!result)
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
{
|
||||
std::string err_msg = "Postgis Plugin: ";
|
||||
err_msg += status();
|
||||
err_msg += "\nConnection string: '";
|
||||
err_msg += "Connection string: '";
|
||||
err_msg += connection_str;
|
||||
err_msg += "'\n";
|
||||
MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: creation failed, closing connection - " << this;
|
||||
|
@ -71,7 +71,7 @@ public:
|
|||
if ( ! ok ) {
|
||||
std::string err_msg = "Postgis Plugin: ";
|
||||
err_msg += status();
|
||||
err_msg += "\nConnection string: '";
|
||||
err_msg += "Connection string: '";
|
||||
err_msg += connection_str;
|
||||
err_msg += "'\n";
|
||||
close();
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
{
|
||||
std::string err_msg = "Postgis Plugin: ";
|
||||
err_msg += status();
|
||||
err_msg += "\nin executeQuery Full sql was: '";
|
||||
err_msg += "in executeQuery Full sql was: '";
|
||||
err_msg += sql;
|
||||
err_msg += "'\n";
|
||||
if ( result ) PQclear(result);
|
||||
|
@ -142,12 +142,19 @@ public:
|
|||
std::string status;
|
||||
if (conn_)
|
||||
{
|
||||
if ( isOK() ) return PQerrorMessage(conn_);
|
||||
else return "Bad connection";
|
||||
char * err_msg = PQerrorMessage(conn_);
|
||||
if (err_msg == nullptr)
|
||||
{
|
||||
status = "Bad connection\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
status = std::string(err_msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = "Uninitialized connection";
|
||||
status = "Uninitialized connection\n";
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -167,7 +174,7 @@ public:
|
|||
{
|
||||
std::string err_msg = "Postgis Plugin: ";
|
||||
err_msg += status();
|
||||
err_msg += "\nin executeAsyncQuery Full sql was: '";
|
||||
err_msg += "in executeAsyncQuery Full sql was: '";
|
||||
err_msg += sql;
|
||||
err_msg += "'\n";
|
||||
clearAsyncResult(PQgetResult(conn_));
|
||||
|
@ -191,7 +198,7 @@ public:
|
|||
{
|
||||
std::string err_msg = "Postgis Plugin: ";
|
||||
err_msg += status();
|
||||
err_msg += "\nin getNextAsyncResult";
|
||||
err_msg += "in getNextAsyncResult";
|
||||
clearAsyncResult(result);
|
||||
// We need to guarde against losing the connection
|
||||
// (i.e db restart) so here we invalidate the full connection
|
||||
|
@ -208,7 +215,7 @@ public:
|
|||
{
|
||||
std::string err_msg = "Postgis Plugin: ";
|
||||
err_msg += status();
|
||||
err_msg += "\nin getAsyncResult";
|
||||
err_msg += "in getAsyncResult";
|
||||
clearAsyncResult(result);
|
||||
// We need to be guarded against losing the connection
|
||||
// (i.e db restart), we invalidate the full connection
|
||||
|
|
|
@ -159,6 +159,10 @@ postgis_datasource::postgis_datasource(parameters const& params)
|
|||
geometry_table_ = geometry_table_.substr(0);
|
||||
}
|
||||
|
||||
// NOTE: geometry_table_ how should ideally be a table name, but
|
||||
// there are known edge cases where this will break down and
|
||||
// geometry_table_ may even be empty: https://github.com/mapnik/mapnik/issues/2718
|
||||
|
||||
// If we do not know both the geometry_field and the srid
|
||||
// then first attempt to fetch the geometry name from a geometry_columns entry.
|
||||
// This will return no records if we are querying a bogus table returned
|
||||
|
@ -166,7 +170,7 @@ postgis_datasource::postgis_datasource(parameters const& params)
|
|||
// the table parameter references a table, view, or subselect not
|
||||
// registered in the geometry columns.
|
||||
geometryColumn_ = geometry_field_;
|
||||
if (geometryColumn_.empty() || srid_ == 0)
|
||||
if (!geometry_table_.empty() && (geometryColumn_.empty() || srid_ == 0))
|
||||
{
|
||||
#ifdef MAPNIK_STATS
|
||||
mapnik::progress_timer __stats2__(std::clog, "postgis_datasource::init(get_srid_and_geometry_column)");
|
||||
|
@ -223,12 +227,20 @@ postgis_datasource::postgis_datasource(parameters const& params)
|
|||
// If we still do not know the srid then we can try to fetch
|
||||
// it from the 'geometry_table_' parameter, which should work even if it is
|
||||
// a subselect as long as we know the geometry_field to query
|
||||
if (! geometryColumn_.empty() && srid_ <= 0)
|
||||
if (!geometryColumn_.empty() && srid_ <= 0)
|
||||
{
|
||||
std::ostringstream s;
|
||||
|
||||
s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM "
|
||||
<< populate_tokens(geometry_table_) << " WHERE \"" << geometryColumn_ << "\" IS NOT NULL LIMIT 1;";
|
||||
s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM ";
|
||||
if (!geometry_table_.empty())
|
||||
{
|
||||
s << geometry_table_;
|
||||
}
|
||||
else
|
||||
{
|
||||
s << populate_tokens(table_);
|
||||
}
|
||||
s << " WHERE \"" << geometryColumn_ << "\" IS NOT NULL LIMIT 1;";
|
||||
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
if (rs->next())
|
||||
|
|
|
@ -251,7 +251,7 @@ if env['PLUGIN_LINKING'] == 'static':
|
|||
lib_env.AppendUnique(CPPPATH='../plugins/')
|
||||
for plugin in env['REQUESTED_PLUGINS']:
|
||||
details = env['PLUGINS'][plugin]
|
||||
if details['lib'] in env['LIBS'] or not details['lib']:
|
||||
if not details['lib'] or details['lib'] in env['LIBS']:
|
||||
plugin_env = SConscript('../plugins/input/%s/build.py' % plugin)
|
||||
if not plugin_env:
|
||||
print("Notice: no 'plugin_env' variable found for plugin: '%s'" % plugin)
|
||||
|
|
|
@ -40,18 +40,29 @@ expression_ptr parse_expression(std::string const& str)
|
|||
auto node = std::make_shared<expr_node>();
|
||||
std::string::const_iterator itr = str.begin();
|
||||
std::string::const_iterator end = str.end();
|
||||
try {
|
||||
bool r = boost::spirit::qi::phrase_parse(itr, end, g, space, *node);
|
||||
if (r && itr == end)
|
||||
bool r = false;
|
||||
try
|
||||
{
|
||||
r = boost::spirit::qi::phrase_parse(itr, end, g, space, *node);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
if (std::string("boost::spirit::qi::expectation_failure") == std::string(ex.what()))
|
||||
{
|
||||
return node;
|
||||
// no need to show "boost::spirit::qi::expectation_failure" which is a std::runtime_error
|
||||
throw config_error("Failed to parse expression: \"" + str + "\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw config_error("Failed to parse expression: \"" + str + "\"");
|
||||
// show "Could not initialize ICU resources" from boost::regex which is a std::runtime_error
|
||||
throw config_error(std::string(ex.what()) + " for expression: \"" + str + "\"");
|
||||
}
|
||||
}
|
||||
catch (std::exception const&) // boost::spirit::qi::expectation_failure
|
||||
if (r && itr == end)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw config_error("Failed to parse expression: \"" + str + "\"");
|
||||
}
|
||||
|
|
|
@ -94,7 +94,17 @@ struct visitor_image_copy_so
|
|||
|
||||
T0 operator() (T0 const& src)
|
||||
{
|
||||
return T0(src);
|
||||
if (offset_ == src.get_offset() && scaling_ == src.get_scaling())
|
||||
{
|
||||
return T0(src);
|
||||
}
|
||||
else
|
||||
{
|
||||
T0 dst(src);
|
||||
dst.set_scaling(scaling_);
|
||||
dst.set_offset(offset_);
|
||||
return T0(std::move(dst));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
|
@ -340,6 +350,10 @@ MAPNIK_DECL image_any image_copy(image_any const& data, image_dtype type, double
|
|||
return image_any(std::move(image_copy<image_gray64f>(data, offset, scaling)));
|
||||
case image_dtype_null:
|
||||
throw std::runtime_error("Can not cast a null image");
|
||||
case IMAGE_DTYPE_MAX:
|
||||
default:
|
||||
throw std::runtime_error("Can not cast unknown type");
|
||||
|
||||
}
|
||||
throw std::runtime_error("Unknown image type passed");
|
||||
}
|
||||
|
|
|
@ -46,16 +46,32 @@ jpeg_saver::jpeg_saver(std::ostream & stream, std::string const& t):
|
|||
stream_(stream), t_(t) {}
|
||||
|
||||
template <typename T>
|
||||
void process_rgba8_jpeg(T const& image, std::string const& t, std::ostream & stream)
|
||||
void process_rgba8_jpeg(T const& image, std::string const& type, std::ostream & stream)
|
||||
{
|
||||
#if defined(HAVE_JPEG)
|
||||
int quality = 85;
|
||||
std::string val = t.substr(4);
|
||||
if (!val.empty())
|
||||
//std::string val = type.substr(4);
|
||||
if (type != "jpeg")
|
||||
{
|
||||
if (!mapnik::util::string2int(val,quality) || quality < 0 || quality > 100)
|
||||
boost::char_separator<char> sep(":");
|
||||
boost::tokenizer< boost::char_separator<char> > tokens(type, sep);
|
||||
for (auto const& t : tokens)
|
||||
{
|
||||
throw ImageWriterException("invalid jpeg quality: '" + val + "'");
|
||||
if (t == "jpeg")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (boost::algorithm::starts_with(t, "quality="))
|
||||
{
|
||||
std::string val = t.substr(8);
|
||||
if (!val.empty())
|
||||
{
|
||||
if (!mapnik::util::string2int(val,quality) || quality < 0 || quality > 100)
|
||||
{
|
||||
throw ImageWriterException("invalid jpeg quality: '" + val + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
save_as_jpeg(stream, quality, image);
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
"objects": {
|
||||
"escaped": {
|
||||
"type": "GeometryCollection",
|
||||
"bbox": [
|
||||
-180,
|
||||
-90,
|
||||
180,
|
||||
90
|
||||
],
|
||||
"geometries": [
|
||||
{
|
||||
"type": "Point",
|
||||
|
|
|
@ -10,6 +10,12 @@ def setup():
|
|||
# from another directory we need to chdir()
|
||||
os.chdir(execution_path('.'))
|
||||
|
||||
def test_type():
|
||||
im = mapnik.Image(256, 256)
|
||||
eq_(im.get_type(), mapnik.ImageType.rgba8)
|
||||
im = mapnik.Image(256, 256, mapnik.ImageType.gray8)
|
||||
eq_(im.get_type(), mapnik.ImageType.gray8)
|
||||
|
||||
def test_image_premultiply():
|
||||
im = mapnik.Image(256,256)
|
||||
eq_(im.premultiplied(),False)
|
||||
|
|
|
@ -53,7 +53,7 @@ def test_can_parse_xml_with_deprecated_properties():
|
|||
except RuntimeError, e:
|
||||
# only test datasources that we have installed
|
||||
if not 'Could not create datasource' in str(e) \
|
||||
and not 'Bad connection' in str(e):
|
||||
and not 'could not connect' in str(e):
|
||||
failures.append('Failed to load valid map %s (%s)' % (filename,e))
|
||||
eq_(len(failures),0,'\n'+'\n'.join(failures))
|
||||
mapnik.logger.set_severity(default_logging_severity)
|
||||
|
@ -73,7 +73,7 @@ def test_good_files():
|
|||
except RuntimeError, e:
|
||||
# only test datasources that we have installed
|
||||
if not 'Could not create datasource' in str(e) \
|
||||
and not 'Bad connection' in str(e):
|
||||
and not 'could not connect' in str(e):
|
||||
failures.append('Failed to load valid map %s (%s)' % (filename,e))
|
||||
eq_(len(failures),0,'\n'+'\n'.join(failures))
|
||||
|
||||
|
|
|
@ -283,6 +283,16 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
|
|||
eq_(meta['encoding'],u'UTF8')
|
||||
eq_(meta['geometry_type'],mapnik.DataGeometryType.Polygon)
|
||||
|
||||
def test_bad_connection():
|
||||
try:
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,
|
||||
table='test',
|
||||
max_size=20,
|
||||
geometry_field='geom',
|
||||
user="rolethatdoesnotexist")
|
||||
except Exception, e:
|
||||
assert 'role "rolethatdoesnotexist" does not exist' in str(e)
|
||||
|
||||
def test_empty_db():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='empty')
|
||||
fs = ds.featureset()
|
||||
|
@ -844,7 +854,8 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
|
|||
fs = ds_bad.featureset()
|
||||
for feature in fs:
|
||||
pass
|
||||
except RuntimeError:
|
||||
except RuntimeError, e:
|
||||
assert 'invalid input syntax for integer' in str(e)
|
||||
failed = True
|
||||
|
||||
eq_(failed,True)
|
||||
|
@ -907,7 +918,8 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
|
|||
mapnik.render_to_file(map1,'/tmp/mapnik-postgis-test-map1.png', 'png')
|
||||
# Test must fail if error was not raised just above
|
||||
eq_(False,True)
|
||||
except RuntimeError:
|
||||
except RuntimeError, e:
|
||||
assert 'invalid input syntax for integer' in str(e)
|
||||
pass
|
||||
# This used to raise an exception before correction of issue 2042
|
||||
mapnik.render_to_file(map2,'/tmp/mapnik-postgis-test-map2.png', 'png')
|
||||
|
@ -1158,6 +1170,42 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
|
|||
eq_(meta.get('key_field'),"gid")
|
||||
eq_(meta['geometry_type'],None)
|
||||
|
||||
# currently needs manual `geometry_table` passed
|
||||
# to avoid misparse of `geometry_table`
|
||||
# in the future ideally this would not need manual `geometry_table`
|
||||
# https://github.com/mapnik/mapnik/issues/2718
|
||||
# currently `bogus` would be picked automatically for geometry_table
|
||||
def test_broken_parsing_of_comments():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''
|
||||
(select * FROM test) AS data
|
||||
-- select this from bogus''',
|
||||
geometry_table='test')
|
||||
fs = ds.featureset()
|
||||
for id in range(1,5):
|
||||
eq_(fs.next().id(),id)
|
||||
|
||||
meta = ds.describe()
|
||||
eq_(meta['srid'],4326)
|
||||
eq_(meta['geometry_type'],mapnik.DataGeometryType.Collection)
|
||||
|
||||
# same
|
||||
# to avoid misparse of `geometry_table`
|
||||
# in the future ideally this would not need manual `geometry_table`
|
||||
# https://github.com/mapnik/mapnik/issues/2718
|
||||
# currently nothing would be picked automatically for geometry_table
|
||||
def test_broken_parsing_of_comments():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''
|
||||
(select * FROM test) AS data
|
||||
-- select this from bogus.''',
|
||||
geometry_table='test')
|
||||
fs = ds.featureset()
|
||||
for id in range(1,5):
|
||||
eq_(fs.next().id(),id)
|
||||
|
||||
meta = ds.describe()
|
||||
eq_(meta['srid'],4326)
|
||||
eq_(meta['geometry_type'],mapnik.DataGeometryType.Collection)
|
||||
|
||||
|
||||
atexit.register(postgis_takedown)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ def compare_map(xml):
|
|||
except RuntimeError, e:
|
||||
# only test datasources that we have installed
|
||||
if not 'Could not create datasource' in str(e) \
|
||||
and not 'Bad connection' in str(e):
|
||||
and not 'could not connect' in str(e):
|
||||
raise RuntimeError(str(e))
|
||||
return
|
||||
(handle, test_map) = tempfile.mkstemp(suffix='.xml', prefix='mapnik-temp-map1-')
|
||||
|
|
|
@ -214,7 +214,7 @@ def render(filename, config, scale_factor, reporting):
|
|||
return
|
||||
except Exception, e:
|
||||
if 'Could not create datasource' in str(e) \
|
||||
or 'Bad connection' in str(e):
|
||||
or 'could not connect' in str(e):
|
||||
return m
|
||||
reporting.other_error(filename, repr(e))
|
||||
return m
|
||||
|
|
Loading…
Reference in a new issue