Merge remote-tracking branch 'upstream/master' into libimagequant
This commit is contained in:
commit
d0c1bed5a5
40 changed files with 1335 additions and 546 deletions
32
SConstruct
32
SConstruct
|
@ -872,6 +872,24 @@ return 0;
|
|||
context.Result(ret[0])
|
||||
return ret[1].strip()
|
||||
|
||||
def CheckBoostScopedEnum(context, silent=False):
|
||||
if not silent:
|
||||
context.Message('Checking whether Boost was compiled with C++11 scoped enums ... ')
|
||||
ret = context.TryLink("""
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::filesystem::path a, b;
|
||||
boost::filesystem::copy_file(a, b);
|
||||
return 0;
|
||||
}
|
||||
""", '.cpp')
|
||||
if silent:
|
||||
context.did_show_result=1
|
||||
context.Result(ret)
|
||||
return ret
|
||||
|
||||
def icu_at_least_four_two(context):
|
||||
ret = context.TryRun("""
|
||||
|
||||
|
@ -1054,6 +1072,7 @@ conf_tests = { 'prioritize_paths' : prioritize_paths,
|
|||
'boost_regex_has_icu' : boost_regex_has_icu,
|
||||
'sqlite_has_rtree' : sqlite_has_rtree,
|
||||
'supports_cxx11' : supports_cxx11,
|
||||
'CheckBoostScopedEnum' : CheckBoostScopedEnum,
|
||||
}
|
||||
|
||||
def GetMapnikLibVersion():
|
||||
|
@ -1443,6 +1462,19 @@ if not preconfigured:
|
|||
color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0])
|
||||
env['SKIPPED_DEPS'].append('boost ' + libinfo[0])
|
||||
|
||||
# Boost versions before 1.57 are broken when the system package and
|
||||
# Mapnik are compiled against different standards. On Ubuntu 14.04
|
||||
# using boost 1.54, it breaks scoped enums. It's a bit of a hack to
|
||||
# just turn it off like this, but seems the only available work-
|
||||
# around. See https://svn.boost.org/trac/boost/ticket/6779 for more
|
||||
# details.
|
||||
boost_version = [int(x) for x in env.get('BOOST_LIB_VERSION_FROM_HEADER').split('_')]
|
||||
if not conf.CheckBoostScopedEnum():
|
||||
if boost_version < [1, 51]:
|
||||
env.Append(CXXFLAGS = '-DBOOST_NO_SCOPED_ENUMS')
|
||||
elif boost_version < [1, 57]:
|
||||
env.Append(CXXFLAGS = '-DBOOST_NO_CXX11_SCOPED_ENUMS')
|
||||
|
||||
if not env['HOST'] and env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
|
||||
# http://lists.boost.org/Archives/boost/2009/03/150076.php
|
||||
# we need libicui18n if using static boost libraries, so it is
|
||||
|
|
|
@ -43,6 +43,7 @@ benchmarks = [
|
|||
"test_font_registration.cpp",
|
||||
"test_rendering.cpp",
|
||||
"test_rendering_shared_map.cpp",
|
||||
# "test_numeric_cast_vs_static_cast.cpp",
|
||||
]
|
||||
for cpp_test in benchmarks:
|
||||
test_program = test_env_local.Program('out/'+cpp_test.replace('.cpp',''), source=[cpp_test])
|
||||
|
|
87
benchmark/test_numeric_cast_vs_static_cast.cpp
Normal file
87
benchmark/test_numeric_cast_vs_static_cast.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include "bench_framework.hpp"
|
||||
// boost
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
static double STEP_NUM = 0.0000000001;
|
||||
static std::uint8_t START_NUM = 2;
|
||||
|
||||
class test_static : public benchmark::test_case
|
||||
{
|
||||
double step_;
|
||||
std::uint8_t start_;
|
||||
public:
|
||||
test_static(mapnik::parameters const& params)
|
||||
: test_case(params),
|
||||
step_(STEP_NUM),
|
||||
start_(START_NUM) {}
|
||||
bool validate() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool operator()() const
|
||||
{
|
||||
double value_ = 0.0;
|
||||
std::uint8_t x;
|
||||
for (std::size_t i=0;i<iterations_;++i) {
|
||||
double c = static_cast<double>(start_) * value_;
|
||||
if (c >= 256.0) c = 255.0;
|
||||
if (c < 0.0) c = 0.0;
|
||||
x = static_cast<std::uint8_t>(c);
|
||||
value_ += step_;
|
||||
}
|
||||
return static_cast<double>(x) < (static_cast<double>(start_) * value_);
|
||||
}
|
||||
};
|
||||
|
||||
using boost::numeric::positive_overflow;
|
||||
using boost::numeric::negative_overflow;
|
||||
|
||||
class test_numeric : public benchmark::test_case
|
||||
{
|
||||
double step_;
|
||||
std::uint8_t start_;
|
||||
public:
|
||||
test_numeric(mapnik::parameters const& params)
|
||||
: test_case(params),
|
||||
step_(STEP_NUM),
|
||||
start_(START_NUM) {}
|
||||
bool validate() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool operator()() const
|
||||
{
|
||||
double value_ = 0.0;
|
||||
std::uint8_t x;
|
||||
for (std::size_t i=0;i<iterations_;++i) {
|
||||
try {
|
||||
x = boost::numeric_cast<std::uint8_t>(start_ * value_);
|
||||
}
|
||||
catch(negative_overflow&)
|
||||
{
|
||||
x = std::numeric_limits<std::uint8_t>::min();
|
||||
}
|
||||
catch(positive_overflow&)
|
||||
{
|
||||
x = std::numeric_limits<std::uint8_t>::max();
|
||||
}
|
||||
value_ += step_;
|
||||
}
|
||||
return static_cast<double>(x) < (static_cast<double>(start_) * value_);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
mapnik::parameters params;
|
||||
benchmark::handle_args(argc,argv,params);
|
||||
{
|
||||
test_static test_runner(params);
|
||||
run(test_runner,"static_cast");
|
||||
}
|
||||
{
|
||||
test_numeric test_runner(params);
|
||||
run(test_runner,"numeric_cast");
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
// mapnik (should not depend on anything that need to use this)
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/unique_lock.hpp>
|
||||
#include <mapnik/utils.hpp>
|
||||
#include <mapnik/util/noncopyable.hpp>
|
||||
|
||||
|
@ -70,7 +69,7 @@ namespace mapnik {
|
|||
static void set_severity(severity_type const& severity_level)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(severity_mutex_);
|
||||
std::lock_guard<std::mutex> lock(severity_mutex_);
|
||||
#endif
|
||||
|
||||
severity_level_ = severity_level;
|
||||
|
@ -94,7 +93,7 @@ namespace mapnik {
|
|||
severity_type const& security_level)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(severity_mutex_);
|
||||
std::lock_guard<std::mutex> lock(severity_mutex_);
|
||||
#endif
|
||||
if (! object_name.empty())
|
||||
{
|
||||
|
@ -105,7 +104,7 @@ namespace mapnik {
|
|||
static void clear_object_severity()
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(severity_mutex_);
|
||||
std::lock_guard<std::mutex> lock(severity_mutex_);
|
||||
#endif
|
||||
|
||||
object_severity_level_.clear();
|
||||
|
@ -120,7 +119,7 @@ namespace mapnik {
|
|||
static void set_format(std::string const& format)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(format_mutex_);
|
||||
std::lock_guard<std::mutex> lock(format_mutex_);
|
||||
#endif
|
||||
format_ = format;
|
||||
}
|
||||
|
@ -166,7 +165,7 @@ namespace mapnik {
|
|||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
static std::mutex mutex;
|
||||
mapnik::scoped_lock lock(mutex);
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
#endif
|
||||
std::clog << logger::str() << " " << s.str() << std::endl;
|
||||
}
|
||||
|
|
|
@ -180,17 +180,22 @@ public:
|
|||
{
|
||||
// TODO: Enum value strings with underscore are deprecated in Mapnik 3.x
|
||||
// and support will be removed in Mapnik 4.x.
|
||||
bool deprecated = false;
|
||||
std::string str_copy(str);
|
||||
if (str_copy.find('_') != std::string::npos)
|
||||
{
|
||||
std::replace(str_copy.begin(), str_copy.end(), '_', '-');
|
||||
MAPNIK_LOG_ERROR(enumerations) << "enumeration value (" << str << ") using \"_\" is deprecated and will be removed in Mapnik 4.x, use '" << str_copy << "' instead";
|
||||
deprecated = true;
|
||||
}
|
||||
for (unsigned i = 0; i < THE_MAX; ++i)
|
||||
{
|
||||
if (str_copy == our_strings_[i])
|
||||
{
|
||||
value_ = static_cast<ENUM>(i);
|
||||
if (deprecated)
|
||||
{
|
||||
MAPNIK_LOG_ERROR(enumerations) << "enumeration value (" << str << ") using \"_\" is deprecated and will be removed in Mapnik 4.x, use '" << str_copy << "' instead";
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -520,10 +520,6 @@ bool interior_position(PathType & path, double & x, double & y)
|
|||
if (!label::centroid(path, x,y))
|
||||
return false;
|
||||
|
||||
// if we are not a polygon, or the default is within the polygon we are done
|
||||
if (hit_test(path,x,y,0.001))
|
||||
return true;
|
||||
|
||||
// otherwise we find a horizontal line across the polygon and then return the
|
||||
// center of the widest intersection between the polygon and the line.
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/pixel_types.hpp>
|
||||
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
// boost
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
|
||||
|
@ -136,17 +136,11 @@ MAPNIK_DECL bool is_solid (image_view_any const& image);
|
|||
template <typename T>
|
||||
MAPNIK_DECL bool is_solid (T const& image);
|
||||
|
||||
// SET ALPHA
|
||||
MAPNIK_DECL void set_alpha (image_any & image, float opacity);
|
||||
// APPLY OPACITY
|
||||
MAPNIK_DECL void apply_opacity (image_any & image, float opacity);
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void set_alpha (T & image, float opacity);
|
||||
|
||||
// MULTIPLY ALPHA
|
||||
MAPNIK_DECL void multiply_alpha (image_any & image, float opacity);
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void multiply_alpha (T & image, float opacity);
|
||||
MAPNIK_DECL void apply_opacity (T & image, float opacity);
|
||||
|
||||
// SET GRAYSCALE TO ALPHA
|
||||
MAPNIK_DECL void set_grayscale_to_alpha (image_any & image);
|
||||
|
@ -215,10 +209,10 @@ inline bool check_bounds (T const& data, std::size_t x, std::size_t y)
|
|||
}
|
||||
|
||||
// COMPOSITE_PIXEL
|
||||
MAPNIK_DECL void composite_pixel(image_any & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity );
|
||||
MAPNIK_DECL void composite_pixel(image_any & data, composite_mode_e comp_op, std::size_t x, std::size_t y, unsigned c, unsigned cover, double opacity );
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void composite_pixel(T & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity );
|
||||
MAPNIK_DECL void composite_pixel(T & data, composite_mode_e comp_op, std::size_t x, std::size_t y, unsigned c, unsigned cover, double opacity );
|
||||
|
||||
// SET PIXEL
|
||||
template <typename T>
|
||||
|
@ -330,15 +324,16 @@ MAPNIK_DECL T get_pixel(image_view<image<gray64s_t> > const& data, std::size_t x
|
|||
template <typename T>
|
||||
MAPNIK_DECL T get_pixel(image_view<image<gray64f_t> > const& data, std::size_t x, std::size_t y);
|
||||
|
||||
// VIEW TO STRING
|
||||
MAPNIK_DECL void view_to_string (image_view_any const& view, std::ostringstream & ss);
|
||||
// VIEW TO OUTPUT STREAM
|
||||
template <typename Out>
|
||||
MAPNIK_DECL void view_to_stream (image_view_any const& view, Out & os);
|
||||
|
||||
// CREATE VIEW
|
||||
MAPNIK_DECL image_view_any create_view (image_any const& data, unsigned x, unsigned y, unsigned w, unsigned h);
|
||||
MAPNIK_DECL image_view_any create_view (image_any const& data, std::size_t x, std::size_t y, std::size_t w, std::size_t h);
|
||||
|
||||
// COMPARE
|
||||
template <typename T>
|
||||
MAPNIK_DECL unsigned compare(T const& im1, T const& im2, double threshold = 0, bool alpha = true);
|
||||
MAPNIK_DECL std::size_t compare(T const& im1, T const& im2, double threshold = 0.0, bool alpha = true);
|
||||
|
||||
inline bool is_png(std::string const& filename)
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ extract_bounding_box_grammar<Iterator, ErrorHandler>::extract_bounding_box_gramm
|
|||
qi::_b_type _b;
|
||||
qi::eps_type eps;
|
||||
qi::raw_type raw;
|
||||
boost::spirit::standard_wide::char_type char_;
|
||||
qi::char_type char_;
|
||||
boost::spirit::repository::qi::iter_pos_type iter_pos;
|
||||
using qi::fail;
|
||||
using qi::on_error;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define MAPNIK_POOL_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/unique_lock.hpp>
|
||||
#include <mapnik/utils.hpp>
|
||||
#include <mapnik/util/noncopyable.hpp>
|
||||
|
||||
|
@ -71,7 +70,7 @@ public:
|
|||
HolderType borrowObject()
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
|
||||
typename ContType::iterator itr=pool_.begin();
|
||||
|
@ -106,7 +105,7 @@ public:
|
|||
unsigned size() const
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
return pool_.size();
|
||||
}
|
||||
|
@ -114,7 +113,7 @@ public:
|
|||
unsigned max_size() const
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
return maxSize_;
|
||||
}
|
||||
|
@ -122,7 +121,7 @@ public:
|
|||
void set_max_size(unsigned size)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
maxSize_ = std::max(maxSize_,size);
|
||||
}
|
||||
|
@ -130,7 +129,7 @@ public:
|
|||
unsigned initial_size() const
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
return initialSize_;
|
||||
}
|
||||
|
@ -138,7 +137,7 @@ public:
|
|||
void set_initial_size(unsigned size)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
if (size > initialSize_)
|
||||
{
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2014 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_UNIQUE_LOCK_HPP
|
||||
#define MAPNIK_UNIQUE_LOCK_HPP
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
using scoped_lock = std::unique_lock<std::mutex>;
|
||||
}
|
||||
|
||||
#endif // MAPNIK_UNIQUE_LOCK_HPP
|
|
@ -24,7 +24,6 @@
|
|||
#define MAPNIK_UTILS_HPP
|
||||
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/unique_lock.hpp>
|
||||
|
||||
// stl
|
||||
#include <stdexcept> // std::runtime_error
|
||||
|
@ -123,7 +122,7 @@ protected:
|
|||
if (! pInstance_)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
if (! pInstance_)
|
||||
{
|
||||
|
|
|
@ -60,7 +60,7 @@ class MAPNIK_DECL geometry_utils : private util::noncopyable
|
|||
public:
|
||||
|
||||
static mapnik::geometry::geometry<double> from_wkb(const char* wkb,
|
||||
unsigned size,
|
||||
std::size_t size,
|
||||
wkbFormat format = wkbGeneric);
|
||||
};
|
||||
|
||||
|
|
|
@ -334,6 +334,9 @@ void ogr_datasource::init(mapnik::parameters const& params)
|
|||
switch (type_oid)
|
||||
{
|
||||
case OFTInteger:
|
||||
#if GDAL_VERSION_MAJOR >= 2
|
||||
case OFTInteger64:
|
||||
#endif
|
||||
desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Integer));
|
||||
break;
|
||||
|
||||
|
@ -351,6 +354,9 @@ void ogr_datasource::init(mapnik::parameters const& params)
|
|||
break;
|
||||
|
||||
case OFTIntegerList:
|
||||
#if GDAL_VERSION_MAJOR >= 2
|
||||
case OFTInteger64List:
|
||||
#endif
|
||||
case OFTRealList:
|
||||
case OFTStringList:
|
||||
case OFTWideStringList: // deprecated !
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "ogr_converter.hpp"
|
||||
#include "ogr_index.hpp"
|
||||
|
||||
#include <gdal_version.h>
|
||||
|
||||
using mapnik::query;
|
||||
using mapnik::box2d;
|
||||
using mapnik::feature_ptr;
|
||||
|
@ -139,6 +141,9 @@ feature_ptr ogr_index_featureset<filterT>::next()
|
|||
switch (type_oid)
|
||||
{
|
||||
case OFTInteger:
|
||||
#if GDAL_VERSION_MAJOR >= 2
|
||||
case OFTInteger64:
|
||||
#endif
|
||||
{
|
||||
feature->put<mapnik::value_integer>(fld_name,poFeature->GetFieldAsInteger (i));
|
||||
break;
|
||||
|
@ -158,6 +163,9 @@ feature_ptr ogr_index_featureset<filterT>::next()
|
|||
}
|
||||
|
||||
case OFTIntegerList:
|
||||
#if GDAL_VERSION_MAJOR >= 2
|
||||
case OFTInteger64List:
|
||||
#endif
|
||||
case OFTRealList:
|
||||
case OFTStringList:
|
||||
case OFTWideStringList: // deprecated !
|
||||
|
|
|
@ -89,7 +89,7 @@ datasource_ptr datasource_cache::create(parameters const& params)
|
|||
// add scope to ensure lock is released asap
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
itr=plugins_.find(*type);
|
||||
if (itr == plugins_.end())
|
||||
|
@ -156,7 +156,7 @@ std::vector<std::string> datasource_cache::plugin_names()
|
|||
bool datasource_cache::register_datasources(std::string const& dir, bool recurse)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
if (!mapnik::util::exists(dir))
|
||||
{
|
||||
|
|
|
@ -84,7 +84,7 @@ unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *
|
|||
bool freetype_engine::register_font(std::string const& file_name)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
font_library library;
|
||||
return register_font_impl(file_name, library, global_font_file_mapping_);
|
||||
|
@ -166,7 +166,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name,
|
|||
bool freetype_engine::register_fonts(std::string const& dir, bool recurse)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
font_library library;
|
||||
return register_fonts_impl(dir, library, global_font_file_mapping_, recurse);
|
||||
|
@ -338,7 +338,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name,
|
|||
if (file.open())
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
auto result = global_memory_fonts.emplace(itr->second.second, std::make_pair(std::move(file.data()),file.size()));
|
||||
FT_Face face;
|
||||
|
|
|
@ -427,10 +427,10 @@ struct is_solid_visitor
|
|||
{
|
||||
pixel_type const* first_row = data.get_row(0);
|
||||
pixel_type const first_pixel = first_row[0];
|
||||
for (unsigned y = 0; y < data.height(); ++y)
|
||||
for (std::size_t y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type const * row = data.get_row(y);
|
||||
for (unsigned x = 0; x < data.width(); ++x)
|
||||
for (std::size_t x = 0; x < data.width(); ++x)
|
||||
{
|
||||
if (first_pixel != row[x])
|
||||
{
|
||||
|
@ -633,101 +633,25 @@ inline T clamp(T d, T min, T max)
|
|||
}
|
||||
|
||||
}
|
||||
struct visitor_set_alpha
|
||||
struct visitor_apply_opacity
|
||||
{
|
||||
visitor_set_alpha(float opacity)
|
||||
visitor_apply_opacity(float opacity)
|
||||
: opacity_(clamp(opacity, 0.0f, 1.0f)) {}
|
||||
|
||||
void operator() (image_rgba8 & data) const
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
pixel_type a1 = static_cast<pixel_type>(255.0 * opacity_);
|
||||
for (unsigned int y = 0; y < data.height(); ++y)
|
||||
for (std::size_t y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type* row_to = data.get_row(y);
|
||||
for (unsigned int x = 0; x < data.width(); ++x)
|
||||
for (std::size_t x = 0; x < data.width(); ++x)
|
||||
{
|
||||
pixel_type rgba = row_to[x];
|
||||
pixel_type a0 = (rgba >> 24) & 0xff;
|
||||
if (a0 == a1) continue;
|
||||
|
||||
pixel_type a = static_cast<pixel_type>(((rgba >> 24) & 0xff) * opacity_);
|
||||
pixel_type r = rgba & 0xff;
|
||||
pixel_type g = (rgba >> 8 ) & 0xff;
|
||||
pixel_type b = (rgba >> 16) & 0xff;
|
||||
|
||||
row_to[x] = (a1 << 24)| (b << 16) | (g << 8) | (r) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator() (T & data) const
|
||||
{
|
||||
throw std::runtime_error("Error: set_alpha with " + std::string(typeid(data).name()) + " is not supported");
|
||||
}
|
||||
|
||||
private:
|
||||
float const opacity_;
|
||||
};
|
||||
|
||||
} // end detail ns
|
||||
|
||||
MAPNIK_DECL void set_alpha(image_any & data, float opacity)
|
||||
{
|
||||
// Prior to calling the data must not be premultiplied
|
||||
bool remultiply = mapnik::demultiply_alpha(data);
|
||||
util::apply_visitor(detail::visitor_set_alpha(opacity), data);
|
||||
if (remultiply)
|
||||
{
|
||||
mapnik::premultiply_alpha(data);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void set_alpha(T & data, float opacity)
|
||||
{
|
||||
// Prior to calling the data must not be premultiplied
|
||||
bool remultiply = mapnik::demultiply_alpha(data);
|
||||
detail::visitor_set_alpha visit(opacity);
|
||||
visit(data);
|
||||
if (remultiply)
|
||||
{
|
||||
mapnik::premultiply_alpha(data);
|
||||
}
|
||||
}
|
||||
|
||||
template MAPNIK_DECL void set_alpha(image_rgba8 &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray8 &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray8s &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray16 &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray16s &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray32 &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray32s &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray32f &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray64 &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray64s &, float);
|
||||
template MAPNIK_DECL void set_alpha(image_gray64f &, float);
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct visitor_multiply_alpha
|
||||
{
|
||||
visitor_multiply_alpha(float opacity)
|
||||
: opacity_(clamp(opacity, 0.0f, 1.0f)) {}
|
||||
|
||||
void operator() (image_rgba8 & data) const
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
for (unsigned int y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type* row_to = data.get_row(y);
|
||||
for (unsigned int x = 0; x < data.width(); ++x)
|
||||
{
|
||||
pixel_type rgba = row_to[x];
|
||||
pixel_type a = static_cast<uint8_t>(((rgba >> 24) & 0xff) * opacity_);
|
||||
pixel_type r = rgba & 0xff;
|
||||
pixel_type g = (rgba >> 8 ) & 0xff;
|
||||
pixel_type b = (rgba >> 16) & 0xff;
|
||||
row_to[x] = (a << 24)| (b << 16) | (g << 8) | (r) ;
|
||||
}
|
||||
}
|
||||
|
@ -736,21 +660,20 @@ struct visitor_multiply_alpha
|
|||
template <typename T>
|
||||
void operator() (T & data) const
|
||||
{
|
||||
throw std::runtime_error("Error: multiply_alpha with " + std::string(typeid(data).name()) + " is not supported");
|
||||
throw std::runtime_error("Error: apply_opacity with " + std::string(typeid(data).name()) + " is not supported");
|
||||
}
|
||||
|
||||
private:
|
||||
float const opacity_;
|
||||
|
||||
};
|
||||
|
||||
} // end detail ns
|
||||
|
||||
MAPNIK_DECL void multiply_alpha(image_any & data, float opacity)
|
||||
MAPNIK_DECL void apply_opacity(image_any & data, float opacity)
|
||||
{
|
||||
// Prior to calling the data must not be premultiplied
|
||||
bool remultiply = mapnik::demultiply_alpha(data);
|
||||
util::apply_visitor(detail::visitor_multiply_alpha(opacity), data);
|
||||
util::apply_visitor(detail::visitor_apply_opacity(opacity), data);
|
||||
if (remultiply)
|
||||
{
|
||||
mapnik::premultiply_alpha(data);
|
||||
|
@ -758,11 +681,11 @@ MAPNIK_DECL void multiply_alpha(image_any & data, float opacity)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void multiply_alpha(T & data, float opacity)
|
||||
MAPNIK_DECL void apply_opacity(T & data, float opacity)
|
||||
{
|
||||
// Prior to calling the data must not be premultiplied
|
||||
bool remultiply = mapnik::demultiply_alpha(data);
|
||||
detail::visitor_multiply_alpha visit(opacity);
|
||||
detail::visitor_apply_opacity visit(opacity);
|
||||
visit(data);
|
||||
if (remultiply)
|
||||
{
|
||||
|
@ -770,17 +693,17 @@ MAPNIK_DECL void multiply_alpha(T & data, float opacity)
|
|||
}
|
||||
}
|
||||
|
||||
template MAPNIK_DECL void multiply_alpha(image_rgba8 &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray8 &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray8s &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray16 &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray16s &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray32 &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray32s &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray32f &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray64 &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray64s &, float);
|
||||
template MAPNIK_DECL void multiply_alpha(image_gray64f &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_rgba8 &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray8 &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray8s &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray16 &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray16s &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray32 &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray32s &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray32f &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray64 &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray64s &, float);
|
||||
template MAPNIK_DECL void apply_opacity(image_gray64f &, float);
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
@ -789,10 +712,10 @@ struct visitor_set_grayscale_to_alpha
|
|||
void operator() (image_rgba8 & data) const
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
for (unsigned int y = 0; y < data.height(); ++y)
|
||||
for (std::size_t y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type* row_from = data.get_row(y);
|
||||
for (unsigned int x = 0; x < data.width(); ++x)
|
||||
for (std::size_t x = 0; x < data.width(); ++x)
|
||||
{
|
||||
pixel_type rgba = row_from[x];
|
||||
pixel_type r = rgba & 0xff;
|
||||
|
@ -822,10 +745,10 @@ struct visitor_set_grayscale_to_alpha_c
|
|||
void operator() (image_rgba8 & data) const
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
for (unsigned int y = 0; y < data.height(); ++y)
|
||||
for (std::size_t y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type* row_from = data.get_row(y);
|
||||
for (unsigned int x = 0; x < data.width(); ++x)
|
||||
for (std::size_t x = 0; x < data.width(); ++x)
|
||||
{
|
||||
pixel_type rgba = row_from[x];
|
||||
pixel_type r = rgba & 0xff;
|
||||
|
@ -934,10 +857,10 @@ struct visitor_set_color_to_alpha
|
|||
void operator() (image_rgba8 & data) const
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
for (unsigned y = 0; y < data.height(); ++y)
|
||||
for (std::size_t y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type* row_from = data.get_row(y);
|
||||
for (unsigned x = 0; x < data.width(); ++x)
|
||||
for (std::size_t x = 0; x < data.width(); ++x)
|
||||
{
|
||||
pixel_type rgba = row_from[x];
|
||||
pixel_type r = rgba & 0xff;
|
||||
|
@ -1292,7 +1215,7 @@ namespace detail {
|
|||
|
||||
struct visitor_set_rectangle
|
||||
{
|
||||
visitor_set_rectangle(image_any const & src, int x0, int y0)
|
||||
visitor_set_rectangle(image_any const & src, std::size_t x0, std::size_t y0)
|
||||
: src_(src), x0_(x0), y0_(y0) {}
|
||||
|
||||
void operator()(image_rgba8 & dst) const
|
||||
|
@ -1351,35 +1274,35 @@ struct visitor_set_rectangle
|
|||
}
|
||||
private:
|
||||
image_any const& src_;
|
||||
int x0_;
|
||||
int y0_;
|
||||
std::size_t x0_;
|
||||
std::size_t y0_;
|
||||
};
|
||||
|
||||
} // end detail ns
|
||||
|
||||
MAPNIK_DECL void set_rectangle(image_any & dst, image_any const& src, int x, int y)
|
||||
MAPNIK_DECL void set_rectangle(image_any & dst, image_any const& src, std::size_t x, std::size_t y)
|
||||
{
|
||||
util::apply_visitor(detail::visitor_set_rectangle(src, x, y), dst);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void set_rectangle (T & dst, T const& src, int x, int y)
|
||||
MAPNIK_DECL void set_rectangle (T & dst, T const& src, std::size_t x, std::size_t y)
|
||||
{
|
||||
detail::visitor_set_rectangle visit(src, x, y);
|
||||
visit(dst);
|
||||
}
|
||||
|
||||
template MAPNIK_DECL void set_rectangle(image_rgba8 &, image_rgba8 const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray8 &, image_gray8 const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray8s &, image_gray8s const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray16 &, image_gray16 const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray16s &, image_gray16s const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray32 &, image_gray32 const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray32s &, image_gray32s const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray32f &, image_gray32f const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray64 &, image_gray64 const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray64s &, image_gray64s const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray64f &, image_gray64f const&, int, int);
|
||||
template MAPNIK_DECL void set_rectangle(image_rgba8 &, image_rgba8 const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray8 &, image_gray8 const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray8s &, image_gray8s const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray16 &, image_gray16 const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray16s &, image_gray16s const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray32 &, image_gray32 const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray32s &, image_gray32s const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray32f &, image_gray32f const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray64 &, image_gray64 const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray64s &, image_gray64s const&, std::size_t, std::size_t);
|
||||
template MAPNIK_DECL void set_rectangle(image_gray64f &, image_gray64f const&, std::size_t, std::size_t);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
@ -1388,9 +1311,9 @@ struct visitor_composite_pixel
|
|||
{
|
||||
// Obviously c variable would only work for rgba8 currently, but didn't want to
|
||||
// make this a template class until new rgba types exist.
|
||||
visitor_composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity)
|
||||
visitor_composite_pixel(composite_mode_e comp_op, std::size_t x, std::size_t y, unsigned c, unsigned cover, double opacity)
|
||||
: opacity_(clamp(opacity, 0.0, 1.0)),
|
||||
op_(op),
|
||||
comp_op_(comp_op),
|
||||
x_(x),
|
||||
y_(y),
|
||||
c_(c),
|
||||
|
@ -1410,7 +1333,7 @@ struct visitor_composite_pixel
|
|||
value_type cb = (c_ >> 16 ) & 0xff;
|
||||
value_type cg = (c_ >> 8) & 0xff;
|
||||
value_type cr = (c_ & 0xff);
|
||||
blender_type::blend_pix(op_, reinterpret_cast<value_type*>(&rgba), cr, cg, cb, ca, cover_);
|
||||
blender_type::blend_pix(comp_op_, reinterpret_cast<value_type*>(&rgba), cr, cg, cb, ca, cover_);
|
||||
data(x_,y_) = rgba;
|
||||
}
|
||||
}
|
||||
|
@ -1423,9 +1346,9 @@ struct visitor_composite_pixel
|
|||
|
||||
private:
|
||||
double const opacity_;
|
||||
unsigned op_;
|
||||
int const x_;
|
||||
int const y_;
|
||||
composite_mode_e comp_op_;
|
||||
std::size_t const x_;
|
||||
std::size_t const y_;
|
||||
int const c_;
|
||||
unsigned const cover_;
|
||||
|
||||
|
@ -1433,29 +1356,29 @@ struct visitor_composite_pixel
|
|||
|
||||
} // end detail ns
|
||||
|
||||
MAPNIK_DECL void composite_pixel(image_any & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity )
|
||||
MAPNIK_DECL void composite_pixel(image_any & data, composite_mode_e comp_op, std::size_t x, std::size_t y, unsigned c, unsigned cover, double opacity )
|
||||
{
|
||||
util::apply_visitor(detail::visitor_composite_pixel(op, x, y, c, cover, opacity), data);
|
||||
util::apply_visitor(detail::visitor_composite_pixel(comp_op, x, y, c, cover, opacity), data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void composite_pixel(T & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity )
|
||||
MAPNIK_DECL void composite_pixel(T & data, composite_mode_e comp_op, std::size_t x, std::size_t y, unsigned c, unsigned cover, double opacity )
|
||||
{
|
||||
detail::visitor_composite_pixel visitor(op, x, y, c, cover, opacity);
|
||||
detail::visitor_composite_pixel visitor(comp_op, x, y, c, cover, opacity);
|
||||
visitor(data);
|
||||
}
|
||||
|
||||
template MAPNIK_DECL void composite_pixel(image_rgba8 &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray8 &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray8s &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray16 &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray16s &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray32 &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray32s &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray32f &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray64 &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray64s &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray64f &, unsigned, int, int, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_rgba8 &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray8 &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray8s &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray16 &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray16s &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray32 &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray32s &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray32f &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray64 &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray64s &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
template MAPNIK_DECL void composite_pixel(image_gray64f &, composite_mode_e, std::size_t, std::size_t, unsigned, unsigned, double);
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
@ -2285,39 +2208,42 @@ template MAPNIK_DECL double get_pixel(image_view_gray64f const&, std::size_t, st
|
|||
namespace detail
|
||||
{
|
||||
|
||||
struct visitor_view_to_string
|
||||
template <typename Out>
|
||||
struct visitor_view_to_stream
|
||||
{
|
||||
visitor_view_to_string(std::ostringstream & ss)
|
||||
: ss_(ss) {}
|
||||
visitor_view_to_stream(Out & os)
|
||||
: os_(os) {}
|
||||
|
||||
template <typename T>
|
||||
void operator() (T const& view)
|
||||
{
|
||||
for (std::size_t i=0;i<view.height();i++)
|
||||
{
|
||||
ss_.write(reinterpret_cast<const char*>(view.get_row(i)),
|
||||
os_.write(reinterpret_cast<const char*>(view.get_row(i)),
|
||||
view.row_size());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostringstream & ss_;
|
||||
Out & os_;
|
||||
};
|
||||
|
||||
} // end detail ns
|
||||
|
||||
|
||||
MAPNIK_DECL void view_to_string (image_view_any const& view, std::ostringstream & ss)
|
||||
template <typename Out>
|
||||
void view_to_stream (image_view_any const& view, Out & os)
|
||||
{
|
||||
util::apply_visitor(detail::visitor_view_to_string(ss), view);
|
||||
util::apply_visitor(detail::visitor_view_to_stream<Out>(os), view);
|
||||
}
|
||||
|
||||
template MAPNIK_DECL void view_to_stream(image_view_any const& view, std::ostringstream & os);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct visitor_create_view
|
||||
{
|
||||
visitor_create_view(unsigned x,unsigned y, unsigned w, unsigned h)
|
||||
visitor_create_view(std::size_t x, std::size_t y, std::size_t w, std::size_t h)
|
||||
: x_(x), y_(y), w_(w), h_(h) {}
|
||||
|
||||
image_view_any operator() (image_null const&) const
|
||||
|
@ -2332,33 +2258,33 @@ struct visitor_create_view
|
|||
return image_view_any(view);
|
||||
}
|
||||
private:
|
||||
unsigned const x_;
|
||||
unsigned const y_;
|
||||
unsigned const w_;
|
||||
unsigned const h_;
|
||||
std::size_t const x_;
|
||||
std::size_t const y_;
|
||||
std::size_t const w_;
|
||||
std::size_t const h_;
|
||||
};
|
||||
|
||||
} // end detail ns
|
||||
|
||||
MAPNIK_DECL image_view_any create_view(image_any const& data,unsigned x,unsigned y, unsigned w,unsigned h)
|
||||
MAPNIK_DECL image_view_any create_view(image_any const& data, std::size_t x, std::size_t y, std::size_t w, std::size_t h)
|
||||
{
|
||||
return util::apply_visitor(detail::visitor_create_view(x, y, w, h), data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL unsigned compare(T const& im1, T const& im2, double threshold, bool)
|
||||
MAPNIK_DECL std::size_t compare(T const& im1, T const& im2, double threshold, bool)
|
||||
{
|
||||
using pixel_type = typename T::pixel_type;
|
||||
if (im1.width() != im2.width() || im1.height() != im2.height())
|
||||
{
|
||||
return im1.width() * im1.height();
|
||||
}
|
||||
unsigned difference = 0;
|
||||
for (unsigned int y = 0; y < im1.height(); ++y)
|
||||
std::size_t difference = 0;
|
||||
for (std::size_t y = 0; y < im1.height(); ++y)
|
||||
{
|
||||
const pixel_type * row_from = im1.get_row(y);
|
||||
const pixel_type * row_from2 = im2.get_row(y);
|
||||
for (unsigned int x = 0; x < im1.width(); ++x)
|
||||
for (std::size_t x = 0; x < im1.width(); ++x)
|
||||
{
|
||||
double d = std::abs(static_cast<double>(row_from[x]) - static_cast<double>(row_from2[x]));
|
||||
if (d > threshold)
|
||||
|
@ -2370,25 +2296,25 @@ MAPNIK_DECL unsigned compare(T const& im1, T const& im2, double threshold, bool)
|
|||
return difference;
|
||||
}
|
||||
|
||||
template MAPNIK_DECL unsigned compare(image_gray8 const&, image_gray8 const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray8s const&, image_gray8s const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray16 const&, image_gray16 const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray16s const&, image_gray16s const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray32 const&, image_gray32 const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray32s const&, image_gray32s const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray32f const&, image_gray32f const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray64 const&, image_gray64 const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray64s const&, image_gray64s const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray64f const&, image_gray64f const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray8 const&, image_gray8 const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray8s const&, image_gray8s const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray16 const&, image_gray16 const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray16s const&, image_gray16s const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray32 const&, image_gray32 const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray32s const&, image_gray32s const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray32f const&, image_gray32f const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray64 const&, image_gray64 const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray64s const&, image_gray64s const&, double, bool);
|
||||
template MAPNIK_DECL std::size_t compare(image_gray64f const&, image_gray64f const&, double, bool);
|
||||
|
||||
template <>
|
||||
MAPNIK_DECL unsigned compare<image_null>(image_null const&, image_null const&, double, bool)
|
||||
MAPNIK_DECL std::size_t compare<image_null>(image_null const&, image_null const&, double, bool)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
MAPNIK_DECL unsigned compare<image_rgba8>(image_rgba8 const& im1, image_rgba8 const& im2, double threshold, bool alpha)
|
||||
MAPNIK_DECL std::size_t compare<image_rgba8>(image_rgba8 const& im1, image_rgba8 const& im2, double threshold, bool alpha)
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
if (im1.width() != im2.width() || im1.height() != im2.height())
|
||||
|
@ -2537,7 +2463,7 @@ struct visitor_compare
|
|||
alpha_(alpha) {}
|
||||
|
||||
template <typename T>
|
||||
unsigned operator() (T const & im1) const
|
||||
std::size_t operator() (T const & im1) const
|
||||
{
|
||||
if (!im2_.is<T>())
|
||||
{
|
||||
|
@ -2555,7 +2481,7 @@ struct visitor_compare
|
|||
} // end detail ns
|
||||
|
||||
template <>
|
||||
MAPNIK_DECL unsigned compare<image_any>(image_any const& im1, image_any const& im2, double threshold, bool alpha)
|
||||
MAPNIK_DECL std::size_t compare<image_any>(image_any const& im1, image_any const& im2, double threshold, bool alpha)
|
||||
{
|
||||
return util::apply_visitor(detail::visitor_compare(im2, threshold, alpha), im1);
|
||||
}
|
||||
|
|
|
@ -54,8 +54,7 @@ void process_rgba8_jpeg(T const& image, std::string const& type, std::ostream &
|
|||
auto const& val = kv.second;
|
||||
|
||||
if ( key == "jpeg" ) continue;
|
||||
|
||||
if ( key == "quality")
|
||||
else if ( key == "quality")
|
||||
{
|
||||
if (val && ! (*val).empty())
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ void handle_tiff_options(std::string const& type,
|
|||
auto const& key = kv.first;
|
||||
auto const& val = kv.second;
|
||||
if (key == "tiff") continue;
|
||||
if (key == "compression")
|
||||
else if (key == "compression")
|
||||
{
|
||||
if (val && !(*val).empty())
|
||||
{
|
||||
|
|
|
@ -57,8 +57,7 @@ void handle_webp_options(std::string const& type,
|
|||
auto const& val = kv.second;
|
||||
|
||||
if (key == "webp") continue;
|
||||
|
||||
if (key == "quality")
|
||||
else if (key == "quality")
|
||||
{
|
||||
if (val && !(*val).empty())
|
||||
{
|
||||
|
|
|
@ -1658,12 +1658,14 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::string &
|
|||
{
|
||||
if (node.is_text())
|
||||
{
|
||||
error_message += "\n* text '" + node.text() + "'";
|
||||
error_message += "\n* text '" + node.text();
|
||||
}
|
||||
else
|
||||
{
|
||||
error_message += "\n* node '" + node.name() + "' at line " + node.line_to_string();
|
||||
error_message += "\n* node '" + node.name();
|
||||
}
|
||||
error_message += "' at line " + node.line_to_string();
|
||||
|
||||
return; //All attributes and children are automatically unprocessed, too.
|
||||
}
|
||||
xml_node::attribute_map const& attrs = node.get_attributes();
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace mapnik
|
|||
void mapped_memory_cache::clear()
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
return cache_.clear();
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ void mapped_memory_cache::clear()
|
|||
bool mapped_memory_cache::insert(std::string const& uri, mapped_region_ptr mem)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
return cache_.emplace(uri,mem).second;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ bool mapped_memory_cache::insert(std::string const& uri, mapped_region_ptr mem)
|
|||
boost::optional<mapped_region_ptr> mapped_memory_cache::find(std::string const& uri, bool update_cache)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
using iterator_type = std::unordered_map<std::string, mapped_region_ptr>::const_iterator;
|
||||
boost::optional<mapped_region_ptr> result;
|
||||
|
|
|
@ -70,7 +70,7 @@ marker_cache::~marker_cache() {}
|
|||
void marker_cache::clear()
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
using iterator_type = boost::unordered_map<std::string, std::shared_ptr<mapnik::marker const> >::const_iterator;
|
||||
iterator_type itr = marker_cache_.begin();
|
||||
|
@ -112,7 +112,7 @@ bool marker_cache::insert_svg(std::string const& name, std::string const& svg_st
|
|||
bool marker_cache::insert_marker(std::string const& uri, mapnik::marker && path)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
return marker_cache_.emplace(uri,std::make_shared<mapnik::marker const>(std::move(path))).second;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ std::shared_ptr<mapnik::marker const> marker_cache::find(std::string const& uri,
|
|||
}
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
using iterator_type = boost::unordered_map<std::string, std::shared_ptr<mapnik::marker const> >::const_iterator;
|
||||
iterator_type itr = marker_cache_.find(uri);
|
||||
|
|
|
@ -120,7 +120,7 @@ void projection::init_proj4() const
|
|||
}
|
||||
#else
|
||||
#if defined(MAPNIK_THREADSAFE)
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
proj_ = pj_init_plus(params_.c_str());
|
||||
if (!proj_) throw proj_init_error(params_);
|
||||
|
@ -158,7 +158,7 @@ void projection::forward(double & x, double &y ) const
|
|||
throw std::runtime_error("projection::forward not supported unless proj4 is initialized");
|
||||
}
|
||||
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
projUV p;
|
||||
p.u = x * DEG_TO_RAD;
|
||||
|
@ -185,7 +185,7 @@ void projection::inverse(double & x,double & y) const
|
|||
}
|
||||
|
||||
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
if (is_geographic_)
|
||||
{
|
||||
|
@ -207,7 +207,7 @@ projection::~projection()
|
|||
{
|
||||
#ifdef MAPNIK_USE_PROJ4
|
||||
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480
|
||||
mapnik::scoped_lock lock(mutex_);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
#endif
|
||||
if (proj_)
|
||||
{
|
||||
|
|
|
@ -404,7 +404,7 @@ private:
|
|||
};
|
||||
|
||||
mapnik::geometry::geometry<double> geometry_utils::from_wkb(const char* wkb,
|
||||
unsigned size,
|
||||
std::size_t size,
|
||||
wkbFormat format)
|
||||
{
|
||||
wkb_reader reader(wkb, size, format);
|
||||
|
|
|
@ -11,9 +11,9 @@ if not env['CPP_TESTS']:
|
|||
os.unlink(cpp_test_bin)
|
||||
else:
|
||||
test_env['LIBS'] = [env['MAPNIK_NAME']]
|
||||
test_env.AppendUnique(LIBS=copy(env['LIBMAPNIK_LIBS']))
|
||||
test_env.AppendUnique(LIBS='mapnik-wkt')
|
||||
test_env.AppendUnique(LIBS='mapnik-json')
|
||||
test_env.AppendUnique(LIBS=copy(env['LIBMAPNIK_LIBS']))
|
||||
if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
|
||||
test_env.AppendUnique(LIBS='dl')
|
||||
test_env.AppendUnique(CXXFLAGS='-g')
|
||||
|
@ -45,7 +45,6 @@ else:
|
|||
# visual tests
|
||||
source = Split(
|
||||
"""
|
||||
visual/config.cpp
|
||||
visual/report.cpp
|
||||
visual/runner.cpp
|
||||
visual/run.cpp
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6802b27950218d7f620ffb7e73c5213aa003ea3c
|
||||
Subproject commit 419f955634dec99fe1417b6e7092d608803e0f90
|
|
@ -1 +1 @@
|
|||
Subproject commit 03407519069c6510da49b130ea03fba4fc22161c
|
||||
Subproject commit 39f739a5f05034d3ced1a9970ddd9f81d2317ea2
|
5
test/run
5
test/run
|
@ -25,7 +25,10 @@ if [ -n "$(find test/standalone/ -maxdepth 1 -name '*-bin' -print -quit)" ]; the
|
|||
fi
|
||||
|
||||
run_substep "Running visual tests..."
|
||||
./test/visual/run
|
||||
if [ -z "$JOBS" ]; then
|
||||
JOBS=1
|
||||
fi
|
||||
./test/visual/run -j $JOBS
|
||||
failures=$((failures+$?))
|
||||
|
||||
exit $failures
|
||||
|
|
64
test/standalone/agg_rasterizer_integer_overflow_test.cpp
Normal file
64
test/standalone/agg_rasterizer_integer_overflow_test.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/memory_datasource.hpp>
|
||||
#include <mapnik/json/feature_parser.hpp>
|
||||
#include <mapnik/feature_type_style.hpp>
|
||||
#include <mapnik/rule.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/layer.hpp>
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// geojson box of the world
|
||||
const std::string geojson("{ \"type\": \"Feature\", \"properties\": { }, \"geometry\": { \"type\": \"Polygon\", \"coordinates\": [ [ [ -17963313.143242701888084, -6300857.11560364998877 ], [ -17963313.143242701888084, 13071343.332991421222687 ], [ 7396658.353099936619401, 13071343.332991421222687 ], [ 7396658.353099936619401, -6300857.11560364998877 ], [ -17963313.143242701888084, -6300857.11560364998877 ] ] ] } }");
|
||||
|
||||
TEST_CASE("agg_rasterizer_integer_overflow") {
|
||||
|
||||
SECTION("coordinates_do_not_overflow_and_polygon_is_rendered") {
|
||||
auto expected_color = mapnik::color("white");
|
||||
|
||||
mapnik::Map m(256,256);
|
||||
m.set_background(mapnik::color("black"));
|
||||
|
||||
mapnik::feature_type_style s;
|
||||
{
|
||||
mapnik::rule r;
|
||||
mapnik::polygon_symbolizer sym;
|
||||
mapnik::put(sym, mapnik::keys::fill, expected_color);
|
||||
mapnik::put(sym, mapnik::keys::clip, false);
|
||||
r.append(std::move(sym));
|
||||
s.add_rule(std::move(r));
|
||||
}
|
||||
m.insert_style("style",std::move(s));
|
||||
|
||||
mapnik::layer lyr("Layer");
|
||||
lyr.styles().emplace_back("style");
|
||||
{
|
||||
auto ds = std::make_shared<mapnik::memory_datasource>(mapnik::parameters());
|
||||
auto context = std::make_shared<mapnik::context_type>();
|
||||
auto f = std::make_shared<mapnik::feature_impl>(context, 0);
|
||||
REQUIRE(mapnik::json::from_geojson(geojson, *f));
|
||||
ds->push(f);
|
||||
lyr.set_datasource(ds);
|
||||
}
|
||||
m.add_layer(std::move(lyr));
|
||||
|
||||
// 17/20864/45265.png
|
||||
m.zoom_to_box(mapnik::box2d<double>(-13658379.710221574,6197514.253362091,-13657768.213995293,6198125.749588372));
|
||||
|
||||
// works 15/5216/11316.png
|
||||
//m.zoom_to_box(mapnik::box2d<double>(-13658379.710221574,6195679.764683247,-13655933.72531645,6198125.749588372));
|
||||
|
||||
mapnik::image_rgba8 im(256, 256);
|
||||
{
|
||||
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
REQUIRE(im(128,128) == expected_color.rgba());
|
||||
} // SECTION
|
||||
} // TEST_CASE
|
684
test/standalone/csv_test.cpp
Normal file
684
test/standalone/csv_test.cpp
Normal file
|
@ -0,0 +1,684 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/datasource.hpp>
|
||||
#include <mapnik/datasource_cache.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geometry_types.hpp>
|
||||
#include <mapnik/geometry_type.hpp>
|
||||
#include <mapnik/expression.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace bfs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
void add_csv_files(bfs::path dir, std::vector<bfs::path> &csv_files) {
|
||||
for (auto const &entry : boost::make_iterator_range(
|
||||
bfs::directory_iterator(dir), bfs::directory_iterator())) {
|
||||
auto path = entry.path();
|
||||
if (path.extension().native() == ".csv") {
|
||||
csv_files.emplace_back(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(mapnik::attribute_descriptor const &a,
|
||||
mapnik::attribute_descriptor const &b) {
|
||||
return ((a.get_name() == b.get_name()) &&
|
||||
(a.get_type() == b.get_type()) &&
|
||||
(a.is_primary_key() == b.is_primary_key()) &
|
||||
(a.get_size() == b.get_size()) &&
|
||||
(a.get_precision() == b.get_precision()));
|
||||
}
|
||||
|
||||
mapnik::datasource_ptr get_csv_ds(std::string const &file_name, bool strict = true) {
|
||||
mapnik::parameters params;
|
||||
params["type"] = std::string("csv");
|
||||
params["file"] = file_name;
|
||||
params["strict"] = mapnik::value_bool(strict);
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
// require a non-null pointer returned
|
||||
REQUIRE(bool(ds));
|
||||
return ds;
|
||||
}
|
||||
|
||||
void require_field_names(std::vector<mapnik::attribute_descriptor> const &fields,
|
||||
std::initializer_list<std::string> const &names) {
|
||||
REQUIRE(fields.size() == names.size());
|
||||
auto itr_a = fields.begin();
|
||||
auto const end_a = fields.end();
|
||||
auto itr_b = names.begin();
|
||||
for (; itr_a != end_a; ++itr_a, ++itr_b) {
|
||||
CHECK(itr_a->get_name() == *itr_b);
|
||||
}
|
||||
}
|
||||
|
||||
void require_field_types(std::vector<mapnik::attribute_descriptor> const &fields,
|
||||
std::initializer_list<mapnik::eAttributeType> const &types) {
|
||||
REQUIRE(fields.size() == types.size());
|
||||
auto itr_a = fields.begin();
|
||||
auto const end_a = fields.end();
|
||||
auto itr_b = types.begin();
|
||||
for (; itr_a != end_a; ++itr_a, ++itr_b) {
|
||||
CHECK(itr_a->get_type() == *itr_b);
|
||||
}
|
||||
}
|
||||
|
||||
mapnik::featureset_ptr all_features(mapnik::datasource_ptr ds) {
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
mapnik::query query(ds->envelope());
|
||||
for (auto const &field : fields) {
|
||||
query.add_property_name(field.get_name());
|
||||
}
|
||||
return ds->features(query);
|
||||
}
|
||||
|
||||
std::size_t count_features(mapnik::featureset_ptr features) {
|
||||
std::size_t count = 0;
|
||||
while (features->next()) {
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
using attr = std::tuple<std::string, mapnik::value>;
|
||||
void require_attributes(mapnik::feature_ptr feature,
|
||||
std::initializer_list<attr> const &attrs) {
|
||||
REQUIRE(bool(feature));
|
||||
for (auto const &kv : attrs) {
|
||||
REQUIRE(feature->has_key(std::get<0>(kv)));
|
||||
CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv));
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
struct feature_count {
|
||||
template <typename T>
|
||||
std::size_t operator()(T const &geom) const {
|
||||
return mapnik::util::apply_visitor(*this, geom);
|
||||
}
|
||||
|
||||
std::size_t operator()(mapnik::geometry::geometry_empty const &) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::point<T> const &) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::line_string<T> const &) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::polygon<T> const &) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::multi_point<T> const &mp) const {
|
||||
return mp.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::multi_line_string<T> const &mls) const {
|
||||
return mls.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::multi_polygon<T> const &mp) const {
|
||||
return mp.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t operator()(mapnik::geometry::geometry_collection<T> const &col) const {
|
||||
std::size_t sum = 0;
|
||||
for (auto const &geom : col) {
|
||||
sum += operator()(geom);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
std::size_t feature_count(mapnik::geometry::geometry<T> const &g) {
|
||||
return detail::feature_count()(g);
|
||||
}
|
||||
|
||||
void require_geometry(mapnik::feature_ptr feature,
|
||||
std::size_t num_parts,
|
||||
mapnik::geometry::geometry_types type) {
|
||||
REQUIRE(bool(feature));
|
||||
CHECK(mapnik::geometry::geometry_type(feature->get_geometry()) == type);
|
||||
CHECK(feature_count(feature->get_geometry()) == num_parts);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
const bool registered = mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
|
||||
|
||||
TEST_CASE("csv") {
|
||||
REQUIRE(registered);
|
||||
|
||||
// make the tests silent since we intentially test error conditions that are noisy
|
||||
auto const severity = mapnik::logger::instance().get_severity();
|
||||
mapnik::logger::instance().set_severity(mapnik::logger::none);
|
||||
|
||||
// check the CSV datasource is loaded
|
||||
const std::vector<std::string> plugin_names =
|
||||
mapnik::datasource_cache::instance().plugin_names();
|
||||
const bool have_csv_plugin =
|
||||
std::find(plugin_names.begin(), plugin_names.end(), "csv") != plugin_names.end();
|
||||
|
||||
SECTION("broken files") {
|
||||
if (have_csv_plugin) {
|
||||
std::vector<bfs::path> broken;
|
||||
add_csv_files("test/data/csv/fails", broken);
|
||||
add_csv_files("test/data/csv/warns", broken);
|
||||
broken.emplace_back("test/data/csv/fails/does_not_exist.csv");
|
||||
|
||||
for (auto const &path : broken) {
|
||||
REQUIRE_THROWS(get_csv_ds(path.native()));
|
||||
}
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("good files") {
|
||||
if (have_csv_plugin) {
|
||||
std::vector<bfs::path> good;
|
||||
add_csv_files("test/data/csv", good);
|
||||
add_csv_files("test/data/csv/warns", good);
|
||||
|
||||
for (auto const &path : good) {
|
||||
auto ds = get_csv_ds(path.native(), false);
|
||||
// require a non-null pointer returned
|
||||
REQUIRE(bool(ds));
|
||||
}
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("lon/lat detection") {
|
||||
for (auto const &lon_name : {std::string("lon"), std::string("lng")}) {
|
||||
auto ds = get_csv_ds((boost::format("test/data/csv/%1%_lat.csv") % lon_name).str());
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {lon_name, "lat"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer});
|
||||
|
||||
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
|
||||
|
||||
mapnik::query query(ds->envelope());
|
||||
for (auto const &field : fields) {
|
||||
query.add_property_name(field.get_name());
|
||||
}
|
||||
auto features = ds->features(query);
|
||||
auto feature = features->next();
|
||||
|
||||
require_attributes(feature, {
|
||||
attr { lon_name, mapnik::value_integer(0) },
|
||||
attr { "lat", mapnik::value_integer(0) }
|
||||
});
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("type detection") {
|
||||
auto ds = get_csv_ds("test/data/csv/nypd.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"Precinct", "Phone", "Address", "City", "geo_longitude", "geo_latitude", "geo_accuracy"});
|
||||
require_field_types(fields, {mapnik::String, mapnik::String, mapnik::String, mapnik::String, mapnik::Double, mapnik::Double, mapnik::String});
|
||||
|
||||
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
|
||||
CHECK(count_features(all_features(ds)) == 2);
|
||||
|
||||
auto feature = all_features(ds)->next();
|
||||
require_attributes(feature, {
|
||||
attr { "City", mapnik::value_unicode_string("New York, NY") }
|
||||
, attr { "geo_accuracy", mapnik::value_unicode_string("house") }
|
||||
, attr { "Phone", mapnik::value_unicode_string("(212) 334-0711") }
|
||||
, attr { "Address", mapnik::value_unicode_string("19 Elizabeth Street") }
|
||||
, attr { "Precinct", mapnik::value_unicode_string("5th Precinct") }
|
||||
, attr { "geo_longitude", mapnik::value_integer(-70) }
|
||||
, attr { "geo_latitude", mapnik::value_integer(40) }
|
||||
});
|
||||
} // END SECTION
|
||||
|
||||
SECTION("skipping blank rows") {
|
||||
auto ds = get_csv_ds("test/data/csv/blank_rows.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "name"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
|
||||
|
||||
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
|
||||
CHECK(count_features(all_features(ds)) == 2);
|
||||
} // END SECTION
|
||||
|
||||
SECTION("empty rows") {
|
||||
auto ds = get_csv_ds("test/data/csv/empty_rows.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "text", "date", "integer", "boolean", "float", "time", "datetime", "empty_column"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Integer, mapnik::Boolean, mapnik::Double, mapnik::String, mapnik::String, mapnik::String});
|
||||
|
||||
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
|
||||
CHECK(count_features(all_features(ds)) == 4);
|
||||
|
||||
auto featureset = all_features(ds);
|
||||
auto feature = featureset->next();
|
||||
require_attributes(feature, {
|
||||
attr { "x", mapnik::value_integer(0) }
|
||||
, attr { "empty_column", mapnik::value_unicode_string("") }
|
||||
, attr { "text", mapnik::value_unicode_string("a b") }
|
||||
, attr { "float", mapnik::value_double(1.0) }
|
||||
, attr { "datetime", mapnik::value_unicode_string("1971-01-01T04:14:00") }
|
||||
, attr { "y", mapnik::value_integer(0) }
|
||||
, attr { "boolean", mapnik::value_bool(true) }
|
||||
, attr { "time", mapnik::value_unicode_string("04:14:00") }
|
||||
, attr { "date", mapnik::value_unicode_string("1971-01-01") }
|
||||
, attr { "integer", mapnik::value_integer(40) }
|
||||
});
|
||||
|
||||
while (bool(feature = featureset->next())) {
|
||||
CHECK(feature->size() == 10);
|
||||
CHECK(feature->get("empty_column") == mapnik::value_unicode_string(""));
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("slashes") {
|
||||
auto ds = get_csv_ds("test/data/csv/has_attributes_with_slashes.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "name"});
|
||||
// NOTE: y column is integer, even though a double value is used below in the test?
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
|
||||
|
||||
auto featureset = all_features(ds);
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}
|
||||
, attr{"y", 0}
|
||||
, attr{"name", mapnik::value_unicode_string("a/a") } });
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 1}
|
||||
, attr{"y", 4}
|
||||
, attr{"name", mapnik::value_unicode_string("b/b") } });
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 10}
|
||||
, attr{"y", 2.5}
|
||||
, attr{"name", mapnik::value_unicode_string("c/c") } });
|
||||
} // END SECTION
|
||||
|
||||
SECTION("wkt field") {
|
||||
using mapnik::geometry::geometry_types;
|
||||
|
||||
auto ds = get_csv_ds("test/data/csv/wkt.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"type"});
|
||||
require_field_types(fields, {mapnik::String});
|
||||
|
||||
auto featureset = all_features(ds);
|
||||
require_geometry(featureset->next(), 1, geometry_types::Point);
|
||||
require_geometry(featureset->next(), 1, geometry_types::LineString);
|
||||
require_geometry(featureset->next(), 1, geometry_types::Polygon);
|
||||
require_geometry(featureset->next(), 1, geometry_types::Polygon);
|
||||
require_geometry(featureset->next(), 4, geometry_types::MultiPoint);
|
||||
require_geometry(featureset->next(), 2, geometry_types::MultiLineString);
|
||||
require_geometry(featureset->next(), 2, geometry_types::MultiPolygon);
|
||||
require_geometry(featureset->next(), 2, geometry_types::MultiPolygon);
|
||||
} // END SECTION
|
||||
|
||||
SECTION("handling of missing header") {
|
||||
// TODO: does this mean 'missing_header.csv' should be in the warnings
|
||||
// subdirectory, since it doesn't work in strict mode?
|
||||
auto ds = get_csv_ds("test/data/csv/missing_header.csv", false);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"one", "two", "x", "y", "_4", "aftermissing"});
|
||||
auto feature = all_features(ds)->next();
|
||||
REQUIRE(feature);
|
||||
REQUIRE(feature->has_key("_4"));
|
||||
CHECK(feature->get("_4") == mapnik::value_unicode_string("missing"));
|
||||
} // END SECTION
|
||||
|
||||
SECTION("handling of headers that are numbers") {
|
||||
auto ds = get_csv_ds("test/data/csv/numbers_for_headers.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "1990", "1991", "1992"});
|
||||
auto feature = all_features(ds)->next();
|
||||
require_attributes(feature, {
|
||||
attr{"x", 0}
|
||||
, attr{"y", 0}
|
||||
, attr{"1990", 1}
|
||||
, attr{"1991", 2}
|
||||
, attr{"1992", 3}
|
||||
});
|
||||
auto expression = mapnik::parse_expression("[1991]=2");
|
||||
REQUIRE(bool(expression));
|
||||
auto value = mapnik::util::apply_visitor(
|
||||
mapnik::evaluate<mapnik::feature_impl, mapnik::value_type, mapnik::attributes>(
|
||||
*feature, mapnik::attributes()), *expression);
|
||||
CHECK(value == true);
|
||||
} // END SECTION
|
||||
|
||||
SECTION("quoted numbers") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
auto ds = get_csv_ds("test/data/csv/quoted_numbers.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "label"});
|
||||
auto featureset = all_features(ds);
|
||||
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"label", ustring("0,0") } });
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 5}, attr{"y", 5}, attr{"label", ustring("5,5") } });
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 5}, attr{"label", ustring("0,5") } });
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 5}, attr{"y", 0}, attr{"label", ustring("5,0") } });
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 2.5}, attr{"y", 2.5}, attr{"label", ustring("2.5,2.5") } });
|
||||
|
||||
} // END SECTION
|
||||
|
||||
SECTION("reading newlines") {
|
||||
for (auto const &platform : {std::string("windows"), std::string("mac")}) {
|
||||
std::string file_name = (boost::format("test/data/csv/%1%_newlines.csv") % platform).str();
|
||||
auto ds = get_csv_ds(file_name);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "z"});
|
||||
require_attributes(all_features(ds)->next(), {
|
||||
attr{"x", 1}, attr{"y", 10}, attr{"z", 9999.9999} });
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("mixed newlines") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
for (auto const &file : {
|
||||
std::string("test/data/csv/mac_newlines_with_unix_inline.csv")
|
||||
, std::string("test/data/csv/mac_newlines_with_unix_inline_escaped.csv")
|
||||
, std::string("test/data/csv/windows_newlines_with_unix_inline.csv")
|
||||
, std::string("test/data/csv/windows_newlines_with_unix_inline_escaped.csv")
|
||||
}) {
|
||||
auto ds = get_csv_ds(file);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "line"});
|
||||
require_attributes(all_features(ds)->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}
|
||||
, attr{"line", ustring("many\n lines\n of text\n with unix newlines")} });
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("tabs") {
|
||||
auto ds = get_csv_ds("test/data/csv/tabs_in_csv.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "z"});
|
||||
require_attributes(all_features(ds)->next(), {
|
||||
attr{"x", -122}, attr{"y", 48}, attr{"z", 0} });
|
||||
} // END SECTION
|
||||
|
||||
SECTION("separators") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
for (auto const &file : {
|
||||
std::string("test/data/csv/pipe_delimiters.csv")
|
||||
, std::string("test/data/csv/semicolon_delimiters.csv")
|
||||
}) {
|
||||
auto ds = get_csv_ds(file);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "z"});
|
||||
require_attributes(all_features(ds)->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"z", ustring("hello")} });
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("null and bool keywords are empty strings") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
auto ds = get_csv_ds("test/data/csv/nulls_and_booleans_as_strings.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "null", "boolean"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::Boolean});
|
||||
|
||||
auto featureset = all_features(ds);
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"null", ustring("null")}, attr{"boolean", true}});
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"null", ustring("")}, attr{"boolean", false}});
|
||||
} // END SECTION
|
||||
|
||||
SECTION("nonexistent query fields throw") {
|
||||
auto ds = get_csv_ds("test/data/csv/lon_lat.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"lon", "lat"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer});
|
||||
|
||||
mapnik::query query(ds->envelope());
|
||||
for (auto const &field : fields) {
|
||||
query.add_property_name(field.get_name());
|
||||
}
|
||||
// also add an invalid one, triggering throw
|
||||
query.add_property_name("bogus");
|
||||
|
||||
REQUIRE_THROWS(ds->features(query));
|
||||
} // END SECTION
|
||||
|
||||
SECTION("leading zeros mean strings") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
auto ds = get_csv_ds("test/data/csv/leading_zeros.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "fips"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
|
||||
|
||||
auto featureset = all_features(ds);
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("001")}});
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("003")}});
|
||||
require_attributes(featureset->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("005")}});
|
||||
} // END SECTION
|
||||
|
||||
SECTION("advanced geometry detection") {
|
||||
using row = std::pair<std::string, mapnik::datasource_geometry_t>;
|
||||
|
||||
for (row r : {
|
||||
row{"point", mapnik::datasource_geometry_t::Point}
|
||||
, row{"poly", mapnik::datasource_geometry_t::Polygon}
|
||||
, row{"multi_poly", mapnik::datasource_geometry_t::Polygon}
|
||||
, row{"line", mapnik::datasource_geometry_t::LineString}
|
||||
}) {
|
||||
std::string file_name = (boost::format("test/data/csv/%1%_wkt.csv") % r.first).str();
|
||||
auto ds = get_csv_ds(file_name);
|
||||
CHECK(ds->get_geometry_type() == r.second);
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("creation of CSV from in-memory strings") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
for (auto const &name : {std::string("Winthrop, WA"), std::string(u8"Qu\u00e9bec")}) {
|
||||
std::string csv_string =
|
||||
(boost::format(
|
||||
"wkt,Name\n"
|
||||
"\"POINT (120.15 48.47)\",\"%1%\"\n"
|
||||
) % name).str();
|
||||
|
||||
mapnik::parameters params;
|
||||
params["type"] = std::string("csv");
|
||||
params["inline"] = csv_string;
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(bool(ds));
|
||||
|
||||
auto feature = all_features(ds)->next();
|
||||
REQUIRE(bool(feature));
|
||||
REQUIRE(feature->has_key("Name"));
|
||||
CHECK(feature->get("Name") == ustring(name.c_str()));
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("geojson quoting") {
|
||||
using mapnik::geometry::geometry_types;
|
||||
|
||||
for (auto const &file : {
|
||||
std::string("test/data/csv/geojson_double_quote_escape.csv")
|
||||
, std::string("test/data/csv/geojson_single_quote.csv")
|
||||
, std::string("test/data/csv/geojson_2x_double_quote_filebakery_style.csv")
|
||||
}) {
|
||||
auto ds = get_csv_ds(file);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"type"});
|
||||
require_field_types(fields, {mapnik::String});
|
||||
|
||||
auto featureset = all_features(ds);
|
||||
require_geometry(featureset->next(), 1, geometry_types::Point);
|
||||
require_geometry(featureset->next(), 1, geometry_types::LineString);
|
||||
require_geometry(featureset->next(), 1, geometry_types::Polygon);
|
||||
require_geometry(featureset->next(), 1, geometry_types::Polygon);
|
||||
require_geometry(featureset->next(), 4, geometry_types::MultiPoint);
|
||||
require_geometry(featureset->next(), 2, geometry_types::MultiLineString);
|
||||
require_geometry(featureset->next(), 2, geometry_types::MultiPolygon);
|
||||
require_geometry(featureset->next(), 2, geometry_types::MultiPolygon);
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("blank undelimited rows are still parsed") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
|
||||
// TODO: does this mean this CSV file should be in the warnings
|
||||
// subdirectory, since it doesn't work in strict mode?
|
||||
auto ds = get_csv_ds("test/data/csv/more_headers_than_column_values.csv", false);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "one", "two", "three"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::String});
|
||||
|
||||
require_attributes(all_features(ds)->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"one", ustring("")}, attr{"two", ustring("")}, attr{"three", ustring("")} });
|
||||
} // END SECTION
|
||||
|
||||
SECTION("fewer headers than rows throws") {
|
||||
REQUIRE_THROWS(get_csv_ds("test/data/csv/more_column_values_than_headers.csv"));
|
||||
} // END SECTION
|
||||
|
||||
SECTION("feature ID only incremented for valid rows") {
|
||||
auto ds = get_csv_ds("test/data/csv/warns/feature_id_counting.csv", false);
|
||||
auto fs = all_features(ds);
|
||||
|
||||
// first
|
||||
auto feature = fs->next();
|
||||
REQUIRE(bool(feature));
|
||||
CHECK(feature->id() == 1);
|
||||
|
||||
// second, should have skipped bogus one
|
||||
feature = fs->next();
|
||||
REQUIRE(bool(feature));
|
||||
CHECK(feature->id() == 2);
|
||||
|
||||
feature = fs->next();
|
||||
CHECK(!feature);
|
||||
} // END SECTION
|
||||
|
||||
SECTION("dynamically defining headers") {
|
||||
using ustring = mapnik::value_unicode_string;
|
||||
using row = std::pair<std::string, std::size_t>;
|
||||
|
||||
for (auto const &r : {
|
||||
row{"test/data/csv/fails/needs_headers_two_lines.csv", 2}
|
||||
, row{"test/data/csv/fails/needs_headers_one_line.csv", 1}
|
||||
, row{"test/data/csv/fails/needs_headers_one_line_no_newline.csv", 1}
|
||||
}) {
|
||||
mapnik::parameters params;
|
||||
params["type"] = std::string("csv");
|
||||
params["file"] = r.first;
|
||||
params["headers"] = "x,y,name";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(bool(ds));
|
||||
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "name"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
|
||||
require_attributes(all_features(ds)->next(), {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"name", ustring("data_name")} });
|
||||
REQUIRE(count_features(all_features(ds)) == r.second);
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
SECTION("64bit int fields work") {
|
||||
auto ds = get_csv_ds("test/data/csv/64bit_int.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "bigint"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::Integer});
|
||||
|
||||
auto fs = all_features(ds);
|
||||
auto feature = fs->next();
|
||||
require_attributes(feature, {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"bigint", 2147483648} });
|
||||
|
||||
feature = fs->next();
|
||||
require_attributes(feature, {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"bigint", 9223372036854775807ll} });
|
||||
require_attributes(feature, {
|
||||
attr{"x", 0}, attr{"y", 0}, attr{"bigint", 0x7FFFFFFFFFFFFFFFll} });
|
||||
} // END SECTION
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
SECTION("various number types") {
|
||||
auto ds = get_csv_ds("test/data/csv/number_types.csv");
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"x", "y", "floats"});
|
||||
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::Double});
|
||||
|
||||
auto fs = all_features(ds);
|
||||
for (double d : { .0, +.0, 1e-06, -1e-06, 0.000001, 1.234e+16, 1.234e+16 }) {
|
||||
auto feature = fs->next();
|
||||
REQUIRE(bool(feature));
|
||||
CHECK(feature->get("floats").get<mapnik::value_double>() == Approx(d));
|
||||
}
|
||||
} // END SECTION
|
||||
|
||||
SECTION("manually supplied extent") {
|
||||
std::string csv_string("wkt,Name\n");
|
||||
mapnik::parameters params;
|
||||
params["type"] = std::string("csv");
|
||||
params["inline"] = csv_string;
|
||||
params["extent"] = "-180,-90,180,90";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(bool(ds));
|
||||
|
||||
auto box = ds->envelope();
|
||||
CHECK(box.minx() == -180);
|
||||
CHECK(box.miny() == -90);
|
||||
CHECK(box.maxx() == 180);
|
||||
CHECK(box.maxy() == 90);
|
||||
} // END SECTION
|
||||
|
||||
SECTION("inline geojson") {
|
||||
std::string csv_string = "geojson\n'{\"coordinates\":[-92.22568,38.59553],\"type\":\"Point\"}'";
|
||||
mapnik::parameters params;
|
||||
params["type"] = std::string("csv");
|
||||
params["inline"] = csv_string;
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(bool(ds));
|
||||
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {});
|
||||
|
||||
// TODO: this originally had the following comment:
|
||||
// - re-enable after https://github.com/mapnik/mapnik/issues/2319 is fixed
|
||||
// but that seems to have been merged and tested separately?
|
||||
auto fs = all_features(ds);
|
||||
auto feat = fs->next();
|
||||
CHECK(feature_count(feat->get_geometry()) == 1);
|
||||
} // END SECTION
|
||||
|
||||
mapnik::logger::instance().set_severity(severity);
|
||||
} // END TEST CASE
|
163
test/unit/core/box2d_test.cpp
Normal file
163
test/unit/core/box2d_test.cpp
Normal file
|
@ -0,0 +1,163 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <mapnik/coord.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
|
||||
TEST_CASE("box2d") {
|
||||
SECTION("coord init") {
|
||||
auto c = mapnik::coord2d(100, 100);
|
||||
|
||||
REQUIRE(c.x == 100);
|
||||
REQUIRE(c.y == 100);
|
||||
}
|
||||
|
||||
SECTION("coord multiplication") {
|
||||
auto c = mapnik::coord2d(100, 100);
|
||||
c *= 2;
|
||||
|
||||
REQUIRE(c.x == 200);
|
||||
REQUIRE(c.y == 200);
|
||||
}
|
||||
|
||||
SECTION("envelope init") {
|
||||
auto e = mapnik::box2d<double>(100, 100, 200, 200);
|
||||
|
||||
REQUIRE(e.contains(100, 100));
|
||||
REQUIRE(e.contains(100, 200));
|
||||
REQUIRE(e.contains(200, 200));
|
||||
REQUIRE(e.contains(200, 100));
|
||||
|
||||
REQUIRE(e.contains(e.center()));
|
||||
|
||||
REQUIRE(!e.contains(99.9, 99.9));
|
||||
REQUIRE(!e.contains(99.9, 200.1));
|
||||
REQUIRE(!e.contains(200.1, 200.1));
|
||||
REQUIRE(!e.contains(200.1, 99.9));
|
||||
|
||||
REQUIRE(e.width() == 100);
|
||||
REQUIRE(e.height() == 100);
|
||||
|
||||
REQUIRE(e.minx() == 100);
|
||||
REQUIRE(e.miny() == 100);
|
||||
|
||||
REQUIRE(e.maxx() == 200);
|
||||
REQUIRE(e.maxy() == 200);
|
||||
|
||||
REQUIRE(e[0] == 100);
|
||||
REQUIRE(e[1] == 100);
|
||||
REQUIRE(e[2] == 200);
|
||||
REQUIRE(e[3] == 200);
|
||||
REQUIRE(e[0] == e[-4]);
|
||||
REQUIRE(e[1] == e[-3]);
|
||||
REQUIRE(e[2] == e[-2]);
|
||||
REQUIRE(e[3] == e[-1]);
|
||||
|
||||
auto c = e.center();
|
||||
|
||||
REQUIRE(c.x == 150);
|
||||
REQUIRE(c.y == 150);
|
||||
}
|
||||
|
||||
SECTION("envelope static init") {
|
||||
auto e = mapnik::box2d<double>(100, 100, 200, 200);
|
||||
|
||||
mapnik::box2d<double> e1, e2, e3;
|
||||
REQUIRE(e1.from_string("100 100 200 200"));
|
||||
REQUIRE(e2.from_string("100,100,200,200"));
|
||||
REQUIRE(e3.from_string("100 , 100 , 200 , 200"));
|
||||
|
||||
REQUIRE(e == e1);
|
||||
REQUIRE(e == e2);
|
||||
REQUIRE(e == e3);
|
||||
}
|
||||
|
||||
SECTION("envelope multiplication") {
|
||||
// no width then no impact of multiplication
|
||||
{
|
||||
auto a = mapnik::box2d<int>(100, 100, 100, 100);
|
||||
a *= 5;
|
||||
|
||||
REQUIRE(a.minx() == 100);
|
||||
REQUIRE(a.miny() == 100);
|
||||
REQUIRE(a.maxx() == 100);
|
||||
REQUIRE(a.maxy() == 100);
|
||||
}
|
||||
|
||||
{
|
||||
auto a = mapnik::box2d<double>(100.0, 100.0, 100.0, 100.0);
|
||||
a *= 5;
|
||||
|
||||
REQUIRE(a.minx() == 100);
|
||||
REQUIRE(a.miny() == 100);
|
||||
REQUIRE(a.maxx() == 100);
|
||||
REQUIRE(a.maxy() == 100);
|
||||
}
|
||||
|
||||
{
|
||||
auto a = mapnik::box2d<double>(100.0, 100.0, 100.001, 100.001);
|
||||
a *= 5;
|
||||
|
||||
REQUIRE(a.minx() == Approx( 99.9980));
|
||||
REQUIRE(a.miny() == Approx( 99.9980));
|
||||
REQUIRE(a.maxx() == Approx(100.0030));
|
||||
REQUIRE(a.maxy() == Approx(100.0030));
|
||||
}
|
||||
|
||||
{
|
||||
auto e = mapnik::box2d<double>(100, 100, 200, 200);
|
||||
e *= 2;
|
||||
|
||||
REQUIRE(e.minx() == 50);
|
||||
REQUIRE(e.miny() == 50);
|
||||
REQUIRE(e.maxx() == 250);
|
||||
REQUIRE(e.maxy() == 250);
|
||||
|
||||
REQUIRE(e.contains(50, 50));
|
||||
REQUIRE(e.contains(50, 250));
|
||||
REQUIRE(e.contains(250, 250));
|
||||
REQUIRE(e.contains(250, 50));
|
||||
|
||||
REQUIRE(!e.contains(49.9, 49.9));
|
||||
REQUIRE(!e.contains(49.9, 250.1));
|
||||
REQUIRE(!e.contains(250.1, 250.1));
|
||||
REQUIRE(!e.contains(250.1, 49.9));
|
||||
|
||||
REQUIRE(e.contains(e.center()));
|
||||
|
||||
REQUIRE(e.width() == 200);
|
||||
REQUIRE(e.height() == 200);
|
||||
|
||||
REQUIRE(e.minx() == 50);
|
||||
REQUIRE(e.miny() == 50);
|
||||
|
||||
REQUIRE(e.maxx() == 250);
|
||||
REQUIRE(e.maxy() == 250);
|
||||
|
||||
auto c = e.center();
|
||||
|
||||
REQUIRE(c.x == 150);
|
||||
REQUIRE(c.y == 150);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("envelope clipping") {
|
||||
auto e1 = mapnik::box2d<double>(-180,-90,180,90);
|
||||
auto e2 = mapnik::box2d<double>(-120,40,-110,48);
|
||||
e1.clip(e2);
|
||||
REQUIRE(e1 == e2);
|
||||
|
||||
// madagascar in merc
|
||||
e1 = mapnik::box2d<double>(4772116.5490, -2744395.0631, 5765186.4203, -1609458.0673);
|
||||
e2 = mapnik::box2d<double>(5124338.3753, -2240522.1727, 5207501.8621, -2130452.8520);
|
||||
e1.clip(e2);
|
||||
REQUIRE(e1 == e2);
|
||||
|
||||
// nz in lon/lat
|
||||
e1 = mapnik::box2d<double>(163.8062, -47.1897, 179.3628, -33.9069);
|
||||
e2 = mapnik::box2d<double>(173.7378, -39.6395, 174.4849, -38.9252);
|
||||
e1.clip(e2);
|
||||
REQUIRE(e1 == e2);
|
||||
}
|
||||
|
||||
} // TEST_CASE
|
|
@ -5,7 +5,7 @@
|
|||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
|
||||
TEST_CASE("image multiply_alpha") {
|
||||
TEST_CASE("image apply_opacity") {
|
||||
|
||||
SECTION("test rgba8") {
|
||||
|
||||
|
@ -22,10 +22,10 @@ SECTION("test rgba8") {
|
|||
mapnik::fill(im2, c2); // Because c1 is premultiplied it will make the image premultiplied
|
||||
mapnik::fill(im2_any, c2); // Because c1 is premultiplied it will make the image premultiplied
|
||||
|
||||
mapnik::multiply_alpha(im, 0.75);
|
||||
mapnik::multiply_alpha(im_any, 0.75);
|
||||
mapnik::multiply_alpha(im2, 0.75);
|
||||
mapnik::multiply_alpha(im2_any, 0.75);
|
||||
mapnik::apply_opacity(im, 0.75);
|
||||
mapnik::apply_opacity(im_any, 0.75);
|
||||
mapnik::apply_opacity(im2, 0.75);
|
||||
mapnik::apply_opacity(im2_any, 0.75);
|
||||
|
||||
mapnik::color out;
|
||||
// This should have only changed the alpha, as it was not premultipleid
|
||||
|
@ -65,7 +65,7 @@ SECTION("test rgba8 overflow") {
|
|||
CHECK(static_cast<int>(out.blue()) == 128);
|
||||
CHECK(static_cast<int>(out.alpha()) == 128);
|
||||
|
||||
mapnik::multiply_alpha(im, 2.5);
|
||||
mapnik::apply_opacity(im, 2.5);
|
||||
|
||||
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 128);
|
||||
|
@ -81,7 +81,7 @@ SECTION("test rgba8 underflow") {
|
|||
mapnik::color c(128,128,128,128); // This color is premultiplied
|
||||
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
|
||||
|
||||
mapnik::multiply_alpha(im, -2.5);
|
||||
mapnik::apply_opacity(im, -2.5);
|
||||
|
||||
mapnik::color out;
|
||||
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
|
||||
|
@ -97,8 +97,8 @@ SECTION("test gray8") {
|
|||
mapnik::image_gray8 im(4,4);
|
||||
mapnik::image_any im_any(mapnik::image_gray8(4,4));
|
||||
|
||||
CHECK_THROWS(mapnik::multiply_alpha(im, 0.25));
|
||||
CHECK_THROWS(mapnik::multiply_alpha(im_any, 0.25));
|
||||
CHECK_THROWS(mapnik::apply_opacity(im, 0.25));
|
||||
CHECK_THROWS(mapnik::apply_opacity(im_any, 0.25));
|
||||
|
||||
} // END SECTION
|
||||
} // END TEST_CASE
|
|
@ -1,101 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/image_any.hpp>
|
||||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
|
||||
TEST_CASE("image set_alpha") {
|
||||
|
||||
SECTION("test rgba8") {
|
||||
|
||||
mapnik::image_rgba8 im(4,4);
|
||||
mapnik::image_rgba8 im2(4,4,true,true); // Initialize as already premultiplied
|
||||
mapnik::image_any im_any(mapnik::image_rgba8(4,4));
|
||||
mapnik::image_any im2_any(mapnik::image_rgba8(4,4,true,true));
|
||||
|
||||
// Fill the images with meaningfull values
|
||||
mapnik::color c1(57,70,128,128); // This color is not premultiplied
|
||||
mapnik::color c2(57,70,128,128, true); // This color is premultiplied
|
||||
mapnik::fill(im, c1); // Because c1 is not premultiplied it will make the image not premultiplied
|
||||
mapnik::fill(im_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied
|
||||
mapnik::fill(im2, c2); // Because c1 is premultiplied it will make the image premultiplied
|
||||
mapnik::fill(im2_any, c2); // Because c1 is premultiplied it will make the image premultiplied
|
||||
|
||||
mapnik::set_alpha(im, 0.25);
|
||||
mapnik::set_alpha(im_any, 0.25);
|
||||
mapnik::set_alpha(im2, 0.25);
|
||||
mapnik::set_alpha(im2_any, 0.25);
|
||||
|
||||
|
||||
mapnik::color out;
|
||||
// This should have only changed the alpha, as it was not premultipleid
|
||||
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 57);
|
||||
CHECK(static_cast<int>(out.green()) == 70);
|
||||
CHECK(static_cast<int>(out.blue()) == 128);
|
||||
CHECK(static_cast<int>(out.alpha()) == 63);
|
||||
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 57);
|
||||
CHECK(static_cast<int>(out.green()) == 70);
|
||||
CHECK(static_cast<int>(out.blue()) == 128);
|
||||
CHECK(static_cast<int>(out.alpha()) == 63);
|
||||
// This will be different because it is demultiplied then premultiplied again after setting alpha
|
||||
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 28);
|
||||
CHECK(static_cast<int>(out.green()) == 35);
|
||||
CHECK(static_cast<int>(out.blue()) == 63);
|
||||
CHECK(static_cast<int>(out.alpha()) == 63);
|
||||
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 28);
|
||||
CHECK(static_cast<int>(out.green()) == 35);
|
||||
CHECK(static_cast<int>(out.blue()) == 63);
|
||||
CHECK(static_cast<int>(out.alpha()) == 63);
|
||||
|
||||
} // END SECTION
|
||||
|
||||
SECTION("test rgba8 overflow") {
|
||||
|
||||
mapnik::image_rgba8 im(4,4);
|
||||
mapnik::color c(128,128,128,128); // This color is premultiplied
|
||||
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
|
||||
|
||||
mapnik::set_alpha(im, 1.25);
|
||||
|
||||
mapnik::color out;
|
||||
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 128);
|
||||
CHECK(static_cast<int>(out.green()) == 128);
|
||||
CHECK(static_cast<int>(out.blue()) == 128);
|
||||
CHECK(static_cast<int>(out.alpha()) == 255);
|
||||
|
||||
} // END SECTION
|
||||
|
||||
SECTION("test rgba8 underflow") {
|
||||
|
||||
mapnik::image_rgba8 im(4,4);
|
||||
mapnik::color c(128,128,128,128); // This color is premultiplied
|
||||
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
|
||||
|
||||
mapnik::set_alpha(im, -1.25);
|
||||
|
||||
mapnik::color out;
|
||||
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
|
||||
CHECK(static_cast<int>(out.red()) == 128);
|
||||
CHECK(static_cast<int>(out.green()) == 128);
|
||||
CHECK(static_cast<int>(out.blue()) == 128);
|
||||
CHECK(static_cast<int>(out.alpha()) == 0);
|
||||
|
||||
} // END SECTION
|
||||
|
||||
SECTION("test gray8") {
|
||||
|
||||
mapnik::image_gray8 im(4,4);
|
||||
mapnik::image_any im_any(mapnik::image_gray8(4,4));
|
||||
|
||||
CHECK_THROWS(mapnik::set_alpha(im, 0.25));
|
||||
CHECK_THROWS(mapnik::set_alpha(im_any, 0.25));
|
||||
|
||||
} // END SECTION
|
||||
|
||||
} // END TEST_CASE
|
|
@ -1,40 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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/util/fs.hpp>
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
namespace visual_tests
|
||||
{
|
||||
|
||||
bool ensure_dir(boost::filesystem::path const & dir)
|
||||
{
|
||||
if (!mapnik::util::exists(dir.string()))
|
||||
{
|
||||
return boost::filesystem::create_directories(dir);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -75,8 +75,6 @@ struct result
|
|||
|
||||
using result_list = std::vector<result>;
|
||||
|
||||
bool ensure_dir(boost::filesystem::path const & dir);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/util/fs.hpp>
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
#if defined(HAVE_CAIRO)
|
||||
#include <mapnik/cairo/cairo_renderer.hpp>
|
||||
|
@ -118,7 +117,7 @@ public:
|
|||
{
|
||||
typename Renderer::image_type image(ren.render(map, scale_factor));
|
||||
boost::filesystem::path reference = reference_dir / image_file_name(name, map.width(), map.height(), scale_factor, true);
|
||||
bool reference_exists = mapnik::util::exists(reference.string());
|
||||
bool reference_exists = boost::filesystem::exists(reference);
|
||||
result res;
|
||||
|
||||
res.state = reference_exists ? STATE_OK : STATE_OVERWRITE;
|
||||
|
@ -131,7 +130,7 @@ public:
|
|||
|
||||
if (res.diff)
|
||||
{
|
||||
ensure_dir(output_dir);
|
||||
boost::filesystem::create_directories(output_dir);
|
||||
boost::filesystem::path path = output_dir / image_file_name(name, map.width(), map.height(), scale_factor);
|
||||
res.actual_image_path = path;
|
||||
res.state = STATE_FAIL;
|
||||
|
|
|
@ -189,7 +189,7 @@ void html_report::summary(result_list const & results, boost::filesystem::path c
|
|||
void html_summary(result_list const & results, boost::filesystem::path output_dir)
|
||||
{
|
||||
boost::filesystem::path html_root = output_dir / "visual-test-results";
|
||||
ensure_dir(html_root);
|
||||
boost::filesystem::create_directories(html_root);
|
||||
boost::filesystem::path html_report_path = html_root / "index.html";
|
||||
std::clog << "View failure report at " << html_report_path << "\n";
|
||||
std::ofstream output_file(html_report_path.string());
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <future>
|
||||
|
||||
#include <mapnik/load_map.hpp>
|
||||
#include <mapnik/util/fs.hpp>
|
||||
|
||||
#include "runner.hpp"
|
||||
|
||||
|
@ -52,9 +51,9 @@ private:
|
|||
double scale_factor_;
|
||||
};
|
||||
|
||||
runner::runner(boost::filesystem::path const & styles_dir,
|
||||
boost::filesystem::path const & output_dir,
|
||||
boost::filesystem::path const & reference_dir,
|
||||
runner::runner(runner::path_type const & styles_dir,
|
||||
runner::path_type const & output_dir,
|
||||
runner::path_type const & reference_dir,
|
||||
bool overwrite,
|
||||
std::size_t jobs)
|
||||
: styles_dir_(styles_dir),
|
||||
|
@ -69,22 +68,24 @@ runner::runner(boost::filesystem::path const & styles_dir,
|
|||
|
||||
result_list runner::test_all(report_type & report) const
|
||||
{
|
||||
std::vector<std::string> files = mapnik::util::list_directory(styles_dir_.string());
|
||||
boost::filesystem::directory_iterator begin(styles_dir_);
|
||||
boost::filesystem::directory_iterator end;
|
||||
std::vector<runner::path_type> files(begin, end);
|
||||
return test_parallel(files, report, jobs_);
|
||||
}
|
||||
|
||||
result_list runner::test(std::vector<std::string> const & style_names, report_type & report) const
|
||||
{
|
||||
std::vector<std::string> files(style_names.size());
|
||||
std::vector<runner::path_type> files(style_names.size());
|
||||
std::transform(style_names.begin(), style_names.end(), std::back_inserter(files),
|
||||
[&](std::string const & name)
|
||||
[&](runner::path_type const & name)
|
||||
{
|
||||
return (styles_dir_ / (name + ".xml")).string();
|
||||
return (name.extension() == ".xml") ? name : (styles_dir_ / (name.string() + ".xml"));
|
||||
});
|
||||
return test_parallel(files, report, jobs_);
|
||||
}
|
||||
|
||||
result_list runner::test_parallel(std::vector<std::string> const & files, report_type & report, std::size_t jobs) const
|
||||
result_list runner::test_parallel(std::vector<runner::path_type> const & files, report_type & report, std::size_t jobs) const
|
||||
{
|
||||
result_list results;
|
||||
|
||||
|
@ -137,10 +138,10 @@ result_list runner::test_range(files_iterator begin, files_iterator end, std::re
|
|||
config defaults;
|
||||
result_list results;
|
||||
|
||||
for (std::vector<std::string>::const_iterator i = begin; i != end; i++)
|
||||
for (runner::files_iterator i = begin; i != end; i++)
|
||||
{
|
||||
std::string const & file = *i;
|
||||
if (file.size() >= 3 && file.substr(file.size() - 3) == "xml")
|
||||
runner::path_type const & file = *i;
|
||||
if (file.extension() == ".xml")
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -151,7 +152,7 @@ result_list runner::test_range(files_iterator begin, files_iterator end, std::re
|
|||
{
|
||||
result r;
|
||||
r.state = STATE_ERROR;
|
||||
r.name = file;
|
||||
r.name = file.string();
|
||||
r.error_message = ex.what();
|
||||
results.emplace_back(r);
|
||||
mapnik::util::apply_visitor(report_visitor(r), report.get());
|
||||
|
@ -162,14 +163,14 @@ result_list runner::test_range(files_iterator begin, files_iterator end, std::re
|
|||
return results;
|
||||
}
|
||||
|
||||
result_list runner::test_one(std::string const& style_path, config cfg, report_type & report) const
|
||||
result_list runner::test_one(runner::path_type const& style_path, config cfg, report_type & report) const
|
||||
{
|
||||
mapnik::Map m(cfg.sizes.front().width, cfg.sizes.front().height);
|
||||
result_list results;
|
||||
|
||||
try
|
||||
{
|
||||
mapnik::load_map(m, style_path, true);
|
||||
mapnik::load_map(m, style_path.string(), true);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
|
@ -199,8 +200,7 @@ result_list runner::test_one(std::string const& style_path, config cfg, report_t
|
|||
parse_map_sizes(*sizes, cfg.sizes);
|
||||
}
|
||||
|
||||
boost::filesystem::path p(style_path);
|
||||
std::string name(p.stem().string());
|
||||
std::string name(style_path.stem().string());
|
||||
|
||||
for (map_size const & size : cfg.sizes)
|
||||
{
|
||||
|
|
|
@ -38,11 +38,13 @@ class runner
|
|||
using renderer_type = mapnik::util::variant<renderer<agg_renderer>,
|
||||
renderer<cairo_renderer>/*,
|
||||
renderer<grid_renderer>*/>;
|
||||
using path_type = boost::filesystem::path;
|
||||
using files_iterator = std::vector<path_type>::const_iterator;
|
||||
|
||||
public:
|
||||
runner(boost::filesystem::path const & styles_dir,
|
||||
boost::filesystem::path const & output_dir,
|
||||
boost::filesystem::path const & reference_dir,
|
||||
runner(path_type const & styles_dir,
|
||||
path_type const & output_dir,
|
||||
path_type const & reference_dir,
|
||||
bool overwrite,
|
||||
std::size_t jobs);
|
||||
|
||||
|
@ -50,17 +52,15 @@ public:
|
|||
result_list test(std::vector<std::string> const & style_names, report_type & report) const;
|
||||
|
||||
private:
|
||||
using files_iterator = std::vector<std::string>::const_iterator;
|
||||
|
||||
result_list test_parallel(std::vector<std::string> const & files, report_type & report, std::size_t jobs) const;
|
||||
result_list test_parallel(std::vector<path_type> const & files, report_type & report, std::size_t jobs) const;
|
||||
result_list test_range(files_iterator begin, files_iterator end, std::reference_wrapper<report_type> report) const;
|
||||
result_list test_one(std::string const & style_path, config cfg, report_type & report) const;
|
||||
result_list test_one(path_type const & style_path, config cfg, report_type & report) const;
|
||||
void parse_map_sizes(std::string const & str, std::vector<map_size> & sizes) const;
|
||||
|
||||
const map_sizes_grammar<std::string::const_iterator> map_sizes_parser_;
|
||||
const boost::filesystem::path styles_dir_;
|
||||
const boost::filesystem::path output_dir_;
|
||||
const boost::filesystem::path reference_dir_;
|
||||
const path_type styles_dir_;
|
||||
const path_type output_dir_;
|
||||
const path_type reference_dir_;
|
||||
const std::size_t jobs_;
|
||||
const renderer_type renderers_[boost::mpl::size<renderer_type::types>::value];
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue