Merge pull request #3580 from mapnik/v3.0.x-cherry

Cherry pick stable commits from master into v3.0.x branch
This commit is contained in:
Dane Springmeyer 2016-12-21 11:44:34 -08:00 committed by GitHub
commit 47443526a0
21 changed files with 184 additions and 386 deletions

View file

@ -25,19 +25,27 @@ matrix:
- os: linux
sudo: false
compiler: ": clang"
env: JOBS=8 MASON_PUBLISH=true CXX="ccache clang++-3.8 -Qunused-arguments" CC="clang-3.8" TRIGGER=true
env: JOBS=4 CXX="ccache g++-6" CC="gcc-6"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test']
packages: [ 'libstdc++-5-dev', 'xutils-dev']
packages: [ 'libstdc++-6-dev', 'g++-6', 'xutils-dev']
- os: linux
sudo: false
compiler: ": clang"
env: JOBS=8 MASON_PUBLISH=true CXX="ccache clang++-3.9 -Qunused-arguments" CC="clang-3.9" TRIGGER=true
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test']
packages: [ 'libstdc++-4.9-dev', 'xutils-dev']
- os: linux
sudo: false
compiler: ": clang-coverage"
env: JOBS=8 COVERAGE=true CXX="ccache clang++-3.8 -Qunused-arguments" CC="clang-3.8"
env: JOBS=8 COVERAGE=true CXX="ccache clang++-3.9 -Qunused-arguments" CC="clang-3.9"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'xutils-dev' ]
packages: ['libstdc++-4.9-dev', 'xutils-dev' ]
- os: osx
compiler: ": clang-osx"
# https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions
@ -78,10 +86,12 @@ before_script:
- source bootstrap.sh
- |
if [[ $(uname -s) == 'Linux' ]]; then
mason install clang 3.8.0
export PATH=$(mason prefix clang 3.8.0)/bin:${PATH}
which clang++
export LLVM_COV="$(mason prefix clang 3.8.0)/bin/llvm-cov"
mason install clang++ 3.9.0
export PATH=$(mason prefix clang++ 3.9.0)/bin:${PATH}
mason install llvm-cov 3.9.0
export PATH=$(mason prefix llvm-cov 3.9.0)/bin:${PATH}
which llvm-cov
export LLVM_COV="$(mason prefix llvm-cov 3.9.0)/bin/llvm-cov"
fi
- ccache --version
- ccache -p || true
@ -98,7 +108,10 @@ script:
# (and might work) for the next build
- DURATION=2400
- scripts/travis-command-wrapper.py -s "date" -i 120 --deadline=$(( $(date +%s) + ${DURATION} )) make
- make test
- RESULT=0
- make test || RESULT=$?
# we allow visual failures with g++ for now: https://github.com/mapnik/mapnik/issues/3567
- if [[ ${RESULT} != 0 ]] && [[ ${CXX} =~ 'clang++' ]]; then false; fi;
- enabled ${COVERAGE} coverage
- enabled ${BENCH} make bench

View file

@ -95,6 +95,7 @@ function make_config() {
echo "
CXX = '$CXX'
CC = '$CC'
CUSTOM_CXXFLAGS = '-D_GLIBCXX_USE_CXX11_ABI=0'
RUNTIME_LINK = 'static'
INPUT_PLUGINS = 'all'
PATH = '${MASON_LINKED_REL}/bin'

2
deps/mapbox/variant vendored

@ -1 +1 @@
Subproject commit 9a115c5eb3c09509c70a57b25b283b6e1cbba919
Subproject commit 6317a0b7406395729139327a83a71cfa14513fac

View file

@ -0,0 +1,43 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 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_CXX11_SUPPORT_HPP
#define MAPNIK_CXX11_SUPPORT_HPP
#include <type_traits>
namespace mapnik {
namespace detail {
template <bool B, typename T, typename F>
using conditional_t = typename std::conditional<B, T, F>::type;
template <typename T>
using decay_t = typename std::decay<T>::type;
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
} // namespace detail
} // namespace mapnik
#endif // MAPNIK_CXX11_SUPPORT_HPP

View file

@ -28,7 +28,6 @@
#include <mapnik/debug.hpp>
// stl
#include <bitset>
#include <iostream>
#include <cstdlib>
#include <algorithm>
@ -190,6 +189,8 @@ public:
for (unsigned i = 0; i < THE_MAX; ++i)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
if (str_copy == our_strings_[i])
#pragma GCC diagnostic pop
@ -203,6 +204,8 @@ public:
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
throw illegal_enum_value(std::string("Illegal enumeration value '") +
str + "' for enum " + our_name_);
@ -213,6 +216,8 @@ public:
std::string as_string() const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template"
return our_strings_[value_];
#pragma GCC diagnostic pop

View file

@ -68,16 +68,6 @@ public:
box_elements_.push_back(box_element(box, repeat_key));
}
inline void clear_box_elements()
{
box_elements_.clear();
}
inline text_symbolizer_properties const& get_properties() const
{
return info_ptr_->properties;
}
pixel_position_list const& get();
// Iterate over the given path, placing line-following labels or point labels with respect to label_spacing.

