From 4d4ea3a5766aba018e783fc1375a762a999a9894 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 23 Sep 2016 16:01:07 +0200 Subject: [PATCH 01/21] Fix clang >= 3.9.0 compilation by using `mapbox::util::variant` as alias (via deps/mapbox/variant => "types" branch) --- include/mapnik/util/variant.hpp | 10 +--------- src/save_map.cpp | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/include/mapnik/util/variant.hpp b/include/mapnik/util/variant.hpp index 27993ce3f..b73533d71 100644 --- a/include/mapnik/util/variant.hpp +++ b/include/mapnik/util/variant.hpp @@ -32,15 +32,7 @@ template using recursive_wrapper = typename mapbox::util::recursive_wrapper; template -class variant : public mapbox::util::variant -{ -public: - // tell spirit that this is an adapted variant - struct adapted_variant_tag; - using types = std::tuple; - // inherit ctor's - using mapbox::util::variant::variant; -}; +using variant = typename mapbox::util::variant; // unary visitor interface // const diff --git a/src/save_map.cpp b/src/save_map.cpp index f3d89153c..882d795f9 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -46,7 +46,7 @@ #include #include #include -#include +#include #pragma GCC diagnostic push #include #include From 27a0f3562da32fafd6ce2952903ce59331bd9a72 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Tue, 29 Nov 2016 14:55:06 +0000 Subject: [PATCH 02/21] remove methods that are not referenced anywhere --- include/mapnik/group/group_symbolizer_helper.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/mapnik/group/group_symbolizer_helper.hpp b/include/mapnik/group/group_symbolizer_helper.hpp index 93c7d4f3f..41b784b1c 100644 --- a/include/mapnik/group/group_symbolizer_helper.hpp +++ b/include/mapnik/group/group_symbolizer_helper.hpp @@ -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. From d378ddbf66a2d33ca09087028c18709284e3b78b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 1 Dec 2016 09:50:34 -0800 Subject: [PATCH 03/21] mason packages are currently built with -D_GLIBCXX_USE_CXX11_ABI=0 --- bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap.sh b/bootstrap.sh index e926c26bc..4a7bfa49c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -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' From d5a9322a11b8f96e2d9585e8ad277df5e9deda54 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Nov 2016 12:03:34 -0800 Subject: [PATCH 04/21] use clang 3.9, g++-6 --- .travis.yml | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index f98cb1f65..0df3c2dc8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,19 +25,29 @@ 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 + sudo: required + dist: trusty + 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 +88,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 From b2f7bea7b53970e7a5188b19978156ffda340d2d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Nov 2016 13:01:44 -0800 Subject: [PATCH 05/21] try g++6 on precise --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0df3c2dc8..e71832ce9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,8 +25,7 @@ matrix: - os: linux sudo: false compiler: ": clang" - sudo: required - dist: trusty + sudo: false env: JOBS=4 CXX="ccache g++-6" CC="gcc-6" addons: apt: From 4cd55330ddbedf227062fd0e40037744080b302f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Nov 2016 13:50:08 -0800 Subject: [PATCH 06/21] avoid -Wshadow and 'unrecognized command line option' with gcc --- include/mapnik/offset_converter.hpp | 10 +++++----- include/mapnik/simplify_converter.hpp | 12 ++++++------ scripts/travis-common.sh | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/mapnik/offset_converter.hpp b/include/mapnik/offset_converter.hpp index 310ed808a..8bbb9aa50 100644 --- a/include/mapnik/offset_converter.hpp +++ b/include/mapnik/offset_converter.hpp @@ -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 diff --git a/include/mapnik/simplify_converter.hpp b/include/mapnik/simplify_converter.hpp index 248842504..a8a6c377b 100644 --- a/include/mapnik/simplify_converter.hpp +++ b/include/mapnik/simplify_converter.hpp @@ -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(); } } diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh index 56909b79d..288fcc1ce 100644 --- a/scripts/travis-common.sh +++ b/scripts/travis-common.sh @@ -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/^/ /' From 335c3e4265667943e470d9147514dc8f94ca4c58 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 2 Dec 2016 14:05:16 -0800 Subject: [PATCH 07/21] allow visual test failures with g++ https://github.com/mapnik/mapnik/issues/3567 --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e71832ce9..7dd209fae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -109,7 +109,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 From 701a459427a31457aca6903afcba09a3b51bffee Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Mon, 5 Dec 2016 08:49:16 +0000 Subject: [PATCH 08/21] duplicate code elimination --- src/agg/process_line_pattern_symbolizer.cpp | 78 ++-------- .../process_polygon_pattern_symbolizer.cpp | 136 +++--------------- 2 files changed, 32 insertions(+), 182 deletions(-) diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index dbbb7f26d..e8770e2cd 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -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; - using pattern_filter_type = agg::pattern_filter_bilinear_rgba8; - using pattern_type = agg::line_image_pattern; - using pixfmt_type = agg::pixfmt_custom_blend_rgba; - using renderer_base = agg::renderer_base; - using renderer_type = agg::renderer_outline_image; - using rasterizer_type = agg::rasterizer_outline_aa; - - value_double opacity = get(sym_, feature_, common_.vars_); agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*ras_ptr_, marker, image_tr, 1.0, image); - - value_bool clip = get(sym_, feature_, common_.vars_); - value_double offset = get(sym_, feature_, common_.vars_); - value_double simplify_tolerance = get(sym_, feature_, common_.vars_); - value_double smooth = get(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(get(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(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(sym_, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_); - - box2d 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; - - vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_); - - if (clip) converter.set(); - converter.set(); //always transform - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (std::fabs(offset) > 0.0) converter.set(); // parallel offset - converter.set(); // optional affine transform - if (smooth > 0.0) converter.set(); // optional smooth converter - - using apply_vertex_converter_type = detail::apply_vertex_converter; - using vertex_processor_type = geometry::vertex_processor; - 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; value_double opacity = get(sym_, feature_, common_.vars_); - mapnik::image_rgba8 const& image = marker.get_data(); - value_bool clip = get(sym_, feature_, common_.vars_); value_double offset = get(sym_, feature_, common_.vars_); value_double simplify_tolerance = get(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(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_; diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index f2a0159d1..5e017cf7e 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -88,123 +88,17 @@ struct agg_renderer_process_visitor_p mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*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(sym_, feature_, common_.vars_); - gamma_method_enum gamma_method = get(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(sym_, feature_, common_.vars_); - value_double opacity = get(sym_, feature_, common_.vars_); - value_double simplify_tolerance = get(sym_, feature_, common_.vars_); - value_double smooth = get(sym_, feature_, common_.vars_); - - box2d clip_box = clipping_extent(common_); - - using color = agg::rgba8; - using order = agg::order_rgba; - using blender_type = agg::comp_op_adaptor_rgba_pre; - using pixfmt_type = agg::pixfmt_custom_blend_rgba; - - using wrap_x_type = agg::wrap_mode_repeat; - using wrap_y_type = agg::wrap_mode_repeat; - using img_source_type = agg::image_accessor_wrap; - - using span_gen_type = agg::span_pattern_rgba; - using ren_base = agg::renderer_base; - - using renderer_type = agg::renderer_scanline_aa_alpha, - span_gen_type>; - - pixfmt_type pixf(buf); - pixf.comp_op(static_cast(get(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(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), 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 sa; - renderer_type rp(renb,sa, sg, unsigned(opacity * 255)); - - agg::trans_affine tr; - auto transform = get_optional(sym_, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_); - using vertex_converter_type = vertex_converter; - - 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(); - converter.set(); //always transform - converter.set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - using apply_vertex_converter_type = detail::apply_vertex_converter; - using vertex_processor_type = geometry::vertex_processor; - 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; - using pixfmt_type = agg::pixfmt_custom_blend_rgba; - - using wrap_x_type = agg::wrap_mode_repeat; - using wrap_y_type = agg::wrap_mode_repeat; - using img_source_type = agg::image_accessor_wrap; - - using span_gen_type = agg::span_pattern_rgba; - using ren_base = agg::renderer_base; - - using renderer_type = agg::renderer_scanline_aa_alpha, - 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 clip_box = clipping_extent(common_); + using color = agg::rgba8; + using order = agg::order_rgba; + using blender_type = agg::comp_op_adaptor_rgba_pre; + using pixfmt_type = agg::pixfmt_custom_blend_rgba; + + using wrap_x_type = agg::wrap_mode_repeat; + using wrap_y_type = agg::wrap_mode_repeat; + using img_source_type = agg::image_accessor_wrap; + + using span_gen_type = agg::span_pattern_rgba; + using ren_base = agg::renderer_base; + + using renderer_type = agg::renderer_scanline_aa_alpha, + span_gen_type>; pixfmt_type pixf(buf); pixf.comp_op(static_cast(get(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 const& ras_ptr_; From 2b3fdf1bc9575a52ea3b51aa95af30453cfdca18 Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Wed, 5 Oct 2016 23:51:03 +0200 Subject: [PATCH 09/21] fix #3526 GroupSymbolizer PairLayout with 3+ items --- src/group/group_layout_manager.cpp | 48 ++++++++++++++---------------- test/data-visual | 2 +- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/group/group_layout_manager.cpp b/src/group/group_layout_manager.cpp index ad9aaad7c..a6b60d0ae 100644 --- a/src/group/group_layout_manager.cpp +++ b/src/group/group_layout_manager.cpp @@ -90,30 +90,26 @@ struct process_layout return; } - bound_box layout_box; - int middle_ifirst = safe_cast((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(member_offsets_.size())) - { - layout_box.expand_to_include(make_horiz_pair(static_cast(top_i), layout_box.miny() - y_margin, -1, x_margin, layout.get_max_difference())); - layout_box.expand_to_include(make_horiz_pair(static_cast(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; } }; diff --git a/test/data-visual b/test/data-visual index 941db3d00..f9a3c203b 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 941db3d00920dc7aceaa6797096a7228bc7bac14 +Subproject commit f9a3c203b3657dd1748d788304f83a26efb6439f From 8dee1a9088c8edd1de79bcf35ee0f86ef2ff1eff Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 6 Dec 2016 15:14:28 +0100 Subject: [PATCH 10/21] use mapbox namespace to fix name resolution --- include/mapnik/util/variant_io.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/util/variant_io.hpp b/include/mapnik/util/variant_io.hpp index 02f0be5ca..98978e3ac 100644 --- a/include/mapnik/util/variant_io.hpp +++ b/include/mapnik/util/variant_io.hpp @@ -24,7 +24,7 @@ #define MAPNIK_UTIL_VARIANT_IO_HPP -namespace mapnik { namespace util { +namespace mapbox { namespace util { namespace detail { From 204d30e58d3553278ab6bcda2d4122b0f13f6392 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 13 Dec 2016 15:50:00 +0100 Subject: [PATCH 11/21] simplify hash calculation (we don't need combine with which(), using hash is sufficient) --- include/mapnik/value_hash.hpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/include/mapnik/value_hash.hpp b/include/mapnik/value_hash.hpp index 80e10d855..f1119e0b3 100644 --- a/include/mapnik/value_hash.hpp +++ b/include/mapnik/value_hash.hpp @@ -54,11 +54,6 @@ struct value_hasher return static_cast(val.hashCode()); } - std::size_t operator()(value_integer val) const - { - return static_cast(val); - } - template std::size_t operator()(T const& val) const { @@ -72,10 +67,7 @@ struct value_hasher template 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 From fa2d63c60199a999a4220a534afca1e6a3d73abd Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 13 Dec 2016 15:51:57 +0100 Subject: [PATCH 12/21] remove `hash_combine` (unused) --- include/mapnik/value_hash.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/mapnik/value_hash.hpp b/include/mapnik/value_hash.hpp index f1119e0b3..3a2536c36 100644 --- a/include/mapnik/value_hash.hpp +++ b/include/mapnik/value_hash.hpp @@ -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 From 641cd6555e243c2b24edf9d557f0caf40e4c7dc0 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 13 Dec 2016 16:16:19 +0100 Subject: [PATCH 13/21] expand std::hash and operator== test for all types in mapnik::value --- test/unit/core/conversions_test.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/unit/core/conversions_test.cpp b/test/unit/core/conversions_test.cpp index 43592af01..abd3d7f8e 100644 --- a/test/unit/core/conversions_test.cpp +++ b/test/unit/core/conversions_test.cpp @@ -284,16 +284,19 @@ SECTION("to string") { REQUIRE( string2bool("true",val) ); REQUIRE( val == true ); - // mapnik::value hashability + // mapnik::value hash() and operator== works for all T in value + mapnik::transcoder tr("utf8"); using values_container = std::unordered_map; values_container vc; - mapnik::value val2(1); - vc[val2] = 1; - REQUIRE( vc[1] == static_cast(1) ); + mapnik::value keys[5] = {true, 1, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()} ; + for (auto const& k : keys) + { + vc.insert({k, 123456789}); + REQUIRE( vc[k] == 123456789 ); + } // 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; From 7c41b835caaec67dff911fc4faf83381c43d6632 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 13 Dec 2016 16:39:16 +0100 Subject: [PATCH 14/21] use latest mapbox::variant --- deps/mapbox/variant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 9a115c5eb..02bd1ac4c 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 9a115c5eb3c09509c70a57b25b283b6e1cbba919 +Subproject commit 02bd1ac4c07e6db9fe0f01267853e43b41637b74 From dd5c134f01a42edf4dc0c4f8df340abea79d54e5 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 13 Dec 2016 17:03:09 +0100 Subject: [PATCH 15/21] update test to use `std::unordered_map` --- test/unit/core/conversions_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/core/conversions_test.cpp b/test/unit/core/conversions_test.cpp index abd3d7f8e..9df4d935c 100644 --- a/test/unit/core/conversions_test.cpp +++ b/test/unit/core/conversions_test.cpp @@ -286,13 +286,13 @@ SECTION("to string") { // mapnik::value hash() and operator== works for all T in value mapnik::transcoder tr("utf8"); - using values_container = std::unordered_map; + using values_container = std::unordered_map; values_container vc; - mapnik::value keys[5] = {true, 1, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()} ; + mapnik::value keys[5] = {true, 123456789, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()} ; for (auto const& k : keys) { - vc.insert({k, 123456789}); - REQUIRE( vc[k] == 123456789 ); + vc.insert({k, k}); + REQUIRE( vc[k] == k ); } // mapnik::value << to ostream From f00470dc02917ca40b69d6359df0d61a9fa125b0 Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Tue, 13 Dec 2016 15:50:12 +0100 Subject: [PATCH 16/21] simplify mapnik::value conversion rules - fixes #3570 - avoids recursive exception-specification on value constructor by only constructing a temporary for arithmetic types (everything else passes a reference to the base variant constructor) - also removes `is_same, value>` SFINAE check -- because we're only passing a reference down, explicitly forcing the compiler to use the implicitly-defined copy/move instead is pointless --- include/mapnik/symbolizer_base.hpp | 13 ++-- include/mapnik/value.hpp | 30 +++------ include/mapnik/value_types.hpp | 97 +++++------------------------- 3 files changed, 29 insertions(+), 111 deletions(-) diff --git a/include/mapnik/symbolizer_base.hpp b/include/mapnik/symbolizer_base.hpp index f07cf3d2a..8ece232d0 100644 --- a/include/mapnik/symbolizer_base.hpp +++ b/include/mapnik/symbolizer_base.hpp @@ -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 - strict_value(T const& obj) - : value_base_type(typename detail::mapnik_value_type::type(obj)) - {} - - template + template > strict_value(T && obj) - noexcept(std::is_nothrow_constructible::value) - : value_base_type(std::forward(obj)) + noexcept(std::is_nothrow_constructible::value) + : value_base_type(U(std::forward(obj))) {} }; diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 9ee732385..fb1e817d6 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -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 != 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 ::value, - detail::mapnik_value_type_decay - >::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 > value(T && val) - noexcept(noexcept(U(std::forward(val))) && - std::is_nothrow_constructible::value) + noexcept(std::is_nothrow_constructible::value) : value_base(U(std::forward(val))) {} - template ::value, - detail::mapnik_value_type_decay - >::type::type> + template > value& operator=(T && val) - noexcept(noexcept(U(std::forward(val))) && - std::is_nothrow_assignable::value) + noexcept(std::is_nothrow_assignable::value) { value_base::operator=(U(std::forward(val))); return *this; diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index 235133a34..d1c0c59bd 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -152,90 +152,23 @@ inline std::istream& operator>> ( std::istream & s, value_null & ) namespace detail { -// to mapnik::value_type conversions traits -template -struct is_value_bool -{ - constexpr static bool value = std::is_same::value; -}; -template -struct is_value_integer -{ - constexpr static bool value = std::is_integral::value && !std::is_same::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 -struct is_value_double -{ - constexpr static bool value = std::is_floating_point::value; -}; - -template -struct is_value_unicode_string -{ - constexpr static bool value = std::is_same::value; -}; - -template -struct is_value_string -{ - constexpr static bool value = std::is_same::value; -}; - -template -struct is_value_null -{ - constexpr static bool value = std::is_same::value; -}; - -template -struct mapnik_value_type -{ - using type = T; -}; - -// value_null -template -struct mapnik_value_type::value>::type> -{ - using type = mapnik::value_null; -}; - -// value_bool -template -struct mapnik_value_type::value>::type> -{ - using type = mapnik::value_bool; -}; - -// value_integer -template -struct mapnik_value_type::value>::type> -{ - using type = mapnik::value_integer; -}; - -// value_double -template -struct mapnik_value_type::value>::type> -{ - using type = mapnik::value_double; -}; - -// value_unicode_string -template -struct mapnik_value_type::value>::type> -{ - using type = mapnik::value_unicode_string const&; -}; - -template -using mapnik_value_type_decay = mapnik_value_type::type>; - -template -using is_same_decay = std::is_same::type, - typename std::decay::type>; +template > +using mapnik_value_type_t = + std::conditional_t< + std::is_same::value, value_bool, + std::conditional_t< + std::is_integral
::value, value_integer, + std::conditional_t< + std::is_floating_point
::value, value_double, + T && >>>; } // namespace detail From 96ce2d8b3b6d7d72260fff24425dd4868edba133 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 14 Dec 2016 18:25:41 -0800 Subject: [PATCH 17/21] update to latest variant --- deps/mapbox/variant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 02bd1ac4c..6317a0b74 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 02bd1ac4c07e6db9fe0f01267853e43b41637b74 +Subproject commit 6317a0b7406395729139327a83a71cfa14513fac From 06201e38421dfc16f2c12e1732e27d14c6635383 Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Thu, 15 Dec 2016 11:51:02 +0100 Subject: [PATCH 18/21] bring C++14 type traits aliases for C++11 support --- include/mapnik/cxx11_support.hpp | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 include/mapnik/cxx11_support.hpp diff --git a/include/mapnik/cxx11_support.hpp b/include/mapnik/cxx11_support.hpp new file mode 100644 index 000000000..dafd721dd --- /dev/null +++ b/include/mapnik/cxx11_support.hpp @@ -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 + +namespace mapnik { +namespace detail { + +template +using conditional_t = typename std::conditional::type; + +template +using decay_t = typename std::decay::type; + +template +using enable_if_t = typename std::enable_if::type; + +} // namespace detail +} // namespace mapnik + +#endif // MAPNIK_CXX11_SUPPORT_HPP From fdd542a3c4e852827bbdf2743d15f7fab5e65554 Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Thu, 15 Dec 2016 11:58:50 +0100 Subject: [PATCH 19/21] make mapnik_value_type_t C++11-friendly --- include/mapnik/value_types.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index d1c0c59bd..7682d52b2 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -25,6 +25,7 @@ // mapnik #include +#include #include @@ -34,7 +35,6 @@ #pragma GCC diagnostic pop // stl -#include #include #include @@ -160,13 +160,13 @@ namespace detail { // value_double if T is a floating-point type // T && otherwise -template > +template > using mapnik_value_type_t = - std::conditional_t< + conditional_t< std::is_same::value, value_bool, - std::conditional_t< + conditional_t< std::is_integral
::value, value_integer, - std::conditional_t< + conditional_t< std::is_floating_point
::value, value_double, T && >>>; From 283481b3474aeb357d18ce7114a3da59f978b0df Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 15 Dec 2016 11:33:23 -0800 Subject: [PATCH 20/21] backport warnings fix from master for enumeration --- include/mapnik/enumeration.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index d57955b9f..ded9dc058 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -28,7 +28,6 @@ #include // stl -#include #include #include #include @@ -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 From a3b4e1f575755236e179f36fb2251ee59a6075da Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 15 Dec 2016 13:33:29 -0800 Subject: [PATCH 21/21] remove duplicate sudo:false from travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7dd209fae..387e6772c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,6 @@ matrix: - os: linux sudo: false compiler: ": clang" - sudo: false env: JOBS=4 CXX="ccache g++-6" CC="gcc-6" addons: apt: