Merge branch 'master' into spirit-x3
This commit is contained in:
commit
7e5337b486
30 changed files with 2611 additions and 1345 deletions
|
@ -85,7 +85,7 @@ script:
|
|||
- if [[ ${COVERAGE} != true ]]; then
|
||||
make bench;
|
||||
fi
|
||||
- if [[ ${TEST_RESULT} != 0 ]]; then exit $TEST_RESULT ; fi;
|
||||
- if [[ ${TEST_RESULT:-0} != 0 ]]; then exit $TEST_RESULT ; fi;
|
||||
- if [[ ${MASON_PUBLISH} == true ]]; then
|
||||
./mason_latest.sh build;
|
||||
./mason_latest.sh link;
|
||||
|
|
10
SConstruct
10
SConstruct
|
@ -294,6 +294,7 @@ opts.AddVariables(
|
|||
# Note: setting DEBUG=True will override any custom OPTIMIZATION level
|
||||
BoolVariable('DEBUG', 'Compile a debug version of Mapnik', 'False'),
|
||||
BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'),
|
||||
BoolVariable('DEBUG_SANITIZE', 'Compile a version of Mapnik using clang/llvm address sanitation', 'False'),
|
||||
ListVariable('INPUT_PLUGINS','Input drivers to include',DEFAULT_PLUGINS,PLUGINS.keys()),
|
||||
('WARNING_CXXFLAGS', 'Compiler flags you can set to reduce warning levels which are placed after -Wall.', ''),
|
||||
|
||||
|
@ -1785,7 +1786,7 @@ if not preconfigured:
|
|||
|
||||
# Common flags for g++/clang++ CXX compiler.
|
||||
# TODO: clean up code more to make -Wextra -Wsign-compare -Wsign-conversion -Wconversion viable
|
||||
common_cxx_flags = '-Wall %s %s -ftemplate-depth-300 -Wsign-compare -Wshadow ' % (env['WARNING_CXXFLAGS'], pthread)
|
||||
common_cxx_flags = '-fvisibility=hidden -fvisibility-inlines-hidden -Wall %s %s -ftemplate-depth-300 -Wsign-compare -Wshadow ' % (env['WARNING_CXXFLAGS'], pthread)
|
||||
|
||||
if 'clang++' in env['CXX']:
|
||||
common_cxx_flags += ' -Wno-unsequenced '
|
||||
|
@ -1793,12 +1794,15 @@ if not preconfigured:
|
|||
if env['DEBUG']:
|
||||
env.Append(CXXFLAGS = common_cxx_flags + '-O0')
|
||||
else:
|
||||
# TODO - add back -fvisibility-inlines-hidden
|
||||
# https://github.com/mapnik/mapnik/issues/1863
|
||||
env.Append(CXXFLAGS = common_cxx_flags + '-O%s' % (env['OPTIMIZATION']))
|
||||
if env['DEBUG_UNDEFINED']:
|
||||
env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv')
|
||||
|
||||
if env['DEBUG_SANITIZE']:
|
||||
env.Append(CXXFLAGS = ['-fsanitize=address'])
|
||||
env.Append(LINKFLAGS = ['-fsanitize=address'])
|
||||
|
||||
|
||||
# if requested, sort LIBPATH and CPPPATH one last time before saving...
|
||||
if env['PRIORITIZE_LINKING']:
|
||||
conf.prioritize_paths(silent=True)
|
||||
|
|
33
bootstrap.sh
Executable file → Normal file
33
bootstrap.sh
Executable file → Normal file
|
@ -51,26 +51,28 @@ function install() {
|
|||
ICU_VERSION="55.1"
|
||||
|
||||
function install_mason_deps() {
|
||||
install jpeg_turbo 1.4.0 libjpeg &
|
||||
install libpng 1.6.20 libpng &
|
||||
install libtiff 4.0.4beta libtiff &
|
||||
install libpq 9.4.1 &
|
||||
install sqlite 3.8.8.3 libsqlite3 &
|
||||
install expat 2.1.0 libexpat &
|
||||
wait
|
||||
install icu ${ICU_VERSION} &
|
||||
install proj 4.8.0 libproj &
|
||||
install pixman 0.32.6 libpixman-1 &
|
||||
install cairo 1.14.2 libcairo &
|
||||
install protobuf 2.6.1 &
|
||||
# technically protobuf is not a mapnik core dep, but installing
|
||||
# here by default helps make mapnik-vector-tile builds easier
|
||||
wait
|
||||
install webp 0.4.2 libwebp &
|
||||
install gdal 1.11.2 libgdal &
|
||||
install boost 1.59.0 &
|
||||
install boost_liball 1.59.0 &
|
||||
install freetype 2.6 libfreetype &
|
||||
install harfbuzz 0.9.40 libharfbuzz &
|
||||
install jpeg_turbo 1.4.0 libjpeg &
|
||||
install libpng 1.6.17 libpng &
|
||||
install webp 0.4.2 libwebp &
|
||||
install icu ${ICU_VERSION} &
|
||||
install proj 4.8.0 libproj &
|
||||
install libtiff 4.0.4beta libtiff &
|
||||
install libpq 9.4.0 &
|
||||
install sqlite 3.8.8.1 libsqlite3 &
|
||||
install expat 2.1.0 libexpat &
|
||||
install pixman 0.32.6 libpixman-1 &
|
||||
install cairo 1.14.2 libcairo &
|
||||
install protobuf 2.6.1 &
|
||||
install harfbuzz 0.9.41 libharfbuzz &
|
||||
wait
|
||||
# technically protobuf is not a mapnik core dep, but installing
|
||||
# here by default helps make mapnik-vector-tile builds easier
|
||||
}
|
||||
|
||||
MASON_LINKED_ABS=$(pwd)/mason_packages/.link
|
||||
|
@ -89,7 +91,6 @@ function make_config() {
|
|||
echo "
|
||||
CXX = '$CXX'
|
||||
CC = '$CC'
|
||||
CUSTOM_CXXFLAGS = '-fvisibility=hidden -fvisibility-inlines-hidden -DU_CHARSET_IS_UTF8=1'
|
||||
RUNTIME_LINK = 'static'
|
||||
INPUT_PLUGINS = 'all'
|
||||
PATH = '${MASON_LINKED_REL}/bin'
|
||||
|
|
7
deps/agg/include/agg_vcgen_dash.h
vendored
7
deps/agg/include/agg_vcgen_dash.h
vendored
|
@ -2,8 +2,8 @@
|
|||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
#include <mapnik/config.hpp>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
@ -29,7 +30,7 @@ namespace agg
|
|||
//
|
||||
// See Implementation agg_vcgen_dash.cpp
|
||||
//
|
||||
class vcgen_dash
|
||||
class MAPNIK_DECL vcgen_dash
|
||||
{
|
||||
enum max_dashes_e
|
||||
{
|
||||
|
|
|
@ -90,16 +90,16 @@ struct evaluate
|
|||
return geom.value<value_type,feature_type>(feature_);
|
||||
}
|
||||
|
||||
value_type operator() (binary_node<tags::logical_and> const & x) const
|
||||
value_type operator() (binary_node<tags::logical_and> const& x) const
|
||||
{
|
||||
return (util::apply_visitor(*this, x.left).to_bool())
|
||||
&& (util::apply_visitor(*this, x.right).to_bool());
|
||||
}
|
||||
|
||||
value_type operator() (binary_node<tags::logical_or> const & x) const
|
||||
value_type operator() (binary_node<tags::logical_or> const& x) const
|
||||
{
|
||||
return (util::apply_visitor(*this,x.left).to_bool())
|
||||
|| (util::apply_visitor(*this,x.right).to_bool());
|
||||
return (util::apply_visitor(*this, x.left).to_bool())
|
||||
|| (util::apply_visitor(*this, x.right).to_bool());
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
|
|
|
@ -36,7 +36,7 @@ geometry_empty reproject_internal(geometry_empty const&, proj_transform const&,
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> reproject_internal(point<T> const & p, proj_transform const& proj_trans, unsigned int & n_err)
|
||||
point<T> reproject_internal(point<T> const& p, proj_transform const& proj_trans, unsigned int & n_err)
|
||||
{
|
||||
point<T> new_p(p);
|
||||
if (!proj_trans.forward(new_p))
|
||||
|
@ -47,7 +47,7 @@ point<T> reproject_internal(point<T> const & p, proj_transform const& proj_trans
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
line_string<T> reproject_internal(line_string<T> const & ls, proj_transform const& proj_trans, unsigned int & n_err)
|
||||
line_string<T> reproject_internal(line_string<T> const& ls, proj_transform const& proj_trans, unsigned int & n_err)
|
||||
{
|
||||
line_string<T> new_ls(ls);
|
||||
unsigned int err = proj_trans.forward(new_ls);
|
||||
|
@ -59,7 +59,7 @@ line_string<T> reproject_internal(line_string<T> const & ls, proj_transform cons
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
polygon<T> reproject_internal(polygon<T> const & poly, proj_transform const& proj_trans, unsigned int & n_err)
|
||||
polygon<T> reproject_internal(polygon<T> const& poly, proj_transform const& proj_trans, unsigned int & n_err)
|
||||
{
|
||||
polygon<T> new_poly;
|
||||
linear_ring<T> new_ext(poly.exterior_ring);
|
||||
|
@ -171,7 +171,8 @@ geometry_collection<T> reproject_internal(geometry_collection<T> const & c, proj
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
struct geom_reproj_copy_visitor {
|
||||
struct geom_reproj_copy_visitor
|
||||
{
|
||||
|
||||
geom_reproj_copy_visitor(proj_transform const & proj_trans, unsigned int & n_err)
|
||||
: proj_trans_(proj_trans),
|
||||
|
|
|
@ -63,10 +63,10 @@ struct set_position_impl
|
|||
struct push_position_impl
|
||||
{
|
||||
using result_type = void;
|
||||
template <typename T0,typename T1>
|
||||
template <typename T0, typename T1>
|
||||
result_type operator() (T0 & coords, T1 const& pos) const
|
||||
{
|
||||
if (pos) coords.push_back(*pos);
|
||||
if (pos) coords.emplace_back(*pos);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ public:
|
|||
marker_svg(marker_svg && rhs) noexcept
|
||||
: vector_data_(rhs.vector_data_) {}
|
||||
|
||||
box2d<double> bounding_box() const
|
||||
inline box2d<double> bounding_box() const
|
||||
{
|
||||
return vector_data_->bounding_box();
|
||||
}
|
||||
|
@ -122,11 +122,15 @@ public:
|
|||
return vector_data_->bounding_box().height();
|
||||
}
|
||||
|
||||
mapnik::svg_path_ptr get_data() const
|
||||
inline mapnik::svg_path_ptr get_data() const
|
||||
{
|
||||
return vector_data_;
|
||||
}
|
||||
|
||||
inline std::tuple<double,double> dimensions() const
|
||||
{
|
||||
return std::make_tuple(vector_data_->width(), vector_data_->height());
|
||||
}
|
||||
private:
|
||||
mapnik::svg_path_ptr vector_data_;
|
||||
|
||||
|
@ -136,7 +140,7 @@ struct marker_null
|
|||
{
|
||||
marker_null() = default;
|
||||
public:
|
||||
box2d<double> bounding_box() const
|
||||
inline box2d<double> bounding_box() const
|
||||
{
|
||||
return box2d<double>();
|
||||
}
|
||||
|
|
|
@ -224,7 +224,15 @@ public:
|
|||
attr.stroke_color.opacity(a * s.opacity());
|
||||
attr.stroke_flag = true;
|
||||
}
|
||||
|
||||
void dash_array(dash_array && dash)
|
||||
{
|
||||
path_attributes& attr = cur_attr();
|
||||
attr.dash = std::move(dash);
|
||||
}
|
||||
void dash_offset(double offset)
|
||||
{
|
||||
cur_attr().dash_offset = offset;
|
||||
}
|
||||
void even_odd(bool flag)
|
||||
{
|
||||
cur_attr().even_odd_flag = flag;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/gradient.hpp>
|
||||
#include <mapnik/symbolizer_base.hpp> // dash_array
|
||||
|
||||
namespace mapnik {
|
||||
namespace svg {
|
||||
|
@ -56,7 +57,8 @@ struct path_attributes
|
|||
bool even_odd_flag;
|
||||
bool visibility_flag;
|
||||
bool display_flag;
|
||||
|
||||
dash_array dash;
|
||||
double dash_offset;
|
||||
// Empty constructor
|
||||
path_attributes() :
|
||||
fill_gradient(),
|
||||
|
@ -78,9 +80,10 @@ struct path_attributes
|
|||
stroke_none(false),
|
||||
even_odd_flag(false),
|
||||
visibility_flag(true),
|
||||
display_flag(true)
|
||||
{
|
||||
}
|
||||
display_flag(true),
|
||||
dash(),
|
||||
dash_offset(0.0)
|
||||
{}
|
||||
|
||||
// Copy constructor
|
||||
path_attributes(path_attributes const& attr)
|
||||
|
@ -103,7 +106,9 @@ struct path_attributes
|
|||
stroke_none(attr.stroke_none),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
visibility_flag(attr.visibility_flag),
|
||||
display_flag(attr.display_flag)
|
||||
display_flag(attr.display_flag),
|
||||
dash(attr.dash),
|
||||
dash_offset(attr.dash_offset)
|
||||
{}
|
||||
// Copy constructor with new index value
|
||||
path_attributes(path_attributes const& attr, unsigned idx)
|
||||
|
@ -126,7 +131,9 @@ struct path_attributes
|
|||
stroke_none(attr.stroke_none),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
visibility_flag(attr.visibility_flag),
|
||||
display_flag(attr.display_flag)
|
||||
display_flag(attr.display_flag),
|
||||
dash(attr.dash),
|
||||
dash_offset(attr.dash_offset)
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -73,46 +73,29 @@ namespace mapnik { namespace svg {
|
|||
>> *(-lit(',') >> coord [ line_to_(_1,_a) ] ); // *line_to
|
||||
|
||||
H = (lit('H')[_a = false] | lit('h')[_a = true])
|
||||
>> +double_[ hline_to_(_1,_a) ] ; // +hline_to
|
||||
>> (double_[ hline_to_(_1,_a) ] % -lit(',')) ; // +hline_to
|
||||
|
||||
V = (lit('V')[_a = false] | lit('v')[_a = true])
|
||||
>> +double_ [ vline_to_(_1,_a) ]; // +vline_to
|
||||
>> (double_ [ vline_to_(_1,_a) ] % -lit(',')); // +vline_to
|
||||
|
||||
L = (lit('L')[_a = false] | lit('l')[_a = true])
|
||||
>> +coord [ line_to_(_1,_a) ]; // +line_to
|
||||
>> (coord [ line_to_(_1,_a) ] % -lit(',')); // +line_to
|
||||
|
||||
C = (lit('C')[_a = false] | lit('c')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> coord
|
||||
>> -lit(',')
|
||||
>> coord) [ curve4_(_1,_2,_3,_a) ]; // +curve4
|
||||
>> ((coord >> -lit(',') >> coord >> -lit(',') >> coord) [ curve4_(_1,_2,_3,_a) ] % -lit(',')); // +curve4
|
||||
|
||||
S = (lit('S')[_a = false] | lit('s')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> coord) [ curve4_smooth_(_1,_2,_a) ]; // +curve4_smooth (smooth curveto)
|
||||
>> ((coord >> -lit(',') >> coord) [ curve4_smooth_(_1,_2,_a) ] % -lit(',')); // +curve4_smooth (smooth curveto)
|
||||
|
||||
Q = (lit('Q')[_a = false] | lit('q')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> coord) [ curve3_(_1,_2,_a) ]; // +curve3 (quadratic-bezier-curveto)
|
||||
>> ((coord >> -lit(',') >> coord) [ curve3_(_1,_2,_a) ] % -lit(',')); // +curve3 (quadratic-bezier-curveto)
|
||||
|
||||
T = (lit('T')[_a = false] | lit('t')[_a = true])
|
||||
>> +(coord ) [ curve3_smooth_(_1,_a) ]; // +curve3_smooth (smooth-quadratic-bezier-curveto)
|
||||
>> ((coord ) [ curve3_smooth_(_1,_a) ] % -lit(',')); // +curve3_smooth (smooth-quadratic-bezier-curveto)
|
||||
|
||||
A = (lit('A')[_a = false] | lit('a')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> double_
|
||||
>> -lit(',')
|
||||
>> int_
|
||||
>> -lit(',')
|
||||
>> int_
|
||||
>> -lit(',')
|
||||
>> coord) [arc_to_(_1,_2,_3,_4,_5,_a)]; // arc_to;
|
||||
|
||||
|
||||
>> ((coord >> -lit(',') >> double_ >> -lit(',')
|
||||
>> int_ >> -lit(',') >> int_ >> -lit(',') >> coord) [arc_to_(_1,_2,_3,_4,_5,_a)] % -lit(',')); // arc_to;
|
||||
|
||||
Z = no_case[lit('z')] [close_()]; // close path
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_contour.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_conv_dash.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_bounding_rect.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
@ -60,12 +61,10 @@
|
|||
namespace mapnik {
|
||||
namespace svg {
|
||||
|
||||
// Arbitrary linear gradient specified by two control points. Gradient
|
||||
// value is taken as the normalised distance along the line segment
|
||||
// represented by the two points.
|
||||
|
||||
/**
|
||||
* Arbitrary linear gradient specified by two control points. Gradient
|
||||
* value is taken as the normalised distance along the line segment
|
||||
* represented by the two points.
|
||||
*/
|
||||
class linear_gradient_from_segment
|
||||
{
|
||||
public:
|
||||
|
@ -105,19 +104,28 @@ template <typename VertexSource, typename AttributeSource, typename ScanlineRend
|
|||
class svg_renderer_agg : util::noncopyable
|
||||
{
|
||||
public:
|
||||
using curved_type = agg::conv_curve<VertexSource> ;
|
||||
using curved_stroked_type = agg::conv_stroke<curved_type> ;
|
||||
using curved_type = agg::conv_curve<VertexSource>;
|
||||
// stroke
|
||||
using curved_stroked_type = agg::conv_stroke<curved_type>;
|
||||
using curved_stroked_trans_type = agg::conv_transform<curved_stroked_type>;
|
||||
using curved_trans_type = agg::conv_transform<curved_type> ;
|
||||
using curved_trans_contour_type = agg::conv_contour<curved_trans_type> ;
|
||||
using renderer_base = agg::renderer_base<PixelFormat> ;
|
||||
using vertex_source_type = VertexSource ;
|
||||
using attribute_source_type = AttributeSource ;
|
||||
// stroke dash-array
|
||||
using curved_dashed_type = agg::conv_dash<curved_type>;
|
||||
using curved_dashed_stroked_type = agg::conv_stroke<curved_dashed_type>;
|
||||
using curved_dashed_stroked_trans_type = agg::conv_transform<curved_dashed_stroked_type>;
|
||||
// fill
|
||||
using curved_trans_type = agg::conv_transform<curved_type>;
|
||||
using curved_trans_contour_type = agg::conv_contour<curved_trans_type>;
|
||||
// renderer
|
||||
using renderer_base = agg::renderer_base<PixelFormat>;
|
||||
using vertex_source_type = VertexSource;
|
||||
using attribute_source_type = AttributeSource;
|
||||
|
||||
svg_renderer_agg(VertexSource & source, AttributeSource const& attributes)
|
||||
: source_(source),
|
||||
curved_(source_),
|
||||
curved_dashed_(curved_),
|
||||
curved_stroked_(curved_),
|
||||
curved_dashed_stroked_(curved_dashed_),
|
||||
attributes_(attributes) {}
|
||||
|
||||
template <typename Rasterizer, typename Scanline, typename Renderer>
|
||||
|
@ -191,11 +199,11 @@ public:
|
|||
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup=255;
|
||||
radius*=scaleup;
|
||||
x1*=scaleup;
|
||||
y1*=scaleup;
|
||||
x2*=scaleup;
|
||||
y2*=scaleup;
|
||||
radius *= scaleup;
|
||||
x1 *= scaleup;
|
||||
y1 *= scaleup;
|
||||
x2 *= scaleup;
|
||||
y2 *= scaleup;
|
||||
|
||||
transform.scale(scaleup,scaleup);
|
||||
interpolator_type span_interpolator(transform);
|
||||
|
@ -217,10 +225,10 @@ public:
|
|||
color_func_type>;
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup=255;
|
||||
x1*=scaleup;
|
||||
y1*=scaleup;
|
||||
x2*=scaleup;
|
||||
y2*=scaleup;
|
||||
x1 *= scaleup;
|
||||
y1 *= scaleup;
|
||||
x2 *= scaleup;
|
||||
y2 *= scaleup;
|
||||
|
||||
transform.scale(scaleup,scaleup);
|
||||
|
||||
|
@ -247,10 +255,11 @@ public:
|
|||
|
||||
{
|
||||
using namespace agg;
|
||||
|
||||
trans_affine transform;
|
||||
|
||||
curved_stroked_trans_type curved_stroked_trans(curved_stroked_,transform);
|
||||
curved_trans_type curved_trans(curved_,transform);
|
||||
curved_dashed_stroked_trans_type curved_dashed_stroked_trans(curved_dashed_stroked_, transform);
|
||||
curved_trans_type curved_trans(curved_,transform);
|
||||
curved_trans_contour_type curved_trans_contour(curved_trans);
|
||||
|
||||
curved_trans_contour.auto_detect_orientation(true);
|
||||
|
@ -274,7 +283,6 @@ public:
|
|||
if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
ras.reset();
|
||||
|
||||
// https://github.com/mapnik/mapnik/issues/1129
|
||||
if(std::fabs(curved_trans_contour.width()) <= 1)
|
||||
{
|
||||
|
@ -288,7 +296,8 @@ public:
|
|||
|
||||
if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
render_gradient(ras, sl, ren, attr.fill_gradient, transform, attr.fill_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
|
||||
render_gradient(ras, sl, ren, attr.fill_gradient, transform,
|
||||
attr.fill_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -304,37 +313,79 @@ public:
|
|||
|
||||
if (attr.stroke_flag || attr.stroke_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
curved_stroked_.width(attr.stroke_width);
|
||||
//m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join);
|
||||
curved_stroked_.line_join(attr.line_join);
|
||||
curved_stroked_.line_cap(attr.line_cap);
|
||||
curved_stroked_.miter_limit(attr.miter_limit);
|
||||
curved_stroked_.inner_join(inner_round);
|
||||
curved_stroked_.approximation_scale(scl);
|
||||
|
||||
// If the *visual* line width is considerable we
|
||||
// turn on processing of curve cusps.
|
||||
//---------------------
|
||||
if(attr.stroke_width * scl > 1.0)
|
||||
if (attr.dash.size() > 0)
|
||||
{
|
||||
curved_.angle_tolerance(0.2);
|
||||
}
|
||||
ras.reset();
|
||||
ras.add_path(curved_stroked_trans, attr.index);
|
||||
curved_dashed_stroked_.width(attr.stroke_width);
|
||||
curved_dashed_stroked_.line_join(attr.line_join);
|
||||
curved_dashed_stroked_.line_cap(attr.line_cap);
|
||||
curved_dashed_stroked_.miter_limit(attr.miter_limit);
|
||||
curved_dashed_stroked_.inner_join(inner_round);
|
||||
curved_dashed_stroked_.approximation_scale(scl);
|
||||
|
||||
if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
render_gradient(ras, sl, ren, attr.stroke_gradient, transform, attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
|
||||
// If the *visual* line width is considerable we
|
||||
// turn on processing of curve cups.
|
||||
//---------------------
|
||||
if (attr.stroke_width * scl > 1.0)
|
||||
{
|
||||
curved_.angle_tolerance(0.2);
|
||||
}
|
||||
ras.reset();
|
||||
curved_dashed_.remove_all_dashes();
|
||||
for (auto d : attr.dash)
|
||||
{
|
||||
curved_dashed_.add_dash(std::get<0>(d),std::get<1>(d));
|
||||
}
|
||||
curved_dashed_.dash_start(attr.dash_offset);
|
||||
ras.add_path(curved_dashed_stroked_trans, attr.index);
|
||||
if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
render_gradient(ras, sl, ren, attr.stroke_gradient, transform,
|
||||
attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
ras.filling_rule(fill_non_zero);
|
||||
color = attr.stroke_color;
|
||||
color.opacity(color.opacity() * attr.stroke_opacity * attr.opacity * opacity);
|
||||
ScanlineRenderer ren_s(ren);
|
||||
color.premultiply();
|
||||
ren_s.color(color);
|
||||
render_scanlines(ras, sl, ren_s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ras.filling_rule(fill_non_zero);
|
||||
color = attr.stroke_color;
|
||||
color.opacity(color.opacity() * attr.stroke_opacity * attr.opacity * opacity);
|
||||
ScanlineRenderer ren_s(ren);
|
||||
color.premultiply();
|
||||
ren_s.color(color);
|
||||
render_scanlines(ras, sl, ren_s);
|
||||
curved_stroked_.width(attr.stroke_width);
|
||||
curved_stroked_.line_join(attr.line_join);
|
||||
curved_stroked_.line_cap(attr.line_cap);
|
||||
curved_stroked_.miter_limit(attr.miter_limit);
|
||||
curved_stroked_.inner_join(inner_round);
|
||||
curved_stroked_.approximation_scale(scl);
|
||||
|
||||
// If the *visual* line width is considerable we
|
||||
// turn on processing of curve cups.
|
||||
//---------------------
|
||||
if (attr.stroke_width * scl > 1.0)
|
||||
{
|
||||
curved_.angle_tolerance(0.2);
|
||||
}
|
||||
ras.reset();
|
||||
ras.add_path(curved_stroked_trans, attr.index);
|
||||
if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
render_gradient(ras, sl, ren, attr.stroke_gradient, transform,
|
||||
attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
ras.filling_rule(fill_non_zero);
|
||||
color = attr.stroke_color;
|
||||
color.opacity(color.opacity() * attr.stroke_opacity * attr.opacity * opacity);
|
||||
ScanlineRenderer ren_s(ren);
|
||||
color.premultiply();
|
||||
ren_s.color(color);
|
||||
render_scanlines(ras, sl, ren_s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -409,7 +460,7 @@ public:
|
|||
// If the *visual* line width is considerable we
|
||||
// turn on processing of curve cusps.
|
||||
//---------------------
|
||||
if(attr.stroke_width * scl > 1.0)
|
||||
if (attr.stroke_width * scl > 1.0)
|
||||
{
|
||||
curved_.angle_tolerance(0.2);
|
||||
}
|
||||
|
@ -431,7 +482,9 @@ private:
|
|||
|
||||
VertexSource & source_;
|
||||
curved_type curved_;
|
||||
curved_dashed_type curved_dashed_;
|
||||
curved_stroked_type curved_stroked_;
|
||||
curved_dashed_stroked_type curved_dashed_stroked_;
|
||||
AttributeSource const& attributes_;
|
||||
};
|
||||
|
||||
|
|
|
@ -317,12 +317,8 @@ struct evaluate_expression_wrapper<mapnik::dash_array>
|
|||
mapnik::value_type val = util::apply_visitor(mapnik::evaluate<T2,mapnik::value_type,T3>(feature,vars), expr);
|
||||
if (val.is_null()) return dash_array();
|
||||
dash_array dash;
|
||||
std::vector<double> buf;
|
||||
std::string str = val.to_string();
|
||||
if (util::parse_dasharray(str,buf))
|
||||
{
|
||||
util::add_dashes(buf,dash);
|
||||
}
|
||||
util::parse_dasharray(str,dash);
|
||||
return dash;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -404,9 +404,8 @@ struct set_symbolizer_property_impl<Symbolizer,dash_array,false>
|
|||
boost::optional<std::string> str = node.get_opt_attr<std::string>(name);
|
||||
if (str)
|
||||
{
|
||||
std::vector<double> buf;
|
||||
dash_array dash;
|
||||
if (util::parse_dasharray(*str,buf) && util::add_dashes(buf,dash))
|
||||
if (util::parse_dasharray(*str,dash))
|
||||
{
|
||||
put(sym,key,dash);
|
||||
}
|
||||
|
|
|
@ -23,32 +23,13 @@
|
|||
#ifndef MAPNIK_UTIL_DASHARRAY_PARSER_HPP
|
||||
#define MAPNIK_UTIL_DASHARRAY_PARSER_HPP
|
||||
|
||||
#include <mapnik/symbolizer_base.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace mapnik { namespace util {
|
||||
|
||||
bool parse_dasharray(std::string const& value, std::vector<double>& dasharray);
|
||||
|
||||
inline bool add_dashes(std::vector<double> & buf, std::vector<std::pair<double,double> > & dash)
|
||||
{
|
||||
if (buf.empty()) return false;
|
||||
size_t size = buf.size();
|
||||
if (size % 2 == 1)
|
||||
{
|
||||
buf.insert(buf.end(),buf.begin(),buf.end());
|
||||
}
|
||||
std::vector<double>::const_iterator pos = buf.begin();
|
||||
while (pos != buf.end())
|
||||
{
|
||||
if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0
|
||||
{
|
||||
dash.emplace_back(*pos,*(pos + 1));
|
||||
}
|
||||
pos +=2;
|
||||
}
|
||||
return !buf.empty();
|
||||
}
|
||||
bool parse_dasharray(std::string const& value, dash_array & dash);
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -283,29 +283,20 @@ namespace detail {
|
|||
template <typename T>
|
||||
struct unwrapper
|
||||
{
|
||||
T const& operator() (T const& obj) const
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
T& operator() (T & obj) const
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
static T const& apply_const(T const& obj) {return obj;}
|
||||
static T& apply(T & obj) {return obj;}
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct unwrapper<recursive_wrapper<T>>
|
||||
{
|
||||
auto operator() (recursive_wrapper<T> const& obj) const
|
||||
static auto apply_const(recursive_wrapper<T> const& obj)
|
||||
-> typename recursive_wrapper<T>::type const&
|
||||
{
|
||||
return obj.get();
|
||||
}
|
||||
|
||||
auto operator() (recursive_wrapper<T> & obj) const
|
||||
-> typename recursive_wrapper<T>::type &
|
||||
static auto apply(recursive_wrapper<T> & obj)
|
||||
-> typename recursive_wrapper<T>::type&
|
||||
{
|
||||
return obj.get();
|
||||
}
|
||||
|
@ -314,8 +305,13 @@ struct unwrapper<recursive_wrapper<T>>
|
|||
template <typename T>
|
||||
struct unwrapper<std::reference_wrapper<T>>
|
||||
{
|
||||
auto operator() (std::reference_wrapper<T> const& obj) const
|
||||
-> typename recursive_wrapper<T>::type const&
|
||||
static auto apply_const(std::reference_wrapper<T> const& obj)
|
||||
-> typename std::reference_wrapper<T>::type const&
|
||||
{
|
||||
return obj.get();
|
||||
}
|
||||
static auto apply(std::reference_wrapper<T> & obj)
|
||||
-> typename std::reference_wrapper<T>::type&
|
||||
{
|
||||
return obj.get();
|
||||
}
|
||||
|
@ -332,7 +328,7 @@ struct dispatcher<F, V, R, T, Types...>
|
|||
{
|
||||
if (v.get_type_index() == sizeof...(Types))
|
||||
{
|
||||
return f(unwrapper<T>()(v. template get<T>()));
|
||||
return f(unwrapper<T>::apply_const(v. template get<T>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -344,7 +340,7 @@ struct dispatcher<F, V, R, T, Types...>
|
|||
{
|
||||
if (v.get_type_index() == sizeof...(Types))
|
||||
{
|
||||
return f(unwrapper<T>()(v. template get<T>()));
|
||||
return f(unwrapper<T>::apply(v. template get<T>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -380,8 +376,8 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
|
|||
{
|
||||
if (rhs.get_type_index() == sizeof...(Types)) // call binary functor
|
||||
{
|
||||
return f(unwrapper<T0>()(lhs. template get<T0>()),
|
||||
unwrapper<T1>()(rhs. template get<T1>()));
|
||||
return f(unwrapper<T0>::apply_const(lhs. template get<T0>()),
|
||||
unwrapper<T1>::apply_const(rhs. template get<T1>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -393,8 +389,8 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
|
|||
{
|
||||
if (rhs.get_type_index() == sizeof...(Types)) // call binary functor
|
||||
{
|
||||
return f(unwrapper<T0>()(lhs. template get<T0>()),
|
||||
unwrapper<T1>()(rhs. template get<T1>()));
|
||||
return f(unwrapper<T0>::apply(lhs. template get<T0>()),
|
||||
unwrapper<T1>::apply(rhs. template get<T1>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -430,7 +426,8 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
|
|||
{
|
||||
if (lhs.get_type_index() == sizeof...(Types)) // call binary functor
|
||||
{
|
||||
return f(lhs. template get<T1>(), rhs. template get<T0>());
|
||||
return f(unwrapper<T1>::apply_const(lhs. template get<T1>()),
|
||||
unwrapper<T0>::apply_const(rhs. template get<T0>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -442,7 +439,8 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
|
|||
{
|
||||
if (lhs.get_type_index() == sizeof...(Types)) // call binary functor
|
||||
{
|
||||
return f(lhs. template get<T1>(), rhs. template get<T0>());
|
||||
return f(unwrapper<T1>::apply(lhs. template get<T1>()),
|
||||
unwrapper<T0>::apply(rhs. template get<T0>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -480,7 +478,8 @@ struct binary_dispatcher<F, V, R, T, Types...>
|
|||
{
|
||||
if (v0.get_type_index() == v1.get_type_index())
|
||||
{
|
||||
return f(v0. template get<T>(), v1. template get<T>()); // call binary functor
|
||||
return f(unwrapper<T>::apply_const(v0. template get<T>()),
|
||||
unwrapper<T>::apply_const(v1. template get<T>())); // call binary functor
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -500,7 +499,8 @@ struct binary_dispatcher<F, V, R, T, Types...>
|
|||
{
|
||||
if (v0.get_type_index() == v1.get_type_index())
|
||||
{
|
||||
return f(v0. template get<T>(), v1. template get<T>()); // call binary functor
|
||||
return f(unwrapper<T>::apply(v0. template get<T>()),
|
||||
unwrapper<T>::apply(v1. template get<T>())); // call binary functor
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -60,8 +60,7 @@ if env['PLUGIN_LINKING'] == 'shared':
|
|||
SHLIBPREFIX='',
|
||||
SHLIBSUFFIX='.input',
|
||||
source=plugin_sources,
|
||||
LIBS=libraries,
|
||||
LINKFLAGS=env['CUSTOM_LDFLAGS'])
|
||||
LIBS=libraries)
|
||||
|
||||
# if the plugin links to libmapnik ensure it is built first
|
||||
Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME']))
|
||||
|
|
|
@ -28,27 +28,6 @@ ECHO ========
|
|||
SET PATH=C:\Python27;%PATH%
|
||||
SET PATH=C:\Program Files\7-Zip;%PATH%
|
||||
|
||||
:: *nix style find command comes with git:
|
||||
ECHO checking for unix style 'find'
|
||||
find %USERPROFILE% -name "*.blabla"
|
||||
IF %ERRORLEVEL% EQU 0 GOTO NIX_FIND_FOUND
|
||||
|
||||
IF DEFINED GIT_INSTALL_ROOT SET TEMP_GIT_DIR=%GIT_INSTALL_ROOT%&& GOTO TEST_FIND_AGAIN
|
||||
IF EXIST "C:\Program Files (x86)\Git" SET TEMP_GIT_DIR=C:\Program Files (x86)\Git&& GOTO TEST_FIND_AGAIN
|
||||
IF EXIST "C:\Program Files\Git" SET TEMP_GIT_DIR=C:\Program Files\Git&& GOTO TEST_FIND_AGAIN
|
||||
|
||||
:TEST_FIND_AGAIN
|
||||
SET PATH=%TEMP_GIT_DIR%\bin;%PATH%
|
||||
SET PATH=%TEMP_GIT_DIR%\usr\bin;%PATH%
|
||||
ECHO %PATH%
|
||||
::check again
|
||||
find %USERPROFILE% -name "*.blabla"
|
||||
IF %ERRORLEVEL% NEQ 0 (ECHO unix style find not found && GOTO ERROR)
|
||||
|
||||
|
||||
:NIX_FIND_FOUND
|
||||
ECHO find was found
|
||||
|
||||
::cloning mapnik-gyp
|
||||
if EXIST mapnik-gyp ECHO mapnik-gyp already cloned && GOTO MAPNIK_GYP_ALREADY_HERE
|
||||
CALL git clone https://github.com/mapnik/mapnik-gyp.git
|
||||
|
|
|
@ -36,7 +36,29 @@ namespace mapnik {
|
|||
|
||||
namespace util {
|
||||
|
||||
bool parse_dasharray(std::string const& value, std::vector<double>& dasharray)
|
||||
namespace {
|
||||
inline bool setup_dashes(std::vector<double> & buf, dash_array & dash)
|
||||
{
|
||||
if (buf.empty()) return false;
|
||||
size_t size = buf.size();
|
||||
if (size % 2 == 1)
|
||||
{
|
||||
buf.insert(buf.end(),buf.begin(),buf.end());
|
||||
}
|
||||
std::vector<double>::const_iterator pos = buf.begin();
|
||||
while (pos != buf.end())
|
||||
{
|
||||
if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0
|
||||
{
|
||||
dash.emplace_back(*pos,*(pos + 1));
|
||||
}
|
||||
pos +=2;
|
||||
}
|
||||
return !buf.empty();
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_dasharray(std::string const& value, dash_array & dash)
|
||||
{
|
||||
using namespace boost::spirit;
|
||||
qi::double_type double_;
|
||||
|
@ -49,18 +71,19 @@ bool parse_dasharray(std::string const& value, std::vector<double>& dasharray)
|
|||
// dasharray ::= (length | percentage) (comma-wsp dasharray)?
|
||||
// no support for 'percentage' as viewport is unknown at load_map
|
||||
//
|
||||
std::vector<double> buf;
|
||||
auto first = value.begin();
|
||||
auto last = value.end();
|
||||
bool r = qi::phrase_parse(first, last,
|
||||
(double_[boost::phoenix::push_back(boost::phoenix::ref(dasharray), _1)] %
|
||||
(double_[boost::phoenix::push_back(boost::phoenix::ref(buf), _1)] %
|
||||
no_skip[char_(", ")]
|
||||
| lit("none")),
|
||||
space);
|
||||
if (first != last)
|
||||
if (r && first == last)
|
||||
{
|
||||
return false;
|
||||
return setup_dashes(buf, dash);
|
||||
}
|
||||
return r;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end namespace util
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <mapnik/svg/svg_parser_exception.hpp>
|
||||
#include <mapnik/util/file_io.hpp>
|
||||
#include <mapnik/util/utf_conv_win.hpp>
|
||||
#include <mapnik/util/dasharray_parser.hpp>
|
||||
#include "agg_ellipse.h"
|
||||
#include "agg_rounded_rect.h"
|
||||
#include "agg_span_gradient.h"
|
||||
|
@ -439,7 +440,19 @@ void parse_attr(svg_parser & parser, char const* name, char const* value )
|
|||
{
|
||||
parser.path_.miter_limit(parse_double(parser.error_messages_,value));
|
||||
}
|
||||
|
||||
else if (std::strcmp(name,"stroke-dasharray") == 0)
|
||||
{
|
||||
dash_array dash;
|
||||
if (util::parse_dasharray(value, dash))
|
||||
{
|
||||
parser.path_.dash_array(std::move(dash));
|
||||
}
|
||||
}
|
||||
else if (std::strcmp(name,"stroke-dashoffset") == 0)
|
||||
{
|
||||
double offset = parse_double(parser.error_messages_, value);
|
||||
parser.path_.dash_offset(offset);
|
||||
}
|
||||
else if(std::strcmp(name, "opacity") == 0)
|
||||
{
|
||||
double opacity = parse_double(parser.error_messages_, value);
|
||||
|
|
|
@ -44,9 +44,9 @@ namespace mapnik { namespace svg {
|
|||
svg_path_grammar<iterator_type,skip_type,PathType> g(p);
|
||||
iterator_type first = wkt;
|
||||
iterator_type last = wkt + std::strlen(wkt);
|
||||
return qi::phrase_parse(first, last, g, skip_type());
|
||||
bool status = qi::phrase_parse(first, last, g, skip_type());
|
||||
return (status && (first == last));
|
||||
}
|
||||
template bool MAPNIK_DECL parse_path<svg_converter_type>(const char*, svg_converter_type&);
|
||||
|
||||
template bool parse_path<svg_converter_type>(const char*, svg_converter_type&);
|
||||
|
||||
}}
|
||||
}}
|
||||
|
|
|
@ -598,13 +598,9 @@ image_any tiff_reader<T>::read(unsigned x, unsigned y, unsigned width, unsigned
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void tiff_reader<T>::read_generic(std::size_t, std::size_t, image_rgba8& image)
|
||||
void tiff_reader<T>::read_generic(std::size_t, std::size_t, image_rgba8&)
|
||||
{
|
||||
TIFF* tif = open(stream_);
|
||||
if (tif)
|
||||
{
|
||||
throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled");
|
||||
}
|
||||
throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
2968
test/catch.hpp
2968
test/catch.hpp
File diff suppressed because it is too large
Load diff
|
@ -1 +1 @@
|
|||
Subproject commit 972b039bfc5a5e189f68852c22df717a30c1adf7
|
||||
Subproject commit af88691110b39c75f97140ab4b608b258e53ad51
|
|
@ -68,6 +68,10 @@ mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = tr
|
|||
mapnik::parameters params;
|
||||
params["type"] = std::string("csv");
|
||||
params["file"] = file_name;
|
||||
if (!base.empty())
|
||||
{
|
||||
params["base"] = base;
|
||||
}
|
||||
params["strict"] = mapnik::value_bool(strict);
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
// require a non-null pointer returned
|
||||
|
@ -288,7 +292,7 @@ TEST_CASE("csv") {
|
|||
INFO(ret_posix);
|
||||
CHECK(mapnik::util::exists(filepath + ".index"));
|
||||
}
|
||||
auto ds = get_csv_ds(filepath,true,base);
|
||||
auto ds = get_csv_ds(filename,true,base);
|
||||
CHECK(ds->type() == mapnik::datasource::datasource_t::Vector);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"Precinct", "Phone", "Address", "City", "geo_longitude", "geo_latitude", "geo_accuracy"});
|
||||
|
|
|
@ -29,24 +29,22 @@
|
|||
#include <mapnik/util/fs.hpp>
|
||||
|
||||
/*
|
||||
|
||||
Compile and run just this test:
|
||||
|
||||
clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` && ./test-postgis -d yes
|
||||
|
||||
*/
|
||||
|
||||
namespace {
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
int run(std::string const& command, bool silent = false)
|
||||
int run(std::string const& command, bool okay_to_fail = false)
|
||||
{
|
||||
std::string cmd;
|
||||
if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
|
||||
{
|
||||
cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " ";
|
||||
cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && ";
|
||||
}
|
||||
cmd += command;
|
||||
if (silent)
|
||||
// silence output unless MAPNIK_TEST_DEBUG is defined
|
||||
if (std::getenv("MAPNIK_TEST_DEBUG") == nullptr)
|
||||
{
|
||||
#ifndef _WINDOWS
|
||||
cmd += " 2>/dev/null";
|
||||
|
@ -54,41 +52,243 @@ int run(std::string const& command, bool silent = false)
|
|||
cmd += " 2> nul";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
std::clog << "Running " << cmd << "\n";
|
||||
}
|
||||
bool worked = (std::system(cmd.c_str()) == 0);
|
||||
if (silent == true) return true;
|
||||
if (okay_to_fail == true) return true;
|
||||
return worked;
|
||||
}
|
||||
|
||||
std::string dbname("mapnik-tmp-postgis-test-db");
|
||||
|
||||
TEST_CASE("postgis") {
|
||||
|
||||
SECTION("Postgis data initialization")
|
||||
{
|
||||
REQUIRE(run("dropdb mapnik-tmp-postgis-test-db",true));
|
||||
REQUIRE(run("createdb -T template_postgis mapnik-tmp-postgis-test-db"));
|
||||
std::stringstream cmd;
|
||||
cmd << "psql -q mapnik-tmp-postgis-test-db -f ./test/data/sql/table1.sql";
|
||||
REQUIRE(run(cmd.str()));
|
||||
//don't add 'true' here, to get error message, when drop fails. If it works nothing is output
|
||||
REQUIRE(run("dropdb --if-exists " + dbname));
|
||||
REQUIRE(run("createdb -T template_postgis " + dbname));
|
||||
//REQUIRE(run("createdb " + dbname));
|
||||
// Breaks when raster support is missing (unfortunately this is common)
|
||||
//REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true));
|
||||
REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname));
|
||||
}
|
||||
|
||||
std::string datasource_plugin("./plugins/input/postgis.input");
|
||||
if (mapnik::util::exists(datasource_plugin))
|
||||
mapnik::parameters params;
|
||||
params["type"] = "postgis";
|
||||
params["dbname"] = dbname;
|
||||
|
||||
SECTION("Postgis should throw without 'table' parameter")
|
||||
{
|
||||
SECTION("Postgis plugin initialization")
|
||||
{
|
||||
mapnik::parameters params;
|
||||
params["type"] = "postgis";
|
||||
params["dbname"] = "mapnik-tmp-postgis-test-db";
|
||||
params["table"] = "test";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
CHECK(ds->type() == mapnik::datasource::datasource_t::Vector);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, {"gid"});
|
||||
require_field_types(fields, {mapnik::Integer});
|
||||
}
|
||||
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'")
|
||||
{
|
||||
params["table"] = "test";
|
||||
params["max_async_connection"] = "2";
|
||||
params["max_size"] = "1";
|
||||
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
|
||||
}
|
||||
|
||||
}
|
||||
SECTION("Postgis should throw with invalid metadata query")
|
||||
{
|
||||
params["table"] = "does_not_exist";
|
||||
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
|
||||
}
|
||||
|
||||
SECTION("Postgis should throw with invalid key field")
|
||||
{
|
||||
params["table"] = "test_invalid_id";
|
||||
params["key_field"] = "id";
|
||||
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
|
||||
}
|
||||
|
||||
SECTION("Postgis should throw with multicolumn primary key")
|
||||
{
|
||||
params["table"] = "test_invalid_multi_col_pk";
|
||||
params["autodetect_key_field"] = "true";
|
||||
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
|
||||
}
|
||||
|
||||
SECTION("Postgis should throw without geom column")
|
||||
{
|
||||
params["table"] = "test_no_geom_col";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
CHECK_THROWS(all_features(ds));
|
||||
}
|
||||
|
||||
SECTION("Postgis should throw with invalid credentials")
|
||||
{
|
||||
params["table"] = "test";
|
||||
params["user"] = "not_a_valid_user";
|
||||
params["password"] = "not_a_valid_pwd";
|
||||
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
|
||||
}
|
||||
|
||||
SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit")
|
||||
{
|
||||
params["persist_connection"] = "false";
|
||||
params["table"] = "public.test";
|
||||
params["geometry_field"] = "geom";
|
||||
params["autodetect_key_field"] = "true";
|
||||
params["extent"] = "-1 -1, -1 2, 4 3, 3 -1, -1 -1";
|
||||
params["simplify_geometries"] = "true";
|
||||
params["row_limit"] = "1";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
}
|
||||
|
||||
SECTION("Postgis dataset geometry type")
|
||||
{
|
||||
params["table"] = "(SELECT * FROM test WHERE gid=1) as data";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
|
||||
}
|
||||
|
||||
SECTION("Postgis query field names")
|
||||
{
|
||||
params["table"] = "test";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector);
|
||||
auto fields = ds->get_descriptor().get_descriptors();
|
||||
require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" });
|
||||
require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String });
|
||||
}
|
||||
|
||||
SECTION("Postgis iterate features")
|
||||
{
|
||||
params["table"] = "test";
|
||||
params["key_field"] = "gid";
|
||||
params["max_async_connection"] = "2";
|
||||
//params["cursor_size"] = "2";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
|
||||
auto featureset = ds->features_at_point(mapnik::coord2d(1, 1));
|
||||
mapnik::feature_ptr feature;
|
||||
while ((bool(feature = featureset->next()))) {
|
||||
REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string());
|
||||
REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool());
|
||||
REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double());
|
||||
REQUIRE(feature->get(5).to_string() == feature->get("colnumeric").to_string());
|
||||
}
|
||||
|
||||
featureset = all_features(ds);
|
||||
feature = featureset->next();
|
||||
//deactivate char tests for now: not yet implemented.
|
||||
//add at postgis_datasource.cpp:423
|
||||
//case 18: // char
|
||||
//REQUIRE("A" == feature->get("col-char").to_string());
|
||||
feature = featureset->next();
|
||||
//REQUIRE("B" == feature->get("col-char").to_string());
|
||||
feature = featureset->next();
|
||||
REQUIRE(false == feature->get("col+bool").to_bool());
|
||||
}
|
||||
|
||||
SECTION("Postgis cursorresultest")
|
||||
{
|
||||
params["table"] = "(SELECT * FROM test) as data";
|
||||
params["cursor_size"] = "2";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
auto featureset = all_features(ds);
|
||||
CHECK(count_features(featureset) == 8);
|
||||
|
||||
featureset = all_features(ds);
|
||||
mapnik::feature_ptr feature;
|
||||
while (bool(feature = featureset->next())) {
|
||||
CHECK(feature->size() == 10);
|
||||
}
|
||||
|
||||
featureset = all_features(ds);
|
||||
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point);
|
||||
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point);
|
||||
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPoint);
|
||||
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::LineString);
|
||||
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiLineString);
|
||||
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Polygon);
|
||||
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPolygon);
|
||||
require_geometry(featureset->next(), 3, mapnik::geometry::geometry_types::GeometryCollection);
|
||||
}
|
||||
|
||||
SECTION("Postgis bbox query")
|
||||
{
|
||||
params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
mapnik::box2d<double> ext = ds->envelope();
|
||||
CAPTURE(ext);
|
||||
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
|
||||
REQUIRE(ext.minx() == -2);
|
||||
REQUIRE(ext.miny() == -2);
|
||||
REQUIRE(ext.maxx() == 5);
|
||||
REQUIRE(ext.maxy() == 4);
|
||||
}
|
||||
|
||||
SECTION("Postgis query extent: full dataset")
|
||||
{
|
||||
//include schema to increase coverage
|
||||
params["table"] = "(SELECT * FROM public.test) as data";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
mapnik::box2d<double> ext = ds->envelope();
|
||||
CAPTURE(ext);
|
||||
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
|
||||
REQUIRE(ext.minx() == -2);
|
||||
REQUIRE(ext.miny() == -2);
|
||||
REQUIRE(ext.maxx() == 5);
|
||||
REQUIRE(ext.maxy() == 4);
|
||||
}
|
||||
/* deactivated for merging: still investigating a proper fix
|
||||
SECTION("Postgis query extent from subquery")
|
||||
{
|
||||
params["table"] = "(SELECT * FROM test where gid=4) as data";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
mapnik::box2d<double> ext = ds->envelope();
|
||||
CAPTURE(ext);
|
||||
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
|
||||
REQUIRE(ext.minx() == 0);
|
||||
REQUIRE(ext.miny() == 0);
|
||||
REQUIRE(ext.maxx() == 1);
|
||||
REQUIRE(ext.maxy() == 2);
|
||||
}
|
||||
*/
|
||||
SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'")
|
||||
{
|
||||
params["table"] = "(SELECT * FROM test where gid=4) as data";
|
||||
params["extent_from_subquery"] = "true";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
mapnik::box2d<double> ext = ds->envelope();
|
||||
CAPTURE(ext);
|
||||
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
|
||||
REQUIRE(ext.minx() == 0);
|
||||
REQUIRE(ext.miny() == 0);
|
||||
REQUIRE(ext.maxx() == 1);
|
||||
REQUIRE(ext.maxy() == 2);
|
||||
}
|
||||
/* deactivated for merging: still investigating a proper fix
|
||||
SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'")
|
||||
{
|
||||
// !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000'
|
||||
// https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617
|
||||
params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data";
|
||||
params["extent_from_subquery"] = "true";
|
||||
auto ds = mapnik::datasource_cache::instance().create(params);
|
||||
REQUIRE(ds != nullptr);
|
||||
mapnik::box2d<double> ext = ds->envelope();
|
||||
CAPTURE(ext);
|
||||
INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
|
||||
REQUIRE(ext.minx() == 0);
|
||||
REQUIRE(ext.miny() == 0);
|
||||
REQUIRE(ext.maxx() == 1);
|
||||
REQUIRE(ext.maxy() == 2);
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -1,17 +1,73 @@
|
|||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <mapnik/util/fs.hpp>
|
||||
#include <mapnik/datasource_cache.hpp>
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
|
||||
#include "cleanup.hpp" // run_cleanup()
|
||||
|
||||
std::string plugin_path;
|
||||
|
||||
inline void set_plugin_path(Catch::ConfigData&, std::string const& _plugin_path ) {
|
||||
plugin_path = _plugin_path;
|
||||
}
|
||||
|
||||
std::string working_dir;
|
||||
|
||||
inline void set_working_dir(Catch::ConfigData&, std::string const& _working_dir ) {
|
||||
working_dir = _working_dir;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char* const argv[])
|
||||
{
|
||||
mapnik::datasource_cache::instance().register_datasources("plugins/input/");
|
||||
Catch::Session session;
|
||||
|
||||
int result = Catch::Session().run( argc, argv );
|
||||
auto & cli = session.cli();
|
||||
|
||||
cli["-p"]["--plugins"]
|
||||
.describe("path to mapnik plugins")
|
||||
.bind(&set_plugin_path, "plugins");
|
||||
|
||||
cli["-C"]["--working-directory"]
|
||||
.describe("change working directory")
|
||||
.bind(&set_working_dir, "working directory");
|
||||
|
||||
int result = session.applyCommandLine(argc, argv);
|
||||
|
||||
if (!plugin_path.empty())
|
||||
{
|
||||
if (!mapnik::util::exists(plugin_path))
|
||||
{
|
||||
std::clog << "Could not find " << plugin_path << "\n";
|
||||
return -1;
|
||||
}
|
||||
mapnik::datasource_cache::instance().register_datasources(plugin_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapnik::datasource_cache::instance().register_datasources("plugins/input/");
|
||||
}
|
||||
|
||||
if (!working_dir.empty())
|
||||
{
|
||||
if (!mapnik::util::exists(working_dir))
|
||||
{
|
||||
std::clog << "Could not find " << working_dir << "\n";
|
||||
return -1;
|
||||
}
|
||||
boost::filesystem::current_path(working_dir);
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
result = session.run();
|
||||
}
|
||||
|
||||
testing::run_cleanup();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
176
test/unit/svg/svg_path_parser_test.cpp
Normal file
176
test/unit/svg/svg_path_parser_test.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/vertex.hpp>
|
||||
#include <mapnik/svg/svg_path_parser.hpp>
|
||||
#include <mapnik/svg/svg_converter.hpp>
|
||||
#include <mapnik/marker.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
template <int N = 6>
|
||||
struct vertex_equal
|
||||
{
|
||||
template <typename T>
|
||||
bool operator() (T const& lhs, T const& rhs) const
|
||||
{
|
||||
static const double eps = 1.0 / std::pow(10,N);
|
||||
return (std::fabs(std::get<0>(lhs) - std::get<0>(rhs)) < eps)
|
||||
&& (std::fabs(std::get<1>(lhs) - std::get<1>(rhs)) < eps)
|
||||
&& std::get<2>(lhs) == std::get<2>(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Expected>
|
||||
void test_path_parser(std::string const& str, Expected const& expected)
|
||||
{
|
||||
using namespace mapnik::svg;
|
||||
mapnik::svg_path_ptr marker_path(std::make_shared<mapnik::svg_storage_type>());
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
||||
svg_path_adapter svg_path(stl_storage);
|
||||
svg_converter_type svg(svg_path, marker_path->attributes());
|
||||
|
||||
CHECK(mapnik::svg::parse_path(str.c_str(), svg));
|
||||
double x,y;
|
||||
unsigned cmd;
|
||||
auto & p = svg.storage();
|
||||
std::vector<std::tuple<double,double,unsigned>> vec;
|
||||
while ((cmd = p.vertex(&x,&y)) != mapnik::SEG_END)
|
||||
{
|
||||
vec.emplace_back(x, y, cmd);
|
||||
//std::cerr << "std::make_tuple(" << x << ", " << y << ", " << cmd << ")," << std::endl;
|
||||
}
|
||||
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(), vertex_equal<3>()));
|
||||
}
|
||||
} // anonymous ns
|
||||
|
||||
TEST_CASE("SVG path parser") {
|
||||
|
||||
SECTION("MoveTo/LineTo")
|
||||
{
|
||||
std::string str = "M 100 100 L 300 100 L 200 300 z";
|
||||
std::string str2 = "M100,100L300,100L200,300z";
|
||||
std::string str3 = "M100,100l200 0L200,300z";
|
||||
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||
std::make_tuple(100, 100, 1),
|
||||
std::make_tuple(300, 100, 2),
|
||||
std::make_tuple(200, 300, 2),
|
||||
std::make_tuple(100, 100, 79) };
|
||||
test_path_parser(str, expected);
|
||||
test_path_parser(str2, expected);
|
||||
test_path_parser(str3, expected);
|
||||
}
|
||||
|
||||
SECTION("MoveTo/HLine/VLine")
|
||||
{
|
||||
std::string str = "M100 100H300V200z";
|
||||
std::string str2 = "M100,100h200v100z";
|
||||
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||
std::make_tuple(100, 100, 1),
|
||||
std::make_tuple(300, 100, 2),
|
||||
std::make_tuple(300, 200, 2),
|
||||
std::make_tuple(100, 100, 79)
|
||||
};
|
||||
test_path_parser(str, expected);
|
||||
test_path_parser(str2, expected);
|
||||
}
|
||||
|
||||
SECTION("Arcs")
|
||||
{
|
||||
std::string str = "M300,200 h-150 a150,150 0 1,0 150,-150 z";
|
||||
|
||||
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||
std::make_tuple(300, 200, 1),
|
||||
std::make_tuple(150, 200, 2),
|
||||
std::make_tuple(150, 282.843, 4),
|
||||
std::make_tuple(217.157, 350, 4),
|
||||
std::make_tuple(300, 350, 4),
|
||||
std::make_tuple(382.843, 350, 4),
|
||||
std::make_tuple(450, 282.843, 4),
|
||||
std::make_tuple(450, 200, 4),
|
||||
std::make_tuple(450, 117.157, 4),
|
||||
std::make_tuple(382.843, 50, 4),
|
||||
std::make_tuple(300, 50, 4),
|
||||
std::make_tuple(300, 200, 79)};
|
||||
test_path_parser(str, expected);
|
||||
}
|
||||
|
||||
|
||||
SECTION("Arcs 2")
|
||||
{
|
||||
std::string str = "M275,175 v-150 a150,150 0 0,0 -150,150 z";
|
||||
|
||||
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||
std::make_tuple(275, 175, 1),
|
||||
std::make_tuple(275, 25, 2),
|
||||
std::make_tuple(192.157, 25, 4),
|
||||
std::make_tuple(125, 92.1573, 4),
|
||||
std::make_tuple(125, 175, 4),
|
||||
std::make_tuple(275, 175, 79)};
|
||||
test_path_parser(str, expected);
|
||||
}
|
||||
|
||||
SECTION("Arcs 3")
|
||||
{
|
||||
std::string str = "M600,350 l 50,-25"
|
||||
"a25,25 -30 0,1 50,-25 l 50,-25"
|
||||
"a25,50 -30 0,1 50,-25 l 50,-25"
|
||||
"a25,75 -30 0,1 50,-25 l 50,-25"
|
||||
"a25,100 -30 0,1 50,-25 l 50,-25";
|
||||
|
||||
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||
std::make_tuple(600, 350, 1),
|
||||
std::make_tuple(650, 325, 2),
|
||||
std::make_tuple(643.096, 311.193, 4),
|
||||
std::make_tuple(648.693, 294.404, 4),
|
||||
std::make_tuple(662.5, 287.5, 4),
|
||||
std::make_tuple(676.307, 280.596, 4),
|
||||
std::make_tuple(693.096, 286.193, 4),
|
||||
std::make_tuple(700, 300, 4),
|
||||
std::make_tuple(750, 275, 2),
|
||||
std::make_tuple(734.991, 248.079, 4),
|
||||
std::make_tuple(734.017, 220.66, 4),
|
||||
std::make_tuple(747.825, 213.756, 4),
|
||||
std::make_tuple(761.632, 206.852, 4),
|
||||
std::make_tuple(784.991, 223.079, 4),
|
||||
std::make_tuple(800, 250, 4),
|
||||
std::make_tuple(850, 225, 2),
|
||||
std::make_tuple(827.153, 184.812, 4),
|
||||
std::make_tuple(819.825, 146.636, 4),
|
||||
std::make_tuple(833.632, 139.733, 4),
|
||||
std::make_tuple(847.44, 132.829, 4),
|
||||
std::make_tuple(877.153, 159.812, 4),
|
||||
std::make_tuple(900, 200, 4),
|
||||
std::make_tuple(950, 175, 2),
|
||||
std::make_tuple(919.382, 121.506, 4),
|
||||
std::make_tuple(905.754, 72.5436, 4),
|
||||
std::make_tuple(919.561, 65.64, 4),
|
||||
std::make_tuple(933.368, 58.7365, 4),
|
||||
std::make_tuple(969.382, 96.5057, 4),
|
||||
std::make_tuple(1000, 150, 4),
|
||||
std::make_tuple(1050, 125, 2)};
|
||||
test_path_parser(str, expected);
|
||||
}
|
||||
}
|
|
@ -150,7 +150,8 @@ result_list runner::test_all(report_type & report) const
|
|||
|
||||
result_list runner::test(std::vector<std::string> const & style_names, report_type & report) const
|
||||
{
|
||||
std::vector<runner::path_type> files(style_names.size());
|
||||
std::vector<runner::path_type> files;
|
||||
files.reserve(style_names.size());
|
||||
std::transform(style_names.begin(), style_names.end(), std::back_inserter(files),
|
||||
[&](runner::path_type const & name)
|
||||
{
|
||||
|
|
|
@ -67,6 +67,11 @@ struct main_marker_visitor
|
|||
double opacity = 1;
|
||||
int w = marker.width();
|
||||
int h = marker.height();
|
||||
if (w == 0 || h == 0)
|
||||
{
|
||||
// fallback to svg width/height or viewBox
|
||||
std::tie(w, h) = marker.dimensions();
|
||||
}
|
||||
if (verbose_)
|
||||
{
|
||||
std::clog << "found width of '" << w << "' and height of '" << h << "'\n";
|
||||
|
|
Loading…
Reference in a new issue