View file

@ -77,18 +77,18 @@ struct offset_converter
return threshold_;
}
void set_offset(double value)
void set_offset(double val)
{
if (offset_ != value)
if (offset_ != val)
{
offset_ = value;
offset_ = val;
reset();
}
}
void set_threshold(double value)
void set_threshold(double val)
{
threshold_ = value;
threshold_ = val;
// no need to reset(), since threshold doesn't affect
// offset vertices' computation, it only controls how
// far will we be looking for self-intersections

View file

@ -120,11 +120,11 @@ public:
return algorithm_;
}
void set_simplify_algorithm(simplify_algorithm_e value)
void set_simplify_algorithm(simplify_algorithm_e val)
{
if (algorithm_ != value)
if (algorithm_ != val)
{
algorithm_ = value;
algorithm_ = val;
reset();
}
}
@ -134,11 +134,11 @@ public:
return tolerance_;
}
void set_simplify_tolerance(double value)
void set_simplify_tolerance(double val)
{
if (tolerance_ != value)
if (tolerance_ != val)
{
tolerance_ = value;
tolerance_ = val;
reset();
}
}

View file

@ -100,18 +100,13 @@ struct strict_value : value_base_type
{
strict_value() = default;
strict_value(const char* val)
strict_value(const char* val) noexcept(false)
: value_base_type(std::string(val)) {}
template <typename T>
strict_value(T const& obj)
: value_base_type(typename detail::mapnik_value_type<T>::type(obj))
{}
template <typename T>
template <typename T, typename U = detail::mapnik_value_type_t<T>>
strict_value(T && obj)
noexcept(std::is_nothrow_constructible<value_base_type, T && >::value)
: value_base_type(std::forward<T>(obj))
noexcept(std::is_nothrow_constructible<value_base_type, U>::value)
: value_base_type(U(std::forward<T>(obj)))
{}
};

View file

@ -32,15 +32,7 @@ template <typename T>
using recursive_wrapper = typename mapbox::util::recursive_wrapper<T>;
template<typename... Types>
class variant : public mapbox::util::variant<Types...>
{
public:
// tell spirit that this is an adapted variant
struct adapted_variant_tag;
using types = std::tuple<Types...>;
// inherit ctor's
using mapbox::util::variant<Types...>::variant;
};
using variant = typename mapbox::util::variant<Types...>;
// unary visitor interface
// const

View file

@ -24,7 +24,7 @@
#define MAPNIK_UTIL_VARIANT_IO_HPP
namespace mapnik { namespace util {
namespace mapbox { namespace util {
namespace detail {

View file

@ -47,30 +47,20 @@ class MAPNIK_DECL value : public value_base
public:
value() = default;
// conversion from type T is done via a temporary of type U, which
// is determined by mapnik_value_type;
// enable_if< decay<T> != value > is necessary to avoid ill-formed
// recursion in noexcept specifier; and it also prevents using this
// constructor where implicitly-declared copy/move should be used
// (e.g. value(value&))
template <typename T,
typename U = typename std::enable_if<
!detail::is_same_decay<T, value>::value,
detail::mapnik_value_type_decay<T>
>::type::type>
// Conversion from type T is done via a temporary value or reference
// of type U, which is determined by mapnik_value_type_t.
//
// CAVEAT: We don't check `noexcept(conversion from T to U)`.
// But since the type U is either value_bool, value_integer,
// value_double or T &&, this conversion SHOULD NEVER throw.
template <typename T, typename U = detail::mapnik_value_type_t<T>>
value(T && val)
noexcept(noexcept(U(std::forward<T>(val))) &&
std::is_nothrow_constructible<value_base, U && >::value)
noexcept(std::is_nothrow_constructible<value_base, U>::value)
: value_base(U(std::forward<T>(val))) {}
template <typename T,
typename U = typename std::enable_if<
!detail::is_same_decay<T, value>::value,
detail::mapnik_value_type_decay<T>
>::type::type>
template <typename T, typename U = detail::mapnik_value_type_t<T>>
value& operator=(T && val)
noexcept(noexcept(U(std::forward<T>(val))) &&
std::is_nothrow_assignable<value_base, U && >::value)
noexcept(std::is_nothrow_assignable<value_base, U>::value)
{
value_base::operator=(U(std::forward<T>(val)));
return *this;

View file

@ -37,11 +37,6 @@
namespace mapnik { namespace detail {
inline void hash_combine(std::size_t & seed, std::size_t val)
{
seed ^= val + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
struct value_hasher
{
std::size_t operator() (value_null val) const
@ -54,11 +49,6 @@ struct value_hasher
return static_cast<std::size_t>(val.hashCode());
}
std::size_t operator()(value_integer val) const
{
return static_cast<std::size_t>(val);
}
template <class T>
std::size_t operator()(T const& val) const
{
@ -72,10 +62,7 @@ struct value_hasher
template <typename T>
std::size_t mapnik_hash_value(T const& val)
{
std::size_t seed = 0;
detail::hash_combine(seed, util::apply_visitor(detail::value_hasher(), val));
detail::hash_combine(seed, val.which());
return seed;
return util::apply_visitor(detail::value_hasher(), val);
}
} // namespace mapnik

View file

@ -25,6 +25,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/cxx11_support.hpp>
#include <mapnik/pixel_types.hpp>
@ -34,7 +35,6 @@
#pragma GCC diagnostic pop
// stl
#include <type_traits>
#include <iosfwd>
#include <cstddef>
@ -152,90 +152,23 @@ inline std::istream& operator>> ( std::istream & s, value_null & )
namespace detail {
// to mapnik::value_type conversions traits
template <typename T>
struct is_value_bool
{
constexpr static bool value = std::is_same<T, bool>::value;
};
template <typename T>
struct is_value_integer
{
constexpr static bool value = std::is_integral<T>::value && !std::is_same<T, bool>::value;
};
// Helper metafunction for mapnik::value construction and assignment.
// Returns:
// value_bool if T is bool
// value_integer if T is an integral type (except bool)
// value_double if T is a floating-point type
// T && otherwise
template <typename T>
struct is_value_double
{
constexpr static bool value = std::is_floating_point<T>::value;
};
template <typename T>
struct is_value_unicode_string
{
constexpr static bool value = std::is_same<T, typename mapnik::value_unicode_string>::value;
};
template <typename T>
struct is_value_string
{
constexpr static bool value = std::is_same<T, typename std::string>::value;
};
template <typename T>
struct is_value_null
{
constexpr static bool value = std::is_same<T, typename mapnik::value_null>::value;
};
template <typename T, class Enable = void>
struct mapnik_value_type
{
using type = T;
};
// value_null
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_null<T>::value>::type>
{
using type = mapnik::value_null;
};
// value_bool
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_bool<T>::value>::type>
{
using type = mapnik::value_bool;
};
// value_integer
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_integer<T>::value>::type>
{
using type = mapnik::value_integer;
};
// value_double
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_double<T>::value>::type>
{
using type = mapnik::value_double;
};
// value_unicode_string
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_unicode_string<T>::value>::type>
{
using type = mapnik::value_unicode_string const&;
};
template <typename T>
using mapnik_value_type_decay = mapnik_value_type<typename std::decay<T>::type>;
template <typename T, typename U>
using is_same_decay = std::is_same<typename std::decay<T>::type,
typename std::decay<U>::type>;
template <typename T, typename dT = decay_t<T>>
using mapnik_value_type_t =
conditional_t<
std::is_same<dT, bool>::value, value_bool,
conditional_t<
std::is_integral<dT>::value, value_integer,
conditional_t<
std::is_floating_point<dT>::value, value_double,
T && >>>;
} // namespace detail

View file

@ -83,9 +83,9 @@ config_override () {
configure () {
if enabled ${COVERAGE}; then
./configure "$@" PREFIX=${PREFIX} PGSQL2SQLITE=False SVG2PNG=False SVG_RENDERER=False \
COVERAGE=True DEBUG=True WARNING_CXXFLAGS="-Wno-unknown-warning-option"
COVERAGE=True DEBUG=True
else
./configure "$@" PREFIX=${PREFIX} WARNING_CXXFLAGS="-Wno-unknown-warning-option"
./configure "$@" PREFIX=${PREFIX}
fi
# print final config values, sorted and indented
sort -sk1,1 ./config.py | sed -e 's/^/ /'

View file

@ -79,79 +79,22 @@ struct agg_renderer_process_visitor_l
void operator() (marker_svg const& marker) const
{
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
using pattern_type = agg::line_image_pattern<pattern_filter_type>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_);
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
agg::rendering_buffer buf(current_buffer_->bytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->row_size());
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(image, opacity);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
double half_stroke = std::max(marker.width()/2.0,marker.height()/2.0);
int rast_clip_padding = static_cast<int>(std::round(half_stroke));
ren.clip_box(-rast_clip_padding,-rast_clip_padding,common_.width_+rast_clip_padding,common_.height_+rast_clip_padding);
rasterizer_type ras(ren);
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
box2d<double> clip_box = clipping_extent(common_);
if (clip)
{
double padding = (double)(common_.query_extent_.width()/pixmap_.width());
if (half_stroke > 1)
padding *= half_stroke;
if (std::fabs(offset) > 0)
padding *= std::fabs(offset) * 1.2;
padding *= common_.scale_factor_;
clip_box.pad(padding);
}
using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag,
affine_transform_tag,
simplify_tag,smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (clip) converter.set<clip_line_tag>();
converter.set<transform_tag>(); //always transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
converter.set<affine_transform_tag>(); // optional affine transform
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer_type>;
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
apply_vertex_converter_type apply(converter, ras);
mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
render(image, marker.width(), marker.height());
}
void operator() (marker_rgba8 const& marker) const
{
render(marker.get_data(), marker.width(), marker.height());
}
private:
void render(mapnik::image_rgba8 const& marker, double width, double height) const
{
using color = agg::rgba8;
using order = agg::order_rgba;
@ -164,8 +107,6 @@ struct agg_renderer_process_visitor_l
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
mapnik::image_rgba8 const& image = marker.get_data();
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
@ -178,10 +119,10 @@ struct agg_renderer_process_visitor_l
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(image, opacity);
pattern_source source(marker, opacity);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
double half_stroke = std::max(marker.width()/2.0,marker.height()/2.0);
double half_stroke = std::max(width / 2.0, height / 2.0);
int rast_clip_padding = static_cast<int>(std::round(half_stroke));
ren.clip_box(-rast_clip_padding,-rast_clip_padding,common_.width_+rast_clip_padding,common_.height_+rast_clip_padding);
rasterizer_type ras(ren);
@ -221,7 +162,6 @@ struct agg_renderer_process_visitor_l
mapnik::util::apply_visitor(vertex_processor_type(apply), feature_.get_geometry());
}
private:
renderer_common & common_;
buffer_type & pixmap_;
buffer_type * current_buffer_;

View file

@ -88,123 +88,17 @@ struct agg_renderer_process_visitor_p
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->row_size());
ras_ptr_->reset();
value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
if (gamma != gamma_ || gamma_method != gamma_method_)
{
set_gamma_method(ras_ptr_, gamma, gamma_method);
gamma_method_ = gamma_method;
gamma_ = gamma;
}
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
box2d<double> clip_box = clipping_extent(common_);
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
ren_base renb(pixf);
unsigned w = image.width();
unsigned h = image.height();
agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
unsigned offset_x=0;
unsigned offset_y=0;
if (alignment == LOCAL_ALIGNMENT)
{
double x0 = 0;
double y0 = 0;
using apply_local_alignment = detail::apply_local_alignment;
apply_local_alignment apply(common_.t_,prj_trans_, clip_box, x0, y0);
util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature_.get_geometry());
offset_x = unsigned(current_buffer_->width() - x0);
offset_y = unsigned(current_buffer_->height() - y0);
}
span_gen_type sg(img_src, offset_x, offset_y);
agg::span_allocator<agg::rgba8> sa;
renderer_type rp(renb,sa, sg, unsigned(opacity * 255));
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
using vertex_converter_type = vertex_converter<clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag,
smooth_tag>;
vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (prj_trans_.equal() && clip) converter.set<clip_poly_tag>();
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer>;
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
apply_vertex_converter_type apply(converter, *ras_ptr_);
mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
agg::scanline_u8 sl;
ras_ptr_->filling_rule(agg::fill_even_odd);
agg::render_scanlines(*ras_ptr_, sl, rp);
render(image);
}
void operator() (marker_rgba8 const& marker) const
{
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
mapnik::image_rgba8 const& image = marker.get_data();
render(marker.get_data());
}
private:
void render(mapnik::image_rgba8 const& image) const
{
agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->row_size());
ras_ptr_->reset();
@ -224,6 +118,23 @@ struct agg_renderer_process_visitor_p
box2d<double> clip_box = clipping_extent(common_);
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
@ -282,7 +193,6 @@ struct agg_renderer_process_visitor_p
agg::render_scanlines(*ras_ptr_, sl, rp);
}
private:
renderer_common & common_;
buffer_type * current_buffer_;
std::unique_ptr<rasterizer> const& ras_ptr_;

View file

@ -90,30 +90,26 @@ struct process_layout
return;
}
bound_box layout_box;
int middle_ifirst = safe_cast<int>((member_boxes_.size() - 1) >> 1);
int top_i = 0;
int bottom_i = 0;
if (middle_ifirst % 2 == 0)
auto max_diff = layout.get_max_difference();
auto layout_box = make_horiz_pair(0, 0.0, 0, x_margin, max_diff);
auto y_shift = 0.5 * layout_box.height();
for (size_t i = 2; i < member_boxes_.size(); i += 2)
{
layout_box = make_horiz_pair(0, 0.0, 0, x_margin, layout.get_max_difference());
top_i = middle_ifirst - 2;
bottom_i = middle_ifirst + 2;
}
else
{
top_i = middle_ifirst - 1;
bottom_i = middle_ifirst + 1;
auto y = layout_box.maxy() + y_margin;
auto pair_box = make_horiz_pair(i, y, 1, x_margin, max_diff);
layout_box.expand_to_include(pair_box);
}
while (bottom_i >= 0 && top_i >= 0 && top_i < static_cast<int>(member_offsets_.size()))
{
layout_box.expand_to_include(make_horiz_pair(static_cast<std::size_t>(top_i), layout_box.miny() - y_margin, -1, x_margin, layout.get_max_difference()));
layout_box.expand_to_include(make_horiz_pair(static_cast<std::size_t>(bottom_i), layout_box.maxy() + y_margin, 1, x_margin, layout.get_max_difference()));
top_i -= 2;
bottom_i += 2;
}
// layout_box.center corresponds to the center of the first row;
// shift offsets so that the whole group is centered vertically
y_shift -= 0.5 * layout_box.height();
for (auto & offset : member_offsets_)
{
offset.y += y_shift;
}
}
private:
@ -146,12 +142,12 @@ private:
// stores corresponding offset, and returns modified bounding box
bound_box box_offset_align(size_t i, double x, double y, int x_dir, int y_dir) const
{
bound_box const& box = member_boxes_[i];
pixel_position offset((x_dir == 0 ? x - input_origin_.x : x - (x_dir < 0 ? box.maxx() : box.minx())),
(y_dir == 0 ? y - input_origin_.y : y - (y_dir < 0 ? box.maxy() : box.miny())));
member_offsets_[i] = offset;
return bound_box(box.minx() + offset.x, box.miny() + offset.y, box.maxx() + offset.x, box.maxy() + offset.y);
auto box = member_boxes_[i];
auto & offset = member_offsets_[i];
offset.x = x - (x_dir == 0 ? input_origin_.x : (x_dir < 0 ? box.maxx() : box.minx()));
offset.y = y - (y_dir == 0 ? input_origin_.y : (y_dir < 0 ? box.maxy() : box.miny()));
box.move(offset.x, offset.y);
return box;
}
};

View file

@ -46,7 +46,7 @@
#include <mapnik/group/group_layout.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/util/variant_io.hpp>
#include <mapbox/variant_io.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/algorithm/string.hpp>

@ -1 +1 @@
Subproject commit 941db3d00920dc7aceaa6797096a7228bc7bac14
Subproject commit f9a3c203b3657dd1748d788304f83a26efb6439f

View file

@ -284,16 +284,19 @@ SECTION("to string") {
REQUIRE( string2bool("true",val) );
REQUIRE( val == true );
// mapnik::value hashability
using values_container = std::unordered_map<mapnik::value, unsigned>;
// mapnik::value hash() and operator== works for all T in value<Types...>
mapnik::transcoder tr("utf8");
using values_container = std::unordered_map<mapnik::value, mapnik::value>;
values_container vc;
mapnik::value val2(1);
vc[val2] = 1;
REQUIRE( vc[1] == static_cast<int>(1) );
mapnik::value keys[5] = {true, 123456789, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()} ;
for (auto const& k : keys)
{
vc.insert({k, k});
REQUIRE( vc[k] == k );
}
// mapnik::value << to ostream
std::stringstream s;
mapnik::transcoder tr("utf-8");
mapnik::value_unicode_string ustr = tr.transcode("hello world!");
mapnik::value streamable(ustr);
s << streamable;