From cfc6b37d71818741d2489c1534a127d443bbf97f Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Tue, 3 May 2016 08:45:48 +0000 Subject: [PATCH 01/98] fix passing scale factor to evaluate_transform() --- include/mapnik/renderer_common/process_point_symbolizer.hpp | 2 +- include/mapnik/symbolizer_base.hpp | 2 +- src/agg/process_line_pattern_symbolizer.cpp | 2 +- src/agg/process_polygon_pattern_symbolizer.cpp | 2 +- src/agg/process_text_symbolizer.cpp | 2 +- src/cairo/process_line_pattern_symbolizer.cpp | 2 +- src/cairo/process_polygon_pattern_symbolizer.cpp | 2 +- src/grid/process_text_symbolizer.cpp | 2 +- src/renderer_common/render_markers_symbolizer.cpp | 4 ++-- src/text/symbolizer_helpers.cpp | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index 12ffba508..ef0863fd6 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -61,7 +61,7 @@ void render_point_symbolizer(point_symbolizer const &sym, agg::trans_affine tr; auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform, common.scale_factor_); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; diff --git a/include/mapnik/symbolizer_base.hpp b/include/mapnik/symbolizer_base.hpp index 8ac446265..fc88c579c 100644 --- a/include/mapnik/symbolizer_base.hpp +++ b/include/mapnik/symbolizer_base.hpp @@ -58,7 +58,7 @@ MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, attributes const& vars, transform_type const& trans_expr, - double scale_factor=1.0); + double scale_factor); struct enumeration_wrapper { diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 3b947a4cc..dbbb7f26d 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -92,7 +92,7 @@ struct agg_renderer_process_visitor_l 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); + 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); diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index e65488622..f2a0159d1 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -84,7 +84,7 @@ struct agg_renderer_process_visitor_p { 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); + 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; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*ras_ptr_, marker, image_tr, 1.0, image); diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index b3794bcf5..685b66c95 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -63,7 +63,7 @@ void agg_renderer::process(text_symbolizer const& sym, if (halo_transform) { agg::trans_affine halo_affine_transform; - evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform); + evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform, common_.scale_factor_); ren.set_halo_transform(halo_affine_transform); } diff --git a/src/cairo/process_line_pattern_symbolizer.cpp b/src/cairo/process_line_pattern_symbolizer.cpp index 7aa85ab41..f53d850a6 100644 --- a/src/cairo/process_line_pattern_symbolizer.cpp +++ b/src/cairo/process_line_pattern_symbolizer.cpp @@ -62,7 +62,7 @@ struct cairo_renderer_process_visitor_l mapnik::rasterizer ras; 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); + 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; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(ras, marker, image_tr, 1.0, image); diff --git a/src/cairo/process_polygon_pattern_symbolizer.cpp b/src/cairo/process_polygon_pattern_symbolizer.cpp index c2b211fd8..4e21234b8 100644 --- a/src/cairo/process_polygon_pattern_symbolizer.cpp +++ b/src/cairo/process_polygon_pattern_symbolizer.cpp @@ -96,7 +96,7 @@ void cairo_renderer::process(polygon_pattern_symbolizer const& sym, 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); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform, common_.scale_factor_); cairo_save_restore guard(context_); context_.set_operator(comp_op); diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 7fe0ff377..d1b6a17b4 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -60,7 +60,7 @@ void grid_renderer::process(text_symbolizer const& sym, if (halo_transform) { agg::trans_affine halo_affine_transform; - evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform); + evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform, common_.scale_factor_); ren.set_halo_transform(halo_affine_transform); } diff --git a/src/renderer_common/render_markers_symbolizer.cpp b/src/renderer_common/render_markers_symbolizer.cpp index 2ecc51bd8..6706cb1cd 100644 --- a/src/renderer_common/render_markers_symbolizer.cpp +++ b/src/renderer_common/render_markers_symbolizer.cpp @@ -159,7 +159,7 @@ struct render_marker_symbolizer_visitor if (auto image_transform = get_optional(sym_, keys::image_transform)) { - evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); } vector_dispatch_type rasterizer_dispatch(marker_ptr, @@ -183,7 +183,7 @@ struct render_marker_symbolizer_visitor setup_transform_scaling(image_tr, mark.width(), mark.height(), feature_, common_.vars_, sym_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); box2d const& bbox = mark.bounding_box(); mapnik::image_rgba8 const& marker = mark.get_data(); // - clamp sizes to > 4 pixels of interactivity diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index c20f51c86..57e4fc79d 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -434,7 +434,7 @@ void text_symbolizer_helper::init_marker() const if (marker->is()) return; agg::trans_affine trans; auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform); + if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform, scale_factor_); double width = marker->width(); double height = marker->height(); double px0 = - 0.5 * width; From b930a5e7f7b0b0a6602dff4de7a2936011622694 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Tue, 3 May 2016 12:07:58 +0000 Subject: [PATCH 02/98] apply scale factor to line spacing --- src/text/text_line.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text/text_line.cpp b/src/text/text_line.cpp index f228e5b93..2d0516731 100644 --- a/src/text/text_line.cpp +++ b/src/text/text_line.cpp @@ -51,7 +51,7 @@ text_line::text_line(text_line && rhs) void text_line::add_glyph(glyph_info && glyph, double scale_factor_) { - line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing); + line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing * scale_factor_); double advance = glyph.advance(); if (glyphs_.empty()) { From ff821c9239615ba9b10d89a54cca6679cdfdf86d Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 3 May 2016 18:02:42 +0200 Subject: [PATCH 03/98] geometry::envelope - deduct value_type of box2d automatically + add missing typedefs --- include/mapnik/geometry.hpp | 33 +++++++++++++------ include/mapnik/geometry_envelope.hpp | 4 +-- include/mapnik/geometry_envelope_impl.hpp | 23 ++++++------- include/mapnik/text/symbolizer_helpers.hpp | 6 +++- include/mapnik/vertex_adapters.hpp | 16 ++++----- include/mapnik/wkt/wkt_generator_grammar.hpp | 2 +- src/box2d.cpp | 1 + src/geometry_envelope.cpp | 23 +++++-------- src/text/symbolizer_helpers.cpp | 34 ++++++++++++++++++-- src/vertex_adapters.cpp | 8 ++--- 10 files changed, 94 insertions(+), 56 deletions(-) diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 69c03e7a5..9807df916 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -33,14 +33,14 @@ namespace mapnik { namespace geometry { template struct point { - using value_type = T; + using coord_type = T; point() {} point(T x_, T y_) : x(x_), y(y_) {} - value_type x; - value_type y; + coord_type x; + coord_type y; }; template @@ -58,6 +58,7 @@ bool operator!=(point const& lhs, point const& rhs) template struct line_string : std::vector > { + using coord_type = T; line_string() = default; explicit line_string(std::size_t size) : std::vector >(size) {} @@ -68,6 +69,7 @@ struct line_string : std::vector > template struct linear_ring : line_string { + using coord_type = T; linear_ring() = default; explicit linear_ring(std::size_t size) : line_string(size) {} @@ -83,8 +85,9 @@ using rings_container = std::vector>; template class InteriorRings = rings_container> struct polygon { - linear_ring exterior_ring; + using coord_type = T; using rings_container = InteriorRings; + linear_ring exterior_ring; rings_container interior_rings; inline void set_exterior_ring(linear_ring && ring) @@ -106,13 +109,22 @@ struct polygon }; template -struct multi_point : line_string {}; +struct multi_point : line_string +{ + using coord_type = T; +}; template -struct multi_line_string : std::vector> {}; +struct multi_line_string : std::vector> +{ + using coord_type = T; +}; template -struct multi_polygon : std::vector> {}; +struct multi_polygon : std::vector> +{ + using coord_type = T; +}; template struct geometry_collection; @@ -132,7 +144,7 @@ using geometry_base = mapnik::util::variant struct geometry : geometry_base { - using value_type = T; + using coord_type = T; geometry() : geometry_base() {} // empty @@ -144,7 +156,10 @@ struct geometry : geometry_base }; template -struct geometry_collection : std::vector> {}; +struct geometry_collection : std::vector> +{ + using coord_type = T; +}; }} diff --git a/include/mapnik/geometry_envelope.hpp b/include/mapnik/geometry_envelope.hpp index 17b8fcb44..981b97849 100644 --- a/include/mapnik/geometry_envelope.hpp +++ b/include/mapnik/geometry_envelope.hpp @@ -26,11 +26,11 @@ #include #include -namespace mapnik { +namespace mapnik { namespace geometry { template -MAPNIK_DECL mapnik::box2d envelope(T const& geom); +MAPNIK_DECL auto envelope(T const& geom) -> box2d; } // end ns geometry } // end ns mapnik diff --git a/include/mapnik/geometry_envelope_impl.hpp b/include/mapnik/geometry_envelope_impl.hpp index 5c39bc386..2ebddb9d9 100644 --- a/include/mapnik/geometry_envelope_impl.hpp +++ b/include/mapnik/geometry_envelope_impl.hpp @@ -28,23 +28,24 @@ namespace mapnik { namespace geometry { namespace detail { +template struct geometry_envelope { - using bbox_type = box2d; + using coord_type = T; + using bbox_type = box2d; bbox_type & bbox; geometry_envelope(bbox_type & bbox_) : bbox(bbox_) {} - template - void operator() (T const& geom) const + template + void operator() (U const& geom) const { return mapnik::util::apply_visitor(*this, geom); } void operator() (mapnik::geometry::geometry_empty const&) const {} - template void operator() (mapnik::geometry::point const& pt) const { if (!bbox.valid()) @@ -54,7 +55,6 @@ struct geometry_envelope bbox.expand_to_include(pt.x, pt.y); } - template void operator() (mapnik::geometry::line_string const& line) const { bool first = true; @@ -72,13 +72,11 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::linear_ring const& ring) const { (*this)(static_cast const&>(ring)); } - template void operator() (mapnik::geometry::polygon const& poly) const { bool first = true; @@ -96,7 +94,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_point const& multi_point) const { bool first = true; @@ -114,7 +111,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_line_string const& multi_line) const { for (auto const& line : multi_line) @@ -123,7 +119,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_polygon const& multi_poly) const { for (auto const& poly : multi_poly) @@ -132,7 +127,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::geometry_collection const& collection) const { for (auto const& geom : collection) @@ -145,10 +139,11 @@ struct geometry_envelope } // end ns detail template -mapnik::box2d envelope(T const& geom) +auto envelope(T const& geom) -> box2d { - box2d bbox; - detail::geometry_envelope op(bbox); + using coord_type = typename T::coord_type; + box2d bbox; + detail::geometry_envelope op(bbox); op(geom); return bbox; } diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index 6d6fbdc49..8fd3c155a 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -158,6 +158,10 @@ protected: void init_marker() const; }; -} //namespace +namespace geometry { +MAPNIK_DECL mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom); +} + +} //namespace mapnik #endif // SYMBOLIZER_HELPERS_HPP diff --git a/include/mapnik/vertex_adapters.hpp b/include/mapnik/vertex_adapters.hpp index 3a41beee0..0c77d7550 100644 --- a/include/mapnik/vertex_adapters.hpp +++ b/include/mapnik/vertex_adapters.hpp @@ -32,10 +32,10 @@ namespace mapnik { namespace geometry { template struct point_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; point_vertex_adapter(point const& pt); - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; void rewind(unsigned) const; geometry_types type () const; point const& pt_; @@ -45,9 +45,9 @@ struct point_vertex_adapter template struct line_string_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; line_string_vertex_adapter(line_string const& line); - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; void rewind(unsigned) const; geometry_types type () const; line_string const& line_; @@ -58,10 +58,10 @@ struct line_string_vertex_adapter template struct polygon_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; polygon_vertex_adapter(polygon const& poly); void rewind(unsigned) const; - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; geometry_types type () const; private: polygon const& poly_; @@ -75,10 +75,10 @@ private: template struct ring_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; ring_vertex_adapter(linear_ring const& ring); void rewind(unsigned) const; - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; geometry_types type () const; private: linear_ring const& ring_; diff --git a/include/mapnik/wkt/wkt_generator_grammar.hpp b/include/mapnik/wkt/wkt_generator_grammar.hpp index 892e55137..f31fcc08e 100644 --- a/include/mapnik/wkt/wkt_generator_grammar.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar.hpp @@ -104,7 +104,7 @@ template struct wkt_generator_grammar : karma::grammar { - using coord_type = typename Geometry::value_type; + using coord_type = typename Geometry::coord_type; wkt_generator_grammar(); // rules karma::rule geometry; diff --git a/src/box2d.cpp b/src/box2d.cpp index 407c054ba..2a87553ce 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -26,6 +26,7 @@ namespace mapnik { template class box2d; +template class box2d; template class box2d; template class box2d; diff --git a/src/geometry_envelope.cpp b/src/geometry_envelope.cpp index 5b3ade6f2..00420fce7 100644 --- a/src/geometry_envelope.cpp +++ b/src/geometry_envelope.cpp @@ -23,30 +23,23 @@ #include #include #include -namespace mapnik { -namespace geometry { + +namespace mapnik { namespace geometry { template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); -template MAPNIK_DECL mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry_empty const& geom); +// single template MAPNIK_DECL mapnik::box2d envelope(point const& geom); template MAPNIK_DECL mapnik::box2d envelope(line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); template MAPNIK_DECL mapnik::box2d envelope(polygon const& geom); +template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); +// multi template MAPNIK_DECL mapnik::box2d envelope(multi_point const& geom); template MAPNIK_DECL mapnik::box2d envelope(multi_line_string const& geom); template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); +// collection template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); - -template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); -template MAPNIK_DECL mapnik::box2d envelope(point const& geom); -template MAPNIK_DECL mapnik::box2d envelope(line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); -template MAPNIK_DECL mapnik::box2d envelope(polygon const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_point const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); +// +template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); } // end ns geometry } // end ns mapnik diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index c20f51c86..31df3b0ea 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -41,8 +41,39 @@ #include #include +namespace mapnik { +namespace geometry { -namespace mapnik { namespace detail { +struct envelope_impl +{ + template + box2d operator() (T const& ref) const + { + return envelope(ref); + } +}; + +mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom) +{ + return mapnik::util::apply_visitor(envelope_impl(), geom); +} + +struct geometry_type_impl +{ + template + auto operator() (T const& ref) const -> decltype(geometry_type(ref)) + { + return geometry_type(ref); + } +}; + +mapnik::geometry::geometry_types geometry_type(mapnik::base_symbolizer_helper::geometry_cref const& geom) +{ + return mapnik::util::apply_visitor(geometry_type_impl(), geom); +} + +} // geometry +namespace detail { template struct apply_vertex_placement @@ -460,7 +491,6 @@ void text_symbolizer_helper::init_marker() const finder_.set_marker(std::make_shared(marker, trans), bbox, unlock_image, marker_displacement); } - template text_symbolizer_helper::text_symbolizer_helper( text_symbolizer const& sym, feature_impl const& feature, diff --git a/src/vertex_adapters.cpp b/src/vertex_adapters.cpp index 06be6c2f4..e96a9e25e 100644 --- a/src/vertex_adapters.cpp +++ b/src/vertex_adapters.cpp @@ -34,7 +34,7 @@ point_vertex_adapter::point_vertex_adapter(point const& pt) first_(true) {} template -unsigned point_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned point_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (first_) { @@ -67,7 +67,7 @@ line_string_vertex_adapter::line_string_vertex_adapter(line_string const& {} template -unsigned line_string_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned line_string_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (current_index_ != end_index_) { @@ -117,7 +117,7 @@ void polygon_vertex_adapter::rewind(unsigned) const start_loop_ = true; } template -unsigned polygon_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned polygon_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (rings_itr_ == rings_end_) { @@ -177,7 +177,7 @@ void ring_vertex_adapter::rewind(unsigned) const } template -unsigned ring_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned ring_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (current_index_ < end_index_) { From 471d6dfe94e27854597ba63ff575404331a47ecd Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 3 May 2016 18:13:41 +0200 Subject: [PATCH 04/98] remove redundant `recursive_wrapper` (via @jfirebaugh : https://github.com/mapbox/geometry.hpp/commit/f00a7aebf1358421061140fcb6adf15e500619d7) --- include/mapnik/geometry.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 9807df916..f97e9e6c6 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -140,7 +140,7 @@ using geometry_base = mapnik::util::variant, multi_line_string, multi_polygon, - mapnik::util::recursive_wrapper > >; + geometry_collection >; template struct geometry : geometry_base { From c0dfc92022b27f230e7117547185a807536a0af4 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 3 May 2016 18:26:46 +0200 Subject: [PATCH 05/98] geometry_envelope - add tests for double/float/int coord_type (ref #3415) --- test/unit/geometry/geometry_envelope_test.cpp | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/test/unit/geometry/geometry_envelope_test.cpp b/test/unit/geometry/geometry_envelope_test.cpp index fd5d78fbd..4a8bdc2ee 100644 --- a/test/unit/geometry/geometry_envelope_test.cpp +++ b/test/unit/geometry/geometry_envelope_test.cpp @@ -1,17 +1,20 @@ - #include "catch.hpp" #include -#include -#include +#include +//#include -TEST_CASE("geometry ops - envelope") { +namespace { -SECTION("envelope_test - double") { +template +void envelope_test() +{ using namespace mapnik::geometry; + using coord_type = T; + { - geometry geom(point(1,2)); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(point(1,2)); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == 1 ); REQUIRE( bbox.miny() == 2 ); REQUIRE( bbox.maxx() == 1 ); @@ -19,80 +22,67 @@ SECTION("envelope_test - double") { } { // Test empty geom - geometry geom = mapnik::geometry::geometry_empty(); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom = mapnik::geometry::geometry_empty(); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE_FALSE( bbox.valid() ); } { - line_string line; + line_string line; line.add_coord(0,0); line.add_coord(1,1); line.add_coord(2,2); - geometry geom(line); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(line); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == 0 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 2 ); REQUIRE( bbox.maxy() == 2 ); } { - line_string line; + line_string line; line.add_coord(0,0); line.add_coord(1,1); line.add_coord(2,2); - line_string line2; + line_string line2; line2.add_coord(0,0); line2.add_coord(-1,-1); line2.add_coord(-2,-2); - multi_line_string multi_line; + multi_line_string multi_line; multi_line.emplace_back(std::move(line)); multi_line.emplace_back(std::move(line2)); - geometry geom(multi_line); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(multi_line); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == -2 ); REQUIRE( bbox.miny() == -2 ); REQUIRE( bbox.maxx() == 2 ); REQUIRE( bbox.maxy() == 2 ); } { - polygon poly; - linear_ring ring; + polygon poly; + linear_ring ring; ring.add_coord(0,0); ring.add_coord(-10,0); ring.add_coord(-10,10); ring.add_coord(0,10); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); - geometry geom(poly); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(poly); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - multi_polygon mp; + multi_polygon mp; mp.push_back(poly); - geometry geom_mp(mp); + geometry geom_mp(mp); bbox = mapnik::geometry::envelope(geom_mp); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - correct(geom); - bbox = mapnik::geometry::envelope(geom); - REQUIRE( bbox.minx() == -10 ); - REQUIRE( bbox.miny() == 0 ); - REQUIRE( bbox.maxx() == 0 ); - REQUIRE( bbox.maxy() == 10 ); - correct(geom_mp); - bbox = mapnik::geometry::envelope(geom_mp); - REQUIRE( bbox.minx() == -10 ); - REQUIRE( bbox.miny() == 0 ); - REQUIRE( bbox.maxx() == 0 ); - REQUIRE( bbox.maxy() == 10 ); - - geometry_collection gc; + geometry_collection gc; bbox = mapnik::geometry::envelope(gc); REQUIRE_FALSE( bbox.valid() ); gc.push_back(geom_mp); @@ -101,7 +91,7 @@ SECTION("envelope_test - double") { REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - gc.emplace_back(point(-50,-50)); + gc.emplace_back(point(-50,-50)); bbox = mapnik::geometry::envelope(gc); REQUIRE( bbox.minx() == -50 ); REQUIRE( bbox.miny() == -50 ); @@ -111,30 +101,30 @@ SECTION("envelope_test - double") { { // polygon with hole - polygon poly; - linear_ring ring; + polygon poly; + linear_ring ring; ring.add_coord(0,0); ring.add_coord(-10,0); ring.add_coord(-10,10); ring.add_coord(0,10); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); - linear_ring hole; + linear_ring hole; hole.add_coord(-7,7); hole.add_coord(-7,3); hole.add_coord(-3,3); hole.add_coord(-3,7); hole.add_coord(-7,7); poly.add_hole(std::move(hole)); - geometry geom(poly); - mapnik::box2d bbox = mapnik::geometry::envelope(poly); + geometry geom(poly); + mapnik::box2d bbox = mapnik::geometry::envelope(poly); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); // add another hole inside the first hole // which should be considered a hit - linear_ring fill; + linear_ring fill; fill.add_coord(-6,4); fill.add_coord(-6,6); fill.add_coord(-4,6); @@ -150,3 +140,14 @@ SECTION("envelope_test - double") { } } + +TEST_CASE("geometry ops - envelope") { + +SECTION("envelope_test") +{ + envelope_test(); + envelope_test(); + envelope_test(); +} + +} From e596ffc1c29697fee306085a422568d74ec2d74c Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 3 May 2016 18:33:06 +0200 Subject: [PATCH 06/98] don't instantiate types that are not used in core library --- src/box2d.cpp | 1 - src/geometry_envelope.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/box2d.cpp b/src/box2d.cpp index 2a87553ce..407c054ba 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -26,7 +26,6 @@ namespace mapnik { template class box2d; -template class box2d; template class box2d; template class box2d; diff --git a/src/geometry_envelope.cpp b/src/geometry_envelope.cpp index 00420fce7..bb79f59ad 100644 --- a/src/geometry_envelope.cpp +++ b/src/geometry_envelope.cpp @@ -38,8 +38,6 @@ template MAPNIK_DECL mapnik::box2d envelope(multi_line_string co template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); // collection template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); -// -template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); } // end ns geometry } // end ns mapnik From 52df451ee33f0b8e642fdddd2a7f150f4a04a219 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 4 May 2016 10:19:17 +0200 Subject: [PATCH 07/98] geometry_envelope_test - fix linking/duplicate symbols (ref #3415) --- test/unit/geometry/geometry_envelope_test.cpp | 3 +-- test/unit/geometry/geometry_test_helper.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/unit/geometry/geometry_test_helper.cpp diff --git a/test/unit/geometry/geometry_envelope_test.cpp b/test/unit/geometry/geometry_envelope_test.cpp index 4a8bdc2ee..75049820a 100644 --- a/test/unit/geometry/geometry_envelope_test.cpp +++ b/test/unit/geometry/geometry_envelope_test.cpp @@ -1,8 +1,7 @@ #include "catch.hpp" #include -#include -//#include +#include namespace { diff --git a/test/unit/geometry/geometry_test_helper.cpp b/test/unit/geometry/geometry_test_helper.cpp new file mode 100644 index 000000000..44bcce596 --- /dev/null +++ b/test/unit/geometry/geometry_test_helper.cpp @@ -0,0 +1,15 @@ +#include +#include +#include + + +namespace mapnik { namespace geometry { +// instantiate types required by geometry_envelope_test +template mapnik::box2d envelope(geometry const& geom); +template mapnik::box2d envelope(geometry const& geom); +template mapnik::box2d envelope(polygon const& geom); +template mapnik::box2d envelope(polygon const& geom); +template mapnik::box2d envelope(geometry_collection const& geom); +template mapnik::box2d envelope(geometry_collection const& geom); + +}} From 464e508dc56df8ac1dc2f0225a210b1c43d1fceb Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Wed, 4 May 2016 14:27:34 +0000 Subject: [PATCH 08/98] visual tests: support for Cairo PS, PDF and SVG renderers --- test/visual/renderer.hpp | 135 ++++++++++++++++++++++++++++++--------- test/visual/run.cpp | 37 +++++++++-- 2 files changed, 137 insertions(+), 35 deletions(-) diff --git a/test/visual/renderer.hpp b/test/visual/renderer.hpp index 6b033f99c..7ea9198df 100644 --- a/test/visual/renderer.hpp +++ b/test/visual/renderer.hpp @@ -38,10 +38,21 @@ #if defined(GRID_RENDERER) #include #endif + #if defined(HAVE_CAIRO) #include #include +#ifdef CAIRO_HAS_SVG_SURFACE +#include #endif +#ifdef CAIRO_HAS_PS_SURFACE +#include +#endif +#ifdef CAIRO_HAS_PDF_SURFACE +#include +#endif +#endif + #if defined(SVG_RENDERER) #include #endif @@ -53,7 +64,7 @@ namespace visual_tests { template -struct renderer_base +struct raster_renderer_base { using image_type = ImageType; @@ -80,7 +91,35 @@ struct renderer_base } }; -struct agg_renderer : renderer_base +struct vector_renderer_base +{ + using image_type = std::string; + + static constexpr const bool support_tiles = false; + + unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const + { + std::ifstream stream(reference.string().c_str(), std::ios_base::in | std::ios_base::binary); + if (!stream) + { + throw std::runtime_error("Could not open: " + reference.string()); + } + std::string expected(std::istreambuf_iterator(stream.rdbuf()), std::istreambuf_iterator()); + return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); + } + + void save(image_type const & image, boost::filesystem::path const& path) const + { + std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); + if (!file) + { + throw std::runtime_error("Cannot open file for writing: " + path.string()); + } + file << image; + } +}; + +struct agg_renderer : raster_renderer_base { static constexpr const char * name = "agg"; @@ -94,7 +133,7 @@ struct agg_renderer : renderer_base }; #if defined(HAVE_CAIRO) -struct cairo_renderer : renderer_base +struct cairo_renderer : raster_renderer_base { static constexpr const char * name = "cairo"; @@ -111,14 +150,65 @@ struct cairo_renderer : renderer_base return image; } }; + +using surface_create_type = cairo_surface_t *(&)(cairo_write_func_t, void *, double, double); + +template +struct cairo_vector_renderer : vector_renderer_base +{ + static cairo_status_t write(void *closure, + const unsigned char *data, + unsigned int length) + { + std::ostringstream & ss = *reinterpret_cast(closure); + ss.write(reinterpret_cast(data), length); + return ss ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR; + } + + image_type render(mapnik::Map const & map, double scale_factor) const + { + std::ostringstream ss(std::stringstream::binary); + mapnik::cairo_surface_ptr image_surface( + SurfaceCreateFunction(write, &ss, map.width(), map.height()), + mapnik::cairo_surface_closer()); + mapnik::cairo_ptr image_context(mapnik::create_context(image_surface)); + mapnik::cairo_renderer ren(map, image_context, scale_factor); + ren.apply(); + cairo_surface_finish(&*image_surface); + return ss.str(); + } +}; + +#ifdef CAIRO_HAS_SVG_SURFACE +struct cairo_svg_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-svg"; + static constexpr const char * ext = ".svg"; +}; +#endif + +#ifdef CAIRO_HAS_PS_SURFACE +struct cairo_ps_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-ps"; + static constexpr const char * ext = ".ps"; +}; +#endif + +#ifdef CAIRO_HAS_PDF_SURFACE +struct cairo_pdf_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-pdf"; + static constexpr const char * ext = ".pdf"; +}; +#endif #endif #if defined(SVG_RENDERER) -struct svg_renderer : renderer_base +struct svg_renderer : vector_renderer_base { static constexpr const char * name = "svg"; static constexpr const char * ext = ".svg"; - static constexpr const bool support_tiles = false; image_type render(mapnik::Map const & map, double scale_factor) const { @@ -128,35 +218,11 @@ struct svg_renderer : renderer_base ren.apply(); return ss.str(); } - - unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const - { - std::ifstream stream(reference.string().c_str(),std::ios_base::in|std::ios_base::binary); - if (!stream.is_open()) - { - throw std::runtime_error("could not open: '" + reference.string() + "'"); - } - std::string expected(std::istreambuf_iterator(stream.rdbuf()),(std::istreambuf_iterator())); - stream.close(); - return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); - } - - void save(image_type const & image, boost::filesystem::path const& path) const - { - std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); - if (!file) { - throw std::runtime_error((std::string("cannot open file for writing file ") + path.string()).c_str()); - } else { - file << image; - file.close(); - } - } - }; #endif #if defined(GRID_RENDERER) -struct grid_renderer : renderer_base +struct grid_renderer : raster_renderer_base { static constexpr const char * name = "grid"; @@ -335,6 +401,15 @@ private: using renderer_type = mapnik::util::variant #if defined(HAVE_CAIRO) ,renderer +#ifdef CAIRO_HAS_SVG_SURFACE + ,renderer +#endif +#ifdef CAIRO_HAS_PS_SURFACE + ,renderer +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + ,renderer +#endif #endif #if defined(SVG_RENDERER) ,renderer diff --git a/test/visual/run.cpp b/test/visual/run.cpp index 70284bc3e..9b6ae879f 100644 --- a/test/visual/run.cpp +++ b/test/visual/run.cpp @@ -48,30 +48,48 @@ namespace po = boost::program_options; runner::renderer_container create_renderers(po::variables_map const & args, boost::filesystem::path const & output_dir, - bool append_all = false) + bool force_append = false) { boost::filesystem::path reference_dir(args["images-dir"].as()); bool overwrite = args.count("overwrite"); runner::renderer_container renderers; - if (append_all || args.count(agg_renderer::name)) + if (force_append || args.count(agg_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } #if defined(HAVE_CAIRO) - if (append_all || args.count(cairo_renderer::name)) + if (force_append || args.count(cairo_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } +#ifdef CAIRO_HAS_SVG_SURFACE + if (args.count(cairo_svg_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif +#ifdef CAIRO_HAS_PS_SURFACE + if (args.count(cairo_ps_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + if (args.count(cairo_pdf_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif #endif #if defined(SVG_RENDERER) - if (append_all || args.count(svg_renderer::name)) + if (force_append || args.count(svg_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } #endif #if defined(GRID_RENDERER) - if (append_all || args.count(grid_renderer::name)) + if (force_append || args.count(grid_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } @@ -112,6 +130,15 @@ int main(int argc, char** argv) (agg_renderer::name, "render with AGG renderer") #if defined(HAVE_CAIRO) (cairo_renderer::name, "render with Cairo renderer") +#ifdef CAIRO_HAS_SVG_SURFACE + (cairo_svg_renderer::name, "render with Cairo SVG renderer") +#endif +#ifdef CAIRO_HAS_PS_SURFACE + (cairo_ps_renderer::name, "render with Cairo PS renderer") +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + (cairo_pdf_renderer::name, "render with Cairo PDF renderer") +#endif #endif #if defined(SVG_RENDERER) (svg_renderer::name, "render with SVG renderer") From d9e75f4ddbabd25fd1e17ceab953ace9dc79eed5 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 5 May 2016 10:31:58 +0200 Subject: [PATCH 09/98] c++ prettify formatting --- include/mapnik/json/generic_json.hpp | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 331341066..2d176bdc6 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -121,10 +121,14 @@ unicode_string::unicode_string() escape = ('x' > hex) [push_utf8(_r1, _1)] - | ('u' > hex4) [push_utf8(_r1, _1)] - | ('U' > hex8) [push_utf8(_r1, _1)] - | char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)] - | eol // continue to next line + | + ('u' > hex4) [push_utf8(_r1, _1)] + | + ('U' > hex8) [push_utf8(_r1, _1)] + | + char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)] + | + eol // continue to next line ; char_esc = @@ -132,7 +136,7 @@ unicode_string::unicode_string() ; double_quoted = - '"' + '"' > *(char_esc(_val) | (~char_('"')) [_val += _1]) > '"' ; @@ -141,18 +145,18 @@ unicode_string::unicode_string() template struct generic_json { - qi::rule value; - qi::int_parser int__; + qi::rule value; + qi::int_parser int__; unicode_string string_; - qi::rule key_value; - qi::rule number; - qi::rule object; - qi::rule array; - qi::rule pairs; - qi::real_parser > strict_double; + qi::rule key_value; + qi::rule number; + qi::rule object; + qi::rule array; + qi::rule pairs; + qi::real_parser> strict_double; // conversions - boost::phoenix::function > integer_converter; - boost::phoenix::function > double_converter; + boost::phoenix::function> integer_converter; + boost::phoenix::function> double_converter; }; }} From db912d9b67bc7f314420ae4f9c9388692e0b8ad7 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 5 May 2016 10:32:29 +0200 Subject: [PATCH 10/98] disable white skipping in stringify_object/stringify_array (ref #3419) --- include/mapnik/json/feature_grammar_impl.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index 61a23f985..1ddf95581 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -44,6 +44,7 @@ feature_grammar::feature_grammar(mapnik::tran qi::_r1_type _r1; qi::eps_type eps; qi::char_type char_; + qi::no_skip_type no_skip; using qi::fail; using qi::on_error; using phoenix::new_; @@ -101,10 +102,10 @@ feature_grammar::feature_grammar(mapnik::tran attribute_value %= json_.number | json_.string_ | stringify_object | stringify_array ; - stringify_object %= char_('{')[_a = 1 ] > *(eps(_a > 0) > (char_('{')[_a +=1] | char_('}')[_a -=1] | char_)) + stringify_object %= char_('{')[_a = 1 ] > no_skip[*(eps(_a > 0) > (char_('{')[_a +=1] | char_('}')[_a -=1] | char_))] ; - stringify_array %= char_('[')[_a = 1 ] > *(eps(_a > 0) > (char_('[')[_a +=1] | char_(']')[_a -=1] | char_)) + stringify_array %= char_('[')[_a = 1 ] > no_skip[*(eps(_a > 0) > (char_('[')[_a +=1] | char_(']')[_a -=1] | char_))] ; feature.name("Feature"); From 9d9c8db23342c8db6d2cce0b2d98fee911d8a842 Mon Sep 17 00:00:00 2001 From: mapsam Date: Thu, 5 May 2016 09:17:08 -0700 Subject: [PATCH 11/98] add geojson unit test for property types/values --- test/data | 2 +- test/unit/datasource/ds_test_util.hpp | 15 ++++--- test/unit/datasource/geojson.cpp | 60 +++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/test/data b/test/data index 6e4b7ff65..71d16376a 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 6e4b7ff65b6a1f0b34ae7cad52fe2c921ca9ea3f +Subproject commit 71d16376a86926e5f7da6c5b71034106fa52d088 diff --git a/test/unit/datasource/ds_test_util.hpp b/test/unit/datasource/ds_test_util.hpp index 6e1c222b4..46868d4e5 100644 --- a/test/unit/datasource/ds_test_util.hpp +++ b/test/unit/datasource/ds_test_util.hpp @@ -106,13 +106,18 @@ inline std::size_t count_features(mapnik::featureset_ptr features) { } using attr = std::tuple; + +#define REQUIRE_ATTRIBUTES(feature, attrs) \ + REQUIRE(bool(feature)); \ + for (auto const &kv : attrs) { \ + REQUIRE(feature->has_key(std::get<0>(kv))); \ + CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); \ + } \ + + inline void require_attributes(mapnik::feature_ptr feature, std::initializer_list const &attrs) { - REQUIRE(bool(feature)); - for (auto const &kv : attrs) { - REQUIRE(feature->has_key(std::get<0>(kv))); - CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); - } + REQUIRE_ATTRIBUTES(feature, attrs); } namespace detail { diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index 0b0f2052a..5d1c76185 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -654,5 +654,65 @@ TEST_CASE("geojson") { } } } + + SECTION("GeoJSON properties are properly expressed") + { + mapnik::parameters params; + params["type"] = "geojson"; + + std::string filename("./test/data/json/escaped.geojson"); + params["file"] = filename; + + // cleanup in the case of a failed previous run + if (mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + + for (auto create_index : { true, false }) + { + if (create_index) + { + CHECK(!mapnik::util::exists(filename + ".index")); + int ret = create_disk_index(filename); + int ret_posix = (ret >> 8) & 0x000000ff; + INFO(ret); + INFO(ret_posix); + CHECK(mapnik::util::exists(filename + ".index")); + } + + for (auto cache_features : {true, false}) + { + params["cache_features"] = cache_features; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(bool(ds)); + auto fields = ds->get_descriptor().get_descriptors(); + std::initializer_list names = {"NOM_FR","array","boolean","description","double","int","name","object","spaces"}; + REQUIRE_FIELD_NAMES(fields, names); + + auto fs = all_features(ds); + REQUIRE(bool(fs)); + std::initializer_list attrs = { + attr{"name", mapnik::value_unicode_string("Test")}, + attr{"NOM_FR", mapnik::value_unicode_string("Québec")}, + attr{"bool", mapnik::value_bool("true")}, + attr{"description", mapnik::value_unicode_string("Test: \u005C")}, + attr{"double", mapnik::value_double(1.1)}, + attr{"int", mapnik::value_integer(1)}, + attr{"object", mapnik::value_unicode_string("{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\": 1,\"double\":1.1,\"boolean\":false,\"NOM_FR\":\"Québec\"}")}, + attr{"spaces", mapnik::value_unicode_string("this has spaces")}, + attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true,\"Québec\"]")} + }; + auto feature = fs->next(); + REQUIRE(bool(feature)); + REQUIRE_ATTRIBUTES(feature, attrs); + } + // cleanup + if (create_index && mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + } + } } } From 086157e26b09a5876800f19dd20905f0bb54833e Mon Sep 17 00:00:00 2001 From: mapsam Date: Thu, 5 May 2016 13:38:28 -0700 Subject: [PATCH 12/98] one step deeper, moar arrays/objects --- test/data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data b/test/data index 71d16376a..c3ac2edbe 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 71d16376a86926e5f7da6c5b71034106fa52d088 +Subproject commit c3ac2edbe070489b2a11097a747362a9bb40de16 From 966a4ae366ab4a7d5c7afffb85678e622d15243b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 May 2016 19:09:05 -0700 Subject: [PATCH 13/98] avoid warnings with boost 1.60 [skip ci] --- include/mapnik/warning_ignore.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mapnik/warning_ignore.hpp b/include/mapnik/warning_ignore.hpp index 62b789997..95249b8bf 100644 --- a/include/mapnik/warning_ignore.hpp +++ b/include/mapnik/warning_ignore.hpp @@ -23,6 +23,7 @@ #pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc #pragma GCC diagnostic ignored "-Wpragmas" // gcc +#pragma GCC diagnostic ignored "-W#pragma-messages" #pragma GCC diagnostic ignored "-Wunsequenced" #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-parameter" From 7374f82414ee4ed586394a039192bd071a07386c Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 09:47:40 +0200 Subject: [PATCH 14/98] generic_json - add support for JSON object and array type in json_value + update rules attributes --- include/mapnik/json/generic_json.hpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 2d176bdc6..26a1fd1e3 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #pragma GCC diagnostic pop namespace mapnik { namespace json { @@ -39,7 +40,21 @@ namespace qi = boost::spirit::qi; namespace standard = boost::spirit::standard; namespace phoenix = boost::phoenix; using space_type = standard::space_type; -using json_value = mapnik::util::variant; + +struct json_value; + +using json_value_base = mapnik::util::variant>, + mapnik::util::recursive_wrapper > >; +struct json_value : json_value_base +{ + using json_value_base::json_value_base; +}; + using uchar = std::uint32_t; // a unicode code point // unicode string grammar via boost/libs/spirit/example/qi/json/json/parser/grammar.hpp @@ -145,14 +160,14 @@ unicode_string::unicode_string() template struct generic_json { - qi::rule value; + qi::rule value; qi::int_parser int__; unicode_string string_; - qi::rule key_value; + qi::rule(), space_type> key_value; qi::rule number; - qi::rule object; - qi::rule array; - qi::rule pairs; + qi::rule(), space_type> object; + qi::rule(), space_type> array; + qi::rule(), space_type> pairs; qi::real_parser> strict_double; // conversions boost::phoenix::function> integer_converter; From e528b433d4a7526c76bf09cc138d9238ea279b1c Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 09:50:45 +0200 Subject: [PATCH 15/98] geojson feature_grammar - parse objects and arrays into json_value before applying "stringifier" #3419 https://github.com/mapnik/node-mapnik/issues/642 --- include/mapnik/json/feature_grammar.hpp | 81 +++++++++++++++++++- include/mapnik/json/feature_grammar_impl.hpp | 15 ++-- 2 files changed, 83 insertions(+), 13 deletions(-) diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index ae59e3bf0..e63052eb5 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #pragma GCC diagnostic push #include @@ -45,8 +46,72 @@ namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; namespace fusion = boost::fusion; -class attribute_value_visitor +namespace { +struct stringifier +{ + std::string operator()(std::string const& val) const + { + return "\"" + val + "\""; + } + std::string operator()(value_null) const + { + return "null"; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_integer val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(std::vector const& array) const + { + std::string str = "["; + bool first = true; + for (auto const& val : array) + { + if (first) first = false; + else str += ","; + str += mapnik::util::apply_visitor(*this, val); + } + str += "]"; + return str; + } + + std::string operator()(std::unordered_map const& object) const + { + std::string str = "{"; + bool first = true; + for (auto const& kv : object) + { + if (first) first = false; + else str += ","; + str += kv.first; + str += ":"; + str += mapnik::util::apply_visitor(*this, kv.second); + } + str += "}"; + return str; + } +}; + +} // anonymous ns + +struct attribute_value_visitor { public: attribute_value_visitor(mapnik::transcoder const& tr) @@ -57,6 +122,18 @@ public: return mapnik::value(tr_.transcode(val.c_str())); } + mapnik::value operator()(std::vector const& array) const + { + std::string str = stringifier()(array); + return mapnik::value(tr_.transcode(str.c_str())); + } + + mapnik::value operator()(std::unordered_map const& object) const + { + std::string str = stringifier()(object); + return mapnik::value(tr_.transcode(str.c_str())); + } + template mapnik::value operator()(T const& val) const { @@ -102,8 +179,6 @@ struct feature_grammar : qi::grammar qi::rule properties; qi::rule, void(FeatureType &),space_type> attributes; qi::rule attribute_value; - qi::rule, std::string(), space_type> stringify_object; - qi::rule, std::string(), space_type> stringify_array; // functions phoenix::function put_property_; phoenix::function set_geometry; diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index 1ddf95581..c6340d779 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -44,7 +44,6 @@ feature_grammar::feature_grammar(mapnik::tran qi::_r1_type _r1; qi::eps_type eps; qi::char_type char_; - qi::no_skip_type no_skip; using qi::fail; using qi::on_error; using phoenix::new_; @@ -57,17 +56,19 @@ feature_grammar::feature_grammar(mapnik::tran json_.pairs = json_.key_value % lit(',') ; - json_.key_value = (json_.string_ > lit(':') > json_.value) + json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > *json_.pairs + > json_.pairs > lit('}') ; + json_.array = lit('[') > json_.value > *(lit(',') > json_.value) > lit(']') ; + json_.number = json_.strict_double[_val = json_.double_converter(_1)] | json_.int__[_val = json_.integer_converter(_1)] | lit("true") [_val = true] @@ -99,13 +100,7 @@ feature_grammar::feature_grammar(mapnik::tran attributes = (json_.string_ [_a = _1] > lit(':') > attribute_value [put_property_(_r1,_a,_1)]) % lit(',') ; - attribute_value %= json_.number | json_.string_ | stringify_object | stringify_array - ; - - stringify_object %= char_('{')[_a = 1 ] > no_skip[*(eps(_a > 0) > (char_('{')[_a +=1] | char_('}')[_a -=1] | char_))] - ; - - stringify_array %= char_('[')[_a = 1 ] > no_skip[*(eps(_a > 0) > (char_('[')[_a +=1] | char_(']')[_a -=1] | char_))] + attribute_value %= json_.number | json_.string_ | json_.object | json_.array ; feature.name("Feature"); From 6bd708af8675fcb1261e69e5ca862630014ce55a Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 09:55:54 +0200 Subject: [PATCH 16/98] fix generic_json usage across grammars --- .../json/extract_bounding_box_grammar_impl.hpp | 2 +- include/mapnik/json/geometry_grammar_impl.hpp | 2 +- include/mapnik/json/topojson_grammar_impl.hpp | 2 +- include/mapnik/json/topojson_utils.hpp | 9 ++++++++- plugins/input/topojson/topojson_datasource.cpp | 14 +++----------- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp index 8a7fc331c..c6db10b51 100644 --- a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp +++ b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp @@ -154,7 +154,7 @@ extract_bounding_box_grammar::extract_bounding_bo json.key_value = (json.string_ >> lit(':') >> json.value) ; - json.object = lit('{') >> *json.pairs >> lit('}') + json.object = lit('{') >> json.pairs >> lit('}') ; json.array = lit('[') diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index 3c5693f91..535cca727 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -65,7 +65,7 @@ geometry_grammar::geometry_grammar() ; json_.object = lit('{') - > *json_.pairs + > json_.pairs > lit('}') ; json_.array = lit('[') diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index ca8607996..4fdedc86b 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -139,7 +139,7 @@ topojson_grammar::topojson_grammar() json.key_value = (json.string_ >> lit(':') >> json.value) ; - json.object = lit('{') >> *json.pairs >> lit('}') + json.object = lit('{') >> json.pairs >> lit('}') ; json.array = lit('[') diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index c4de30683..9e132a168 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -257,7 +257,14 @@ public: { return mapnik::value(tr_.transcode(val.c_str())); } - + mapnik::value operator()(std::vector const& arr) const + { + return mapnik::value(tr_.transcode("FAIL ARRAY")); + } + mapnik::value operator()(std::unordered_map const& obj) const + { + return mapnik::value(tr_.transcode("FAIL OBJECT")); + } template mapnik::value operator()(T const& val) const { diff --git a/plugins/input/topojson/topojson_datasource.cpp b/plugins/input/topojson/topojson_datasource.cpp index 4c4e6b5df..bb346c492 100644 --- a/plugins/input/topojson/topojson_datasource.cpp +++ b/plugins/input/topojson/topojson_datasource.cpp @@ -67,17 +67,9 @@ struct attr_value_converter return mapnik::Boolean; } - mapnik::eAttributeType operator() (std::string const& /*val*/) const - { - return mapnik::String; - } - - mapnik::eAttributeType operator() (mapnik::value_unicode_string const& /*val*/) const - { - return mapnik::String; - } - - mapnik::eAttributeType operator() (mapnik::value_null const& /*val*/) const + // string, object, array + template + mapnik::eAttributeType operator() (T const& /*val*/) const { return mapnik::String; } From 21487f36b9d91e98037a3b24bf7d348706c19731 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 10:15:44 +0200 Subject: [PATCH 17/98] json - refactor stringifier and attribute_value_visitor into separate *.hpp and share between geojson and topojson grammars --- .../mapnik/json/attribute_value_visitor.hpp | 68 +++++++++++ include/mapnik/json/feature_grammar.hpp | 106 +----------------- include/mapnik/json/stringifier.hpp | 100 +++++++++++++++++ include/mapnik/json/topojson_utils.hpp | 32 +----- 4 files changed, 173 insertions(+), 133 deletions(-) create mode 100644 include/mapnik/json/attribute_value_visitor.hpp create mode 100644 include/mapnik/json/stringifier.hpp diff --git a/include/mapnik/json/attribute_value_visitor.hpp b/include/mapnik/json/attribute_value_visitor.hpp new file mode 100644 index 000000000..dd27495ca --- /dev/null +++ b/include/mapnik/json/attribute_value_visitor.hpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * + * 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_JSON_ATTRIBUTE_VALUE_VISITOR_HPP +#define MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP + +// mapnik +#include +#include +#include +#include + +namespace mapnik { namespace json { + +struct attribute_value_visitor +{ +public: + attribute_value_visitor(mapnik::transcoder const& tr) + : tr_(tr) {} + + mapnik::value operator()(std::string const& val) const + { + return mapnik::value(tr_.transcode(val.c_str())); + } + + mapnik::value operator()(std::vector const& array) const + { + std::string str = stringifier()(array); + return mapnik::value(tr_.transcode(str.c_str())); + } + + mapnik::value operator()(std::unordered_map const& object) const + { + std::string str = stringifier()(object); + return mapnik::value(tr_.transcode(str.c_str())); + } + + template + mapnik::value operator()(T const& val) const + { + return mapnik::value(val); + } + + mapnik::transcoder const& tr_; +}; + +}} + +#endif //MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index e63052eb5..699ec907a 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -24,15 +24,10 @@ #define MAPNIK_FEATURE_GRAMMAR_HPP // mapnik -#include #include #include -#include -#include -#include -#include -#include - +#include +#include #pragma GCC diagnostic push #include #include @@ -46,103 +41,6 @@ namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; namespace fusion = boost::fusion; -namespace { -struct stringifier -{ - std::string operator()(std::string const& val) const - { - return "\"" + val + "\""; - } - - std::string operator()(value_null) const - { - return "null"; - } - - std::string operator()(value_bool val) const - { - return val ? "true" : "false"; - } - - std::string operator()(value_integer val) const - { - std::string str; - util::to_string(str, val); - return str; - } - - std::string operator()(value_double val) const - { - std::string str; - util::to_string(str, val); - return str; - } - - std::string operator()(std::vector const& array) const - { - std::string str = "["; - bool first = true; - for (auto const& val : array) - { - if (first) first = false; - else str += ","; - str += mapnik::util::apply_visitor(*this, val); - } - str += "]"; - return str; - } - - std::string operator()(std::unordered_map const& object) const - { - std::string str = "{"; - bool first = true; - for (auto const& kv : object) - { - if (first) first = false; - else str += ","; - str += kv.first; - str += ":"; - str += mapnik::util::apply_visitor(*this, kv.second); - } - str += "}"; - return str; - } -}; - -} // anonymous ns - -struct attribute_value_visitor -{ -public: - attribute_value_visitor(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value operator()(std::string const& val) const - { - return mapnik::value(tr_.transcode(val.c_str())); - } - - mapnik::value operator()(std::vector const& array) const - { - std::string str = stringifier()(array); - return mapnik::value(tr_.transcode(str.c_str())); - } - - mapnik::value operator()(std::unordered_map const& object) const - { - std::string str = stringifier()(object); - return mapnik::value(tr_.transcode(str.c_str())); - } - - template - mapnik::value operator()(T const& val) const - { - return mapnik::value(val); - } - - mapnik::transcoder const& tr_; -}; - struct put_property { using result_type = void; diff --git a/include/mapnik/json/stringifier.hpp b/include/mapnik/json/stringifier.hpp new file mode 100644 index 000000000..f7d18493a --- /dev/null +++ b/include/mapnik/json/stringifier.hpp @@ -0,0 +1,100 @@ +/***************************************************************************** + * + * 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_JSON_STRINGIFIER_HPP +#define MAPNIK_JSON_STRINGIFIER_HPP + +// mapnik +#include +#include +// stl +#include + + +namespace mapnik { namespace json { + +struct stringifier +{ + std::string operator()(std::string const& val) const + { + return "\"" + val + "\""; + } + + std::string operator()(value_null) const + { + return "null"; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_integer val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(std::vector const& array) const + { + std::string str = "["; + bool first = true; + for (auto const& val : array) + { + if (first) first = false; + else str += ","; + str += mapnik::util::apply_visitor(*this, val); + } + str += "]"; + return str; + } + + std::string operator()(std::unordered_map const& object) const + { + std::string str = "{"; + bool first = true; + for (auto const& kv : object) + { + if (first) first = false; + else str += ","; + str += kv.first; + str += ":"; + str += mapnik::util::apply_visitor(*this, kv.second); + } + str += "}"; + return str; + } +}; + +}} + + +#endif // MAPNIK_JSON_STRINGIFIER_HPP diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index 9e132a168..0402bb687 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * 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 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -246,33 +247,6 @@ private: }; namespace { -struct attribute_value_visitor - -{ -public: - attribute_value_visitor(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value operator()(std::string const& val) const - { - return mapnik::value(tr_.transcode(val.c_str())); - } - mapnik::value operator()(std::vector const& arr) const - { - return mapnik::value(tr_.transcode("FAIL ARRAY")); - } - mapnik::value operator()(std::unordered_map const& obj) const - { - return mapnik::value(tr_.transcode("FAIL OBJECT")); - } - template - mapnik::value operator()(T const& val) const - { - return mapnik::value(val); - } - - mapnik::transcoder const& tr_; -}; template void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::transcoder const& tr) @@ -281,7 +255,7 @@ void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::tr { for (auto const& p : *geom.props) { - feature.put_new(std::get<0>(p), mapnik::util::apply_visitor(attribute_value_visitor(tr),std::get<1>(p))); + feature.put_new(std::get<0>(p), mapnik::util::apply_visitor(mapnik::json::attribute_value_visitor(tr),std::get<1>(p))); } } } From c2bf2be7ba9063fd98f79dea01a8b22a32341b78 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 10:24:25 +0200 Subject: [PATCH 18/98] json - simplify generic_json rules: remove redundant rule --- include/mapnik/json/extract_bounding_box_grammar_impl.hpp | 7 ++----- include/mapnik/json/feature_grammar_impl.hpp | 5 +---- include/mapnik/json/generic_json.hpp | 1 - include/mapnik/json/geometry_grammar_impl.hpp | 7 ++----- include/mapnik/json/topojson_grammar_impl.hpp | 7 ++----- 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp index c6db10b51..9e21baa08 100644 --- a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp +++ b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp @@ -148,13 +148,10 @@ extract_bounding_box_grammar::extract_bounding_bo json.value = json.object | json.array | json.string_ | json.number ; - json.pairs = json.key_value % lit(',') + json.key_value = json.string_ >> lit(':') >> json.value ; - json.key_value = (json.string_ >> lit(':') >> json.value) - ; - - json.object = lit('{') >> json.pairs >> lit('}') + json.object = lit('{') >> json.key_value % lit(',') >> lit('}') ; json.array = lit('[') diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index c6340d779..476826108 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -53,14 +53,11 @@ feature_grammar::feature_grammar(mapnik::tran json_.value = json_.object | json_.array | json_.string_ | json_.number ; - json_.pairs = json_.key_value % lit(',') - ; - json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > json_.pairs + > json_.key_value % lit(',') > lit('}') ; diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 26a1fd1e3..7acbc3430 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -167,7 +167,6 @@ struct generic_json qi::rule number; qi::rule(), space_type> object; qi::rule(), space_type> array; - qi::rule(), space_type> pairs; qi::real_parser> strict_double; // conversions boost::phoenix::function> integer_converter; diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index 535cca727..3c6086da9 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -58,14 +58,11 @@ geometry_grammar::geometry_grammar() json_.value = json_.object | json_.array | json_.string_ | json_.number ; - json_.pairs = json_.key_value % lit(',') - ; - - json_.key_value = (json_.string_ > lit(':') > json_.value) + json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > json_.pairs + > json_.key_value % lit(',') > lit('}') ; json_.array = lit('[') diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 4fdedc86b..f41ccb97c 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -133,13 +133,10 @@ topojson_grammar::topojson_grammar() json.value = json.object | json.array | json.string_ | json.number ; - json.pairs = json.key_value % lit(',') + json.key_value = json.string_ >> lit(':') >> json.value ; - json.key_value = (json.string_ >> lit(':') >> json.value) - ; - - json.object = lit('{') >> json.pairs >> lit('}') + json.object = lit('{') >> json.key_value % lit(',') >> lit('}') ; json.array = lit('[') From 97b8a11a729ea6d5e8371b2c5ef2140b60929286 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 10:57:35 +0200 Subject: [PATCH 19/98] fix includes + use typedefs for json types --- include/mapnik/json/generic_json.hpp | 16 +++++++++++----- include/mapnik/json/stringifier.hpp | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 7acbc3430..35fdeed03 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -34,6 +34,9 @@ #include #pragma GCC diagnostic pop +#include +#include + namespace mapnik { namespace json { namespace qi = boost::spirit::qi; @@ -43,13 +46,16 @@ using space_type = standard::space_type; struct json_value; +using json_array = std::vector; +using json_object = std::unordered_map; +using json_object_element = std::pair; using json_value_base = mapnik::util::variant>, - mapnik::util::recursive_wrapper > >; + mapnik::util::recursive_wrapper, + mapnik::util::recursive_wrapper >; struct json_value : json_value_base { using json_value_base::json_value_base; @@ -163,10 +169,10 @@ struct generic_json qi::rule value; qi::int_parser int__; unicode_string string_; - qi::rule(), space_type> key_value; + qi::rule key_value; qi::rule number; - qi::rule(), space_type> object; - qi::rule(), space_type> array; + qi::rule object; + qi::rule array; qi::real_parser> strict_double; // conversions boost::phoenix::function> integer_converter; diff --git a/include/mapnik/json/stringifier.hpp b/include/mapnik/json/stringifier.hpp index f7d18493a..c8a4b2665 100644 --- a/include/mapnik/json/stringifier.hpp +++ b/include/mapnik/json/stringifier.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include // stl #include From c4d80de56e4543eb5a35e9ba9d187671375291b1 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 10:58:19 +0200 Subject: [PATCH 20/98] update deps --- deps/mapbox/variant | 2 +- test/data | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 3f025adbf..35ca16c74 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 3f025adbf599d8dd9bfca02d45b37e49a2cae841 +Subproject commit 35ca16c74f5712afb4f042f45ea64078fa0b630e diff --git a/test/data b/test/data index 6e4b7ff65..c3ac2edbe 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 6e4b7ff65b6a1f0b34ae7cad52fe2c921ca9ea3f +Subproject commit c3ac2edbe070489b2a11097a747362a9bb40de16 From 8e8482803bb435726534c3b686a56037b7d3e8ad Mon Sep 17 00:00:00 2001 From: Rafa de la Torre Date: Fri, 6 May 2016 14:43:17 +0200 Subject: [PATCH 21/98] If there're overviews, just use them for rendering The current code falls back to the base table for small scales. That approach has some drawbacks cause it forces the original table to share some conditions with its overviews (same SRID, alginment, scale constraints) for the rendering to work properly. What we propose is to always fall back to the highest resolution overview (lowest scale), rather than the original table, in order to avoid coupling the original table with the constraints imposed by rendering and still have them linked (in postgis raster metadata). Please note this approach is not 100% compatible as the base table won't be used. This should be no big deal because overviews can have an arbitrary resolution/scale. --- plugins/input/pgraster/pgraster_datasource.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/input/pgraster/pgraster_datasource.cpp b/plugins/input/pgraster/pgraster_datasource.cpp index 5c49a43aa..9390f3ace 100644 --- a/plugins/input/pgraster/pgraster_datasource.cpp +++ b/plugins/input/pgraster/pgraster_datasource.cpp @@ -878,9 +878,10 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process std::string table_with_bbox; std::string col = geometryColumn_; - if ( use_overviews_ ) { - std::string sch = schema_; - std::string tab = mapnik::sql_utils::unquote_double(raster_table_); + if ( use_overviews_ && !overviews_.empty()) { + std::string sch = overviews_[0].schema; + std::string tab = overviews_[0].table; + col = overviews_[0].column; const double scale = std::min(px_gw, px_gh); std::vector::const_reverse_iterator i; for (i=overviews_.rbegin(); i!=overviews_.rend(); ++i) { From d97583b53e134ca916aebbf9abbc4e8a5851d41f Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 6 May 2016 16:44:18 +0200 Subject: [PATCH 22/98] geojson.cpp - fix and update test --- test/unit/datasource/geojson.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index 5d1c76185..92747e9ac 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -689,19 +689,24 @@ TEST_CASE("geojson") { auto fields = ds->get_descriptor().get_descriptors(); std::initializer_list names = {"NOM_FR","array","boolean","description","double","int","name","object","spaces"}; REQUIRE_FIELD_NAMES(fields, names); - + auto fs = all_features(ds); REQUIRE(bool(fs)); std::initializer_list attrs = { attr{"name", mapnik::value_unicode_string("Test")}, attr{"NOM_FR", mapnik::value_unicode_string("Québec")}, - attr{"bool", mapnik::value_bool("true")}, + attr{"boolean", mapnik::value_bool("true")}, attr{"description", mapnik::value_unicode_string("Test: \u005C")}, attr{"double", mapnik::value_double(1.1)}, attr{"int", mapnik::value_integer(1)}, - attr{"object", mapnik::value_unicode_string("{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\": 1,\"double\":1.1,\"boolean\":false,\"NOM_FR\":\"Québec\"}")}, + attr{"object", mapnik::value_unicode_string("{name:\"waka\",spaces:\"value with spaces\"," + "boolean:false,int:1,another_object:{name:\"nested object\"}," + "double:1.1,NOM_FR:\"Québec\"," + "array:[\"string\",\"value with spaces\",3,1.1,null,true,\"Québec\"]}")}, attr{"spaces", mapnik::value_unicode_string("this has spaces")}, - attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true,\"Québec\"]")} + attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{name:\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")} }; auto feature = fs->next(); REQUIRE(bool(feature)); From 75189905d6108dc62fd85c1f7018410a24c2b12e Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 9 May 2016 11:42:46 +0200 Subject: [PATCH 23/98] upgrade to latest variant.hpp --- SConstruct | 1 + deps/mapbox/variant | 2 +- include/mapnik/util/variant.hpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index a4c4fda74..f61309fa9 100644 --- a/SConstruct +++ b/SConstruct @@ -1610,6 +1610,7 @@ if not preconfigured: # prepend to make sure we link locally env.Prepend(CPPPATH = '#deps/agg/include') env.Prepend(LIBPATH = '#deps/agg') + env.Prepend(CPPPATH = '#deps/mapbox/variant/include') # prepend deps dir for auxillary headers env.Prepend(CPPPATH = '#deps') diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 35ca16c74..1bc46e525 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 35ca16c74f5712afb4f042f45ea64078fa0b630e +Subproject commit 1bc46e525a9dec71af28f822e5fc031c1352ad2e diff --git a/include/mapnik/util/variant.hpp b/include/mapnik/util/variant.hpp index 05dddecf8..3fb00b388 100644 --- a/include/mapnik/util/variant.hpp +++ b/include/mapnik/util/variant.hpp @@ -24,7 +24,7 @@ #define MAPNIK_UTIL_VARIANT_HPP #include -#include +#include #pragma GCC diagnostic push #include From 609e5ba7afccbf53fe21e8a4dbc818e7468474ca Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 9 May 2016 10:03:50 -0700 Subject: [PATCH 24/98] attempt to get caching+ccache working on osx - refs https://blog.travis-ci.com/2016-05-03-caches-are-coming-to-everyone --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 13cf1f20e..adafe517c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: c +language: generic git: depth: 10 @@ -39,10 +39,10 @@ matrix: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] packages: [ 'clang-3.5', 'llvm-3.5-dev' ] - os: osx - compiler: clang + compiler: ": clang-osx" # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions osx_image: xcode7.3 # upgrades clang from 6 -> 7 - env: JOBS=4 MASON_PUBLISH=true + env: JOBS=4 MASON_PUBLISH=true CXX="ccache clang++ -Qunused-arguments" before_install: - source scripts/travis-common.sh From 83768dc3dddab039ac90efc42e32d85ad3055710 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 9 May 2016 12:21:54 -0700 Subject: [PATCH 25/98] travis by compiler cache needs to use language:cpp --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index adafe517c..7548c7c8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: generic +language: cpp git: depth: 10 @@ -25,7 +25,7 @@ matrix: - os: linux sudo: false compiler: ": clang" - env: JOBS=8 MASON_PUBLISH=true CXX="ccache clang++-3.5 -Qunused-arguments" CC="clang-3.5" TRIGGER=true + env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.5 -Qunused-arguments" _CC="clang-3.5" TRIGGER=true addons: apt: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] @@ -33,7 +33,7 @@ matrix: - os: linux sudo: false compiler: ": clang-coverage" - env: JOBS=8 COVERAGE=true LLVM_VERSION="3.5" CXX="ccache clang++-3.5 -Qunused-arguments" CC="clang-3.5" + env: JOBS=8 COVERAGE=true LLVM_VERSION="3.5" _CXX="ccache clang++-3.5 -Qunused-arguments" _CC="clang-3.5" addons: apt: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] @@ -42,9 +42,11 @@ matrix: compiler: ": clang-osx" # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions osx_image: xcode7.3 # upgrades clang from 6 -> 7 - env: JOBS=4 MASON_PUBLISH=true CXX="ccache clang++ -Qunused-arguments" + env: JOBS=4 MASON_PUBLISH=true _CXX="ccache clang++ -Qunused-arguments" before_install: + - if [[ ${_CXX:-false} != false ]]; then export CXX=${_CXX}; fi + - if [[ ${_CC:-false} != false ]]; then export CC=${_CC}; fi - source scripts/travis-common.sh - export PYTHONUSERBASE=$(pwd)/mason_packages/.link - export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PYTHONUSERBASE}/bin:${PATH} From e68de5488309ee52d0a49b2f46f1b5f53fcea99c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 9 May 2016 14:04:55 -0700 Subject: [PATCH 26/98] re-enable osx unit tests now that ccache is working --- scripts/travis-common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh index 15b38ddf5..0899df1ce 100644 --- a/scripts/travis-common.sh +++ b/scripts/travis-common.sh @@ -62,7 +62,7 @@ commit_message_contains () { } commit_message_parse () { - if commit_message_contains '[skip tests]' || [[ $(uname -s) == 'Darwin' ]]; then + if commit_message_contains '[skip tests]'; then config_override "CPP_TESTS = False" fi if commit_message_contains '[skip utils]'; then From 07ca572af4c5529ab1bbe45577d2ff0c1431a80d Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 10 May 2016 15:12:51 +0200 Subject: [PATCH 27/98] fix mapbox/variant install path --- deps/mapnik/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mapnik/build.py b/deps/mapnik/build.py index 0d6dc8486..76529fbda 100644 --- a/deps/mapnik/build.py +++ b/deps/mapnik/build.py @@ -7,7 +7,7 @@ subdirs = { './sparsehash':{'dir':'sparsehash','glob':'*'}, './sparsehash/internal':{'dir':'sparsehash/internal','glob':'*'}, '../agg/include':{'dir':'agg','glob':'agg*'}, - '../mapbox':{'dir':'mapbox/variant','glob':'*/*.hpp'} + '../mapbox/variant/include':{'dir':'mapbox','glob':'*/*.hpp'} } if 'install' in COMMAND_LINE_TARGETS: From f0386e0469ac8baa3e193f9d19f7d1324911f0c8 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 10 May 2016 15:13:30 +0200 Subject: [PATCH 28/98] issue pre-processor #warning if BOOST_MPL_LIMIT_VECTOR_SIZE is defined before config.hpp is included ref #3425 --- include/mapnik/config.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp index 6461a6c08..5b4c82be1 100644 --- a/include/mapnik/config.hpp +++ b/include/mapnik/config.hpp @@ -52,7 +52,10 @@ #define PROJ_ENVELOPE_POINTS 20 +#ifndef BOOST_MPL_LIMIT_VECTOR_SIZE #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 - +#else +#warning "WARNING: BOOST_MPL_LIMIT_VECTOR_SIZE is already defined. Ensure config.hpp is included before any Boost headers" +#endif #endif // MAPNIK_CONFIG_HPP From 3909fe5b7dc46a3cf58259c17dbddbbf631aceff Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 10 May 2016 15:52:02 +0200 Subject: [PATCH 29/98] JSON - store 'object' properties in std::vector to preserve order --- include/mapnik/json/attribute_value_visitor.hpp | 2 +- include/mapnik/json/generic_json.hpp | 5 ++--- include/mapnik/json/stringifier.hpp | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/mapnik/json/attribute_value_visitor.hpp b/include/mapnik/json/attribute_value_visitor.hpp index dd27495ca..206530cae 100644 --- a/include/mapnik/json/attribute_value_visitor.hpp +++ b/include/mapnik/json/attribute_value_visitor.hpp @@ -48,7 +48,7 @@ public: return mapnik::value(tr_.transcode(str.c_str())); } - mapnik::value operator()(std::unordered_map const& object) const + mapnik::value operator()(std::vector > const& object) const { std::string str = stringifier()(object); return mapnik::value(tr_.transcode(str.c_str())); diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 35fdeed03..92f27455d 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -35,7 +35,6 @@ #pragma GCC diagnostic pop #include -#include namespace mapnik { namespace json { @@ -47,8 +46,8 @@ using space_type = standard::space_type; struct json_value; using json_array = std::vector; -using json_object = std::unordered_map; using json_object_element = std::pair; +using json_object = std::vector; using json_value_base = mapnik::util::variant value; qi::int_parser int__; unicode_string string_; - qi::rule key_value; + qi::rule key_value; qi::rule number; qi::rule object; qi::rule array; diff --git a/include/mapnik/json/stringifier.hpp b/include/mapnik/json/stringifier.hpp index c8a4b2665..93906f6ec 100644 --- a/include/mapnik/json/stringifier.hpp +++ b/include/mapnik/json/stringifier.hpp @@ -78,7 +78,7 @@ struct stringifier return str; } - std::string operator()(std::unordered_map const& object) const + std::string operator()(std::vector> const& object) const { std::string str = "{"; bool first = true; From 5e33dc055179d887bb431b93cbe56f544a675442 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 10 May 2016 15:53:14 +0200 Subject: [PATCH 30/98] feature_grammar - simplify further, remove redundant rule --- include/mapnik/json/feature_grammar.hpp | 1 - include/mapnik/json/feature_grammar_impl.hpp | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index 699ec907a..c329eb7f5 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -76,7 +76,6 @@ struct feature_grammar : qi::grammar qi::rule feature_type; qi::rule properties; qi::rule, void(FeatureType &),space_type> attributes; - qi::rule attribute_value; // functions phoenix::function put_property_; phoenix::function set_geometry; diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index 476826108..e34b42100 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -94,18 +94,13 @@ feature_grammar::feature_grammar(mapnik::tran > lit(':') > ((lit('{') > -attributes(_r1) > lit('}')) | lit("null")) ; - attributes = (json_.string_ [_a = _1] > lit(':') > attribute_value [put_property_(_r1,_a,_1)]) % lit(',') - ; - - attribute_value %= json_.number | json_.string_ | json_.object | json_.array + attributes = (json_.string_ [_a = _1] > lit(':') > json_.value [put_property_(_r1,_a,_1)]) % lit(',') ; feature.name("Feature"); feature_type.name("type"); properties.name("properties"); attributes.name("Attributes"); - attribute_value.name("Attribute Value"); - on_error(feature, error_handler(_1, _2, _3, _4)); } From d19ff576dc853667997495e866afb282fac3ebcc Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 10 May 2016 16:03:04 +0200 Subject: [PATCH 31/98] geojson test - fix the order in 'object' to match input (escaped.json) --- test/unit/datasource/geojson.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index 92747e9ac..2b282871a 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -699,10 +699,9 @@ TEST_CASE("geojson") { attr{"description", mapnik::value_unicode_string("Test: \u005C")}, attr{"double", mapnik::value_double(1.1)}, attr{"int", mapnik::value_integer(1)}, - attr{"object", mapnik::value_unicode_string("{name:\"waka\",spaces:\"value with spaces\"," - "boolean:false,int:1,another_object:{name:\"nested object\"}," - "double:1.1,NOM_FR:\"Québec\"," - "array:[\"string\",\"value with spaces\",3,1.1,null,true,\"Québec\"]}")}, + attr{"object", mapnik::value_unicode_string("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],another_object:{name:\"nested object\"}}")}, attr{"spaces", mapnik::value_unicode_string("this has spaces")}, attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true," "\"Québec\",{name:\"object within an array\"}," From 5228dad91a0f9155f2587f9f1544d831ba97848c Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 11 May 2016 10:58:08 +0200 Subject: [PATCH 32/98] 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 1bc46e525..c6ae1ea0a 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 1bc46e525a9dec71af28f822e5fc031c1352ad2e +Subproject commit c6ae1ea0acf8c4392a806ad3abd5b11eb3b8a8ce From 04ce22572885f6530e5a369f205f3aaffc82b92d Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 11 May 2016 12:35:01 +0200 Subject: [PATCH 33/98] update variant (again) to 7f7470fee6a42c3c68f1fa359a28cf762df385c3 --- deps/mapbox/variant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mapbox/variant b/deps/mapbox/variant index c6ae1ea0a..7f7470fee 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit c6ae1ea0acf8c4392a806ad3abd5b11eb3b8a8ce +Subproject commit 7f7470fee6a42c3c68f1fa359a28cf762df385c3 From 38ec14c739702d165a7745abae7616c2afd73746 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 12 May 2016 18:52:05 +0200 Subject: [PATCH 34/98] topojson - use json.value directly --- include/mapnik/json/topojson_grammar.hpp | 1 - include/mapnik/json/topojson_grammar_impl.hpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index eec2bb41a..7f42ce58c 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -70,7 +70,6 @@ private: // properties qi::rule properties; qi::rule attributes; - qi::rule attribute_value; // id qi::rule id; }; diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index f41ccb97c..5d0306e84 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -262,10 +262,9 @@ topojson_grammar::topojson_grammar() >> (( lit('{') >> attributes >> lit('}')) | json.object) ; - attributes = (json.string_ >> lit(':') >> attribute_value) % lit(',') + attributes = (json.string_ >> lit(':') >> json.value) % lit(',') ; - attribute_value %= json.number | json.string_ ; arcs = lit("\"arcs\"") >> lit(':') >> lit('[') >> -( arc % lit(',')) >> lit(']') ; From 44291557591cb256b67a199b6674cd24b46f1801 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 12 May 2016 18:54:48 +0200 Subject: [PATCH 35/98] update test data --- test/data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data b/test/data index c3ac2edbe..57a6b1296 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit c3ac2edbe070489b2a11097a747362a9bb40de16 +Subproject commit 57a6b12960a4ac672fc05a46da1fe63c74ef89e0 From 4e6aeaedfcc0c777ef1615e9c010e8552659adaa Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 13 May 2016 11:50:43 +0200 Subject: [PATCH 36/98] handle empty arrays and objects ref #3426 --- include/mapnik/json/feature_grammar_impl.hpp | 6 +++--- include/mapnik/json/geometry_grammar_impl.hpp | 6 ++++-- include/mapnik/json/topojson_grammar_impl.hpp | 10 ++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index e34b42100..0fc4205ad 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -50,19 +50,19 @@ feature_grammar::feature_grammar(mapnik::tran using phoenix::construct; // generic json types - json_.value = json_.object | json_.array | json_.string_ | json_.number + json_.value = json_.object | json_.array | json_.string_ | json_.number ; json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > json_.key_value % lit(',') + > -(json_.key_value % lit(',')) > lit('}') ; json_.array = lit('[') - > json_.value > *(lit(',') > json_.value) + > -(json_.value % lit(',')) > lit(']') ; diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index 3c6086da9..c02173379 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -62,13 +62,15 @@ geometry_grammar::geometry_grammar() ; json_.object = lit('{') - > json_.key_value % lit(',') + > -(json_.key_value % lit(',')) > lit('}') ; + json_.array = lit('[') - > json_.value > *(lit(',') > json_.value) + > -(json_.value % lit(',')) > lit(']') ; + json_.number = json_.strict_double | json_.int__ | lit("true") diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 5d0306e84..0bb59b041 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -133,15 +133,17 @@ topojson_grammar::topojson_grammar() json.value = json.object | json.array | json.string_ | json.number ; - json.key_value = json.string_ >> lit(':') >> json.value + json.key_value = json.string_ > lit(':') > json.value ; - json.object = lit('{') >> json.key_value % lit(',') >> lit('}') + json.object = lit('{') + > -(json.key_value % lit(',')) + > lit('}') ; json.array = lit('[') - >> json.value >> *(lit(',') >> json.value) - >> lit(']') + > -(json.value % lit(',')) + > lit(']') ; json.number = json.strict_double[_val = json.double_converter(_1)] From 3ec25e36fe4ea61d2a6c63be6ad33585ec7512c4 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 13 May 2016 12:48:56 +0200 Subject: [PATCH 37/98] test geojson.cpp - add empty properties (ref #3426) --- test/unit/datasource/geojson.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index 2b282871a..4387daa10 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -687,7 +687,7 @@ TEST_CASE("geojson") { auto ds = mapnik::datasource_cache::instance().create(params); REQUIRE(bool(ds)); auto fields = ds->get_descriptor().get_descriptors(); - std::initializer_list names = {"NOM_FR","array","boolean","description","double","int","name","object","spaces"}; + std::initializer_list names = {"NOM_FR","array","boolean","description","double","empty_array", "empty_object","int","name","object","spaces"}; REQUIRE_FIELD_NAMES(fields, names); auto fs = all_features(ds); @@ -705,7 +705,9 @@ TEST_CASE("geojson") { attr{"spaces", mapnik::value_unicode_string("this has spaces")}, attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true," "\"Québec\",{name:\"object within an array\"}," - "[\"array\",\"within\",\"an\",\"array\"]]")} + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", mapnik::value_unicode_string("[]")}, + attr{"empty_object", mapnik::value_unicode_string("{}")}, }; auto feature = fs->next(); REQUIRE(bool(feature)); From 9e5b7a9b5ed36cff84ba9270f6f314d3b8397900 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 13 May 2016 12:51:46 +0200 Subject: [PATCH 38/98] update test data --- test/data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data b/test/data index 57a6b1296..765765833 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 57a6b12960a4ac672fc05a46da1fe63c74ef89e0 +Subproject commit 7657658330c7b95f2d431fa199de8b7629b41fab From dc8494357585b218c54bfd5d1743568345daaaee Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 13 May 2016 15:23:47 +0200 Subject: [PATCH 39/98] Fixed https://github.com/mapbox/windows-builds/issues/88 (inheriting constructors not working with msvc-14.0 2015) --- include/mapnik/json/generic_json.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 92f27455d..308f072da 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -57,7 +57,16 @@ using json_value_base = mapnik::util::variant >; struct json_value : json_value_base { + +#ifdef _WINDOWS + json_value() = default; + template + json_value(T && val) + : json_value_base(std::forward(val)) {} +#else + // MSVC 2015 inheriting constructors is not working in this context (support is apparently planned) using json_value_base::json_value_base; +#endif }; using uchar = std::uint32_t; // a unicode code point From 6e326f035d4e482de4728861b233edc348e51b7f Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 12:44:46 +0200 Subject: [PATCH 40/98] minor formatting --- include/mapnik/json/generic_json.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 308f072da..bc71eb67c 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -64,7 +64,7 @@ struct json_value : json_value_base json_value(T && val) : json_value_base(std::forward(val)) {} #else - // MSVC 2015 inheriting constructors is not working in this context (support is apparently planned) + // MSVC 2015 inheriting constructors is not working in this context (support is apparently planned) using json_value_base::json_value_base; #endif }; From 25217549f18005d578d9c0bb31055edda7411250 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 12:53:07 +0200 Subject: [PATCH 41/98] fix topojson parsing (work-in-progress) --- include/mapnik/json/topojson_grammar.hpp | 2 - include/mapnik/json/topojson_grammar_impl.hpp | 54 +++--- include/mapnik/json/topojson_utils.hpp | 162 ++++++++++-------- include/mapnik/json/topology.hpp | 9 +- .../input/topojson/topojson_datasource.cpp | 9 +- test/data | 2 +- test/unit/datasource/ds_test_util.hpp | 1 + test/unit/datasource/topojson.cpp | 40 +++++ 8 files changed, 178 insertions(+), 101 deletions(-) diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index 7f42ce58c..db6f5492e 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -70,8 +70,6 @@ private: // properties qi::rule properties; qi::rule attributes; - // id - qi::rule id; }; }} diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 0bb59b041..316b5e80a 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -71,13 +71,13 @@ BOOST_FUSION_ADAPT_STRUCT( BOOST_FUSION_ADAPT_STRUCT( mapnik::topojson::linestring, - (mapnik::topojson::index_type, ring) + (std::vector, rings) (boost::optional, props) ) BOOST_FUSION_ADAPT_STRUCT( mapnik::topojson::multi_linestring, - (std::vector, rings) + (std::vector >, lines) (boost::optional, props) ) @@ -101,6 +101,8 @@ BOOST_FUSION_ADAPT_STRUCT( (boost::optional, bbox) ) + + namespace mapnik { namespace topojson { namespace qi = boost::spirit::qi; @@ -128,7 +130,6 @@ topojson_grammar::topojson_grammar() // error handler boost::phoenix::function const error_handler; - // generic JSON types json.value = json.object | json.array | json.string_ | json.number ; @@ -180,7 +181,7 @@ topojson_grammar::topojson_grammar() >> lit('{') >> -((omit[json.string_] >> lit(':') - >> (geometry_collection(_val) | geometry)) % lit(',')) + >> (geometry_collection(_val) | geometry[push_back(_val, _1)]) % lit(','))) >> lit('}') ; @@ -195,17 +196,21 @@ topojson_grammar::topojson_grammar() ; geometry_collection = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") - >> -(lit(',') >> omit[bbox]) - >> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(',')) - >> lit(']') - >> lit('}') + >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") + >> -(lit(',') >> omit[bbox]) + >> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(',')) + >> lit(']') + >> lit('}') ; + point = lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"Point\"") >> -(lit(',') >> omit[bbox]) >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') >> coordinate) - ^ (lit(',') >> properties) /*^ (lit(',') >> omit[id])*/) + ^ + (lit(',') >> properties) + ^ + (lit(',') >> omit[json.key_value])) >> lit('}') ; @@ -214,23 +219,30 @@ topojson_grammar::topojson_grammar() >> -(lit(',') >> omit[bbox]) >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') >> lit('[') >> -(coordinate % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) + ^ + (lit(',') >> properties) ^ (lit(',') >> omit[json.key_value])) >> lit('}') ; linestring = lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"LineString\"") - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') >> int_ >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) + >> (lit(',') >> (lit("\"arcs\"") >> lit(':') >> ring) + ^ + (lit(',') >> properties)) + //^ + // (lit(',') >> omit[json.key_value])) >> lit('}') ; multi_linestring = lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"MultiLineString\"") >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') - >> -((lit('[') >> int_ >> lit(']')) % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) + >> ((lit(',') >> lit("\"arcs\"") >> lit(':') + >> lit('[') >> -(ring % lit(',')) >> lit(']')) + ^ + (lit(',') >> properties) + ^ + (lit(',') >> omit[json.key_value])) >> lit('}') ; @@ -239,7 +251,8 @@ topojson_grammar::topojson_grammar() >> -(lit(',') >> omit[bbox]) >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') >> -(ring % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) + ^ (lit(',') >> properties)) + //^ (lit(',') >> omit[json.key_value])) >> lit('}') ; @@ -249,19 +262,16 @@ topojson_grammar::topojson_grammar() >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') >> -((lit('[') >> -(ring % lit(',')) >> lit(']')) % lit(',')) - >> lit(']')) ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) + >> lit(']')) ^ (lit(',') >> properties) ^ (lit(',') >> omit[json.key_value])) >> lit('}') ; - id = lit("\"id\"") >> lit(':') >> omit[json.value] - ; - ring = lit('[') >> -(int_ % lit(',')) >> lit(']') ; properties = lit("\"properties\"") >> lit(':') - >> (( lit('{') >> attributes >> lit('}')) | json.object) + >> lit('{') >> attributes >> lit('}') ; attributes = (json.string_ >> lit(':') >> json.value) % lit(',') diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index 0402bb687..39c759f77 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -40,6 +40,12 @@ struct bounding_box_visitor : topo_(topo), num_arcs_(topo_.arcs.size()) {} + box2d operator() (mapnik::topojson::empty const&) const + { + std::cerr << "EMPTY FAIL" << std::endl; + return box2d(); + } + box2d operator() (mapnik::topojson::point const& pt) const { double x = pt.coord.x; @@ -82,50 +88,15 @@ struct bounding_box_visitor box2d operator() (mapnik::topojson::linestring const& line) const { box2d bbox; + bool first = true; if (num_arcs_ > 0) { - index_type index = line.ring; - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - bool first = true; - double px = 0, py = 0; - auto const& arcs = topo_.arcs[arc_index]; - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - if (first) - { - first = false; - bbox.init(x, y, x, y); - } - else - { - bbox.expand_to_include(x, y); - } - } - } - } - return bbox; - } - - box2d operator() (mapnik::topojson::multi_linestring const& multi_line) const - { - box2d bbox; - if (num_arcs_ > 0) - { - bool first = true; - for (auto index : multi_line.rings) + for (auto index : line.rings) { index_type arc_index = index < 0 ? std::abs(index) - 1 : index; if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) { + double px = 0, py = 0; auto const& arcs = topo_.arcs[arc_index]; for (auto pt : arcs.coordinates) @@ -153,6 +124,47 @@ struct bounding_box_visitor return bbox; } + box2d operator() (mapnik::topojson::multi_linestring const& multi_line) const + { + box2d bbox; + if (num_arcs_ > 0) + { + bool first = true; + for (auto const& line : multi_line.lines) + { + for (auto index : line) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + double px = 0, py = 0; + auto const& arcs = topo_.arcs[arc_index]; + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + if (first) + { + first = false; + bbox.init(x, y, x, y); + } + else + { + bbox.expand_to_include(x, y); + } + } + } + } + } + } + return bbox; + } + box2d operator() (mapnik::topojson::polygon const& poly) const { box2d bbox; @@ -314,29 +326,31 @@ struct feature_generator mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); if (num_arcs_ > 0) { - index_type index = line.ring; - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - auto const& arcs = topo_.arcs[arc_index]; - double px = 0, py = 0; - mapnik::geometry::line_string line_string; - line_string.reserve(arcs.coordinates.size()); + mapnik::geometry::line_string line_string; - for (auto pt : arcs.coordinates) + for (auto index : line.rings) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) { - double x = pt.x; - double y = pt.y; - if (topo_.tr) + auto const& arcs = topo_.arcs[arc_index]; + double px = 0, py = 0; + line_string.reserve(line_string.size() + arcs.coordinates.size()); + for (auto pt : arcs.coordinates) { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + line_string.add_coord(x,y); } - line_string.add_coord(x,y); } - feature->set_geometry(std::move(line_string)); - assign_properties(*feature, line, tr_); } + feature->set_geometry(std::move(line_string)); + assign_properties(*feature, line, tr_); } return feature; } @@ -348,30 +362,34 @@ struct feature_generator { mapnik::geometry::multi_line_string multi_line_string; bool hit = false; - multi_line_string.reserve(multi_line.rings.size()); - for (auto const& index : multi_line.rings) + for (auto const& line : multi_line.lines) { - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + multi_line_string.reserve(multi_line_string.size() + line.size()); + mapnik::geometry::line_string line_string; + for (auto index : line) { - hit = true; - double px = 0, py = 0; - mapnik::geometry::line_string line_string; - auto const& arcs = topo_.arcs[arc_index]; - line_string.reserve(arcs.coordinates.size()); - for (auto pt : arcs.coordinates) + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) { - double x = pt.x; - double y = pt.y; - if (topo_.tr) + hit = true; + double px = 0, py = 0; + auto const& arcs = topo_.arcs[arc_index]; + line_string.reserve(line_string.size() + arcs.coordinates.size()); + for (auto pt : arcs.coordinates) { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + line_string.add_coord(x, y); } - line_string.add_coord(x, y); + } - multi_line_string.push_back(std::move(line_string)); } + multi_line_string.push_back(std::move(line_string)); } if (hit) { diff --git a/include/mapnik/json/topology.hpp b/include/mapnik/json/topology.hpp index 05f35b4ad..048c85528 100644 --- a/include/mapnik/json/topology.hpp +++ b/include/mapnik/json/topology.hpp @@ -62,13 +62,13 @@ struct multi_point struct linestring { - index_type ring ; + std::vector rings ; boost::optional props; }; struct multi_linestring { - std::vector rings; + std::vector > lines; boost::optional props; }; @@ -84,7 +84,10 @@ struct multi_polygon boost::optional props; }; -using geometry = util::variant mapnik::eAttributeType operator() (T const& /*val*/) const @@ -101,6 +100,11 @@ struct geometry_type_visitor { return static_cast(mapnik::datasource_geometry_t::Polygon); } + template + int operator() (T const& ) const + { + return 0; + } }; struct collect_attributes_visitor @@ -109,6 +113,9 @@ struct collect_attributes_visitor collect_attributes_visitor(mapnik::layer_descriptor & desc): desc_(desc) {} + // no-op + void operator() (mapnik::topojson::empty) {} + // template void operator() (GeomType const& g) { diff --git a/test/data b/test/data index 765765833..b2ec613fb 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 7657658330c7b95f2d431fa199de8b7629b41fab +Subproject commit b2ec613fb5fba85e6f810dabe2436c9e5b2d90b0 diff --git a/test/unit/datasource/ds_test_util.hpp b/test/unit/datasource/ds_test_util.hpp index 46868d4e5..6a9c706e6 100644 --- a/test/unit/datasource/ds_test_util.hpp +++ b/test/unit/datasource/ds_test_util.hpp @@ -110,6 +110,7 @@ using attr = std::tuple; #define REQUIRE_ATTRIBUTES(feature, attrs) \ REQUIRE(bool(feature)); \ for (auto const &kv : attrs) { \ + std::cerr << std::get<0>(kv) << std::endl; \ REQUIRE(feature->has_key(std::get<0>(kv))); \ CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); \ } \ diff --git a/test/unit/datasource/topojson.cpp b/test/unit/datasource/topojson.cpp index 25f9ffdaf..78b75de87 100644 --- a/test/unit/datasource/topojson.cpp +++ b/test/unit/datasource/topojson.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include "catch.hpp" +#include "ds_test_util.hpp" #include #include @@ -59,6 +60,7 @@ TEST_CASE("topology") mapnik::transcoder tr("utf8"); for (auto const& path : mapnik::util::list_directory("test/data/topojson/")) { + std::cerr << path << std::endl; mapnik::topojson::topology topo; REQUIRE(parse_topology(path, topo)); for (auto const& geom : topo.geometries) @@ -72,4 +74,42 @@ TEST_CASE("topology") } } } + + SECTION("TopoJSON properties are properly expressed") + { + std::string filename("./test/data/topojson/escaped.topojson"); + mapnik::context_ptr ctx = std::make_shared(); + mapnik::transcoder tr("utf8"); + mapnik::topojson::topology topo; + REQUIRE(parse_topology(filename, topo)); + mapnik::value_integer feature_id = 0; + for (auto const& geom : topo.geometries) + { + mapnik::box2d bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom); + CHECK(bbox.valid()); + mapnik::topojson::feature_generator visitor(ctx, tr, topo, feature_id); + mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom); + CHECK(feature); + CHECK(feature->envelope() == bbox); + std::initializer_list attrs = { + attr{"name", mapnik::value_unicode_string("Test")}, + attr{"NOM_FR", mapnik::value_unicode_string("Québec")}, + attr{"boolean", mapnik::value_bool("true")}, + attr{"description", mapnik::value_unicode_string("Test: \u005C")}, + attr{"double", mapnik::value_double(1.1)}, + attr{"int", mapnik::value_integer(1)}, + attr{"object", mapnik::value_unicode_string("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", mapnik::value_unicode_string("this has spaces")}, + attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{name:\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", mapnik::value_unicode_string("[]")}, + attr{"empty_object", mapnik::value_unicode_string("{}")}, + }; + REQUIRE_ATTRIBUTES(feature, attrs); + } + } + } From 4ca0c21d730b62fd5b52f5a66af6b9c90ec39b0a Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 13:00:03 +0200 Subject: [PATCH 42/98] move phoenix functions into ctor --- include/mapnik/json/positions_grammar.hpp | 23 ------------------ .../mapnik/json/positions_grammar_impl.hpp | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/mapnik/json/positions_grammar.hpp b/include/mapnik/json/positions_grammar.hpp index bc8104611..75a6b21b6 100644 --- a/include/mapnik/json/positions_grammar.hpp +++ b/include/mapnik/json/positions_grammar.hpp @@ -32,7 +32,6 @@ #pragma GCC diagnostic push #include #include -#include #pragma GCC diagnostic pop @@ -40,26 +39,6 @@ namespace mapnik { namespace json { namespace qi = boost::spirit::qi; -struct set_position_impl -{ - using result_type = void; - template - result_type operator() (T0 & coords, T1 const& pos) const - { - if (pos) coords = *pos; - } -}; - -struct push_position_impl -{ - using result_type = void; - template - result_type operator() (T0 & coords, T1 const& pos) const - { - if (pos) coords.emplace_back(*pos); - } -}; - template > struct positions_grammar : qi::grammar @@ -70,8 +49,6 @@ struct positions_grammar : qi::rule ring; qi::rule(), space_type> rings; qi::rule >(), space_type> rings_array; - boost::phoenix::function set_position; - boost::phoenix::function push_position; }; }} diff --git a/include/mapnik/json/positions_grammar_impl.hpp b/include/mapnik/json/positions_grammar_impl.hpp index 90df172c5..65f2a93c0 100644 --- a/include/mapnik/json/positions_grammar_impl.hpp +++ b/include/mapnik/json/positions_grammar_impl.hpp @@ -28,12 +28,33 @@ #include #include #include +#include // stl #include #include namespace mapnik { namespace json { +struct set_position_impl +{ + using result_type = void; + template + result_type operator() (T0 & coords, T1 const& pos) const + { + if (pos) coords = *pos; + } +}; + +struct push_position_impl +{ + using result_type = void; + template + result_type operator() (T0 & coords, T1 const& pos) const + { + if (pos) coords.emplace_back(*pos); + } +}; + template positions_grammar::positions_grammar(ErrorHandler & error_handler) : positions_grammar::base_type(coords,"coordinates") @@ -49,6 +70,9 @@ positions_grammar::positions_grammar(ErrorHandler & erro using qi::fail; using qi::on_error; + boost::phoenix::function set_position; + boost::phoenix::function push_position; + coords = rings_array[_val = _1] | rings [_val = _1] | ring[_val = _1] | pos[set_position(_val,_1)] ; pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']') From 8f74de85253a1c11e40f1bd5396475a59d20d76d Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 13:05:37 +0200 Subject: [PATCH 43/98] remove stderr --- test/unit/datasource/ds_test_util.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/datasource/ds_test_util.hpp b/test/unit/datasource/ds_test_util.hpp index 6a9c706e6..46868d4e5 100644 --- a/test/unit/datasource/ds_test_util.hpp +++ b/test/unit/datasource/ds_test_util.hpp @@ -110,7 +110,6 @@ using attr = std::tuple; #define REQUIRE_ATTRIBUTES(feature, attrs) \ REQUIRE(bool(feature)); \ for (auto const &kv : attrs) { \ - std::cerr << std::get<0>(kv) << std::endl; \ REQUIRE(feature->has_key(std::get<0>(kv))); \ CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); \ } \ From c66fd480b54aba19eb2c87657e6f7b9ea545ad70 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 13:05:53 +0200 Subject: [PATCH 44/98] simplify rules --- include/mapnik/json/topojson_grammar.hpp | 1 - include/mapnik/json/topojson_grammar_impl.hpp | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index db6f5492e..47708def7 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -69,7 +69,6 @@ private: qi::rule()> ring; // properties qi::rule properties; - qi::rule attributes; }; }} diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 316b5e80a..88ac70e3f 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -271,13 +271,9 @@ topojson_grammar::topojson_grammar() properties = lit("\"properties\"") >> lit(':') - >> lit('{') >> attributes >> lit('}') + >> lit('{') >> (json.string_ >> lit(':') >> json.value) % lit(',') >> lit('}') ; - attributes = (json.string_ >> lit(':') >> json.value) % lit(',') - ; - - arcs = lit("\"arcs\"") >> lit(':') >> lit('[') >> -( arc % lit(',')) >> lit(']') ; From de135820047e1c6719c29000b7d7372f01f4a195 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 13:45:05 +0200 Subject: [PATCH 45/98] remove stderr --- test/unit/datasource/topojson.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/datasource/topojson.cpp b/test/unit/datasource/topojson.cpp index 78b75de87..0e1becda0 100644 --- a/test/unit/datasource/topojson.cpp +++ b/test/unit/datasource/topojson.cpp @@ -60,7 +60,6 @@ TEST_CASE("topology") mapnik::transcoder tr("utf8"); for (auto const& path : mapnik::util::list_directory("test/data/topojson/")) { - std::cerr << path << std::endl; mapnik::topojson::topology topo; REQUIRE(parse_topology(path, topo)); for (auto const& geom : topo.geometries) From 7d72cc1930839f05e692c794a034471cfd5d1264 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 17 May 2016 13:47:31 +0200 Subject: [PATCH 46/98] more cleanups --- include/mapnik/json/topojson_utils.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index 39c759f77..94ffd75f7 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -42,7 +42,6 @@ struct bounding_box_visitor box2d operator() (mapnik::topojson::empty const&) const { - std::cerr << "EMPTY FAIL" << std::endl; return box2d(); } From b2cb39dec82ae532b4ddc806d267b7426a3cc2b3 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 17 May 2016 19:44:12 +0200 Subject: [PATCH 47/98] [GDAL plugin] Add support for non-alpha mask band GDAL can support non-alpha mask band, such as a TIFF IFD with Subfile type=transparency mask. This can be typically used to create a GeoTIFF with YCbCr JPEG compression for RGB bands and DEFLATE compression for the mask band. --- plugins/input/gdal/gdal_featureset.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 2a27d35cb..4b1186193 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -551,6 +551,32 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; } } + else if( dataset_.GetRasterCount() > 0 && dataset_.GetRasterBand(1) ) + { + // Check if we have a non-alpha mask band (for example a TIFF internal mask) + int flags = dataset_.GetRasterBand(1)->GetMaskFlags(); + GDALRasterBand* mask = 0; + if (flags == GMF_PER_DATASET) + { + mask = dataset_.GetRasterBand(1)->GetMaskBand(); + } + if (mask) + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: found and processing mask band..."; + if (!raster_has_nodata) + { + raster_io_error = mask->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + } + else + { + MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of mask band"; + } + } + } mapnik::raster_ptr raster = std::make_shared(intersect, image, filter_factor); // set nodata value to be used in raster colorizer if (nodata_value_) raster->set_nodata(*nodata_value_); From c10c27143045e6c3b223a8c05a5add1527cf22bf Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 18 May 2016 10:35:58 +0200 Subject: [PATCH 48/98] dereference once --- include/mapnik/json/topojson_utils.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index 94ffd75f7..01c9b8e62 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -511,8 +511,9 @@ struct feature_generator if (topo_.tr) { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + transform const& tr = *topo_.tr; + x = (px += x) * tr.scale_x + tr.translate_x; + y = (py += y) * tr.scale_y + tr.translate_y; } processed_coords.emplace_back(coordinate{x,y}); } From c85c0fd025f72c6e08f616e3602e50227af4c13a Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 18 May 2016 11:18:26 +0200 Subject: [PATCH 49/98] prealloc memory with reserve --- include/mapnik/json/topojson_utils.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index 01c9b8e62..40a2c91ff 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -437,7 +437,7 @@ struct feature_generator } processed_coords.emplace_back(coordinate{x,y}); } - + linear_ring.reserve(linear_ring.size() + processed_coords.size()); if (reverse) { for (auto const& c : processed_coords | boost::adaptors::reversed) @@ -519,7 +519,7 @@ struct feature_generator } using namespace boost::adaptors; - + linear_ring.reserve(linear_ring.size() + processed_coords.size()); if (reverse) { for (auto const& c : (processed_coords | reversed)) From 7b3f607a01f62ae8e173e778ac0d7267e7507a56 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 18 May 2016 13:13:25 +0200 Subject: [PATCH 50/98] remove `omit` directive as it breaks type deduction and insists on `boost::optional` attribute signature (boost 1.61.0) --- include/mapnik/json/geometry_grammar_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index c02173379..285be2744 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -47,7 +47,6 @@ geometry_grammar::geometry_grammar() qi::_a_type _a; qi::_b_type _b; qi::eps_type eps; - qi::omit_type omit; using qi::fail; using qi::on_error; using phoenix::push_back; @@ -77,6 +76,7 @@ geometry_grammar::geometry_grammar() | lit ("false") | lit("null") ; + geometry = lit('{')[_a = 0] > (((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) | @@ -84,7 +84,7 @@ geometry_grammar::geometry_grammar() | (lit("\"geometries\"") > lit(':') > lit('[') > geometry_collection[_val = _1] > lit(']')) | - omit[json_.key_value]) % lit(',')) [create_geometry(_val,_a,_b)] + json_.key_value) % lit(',')) [create_geometry(_val,_a,_b)] > lit('}') ; From 44ea60ad5f030758cab229ba992151a057d16e5b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 18 May 2016 13:38:07 -0400 Subject: [PATCH 51/98] fix #3431 --- localize.sh | 10 ++++++---- test/run | 12 ++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/localize.sh b/localize.sh index 4b69c2f6b..3d034f508 100755 --- a/localize.sh +++ b/localize.sh @@ -1,10 +1,12 @@ #!/bin/bash + # TODO - use rpath to avoid needing this to run tests locally + export CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ $(uname -s) = 'Darwin' ]; then - export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH} -else - export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH} +if [[ $(uname -s) == 'Darwin' ]]; then + export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH:-""} +elif [[ $(uname -s) == 'Linux' ]]; then + export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH:-""} fi export PATH=$(pwd)/utils/mapnik-render/:${PATH} diff --git a/test/run b/test/run index f623609eb..54c4d6fb4 100755 --- a/test/run +++ b/test/run @@ -1,5 +1,8 @@ #!/usr/bin/env bash +set -o pipefail +set -eu + failures=0 cd "$( dirname "${BASH_SOURCE[0]}" )" @@ -18,9 +21,8 @@ if [ -d "test/data" ]; then run_substep "Running C++ Unit tests..." if [[ -f ./test/unit/run ]]; then - ./test/unit/run - failures=$((failures+$?)) ran_a_test=true + ./test/unit/run || failures=$((failures+$?)) else run_warn "Skipping unit tests since they were not built" fi @@ -31,8 +33,7 @@ if [ -d "test/data" ]; then for FILE in test/standalone/*-bin; do found_test=true ran_a_test=true - ${FILE}; - failures=$((failures+$?)) + ${FILE} || failures=$((failures+$?)) done fi if [[ $found_test == false ]]; then @@ -45,9 +46,8 @@ if [ -d "test/data" ]; then JOBS=1 fi if [[ -f ./test/visual/run ]]; then - ./test/visual/run -j $JOBS ran_a_test=true - failures=$((failures+$?)) + ./test/visual/run -j $JOBS || failures=$((failures+$?)) else run_warn "Skipping visual tests since they were not built" fi From c8cc2670be6e1387256b27c754ea13bc00544071 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 18 May 2016 13:40:00 -0400 Subject: [PATCH 52/98] update visual test data - refs mapnik/mapnik#3416 / mapnik/test-data-visual#34 --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index 725bc22d2..9aba67c2c 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 725bc22d285ef5a558e2e241fd22ff5489f056ce +Subproject commit 9aba67c2c9667e191d2bd24df10fa79b65160cf5 From fee0ad05ce7d7fba0a9b97c3d0e9ce12e008d47d Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Wed, 18 May 2016 20:06:31 +0000 Subject: [PATCH 53/98] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 073fcf61b..45467bc9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ Released: - Raster scaling: fixed crash and clipping negative pixel values of floating point rasters (https://github.com/mapnik/mapnik/pull/3349) - Restored support for unquoted strings in expressions (https://github.com/mapnik/mapnik/pull/3390) - [TWKB](https://github.com/TWKB/) support via https://github.com/mapnik/mapnik/pull/3356 (#3355) + - Visual test runner can render SVG, PDF and Postscript with Cairo renderer (https://github.com/mapnik/mapnik/pull/3418) + - Scale factor is now applied also to `text-line-spacing` and transforms (https://github.com/mapnik/mapnik/pull/3416) ## 3.0.10 From 20a9112135add2df04fb2ed8009639f9a6b45614 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 19 May 2016 19:37:06 -0400 Subject: [PATCH 54/98] remove boost thread checking since it is no longer a dependency --- SConstruct | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/SConstruct b/SConstruct index f61309fa9..694d494fb 100644 --- a/SConstruct +++ b/SConstruct @@ -704,11 +704,7 @@ def FindBoost(context, prefixes, thread_flag): BOOST_INCLUDE_DIR = None BOOST_APPEND = None env['BOOST_APPEND'] = str() - - if env['THREADING'] == 'multi': - search_lib = 'libboost_thread' - else: - search_lib = 'libboost_filesystem' + search_lib = 'libboost_filesystem' # note: must call normpath to strip trailing slash otherwise dirname # does not remove 'lib' and 'include' @@ -1411,15 +1407,6 @@ if not preconfigured: ['program_options', 'boost/program_options.hpp', False] ] - if env['THREADING'] == 'multi': - BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True]) - # on solaris the configure checks for boost_thread - # require the -pthreads flag to be able to check for - # threading support, so we add as a global library instead - # of attaching to cxxflags after configure - if env['PLATFORM'] == 'SunOS': - env.Append(CXXFLAGS = '-pthreads') - # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests if env['PRIORITIZE_LINKING']: conf.prioritize_paths(silent=True) From d7b6b5669ba0a5dd782e70f7c1839560cf4dbaf9 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 19 May 2016 19:37:26 -0400 Subject: [PATCH 55/98] upgrade to latest mason and latest boost via mason --- bootstrap.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 3a6470990..e3ee8bc8f 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -10,7 +10,7 @@ todo - shrink icu data ' -MASON_VERSION="694d08c" +MASON_VERSION="3e0cc5a" function setup_mason() { if [[ ! -d ./.mason ]]; then @@ -20,7 +20,6 @@ function setup_mason() { echo "Updating to latest mason" (cd ./.mason && git fetch && git checkout ${MASON_VERSION}) fi - export MASON_DIR=$(pwd)/.mason export PATH=$(pwd)/.mason:$PATH export CXX=${CXX:-clang++} export CC=${CC:-clang} @@ -63,8 +62,11 @@ function install_mason_deps() { 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 boost 1.61.0 & + install boost_libsystem 1.61.0 & + install boost_libfilesystem 1.61.0 & + install boost_libprogram_options 1.61.0 & + install boost_libregex 1.61.0 & install freetype 2.6 libfreetype & install harfbuzz 0.9.41 libharfbuzz & wait From 01967cfafffad8b5d5767eff9a87405fad367bec Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 23 May 2016 10:51:05 +0200 Subject: [PATCH 56/98] topojson grammar - re-factor to allow geometry elements to be in any order --- include/mapnik/json/topojson_grammar.hpp | 146 +++++++++++++++- include/mapnik/json/topojson_grammar_impl.hpp | 163 +++++------------- 2 files changed, 183 insertions(+), 126 deletions(-) diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index 47708def7..77c58c26a 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -42,6 +42,138 @@ namespace qi = boost::spirit::qi; namespace fusion = boost::fusion; using space_type = mapnik::json::space_type; +struct create_point +{ + using result_type = mapnik::topojson::point; + template + result_type operator()(T0 & coord, T1 & props) const + { + mapnik::topojson::point pt; + if (coord.template is()) + { + auto const& coord_ = coord.template get(); + pt.coord = coord_; + pt.props = props; + } + return pt; + } +}; + +struct create_multi_point +{ + using result_type = mapnik::topojson::multi_point; + template + result_type operator()(T0 & coords, T1 & props) const + { + mapnik::topojson::multi_point mpt; + if (coords.template is>()) + { + auto const& points = coords.template get>(); + mpt. points = points; + mpt.props = props; + } + return mpt; + } +}; + +struct create_line_string +{ + using result_type = mapnik::topojson::linestring; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::linestring line; + if (arcs.template is>()) + { + auto const& arcs_ = arcs.template get>(); + line.rings = arcs_; + line.props = props; + } + return line; + } +}; + +struct create_multi_line_string +{ + using result_type = mapnik::topojson::multi_linestring; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::multi_linestring mline; + if (arcs.template is>>()) + { + auto const& arcs_ = arcs.template get>>(); + mline.lines = arcs_; + mline.props = props; + } + return mline; + } +}; + +struct create_polygon +{ + using result_type = mapnik::topojson::polygon; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::polygon poly; + if (arcs.template is>>()) + { + auto const& arcs_ = arcs.template get>>(); + poly.rings = arcs_; + poly.props = props; + } + return poly; + } +}; + +struct create_multi_polygon +{ + using result_type = mapnik::topojson::multi_polygon; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::multi_polygon mpoly; + if (arcs.template is>>>()) + { + auto const& arcs_ = arcs.template get>>>(); + mpoly.polygons = arcs_; + mpoly.props = props; + } + return mpoly; + } +}; + + +struct create_geometry_impl +{ + using result_type = mapnik::topojson::geometry; + template + result_type operator()(T0 geom_type, T1 & coord, T2 & arcs, T3 & props) const + { + switch (geom_type) + { + case 1: //Point + return create_point()(coord, props); + case 2: //LineString + return create_line_string()(arcs, props); + case 3: //Polygon + return create_polygon()(arcs, props); + case 4: //MultiPoint + return create_multi_point()(coord, props); + case 5: //MultiLineString + return create_multi_line_string()(arcs, props); + case 6: //MultiPolygon + return create_multi_polygon()(arcs, props); + default: + break; + } + return mapnik::topojson::geometry(); //empty + } +}; + +using coordinates_type = util::variant>; +using arcs_type = util::variant, std::vector>, std::vector>>>; template > struct topojson_grammar : qi::grammar @@ -55,20 +187,18 @@ private: qi::rule()> objects; qi::rule()> arcs; qi::rule arc; - qi::rule coordinate; + qi::rule coordinate_; + qi::rule coordinates; qi::rule transform; qi::rule bbox; - qi::rule geometry; - qi::rule point; - qi::rule multi_point; - qi::rule linestring; - qi::rule multi_linestring; - qi::rule polygon; - qi::rule multi_polygon; + qi::rule, mapnik::topojson::geometry(), space_type> geometry; qi::rule&)> geometry_collection; qi::rule()> ring; + qi::rule>()> rings; + qi::rule rings_array; // properties qi::rule properties; + qi::symbols geometry_type_dispatch; }; }} diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 88ac70e3f..00ae2e3cd 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -57,42 +57,6 @@ BOOST_FUSION_ADAPT_STRUCT( (double, maxy) ) -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::point, - (mapnik::topojson::coordinate, coord) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_point, - (std::vector, points) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::linestring, - (std::vector, rings) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_linestring, - (std::vector >, lines) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::polygon, - (std::vector >, rings) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_polygon, - (std::vector > >, polygons) - (boost::optional, props) - ) - BOOST_FUSION_ADAPT_STRUCT( mapnik::topojson::topology, (std::vector, geometries) @@ -123,13 +87,28 @@ topojson_grammar::topojson_grammar() qi::_3_type _3; qi::_4_type _4; qi::_r1_type _r1; + qi::_a_type _a; + qi::_b_type _b; + qi::_c_type _c; + qi::_d_type _d; using qi::fail; using qi::on_error; using phoenix::push_back; using phoenix::construct; + geometry_type_dispatch.add + ("\"Point\"",1) + ("\"LineString\"",2) + ("\"Polygon\"",3) + ("\"MultiPoint\"",4) + ("\"MultiLineString\"",5) + ("\"MultiPolygon\"",6) + ("\"GeometryCollection\"",7) + ; + // error handler boost::phoenix::function const error_handler; + boost::phoenix::function const create_geometry; // generic JSON types json.value = json.object | json.array | json.string_ | json.number ; @@ -185,89 +164,39 @@ topojson_grammar::topojson_grammar() >> lit('}') ; - geometry = - point | - linestring | - polygon | - multi_point | - multi_linestring | - multi_polygon | - omit[json.object] + geometry = lit('{')[_a = 0] + > ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) + | + (lit("\"coordinates\"") > lit(':') > coordinates[_b = _1]) + | + (lit("\"arcs\"") > lit(':') > rings_array[_c = _1]) + | + properties[_d = _1] + | + json.key_value) % lit(',') + > lit('}')[_val = create_geometry(_a, _b, _c, _d)] ; + geometry_collection = lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") - >> -(lit(',') >> omit[bbox]) - >> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(',')) + >> lit(',') >> lit("\"geometries\"") >> lit(':') + >> lit('[') + >> -(geometry[push_back(_r1, _1)] % lit(',')) >> lit(']') >> lit('}') ; - point = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"Point\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') >> coordinate) - ^ - (lit(',') >> properties) - ^ - (lit(',') >> omit[json.key_value])) - >> lit('}') - ; - - multi_point = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiPoint\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') - >> lit('[') >> -(coordinate % lit(',')) >> lit(']')) - ^ - (lit(',') >> properties) ^ (lit(',') >> omit[json.key_value])) - >> lit('}') - ; - - linestring = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"LineString\"") - >> (lit(',') >> (lit("\"arcs\"") >> lit(':') >> ring) - ^ - (lit(',') >> properties)) - //^ - // (lit(',') >> omit[json.key_value])) - >> lit('}') - ; - - multi_linestring = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiLineString\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') >> -(ring % lit(',')) >> lit(']')) - ^ - (lit(',') >> properties) - ^ - (lit(',') >> omit[json.key_value])) - >> lit('}') - ; - - polygon = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"Polygon\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') >> -(ring % lit(',')) >> lit(']')) - ^ (lit(',') >> properties)) - //^ (lit(',') >> omit[json.key_value])) - >> lit('}') - ; - - multi_polygon = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiPolygon\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') - >> -((lit('[') >> -(ring % lit(',')) >> lit(']')) % lit(',')) - >> lit(']')) ^ (lit(',') >> properties) ^ (lit(',') >> omit[json.key_value])) - >> lit('}') - ; - ring = lit('[') >> -(int_ % lit(',')) >> lit(']') ; + rings = lit('[') >> -(ring % lit(',')) >> lit(']') + ; + rings_array = lit('[') >> -(rings % lit(',')) >> lit(']') + | + rings + | + ring + ; properties = lit("\"properties\"") >> lit(':') @@ -277,9 +206,12 @@ topojson_grammar::topojson_grammar() arcs = lit("\"arcs\"") >> lit(':') >> lit('[') >> -( arc % lit(',')) >> lit(']') ; - arc = lit('[') >> -(coordinate % lit(',')) >> lit(']') ; + arc = lit('[') >> -(coordinate_ % lit(',')) >> lit(']') ; - coordinate = lit('[') >> double_ >> lit(',') >> double_ >> lit(']'); + coordinate_ = lit('[') > double_ > lit(',') > double_ > lit(']'); + + coordinates = (lit('[') >> coordinate_ % lit(',') > lit(']')) + | coordinate_; topology.name("topology"); transform.name("transform"); @@ -287,13 +219,8 @@ topojson_grammar::topojson_grammar() arc.name("arc"); arcs.name("arcs"); json.value.name("value"); - coordinate.name("coordinate"); - - point.name("point"); - multi_point.name("multi_point"); - linestring.name("linestring"); - polygon.name("polygon"); - multi_polygon.name("multi_polygon"); + coordinate_.name("coordinate"); + geometry.name("geometry"); geometry_collection.name("geometry_collection"); // error handler on_error(topology, error_handler(_1, _2, _3, _4)); From de0d384ca97836d9bf876716444aec54d8e4cd08 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 23 May 2016 12:25:16 +0200 Subject: [PATCH 57/98] update test data --- test/data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data b/test/data index b2ec613fb..6fc383e0e 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit b2ec613fb5fba85e6f810dabe2436c9e5b2d90b0 +Subproject commit 6fc383e0e12ce01171b676901c8f8754c1714a1b From 06d487c8d18934ba3285d66a1496048cd0ea6721 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 23 May 2016 17:49:20 +0200 Subject: [PATCH 58/98] update visual data --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index 9aba67c2c..36417c679 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 9aba67c2c9667e191d2bd24df10fa79b65160cf5 +Subproject commit 36417c6797f59b638b665fac3701f13ee4f04c5f From 65a23b436dc79b245969050203f3fe0d4e5ea108 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 24 May 2016 10:15:00 +0200 Subject: [PATCH 59/98] bump visual test data --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index 36417c679..ce60039e8 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 36417c6797f59b638b665fac3701f13ee4f04c5f +Subproject commit ce60039e8ddcd8b0067606aa699eeb06826ed391 From b9cc746c0708fa3e68d0c85065653f445899a9c6 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 24 May 2016 10:27:44 +0200 Subject: [PATCH 60/98] sync up visual test data --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index ce60039e8..f69cc73e7 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit ce60039e8ddcd8b0067606aa699eeb06826ed391 +Subproject commit f69cc73e765ed6ac241e8c3d64ab1f4c790086e3 From acb2d56f4962cbd9bdf66f484b3fe7ef642fa912 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 24 May 2016 10:54:34 +0200 Subject: [PATCH 61/98] prefix string literals with `u8""` to force UTF8 encoding (windows) --- test/unit/datasource/geojson.cpp | 26 +++++++++++++------------- test/unit/datasource/topojson.cpp | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index 4387daa10..efbdd063b 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -693,21 +693,21 @@ TEST_CASE("geojson") { auto fs = all_features(ds); REQUIRE(bool(fs)); std::initializer_list attrs = { - attr{"name", mapnik::value_unicode_string("Test")}, - attr{"NOM_FR", mapnik::value_unicode_string("Québec")}, - attr{"boolean", mapnik::value_bool("true")}, - attr{"description", mapnik::value_unicode_string("Test: \u005C")}, + attr{"name", mapnik::value_unicode_string(u8"Test")}, + attr{"NOM_FR", mapnik::value_unicode_string(u8"Québec")}, + attr{"boolean", mapnik::value_bool(u8"true")}, + attr{"description", mapnik::value_unicode_string(u8"Test: \u005C")}, attr{"double", mapnik::value_double(1.1)}, attr{"int", mapnik::value_integer(1)}, - attr{"object", mapnik::value_unicode_string("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" - ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" - ",\"Québec\"],another_object:{name:\"nested object\"}}")}, - attr{"spaces", mapnik::value_unicode_string("this has spaces")}, - attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true," - "\"Québec\",{name:\"object within an array\"}," - "[\"array\",\"within\",\"an\",\"array\"]]")}, - attr{"empty_array", mapnik::value_unicode_string("[]")}, - attr{"empty_object", mapnik::value_unicode_string("{}")}, + attr{"object", mapnik::value_unicode_string(u8"{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + u8",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + u8",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", mapnik::value_unicode_string(u8"this has spaces")}, + attr{"array", mapnik::value_unicode_string(u8"[\"string\",\"value with spaces\",3,1.1,null,true," + u8"\"Québec\",{name:\"object within an array\"}," + u8"[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", mapnik::value_unicode_string(u8"[]")}, + attr{"empty_object", mapnik::value_unicode_string(u8"{}")}, }; auto feature = fs->next(); REQUIRE(bool(feature)); diff --git a/test/unit/datasource/topojson.cpp b/test/unit/datasource/topojson.cpp index 0e1becda0..c0ada73aa 100644 --- a/test/unit/datasource/topojson.cpp +++ b/test/unit/datasource/topojson.cpp @@ -91,21 +91,21 @@ TEST_CASE("topology") CHECK(feature); CHECK(feature->envelope() == bbox); std::initializer_list attrs = { - attr{"name", mapnik::value_unicode_string("Test")}, - attr{"NOM_FR", mapnik::value_unicode_string("Québec")}, + attr{"name", mapnik::value_unicode_string(u8"Test")}, + attr{"NOM_FR", mapnik::value_unicode_string(u8"Québec")}, attr{"boolean", mapnik::value_bool("true")}, - attr{"description", mapnik::value_unicode_string("Test: \u005C")}, + attr{"description", mapnik::value_unicode_string(u8"Test: \u005C")}, attr{"double", mapnik::value_double(1.1)}, attr{"int", mapnik::value_integer(1)}, - attr{"object", mapnik::value_unicode_string("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" - ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" - ",\"Québec\"],another_object:{name:\"nested object\"}}")}, - attr{"spaces", mapnik::value_unicode_string("this has spaces")}, - attr{"array", mapnik::value_unicode_string("[\"string\",\"value with spaces\",3,1.1,null,true," - "\"Québec\",{name:\"object within an array\"}," - "[\"array\",\"within\",\"an\",\"array\"]]")}, - attr{"empty_array", mapnik::value_unicode_string("[]")}, - attr{"empty_object", mapnik::value_unicode_string("{}")}, + attr{"object", mapnik::value_unicode_string(u8"{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + u8",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + u8",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", mapnik::value_unicode_string(u8"this has spaces")}, + attr{"array", mapnik::value_unicode_string(u8"[\"string\",\"value with spaces\",3,1.1,null,true," + u8"\"Québec\",{name:\"object within an array\"}," + u8"[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", mapnik::value_unicode_string(u8"[]")}, + attr{"empty_object", mapnik::value_unicode_string(u8"{}")}, }; REQUIRE_ATTRIBUTES(feature, attrs); } From 37a8aed62db4b51384e11d61e2aa7823f8590b81 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 24 May 2016 12:16:48 +0200 Subject: [PATCH 62/98] transcode input strings to UTF-8 (portability) --- test/unit/datasource/geojson.cpp | 28 +++++++++++++++------------- test/unit/datasource/topojson.cpp | 26 +++++++++++++------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index efbdd063b..1edeb4b55 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -23,6 +23,7 @@ #include "catch.hpp" #include "ds_test_util.hpp" +#include #include #include #include @@ -657,6 +658,7 @@ TEST_CASE("geojson") { SECTION("GeoJSON properties are properly expressed") { + mapnik::transcoder tr("utf8"); mapnik::parameters params; params["type"] = "geojson"; @@ -693,21 +695,21 @@ TEST_CASE("geojson") { auto fs = all_features(ds); REQUIRE(bool(fs)); std::initializer_list attrs = { - attr{"name", mapnik::value_unicode_string(u8"Test")}, - attr{"NOM_FR", mapnik::value_unicode_string(u8"Québec")}, - attr{"boolean", mapnik::value_bool(u8"true")}, - attr{"description", mapnik::value_unicode_string(u8"Test: \u005C")}, + attr{"name", tr.transcode("Test")}, + attr{"NOM_FR", tr.transcode("Québec")}, + attr{"boolean", mapnik::value_bool("true")}, + attr{"description", tr.transcode("Test: \u005C")}, attr{"double", mapnik::value_double(1.1)}, attr{"int", mapnik::value_integer(1)}, - attr{"object", mapnik::value_unicode_string(u8"{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" - u8",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" - u8",\"Québec\"],another_object:{name:\"nested object\"}}")}, - attr{"spaces", mapnik::value_unicode_string(u8"this has spaces")}, - attr{"array", mapnik::value_unicode_string(u8"[\"string\",\"value with spaces\",3,1.1,null,true," - u8"\"Québec\",{name:\"object within an array\"}," - u8"[\"array\",\"within\",\"an\",\"array\"]]")}, - attr{"empty_array", mapnik::value_unicode_string(u8"[]")}, - attr{"empty_object", mapnik::value_unicode_string(u8"{}")}, + attr{"object", tr.transcode("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", tr.transcode("this has spaces")}, + attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{name:\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", tr.transcode("[]")}, + attr{"empty_object", tr.transcode("{}")}, }; auto feature = fs->next(); REQUIRE(bool(feature)); diff --git a/test/unit/datasource/topojson.cpp b/test/unit/datasource/topojson.cpp index c0ada73aa..6b1a2e1b1 100644 --- a/test/unit/datasource/topojson.cpp +++ b/test/unit/datasource/topojson.cpp @@ -51,7 +51,7 @@ bool parse_topology(std::string const& filename, mapnik::topojson::topology & to } -TEST_CASE("topology") +TEST_CASE("topojson") { SECTION("geometry parsing") { @@ -91,21 +91,21 @@ TEST_CASE("topology") CHECK(feature); CHECK(feature->envelope() == bbox); std::initializer_list attrs = { - attr{"name", mapnik::value_unicode_string(u8"Test")}, - attr{"NOM_FR", mapnik::value_unicode_string(u8"Québec")}, + attr{"name", tr.transcode("Test")}, + attr{"NOM_FR", tr.transcode("Québec")}, attr{"boolean", mapnik::value_bool("true")}, - attr{"description", mapnik::value_unicode_string(u8"Test: \u005C")}, + attr{"description", tr.transcode("Test: \u005C")}, attr{"double", mapnik::value_double(1.1)}, attr{"int", mapnik::value_integer(1)}, - attr{"object", mapnik::value_unicode_string(u8"{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" - u8",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" - u8",\"Québec\"],another_object:{name:\"nested object\"}}")}, - attr{"spaces", mapnik::value_unicode_string(u8"this has spaces")}, - attr{"array", mapnik::value_unicode_string(u8"[\"string\",\"value with spaces\",3,1.1,null,true," - u8"\"Québec\",{name:\"object within an array\"}," - u8"[\"array\",\"within\",\"an\",\"array\"]]")}, - attr{"empty_array", mapnik::value_unicode_string(u8"[]")}, - attr{"empty_object", mapnik::value_unicode_string(u8"{}")}, + attr{"object", tr.transcode("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", tr.transcode("this has spaces")}, + attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{name:\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", tr.transcode("[]")}, + attr{"empty_object", tr.transcode("{}")}, }; REQUIRE_ATTRIBUTES(feature, attrs); } From 8af87372727aee24cdb10adaa3a3cc478dd79b0a Mon Sep 17 00:00:00 2001 From: Frederik Ramm Date: Wed, 25 May 2016 10:12:53 +0200 Subject: [PATCH 63/98] Fix DejaVu font directory Fonts in Mapnik tree are now 2.35 not 2.34 --- demo/c++/rundemo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index c07bd5c31..c30170694 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -55,7 +55,7 @@ int main ( int, char** ) try { std::cout << " running demo ... \n"; datasource_cache::instance().register_datasources("plugins/input/"); - freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.34/ttf/DejaVuSans.ttf"); + freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf"); Map m(800,600); m.set_background(parse_color("white")); From cf604518a52d8f2c8dcd57213dbe006dca4432ca Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 25 May 2016 13:08:20 +0200 Subject: [PATCH 64/98] fix typo --- test/visual/run.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/visual/run.cpp b/test/visual/run.cpp index 9b6ae879f..587727906 100644 --- a/test/visual/run.cpp +++ b/test/visual/run.cpp @@ -210,7 +210,7 @@ int main(int argc, char** argv) } catch (std::exception & e) { - std::cerr << "Error runnig tests: " << e.what() << std::endl; + std::cerr << "Error running tests: " << e.what() << std::endl; return 1; } From 2fb032689286d3bd3ae7b7e9a60a6b8b7b725159 Mon Sep 17 00:00:00 2001 From: Wilhelm Berg Date: Wed, 25 May 2016 13:53:23 +0200 Subject: [PATCH 65/98] Update appveyor.yml to use boost 1.60 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f2360211b..34ddc3b6a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ environment: msvs_toolset: 14 - BOOST_VERSION: 59 + BOOST_VERSION: 60 FASTBUILD: 1 matrix: - platform: x64 From 081c003b0eacded0480b5be4d400660a55b42658 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 26 May 2016 11:36:55 +0200 Subject: [PATCH 66/98] c++ style --- src/proj_transform.cpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 1bc806188..833efd90f 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -200,20 +200,21 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co #ifdef MAPNIK_USE_PROJ4 if (is_dest_longlat_) { - int i; - for(i=0; i & ls) const double * x = reinterpret_cast(ptr); double * y = x + 1; double * z = nullptr; - if(!backward(x, y, z, size, 2)) + if (!backward(x, y, z, size, 2)) { return size; } @@ -333,10 +334,7 @@ bool proj_transform::backward (box2d & box) const double miny = std::min(lly, lry); double maxx = std::max(urx, lrx); double maxy = std::max(ury, uly); - box.init(minx, - miny, - maxx, - maxy); + box.init(minx, miny, maxx, maxy); return true; } From a24dfbf6a0539a05566e92470ac4fb251cce322c Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 26 May 2016 16:26:04 +0200 Subject: [PATCH 67/98] simplify logic a bit --- src/proj_transform.cpp | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 833efd90f..9c23d805a 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -313,27 +313,23 @@ bool proj_transform::backward (box2d & box) const if (is_source_equal_dest_) return true; - double llx = box.minx(); - double ulx = box.minx(); - double lly = box.miny(); - double lry = box.miny(); - double lrx = box.maxx(); - double urx = box.maxx(); - double uly = box.maxy(); - double ury = box.maxy(); - double z = 0.0; - if (!backward(llx,lly,z)) + double x[4], y[4]; + x[0] = box.minx(); // llx 0 + y[0] = box.miny(); // lly 1 + x[1] = box.maxx(); // lrx 2 + y[1] = box.miny(); // lry 3 + x[2] = box.minx(); // ulx 4 + y[2] = box.maxy(); // uly 5 + x[3] = box.maxx(); // urx 6 + y[3] = box.maxy(); // ury 7 + + if (!backward(x, y, nullptr, 4, 1)) return false; - if (!backward(lrx,lry,z)) - return false; - if (!backward(ulx,uly,z)) - return false; - if (!backward(urx,ury,z)) - return false; - double minx = std::min(ulx, llx); - double miny = std::min(lly, lry); - double maxx = std::max(urx, lrx); - double maxy = std::max(ury, uly); + + double minx = std::min(x[0], x[2]); + double miny = std::min(y[0], y[1]); + double maxx = std::max(x[1], x[3]); + double maxy = std::max(y[2], y[3]); box.init(minx, miny, maxx, maxy); return true; } @@ -423,7 +419,6 @@ bool proj_transform::backward(box2d& env, int points) const env.re_center(result.center().x, result.center().y); env.height(result.height()); env.width(result.width()); - return true; } From ddd61c55ff78c7eb15a01562fb7615bd1f22912a Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 26 May 2016 17:12:18 +0200 Subject: [PATCH 68/98] fix LGPL link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b677c84e..b58be712a 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,4 @@ Please note that this project is released with a [Contributor Code of Conduct](h # License -Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information. +Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information. From efdc90f69935580ee509429f5423fb6cb7f1dc8d Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 26 May 2016 17:22:18 +0200 Subject: [PATCH 69/98] fix building with BIGINT=no (NOTE: some tests will fail) --- src/xml_tree.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index e342e6861..b14b8e4e0 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -72,8 +72,6 @@ DEFINE_NAME_TRAIT( int, "int") DEFINE_NAME_TRAIT( boolean_type, "boolean_type") #ifdef BIGINT DEFINE_NAME_TRAIT( mapnik::value_integer, "long long" ) -#else -DEFINE_NAME_TRAIT( mapnik::value_integer, "int" ) #endif DEFINE_NAME_TRAIT( std::string, "string" ) DEFINE_NAME_TRAIT( color, "color" ) @@ -416,7 +414,9 @@ compile_get_opt_attr(boolean_type); compile_get_opt_attr(std::string); compile_get_opt_attr(int); compile_get_opt_attr(unsigned); +#ifdef BIGINT compile_get_opt_attr(mapnik::value_integer); +#endif compile_get_opt_attr(float); compile_get_opt_attr(double); compile_get_opt_attr(color); From 503d4eaea1ad6482c864b3c2cea4799b580f6638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Larra=C3=ADn?= Date: Tue, 31 May 2016 12:40:27 -0300 Subject: [PATCH 70/98] fix shapefiles encoding in demo for C++ Mapnik builds without `boost_regex_icu` (see #3440) and the C++ demo does not run: ``` /mapnik# demo/c++/rundemo `mapnik-config --prefix` running demo ... ### std::exception: could not create converter for latin1 ``` --- demo/c++/rundemo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index c30170694..c20c288cf 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -230,7 +230,7 @@ int main ( int, char** ) parameters p; p["type"]="shape"; p["file"]="demo/data/boundaries"; - p["encoding"]="latin1"; + p["encoding"]="utf8"; layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance().create(p)); @@ -295,7 +295,7 @@ int main ( int, char** ) parameters p; p["type"]="shape"; p["file"]="demo/data/popplaces"; - p["encoding"] = "latin1"; + p["encoding"] = "utf8"; layer lyr("Populated Places"); lyr.set_srs(srs_lcc); lyr.set_datasource(datasource_cache::instance().create(p)); From a876070ccbea81d88467385a4b92b905beb6eb15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Larra=C3=ADn?= Date: Tue, 31 May 2016 13:14:27 -0300 Subject: [PATCH 71/98] Fix markdown issue in C++ demo README Commands were rendered incorrectly due to missing spaces, causing that `mapnik-config --prefix` was rendered without backticks, which are necessary. --- demo/c++/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/c++/README.md b/demo/c++/README.md index daa4198c1..548508ee0 100644 --- a/demo/c++/README.md +++ b/demo/c++/README.md @@ -52,11 +52,11 @@ If you do not have svn installed you can grab gyp from: Simply type: - make + make Then to run do: - ./rundemo `mapnik-config --prefix` + ./rundemo `mapnik-config --prefix` On OS X you can also create an xcode project: From 2f9c2a3a9b8909ec3c81e834e259f51bb56a2c84 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 2 Jun 2016 11:33:43 +0200 Subject: [PATCH 72/98] update variant submodule --- deps/mapbox/variant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 7f7470fee..372d7c88f 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 7f7470fee6a42c3c68f1fa359a28cf762df385c3 +Subproject commit 372d7c88fe796a138d0e578328914ac80e5a949a From d30143c60fdc1ba918c3ad1c7546f3cd7ed937ca Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 2 Jun 2016 16:04:18 +0200 Subject: [PATCH 73/98] remove unsupported ESRI data files --- demo/data/boundaries.prj | 1 - demo/data/boundaries.sbx | Bin 116 -> 0 bytes demo/data/boundaries_l.prj | 1 - demo/data/boundaries_l.sbx | Bin 132 -> 0 bytes demo/data/ontdrainage.prj | 1 - demo/data/ontdrainage.sbx | Bin 644 -> 0 bytes demo/data/popplaces.prj | 1 - demo/data/popplaces.sbx | Bin 268 -> 0 bytes demo/data/qcdrainage.prj | 1 - demo/data/qcdrainage.sbx | Bin 644 -> 0 bytes demo/data/roads.prj | 1 - demo/data/roads.sbx | Bin 2060 -> 0 bytes 12 files changed, 6 deletions(-) delete mode 100644 demo/data/boundaries.prj delete mode 100644 demo/data/boundaries.sbx delete mode 100644 demo/data/boundaries_l.prj delete mode 100644 demo/data/boundaries_l.sbx delete mode 100644 demo/data/ontdrainage.prj delete mode 100644 demo/data/ontdrainage.sbx delete mode 100644 demo/data/popplaces.prj delete mode 100644 demo/data/popplaces.sbx delete mode 100644 demo/data/qcdrainage.prj delete mode 100644 demo/data/qcdrainage.sbx delete mode 100644 demo/data/roads.prj delete mode 100644 demo/data/roads.sbx diff --git a/demo/data/boundaries.prj b/demo/data/boundaries.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/boundaries.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/boundaries.sbx b/demo/data/boundaries.sbx deleted file mode 100644 index c66e6e334826fead06c391416ef00853d50f6d14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116 zcmZQzQ0Myp|6c(ECa?kuF&#L%vM=)PbWU(|I@J?)&$!3YQv0t<Ds+5i9m diff --git a/demo/data/boundaries_l.prj b/demo/data/boundaries_l.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/boundaries_l.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/boundaries_l.sbx b/demo/data/boundaries_l.sbx deleted file mode 100644 index e609d80c532a4a5ebdd0a8ac478315907accb75c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmZQzQ0Myp|6c(ECU61@2|60Tw4ML|spmoQZ{>F?*Y!HuNGU8h*0u7$Pif8*{%1uo awP6)80*dkgG002~Aoc@d0U%BSVjTc+z7@s* diff --git a/demo/data/ontdrainage.prj b/demo/data/ontdrainage.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/ontdrainage.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/ontdrainage.sbx b/demo/data/ontdrainage.sbx deleted file mode 100644 index 3739c6198c1be4aef5533db130f86ab3611a26a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmZ|LPbkB27{~Ev_Wf-$+iyZza@b)ZttBmoP;C$)qn!C%Z=rBOlMT^m>0o)ju19BA#!NCM`(d42Cd|t+;`4EMYfRt?%~y z2LrsvhcVQg4&;rR2&DdN}njN>tq>o4Orti^h z?ZCjm1d>+)(t1GJ21w@tX`nq!RX`f3pJ^IY9%OF@0|T=bkPZRTO+eZONS^}ICIE=M BCL#a; diff --git a/demo/data/qcdrainage.prj b/demo/data/qcdrainage.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/qcdrainage.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/qcdrainage.sbx b/demo/data/qcdrainage.sbx deleted file mode 100644 index c73534e785d776f071abda8d3da7af803cb9bc1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmZwEF(`y_7{~GFyzlGId#5CWB^NS7|jASX#iDJ9)tlypf#k|@IsW`iU}5_Se< zF&NY>x7Z8@bjrrye1F}4JMZ%8dEV#$JkS4q&AP)%1(!c^`3q!@r@5+oK<0Zd&R?XD-;DJ2+mJe6 zdnoQh&imR&@i?kpd$i+*i}#Ve{WDbEHR{}*^9glMbJf3Gje|O*J_wP$0?nmw;N}FH zlOoprls~~mvwH2DM%7KD?%RWpcxV<~z&TW$XQcM$f5h~?R#5W~%o+;ViQ1RGVF%JT r)c2-7)cbR@_yCUK7E%}2`Ax34glqVQ+&A%q?Aw^cLCm>$4}1RrwK7B# diff --git a/demo/data/roads.prj b/demo/data/roads.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/roads.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/roads.sbx b/demo/data/roads.sbx deleted file mode 100644 index b804cb3b29618520774d399f9bc2f674b4c584c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2060 zcmZ|NPe|W&9LMpOArqFSG5}&%gbqwrq21<}7545D5wMAY(*`$k@R{ zj1jTMkRc%Zg_OUW)pk4@K$K zKcotB>Nk8|^5h!kq?22CQ>q-rJT724F5(RC;J8%Pi9L7~c~`ZJysKKp6t3fKsd~6{ zUpePo!Y}F9^o%i%?4g!A2mqbNPp=*av6z_Od<6n zH;{Uf2Y8nhe#d>(bCEad_tcM0V;udy9q$MKLh?ipkovVJkUnc2cMaVK^=n^XR*Lza zyfOD>Js*2hK z%vxf4P-9~&&M1I$6N1_dS-532P zhcSm&!}kSr+*jeejMPhdU-Xr9ztl-?qvH=t-%|x7E;WG6opL_ zPd!2Mr#y$x2jSj%d6#|#`M*kMO84o$aK0RL9r{SSU-G0^kUrAR&mPk2;rtZ+Zm(pf zGFU+BWQs`rjPvGj0m+xS6~3`%NH~2kq z4eo>eWE04IS;yN^Bu{n{d7pJ3{(c9E%eoKd%09pxJ_{Zo`5K#$ca23nhjZckD&{zE zB6%CPkvfg;V@zu5!@s5G3=-e$e(W&*OQ_{tZV4YsuhD1OJ*mZc*hkAQek{E{z<1_v zoksG%;rhQzr~UoBbmj}r^BDTgH*w}&-t}g18F`m~j)T&h-jAKaarE3jO9k?Kp296; z9|iYyTWWLvgXnwmw5=iiwcSVRw)?&ZKSK7??zlW|U^ng~`{}4e>U3-(zhB1-9F#f> zNS)4g{6y+$K(gpV6 z^TmGNvDb@tupPaJ?-_L(XYmRCC=G==!|v}_X?PbOO7E>=D{diqMq*fven)>Jn@HY~ zePnO%FXABj`!#8_fO(umevi@RaQ6L}bcwz_@1+AQ$3vv=u_a_bWA1N8`oMXjIDiwl Hg4h28@TK4< From deb5102aacb75ecc9ea0bca6c7351bf3789ae665 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 2 Jun 2016 16:08:31 +0200 Subject: [PATCH 74/98] convert shapefiles to use UTF-8 encoding in DBF files via @glarrain ( ref https://github.com/mapnik/mapnik/pull/3441) --- demo/data/boundaries.dbf | Bin 750 -> 749 bytes demo/data/boundaries_l.dbf | Bin 972 -> 971 bytes demo/data/ontdrainage.dbf | Bin 264968 -> 264967 bytes demo/data/popplaces.dbf | Bin 93538 -> 93537 bytes demo/data/qcdrainage.dbf | Bin 219468 -> 219467 bytes demo/data/roads.dbf | Bin 1127356 -> 1127355 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/demo/data/boundaries.dbf b/demo/data/boundaries.dbf index aeed23561ddcf71dfc6a1ebda696630270444b47..04d2ed661e81020f2f392c4643eeadad7d2ee29a 100644 GIT binary patch delta 122 zcmaFI`j%CWxrB|0iGhKEk?|XlL0xAOljl~%e delta 126 zcmaFM`i@nOIg5priGhKEk?|XlL<8X)<*XT5UM8g`PZnf!o2gsqJxccYncIErUU-~ delta 41 hcmX@jeuiC+Ig5o=kb!}Lkx>gsqJi*@a%-6xr2uB&1ZV&N diff --git a/demo/data/ontdrainage.dbf b/demo/data/ontdrainage.dbf index 33d8004b6565373c8132f09ddb08dab240c528f2..8192650278e81db402f6e703b47c6e8198148de9 100644 GIT binary patch delta 7993 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 diff --git a/demo/data/popplaces.dbf b/demo/data/popplaces.dbf index 408968e8510ef36ea1b6ba46d6b213c7f15b8671..d385b6f1d77eddbb7b4cad833d6f8203bd304396 100644 GIT binary patch delta 2750 zcmZ`*YfPI}80M4$Efgq}Yq(g(Z6KGnFxn1AsU7Knwp>JDz=R4-X;$bgY>CN?w_o@} zF0a{1mbhfPB@}0jvP7L`EH=()7X2~*$PWk0aLyka%g9C)7r(FNoYSu@O_RRudEV!J z-phHv-d&5^Sc@x+orxFSh>3~0h&B=T5%&6`@Fyhl`@o*G3BQP*@0s{fGKz<9#N8== zpK{!xJZ1NKT+`DISV(CATilocb|HR;FuW=0PY!yVak<@grvo-5=gDE}KtgOE7wTl9 z9xf+lL;$t$Um{@!v#g)@dyEu#z6RCeSqf{_kR+S<+haXdjYfyW(oQisy7AZ;x zi|McJaRnVV6x88HCaD8l&W`3goMnX%ax#gQ_j4)UlNX795Bl=63AVR@V)ZW&GpL}X zs5_!2I_Qk+fVcz1KZukTQ?023Qg~cq+sE3tTNH82IuaQ3SY> znrEws8Hk?H?)Q29S0`a1w*fBIe7l#Kq|58~o$*Z1aO{mRt0KP#6{|IoxoKgyMgj69 zJ*3xB3G({L0%~EtAs};H^#)Kfsq58K@%dp5>O>@O$s8#!M~-_IAX$Ey(mh@yJ-w`K|w(YR?pN7H=VdE7d7FV znG7_MO+nb2%WO>^wSmh77Z#vrqzt=-^bBt(nSJwspgjCww&N?sETKxnt zL$v@Ccr21#gKyU{;Ma$k{gIa0@9L?|*EQC}HRV(z(&Obu))dPT3c_jwv$Kp*Q$1%w zR{Y$E$ZE#_zO)~XYF$4{X(fFQ@7RQY$%|1Rs$CSxu*8f)7g#MGH6!Y|e2jYHx%Q}m zDmxf_#=_wIpBg-3LxR=8lUuQ|lgV%H3M+B|QP#~60iueYFrw={EUctAjN_ADb{KGf z@(SA7YjI%0fA41#{?&0Rnm-d8$Nfui(Wb}iLx`+l{LTqMh_l%BYM4Uz2n~Td?35C# z#+aSyU^cHyV&?9t)8q0&TCondIFVH3U&ifDln1NET6k2D56W#7-f*I9GN5-RqI4m! nw($=xHs2gOzfPPke%s=NlWg96?m#9OO(F&Sd|riHCsF?Y`b2DL delta 2442 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�F$B4 z!L}S0OGj9HPS2=t@^*-q6RO!uIg7h^L=14cTQHz9eISG2Ww7J>FuqxCo<9A~-{a%Y zyyTu>_1%D9mEO(3(^b delta 26422 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 JzYYn>@_&;gBs>5B From 7ca86b094745d72a8f36f73749e6f53af808b63b Mon Sep 17 00:00:00 2001 From: Joris Valette Date: Fri, 3 Jun 2016 11:08:45 +0200 Subject: [PATCH 75/98] Fix stroke-width size not included in markers ellipse bounding box --- src/marker_helpers.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/marker_helpers.cpp b/src/marker_helpers.cpp index dc9f67980..eb0202169 100644 --- a/src/marker_helpers.cpp +++ b/src/marker_helpers.cpp @@ -37,6 +37,7 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a { double width = 0.0; double height = 0.0; + double half_stroke_width = 0.0; if (has_key(sym,keys::width) && has_key(sym,keys::height)) { width = get(sym, keys::width, feature, vars, 0.0); @@ -50,6 +51,10 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a { width = height = get(sym, keys::height, feature, vars, 0.0); } + if (has_key(sym,keys::stroke_width)) + { + half_stroke_width = get(sym, keys::stroke_width, feature, vars, 0.0) / 2.0; + } svg::svg_converter_type styled_svg(svg_path, marker_ellipse.attributes()); styled_svg.push_attr(); styled_svg.begin_path(); @@ -59,6 +64,10 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a styled_svg.pop_attr(); double lox,loy,hix,hiy; styled_svg.bounding_rect(&lox, &loy, &hix, &hiy); + lox -= half_stroke_width; + loy -= half_stroke_width; + hix += half_stroke_width; + hiy += half_stroke_width; styled_svg.set_dimensions(width,height); marker_ellipse.set_dimensions(width,height); marker_ellipse.set_bounding_box(lox,loy,hix,hiy); From beb34f9c5e974147c3e5c0cbbf5701212d3b8c29 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 3 Jun 2016 14:45:49 +0200 Subject: [PATCH 76/98] topojson_grammar - rename properties to properties_ to avoid compilation error (gcc) ref #3446 --- include/mapnik/json/topojson_grammar.hpp | 2 +- include/mapnik/json/topojson_grammar_impl.hpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index 77c58c26a..c21be95fe 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -197,7 +197,7 @@ private: qi::rule>()> rings; qi::rule rings_array; // properties - qi::rule properties; + qi::rule properties_; qi::symbols geometry_type_dispatch; }; diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 00ae2e3cd..f868cefc4 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -171,7 +171,7 @@ topojson_grammar::topojson_grammar() | (lit("\"arcs\"") > lit(':') > rings_array[_c = _1]) | - properties[_d = _1] + properties_[_d = _1] | json.key_value) % lit(',') > lit('}')[_val = create_geometry(_a, _b, _c, _d)] @@ -198,7 +198,7 @@ topojson_grammar::topojson_grammar() ring ; - properties = lit("\"properties\"") + properties_ = lit("\"properties\"") >> lit(':') >> lit('{') >> (json.string_ >> lit(':') >> json.value) % lit(',') >> lit('}') ; @@ -221,6 +221,7 @@ topojson_grammar::topojson_grammar() json.value.name("value"); coordinate_.name("coordinate"); geometry.name("geometry"); + properties_.name("properties"); geometry_collection.name("geometry_collection"); // error handler on_error(topology, error_handler(_1, _2, _3, _4)); From 9f3b76fb94e9291adfaea9da25e0d558108202a5 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 6 Jun 2016 11:29:33 +0200 Subject: [PATCH 77/98] update visual data (ref https://github.com/mapnik/mapnik/pull/3445) --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index f69cc73e7..793f014c6 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit f69cc73e765ed6ac241e8c3d64ab1f4c790086e3 +Subproject commit 793f014c6fbe9ba0e034c831a11bb75122833e66 From 1509426088ce2bd1125d6e82a429ab3fe9290157 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 7 Jun 2016 14:02:04 +0200 Subject: [PATCH 78/98] update test data (https://github.com/mapnik/mapnik/pull/3430) --- test/data | 2 +- test/data-visual | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/data b/test/data index 6fc383e0e..e74f1cef0 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 6fc383e0e12ce01171b676901c8f8754c1714a1b +Subproject commit e74f1cef09d579d6ff414cb56970adbe43b7a91b diff --git a/test/data-visual b/test/data-visual index 793f014c6..047985797 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 793f014c6fbe9ba0e034c831a11bb75122833e66 +Subproject commit 047985797ab11ea34ac97e469d0871b6220ea4d3 From 18aa50a59eceb6bceb9befb15219b2b970dc53b9 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 7 Jun 2016 14:19:22 +0200 Subject: [PATCH 79/98] update variant --- deps/mapbox/variant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 372d7c88f..b5728ad76 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 372d7c88fe796a138d0e578328914ac80e5a949a +Subproject commit b5728ad76e1402c130a9330aa44b6f4b655b13b4 From 9e3ccf662997b864aed9e6102598ebab92d7fe57 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 8 Jun 2016 12:21:27 +0200 Subject: [PATCH 80/98] Issue a warning but don't fail if PostgreSQL is not running or it's not accessible (ref #3448) --- test/unit/datasource/postgis.cpp | 497 ++++++++++++++++--------------- 1 file changed, 264 insertions(+), 233 deletions(-) diff --git a/test/unit/datasource/postgis.cpp b/test/unit/datasource/postgis.cpp index 268995216..b8d01cabd 100644 --- a/test/unit/datasource/postgis.cpp +++ b/test/unit/datasource/postgis.cpp @@ -29,12 +29,14 @@ #include /* -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 + 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 */ #include +namespace { + int run(std::string const& command, bool okay_to_fail = false) { std::string cmd; @@ -61,251 +63,280 @@ int run(std::string const& command, bool okay_to_fail = false) return worked; } -std::string dbname("mapnik-tmp-postgis-test-db"); + +std::string const dbname("mapnik-tmp-postgis-test-db"); +bool status = false; + +bool ping_postmaster() +{ + return (run("psql --version") + && run("dropdb --if-exists " + dbname) + && run("createdb -T template_postgis " + dbname)); +} + +} + + TEST_CASE("postgis") { - SECTION("Postgis data initialization") + SECTION("Ping Postmaster (check if server is runnging and accessible") { - //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)); + if (!ping_postmaster()) + { + WARN("Can't run postgis.input tests - check postmaster is running and accessible"); + return; + } + else + { + status = true; + } } - - mapnik::parameters base_params; - base_params["type"] = "postgis"; - base_params["dbname"] = dbname; - - SECTION("Postgis should throw without 'table' parameter") + if (status) { - mapnik::parameters params(base_params); - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - params["table"] = "does_not_exist"; - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw with invalid key field") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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") - { - mapnik::parameters params(base_params); - 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()); + SECTION("Postgis data initialization") + { + //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)); } - 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()); - } + mapnik::parameters base_params; + base_params["type"] = "postgis"; + base_params["dbname"] = dbname; - SECTION("Postgis cursorresultest") - { - mapnik::parameters params(base_params); - 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); + SECTION("Postgis should throw without 'table' parameter") + { + mapnik::parameters params(base_params); + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); } - 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 should throw with 'max_async_connection' greater than 'max_size'") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["max_async_connection"] = "2"; + params["max_size"] = "1"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } - SECTION("Postgis bbox query") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d 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 should throw with invalid metadata query") + { + mapnik::parameters params(base_params); + params["table"] = "does_not_exist"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } - SECTION("Postgis query extent: full dataset") - { - //include schema to increase coverage - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM public.test) as data"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d 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 should throw with invalid key field") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + 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") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d 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 + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM public.test) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d 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") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM test where gid=4) as data"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d 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") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test where gid=4) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d 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'") - { - mapnik::parameters params(base_params); - 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 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'") + { + mapnik::parameters params(base_params); + 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 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'") - { - mapnik::parameters params(base_params); - // !!!! 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 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: subset with 'extent_from_subquery=true' and 'scale_denominator'") + { + mapnik::parameters params(base_params); + // !!!! 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 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); + } */ -} \ No newline at end of file + + } +} From 37d5a328754cddc94bf30f2950c0951fe4c00559 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 8 Jun 2016 12:24:21 +0200 Subject: [PATCH 81/98] make return type `bool` --- test/unit/datasource/postgis.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/unit/datasource/postgis.cpp b/test/unit/datasource/postgis.cpp index b8d01cabd..95ee65851 100644 --- a/test/unit/datasource/postgis.cpp +++ b/test/unit/datasource/postgis.cpp @@ -37,7 +37,7 @@ namespace { -int run(std::string const& command, bool okay_to_fail = false) +bool run(std::string const& command, bool okay_to_fail = false) { std::string cmd; if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) @@ -76,8 +76,6 @@ bool ping_postmaster() } - - TEST_CASE("postgis") { SECTION("Ping Postmaster (check if server is runnging and accessible") From 7e6cc4cfac7291598dd29270c3c17da305601be7 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 13 Jun 2016 11:14:59 +0200 Subject: [PATCH 82/98] make `get_overview_meta(band)` standalone method --- plugins/input/gdal/gdal_featureset.cpp | 68 +++++++++++++------------- plugins/input/gdal/gdal_featureset.hpp | 5 -- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 4b1186193..1377322e3 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -44,6 +44,41 @@ using mapnik::view_transform; using mapnik::datasource_exception; using mapnik::feature_factory; +#ifdef MAPNIK_LOG +namespace { + +void get_overview_meta(GDALRasterBand* band) +{ + int band_overviews = band->GetOverviewCount(); + if (band_overviews > 0) + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: " << band_overviews << " overviews found!"; + + for (int b = 0; b < band_overviews; b++) + { + GDALRasterBand * overview = band->GetOverview(b); + MAPNIK_LOG_DEBUG(gdal) << "Overview= " << b + << " Width=" << overview->GetXSize() + << " Height=" << overview->GetYSize(); + } + } + else + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No overviews found!"; + } + + int bsx,bsy; + double scale; + band->GetBlockSize(&bsx, &bsy); + scale = band->GetScale(); + + MAPNIK_LOG_DEBUG(gdal) << "Block=" << bsx << "x" << bsy + << " Scale=" << scale + << " Type=" << GDALGetDataTypeName(band->GetRasterDataType()) + << "Color=" << GDALGetColorInterpretationName(band->GetColorInterpretation()); +} +} // anonymous ns +#endif gdal_featureset::gdal_featureset(GDALDataset& dataset, int band, gdal_query q, @@ -646,36 +681,3 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) } return feature_ptr(); } - -#ifdef MAPNIK_LOG -void gdal_featureset::get_overview_meta(GDALRasterBand* band) -{ - int band_overviews = band->GetOverviewCount(); - if (band_overviews > 0) - { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: " << band_overviews << " overviews found!"; - - for (int b = 0; b < band_overviews; b++) - { - GDALRasterBand * overview = band->GetOverview(b); - MAPNIK_LOG_DEBUG(gdal) << "Overview= " << b - << " Width=" << overview->GetXSize() - << " Height=" << overview->GetYSize(); - } - } - else - { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No overviews found!"; - } - - int bsx,bsy; - double scale; - band->GetBlockSize(&bsx, &bsy); - scale = band->GetScale(); - - MAPNIK_LOG_DEBUG(gdal) << "Block=" << bsx << "x" << bsy - << " Scale=" << scale - << " Type=" << GDALGetDataTypeName(band->GetRasterDataType()) - << "Color=" << GDALGetColorInterpretationName(band->GetColorInterpretation()); -} -#endif diff --git a/plugins/input/gdal/gdal_featureset.hpp b/plugins/input/gdal/gdal_featureset.hpp index 639028b65..f2f66f796 100644 --- a/plugins/input/gdal/gdal_featureset.hpp +++ b/plugins/input/gdal/gdal_featureset.hpp @@ -73,11 +73,6 @@ public: private: mapnik::feature_ptr get_feature(mapnik::query const& q); mapnik::feature_ptr get_feature_at_point(mapnik::coord2d const& p); - -#ifdef MAPNIK_LOG - void get_overview_meta(GDALRasterBand * band); -#endif - GDALDataset & dataset_; mapnik::context_ptr ctx_; int band_; From 13c48788dbb0fb6ffdde53729643ce6473369be0 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 13 Jun 2016 17:36:37 +0200 Subject: [PATCH 83/98] update .travis.yml to use `clang-3.8` (https://github.com/mapbox/mason/pull/179) --- .travis.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7548c7c8f..c282a2536 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,19 +25,19 @@ matrix: - os: linux sudo: false compiler: ": clang" - env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.5 -Qunused-arguments" _CC="clang-3.5" TRIGGER=true + env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" TRIGGER=true addons: - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] - packages: [ 'clang-3.5' ] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6'] - os: linux sudo: false compiler: ": clang-coverage" - env: JOBS=8 COVERAGE=true LLVM_VERSION="3.5" _CXX="ccache clang++-3.5 -Qunused-arguments" _CC="clang-3.5" + env: JOBS=8 COVERAGE=true LLVM_VERSION="3.8" _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" addons: - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] - packages: [ 'clang-3.5', 'llvm-3.5-dev' ] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6','libstdc++-5-dev' ] - os: osx compiler: ": clang-osx" # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions @@ -58,6 +58,9 @@ before_install: - git_submodule_update --init --depth=10 install: + - ./.mason/mason install clang 3.8.0 + - export PATH=$(./.mason/mason prefix clang 3.8.0)/bin:${PATH} + - which clang++ - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then export CCACHE_READONLY=1; fi - on 'linux' export PYTHONPATH=${PYTHONUSERBASE}/lib/python2.7/site-packages - on 'osx' export PYTHONPATH=${PYTHONUSERBASE}/lib/python/site-packages From 2ef3ae47f6e91200699275de832a53b8e16059f7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 13 Jun 2016 10:51:12 -0700 Subject: [PATCH 84/98] use clang 3.8 from mason --- circle.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/circle.yml b/circle.yml index e7c12d7cf..83a5218a0 100644 --- a/circle.yml +++ b/circle.yml @@ -7,7 +7,7 @@ machine: JOBS: 8 CCACHE_TEMPDIR: /tmp/.ccache-temp CCACHE_COMPRESS: 1 - LLVM_VERSION: 3.7 + LLVM_VERSION: 3.8 pre: - echo "here" post: @@ -25,12 +25,9 @@ dependencies: pre: # https://discuss.circleci.com/t/add-ability-to-cache-apt-get-programs/598/3 - sudo rm -rf /var/cache/apt/archives && sudo ln -s ~/.apt-cache /var/cache/apt/archives && mkdir -p ~/.apt-cache/partial - - sudo wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - - - sudo add-apt-repository -y "deb http://llvm.org/apt/precise/ llvm-toolchain-precise-${LLVM_VERSION} main" - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - - sudo apt-get update -y override: - - sudo apt-get install clang-${LLVM_VERSION} -y + - sudo apt-get update -y post: - which clang-${LLVM_VERSION} - which clang++-${LLVM_VERSION} @@ -38,7 +35,9 @@ dependencies: database: pre: - ./bootstrap.sh - - ./configure CC="clang-${LLVM_VERSION}" CXX="$(pwd)/mason_packages/.link/bin/ccache clang++-${LLVM_VERSION} -Qunused-arguments" + - ./.mason/mason install clang ${LLVM_VERSION}.0 + - ./.mason/mason link clang ${LLVM_VERSION}.0 + - ./configure CC="$(pwd)/mason_packages/.link/bin/clang-${LLVM_VERSION}" CXX="$(pwd)/mason_packages/.link/bin/ccache $(pwd)/mason_packages/.link/bin/clang++-${LLVM_VERSION} -Qunused-arguments" - make override: - psql -c 'create database template_postgis;' From 0fa5ae51587206c1f4671094b760fb280e7af57d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 13 Jun 2016 11:40:15 -0700 Subject: [PATCH 85/98] circleci - remove unneeded lines --- circle.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/circle.yml b/circle.yml index 83a5218a0..cf3e31cb1 100644 --- a/circle.yml +++ b/circle.yml @@ -28,9 +28,6 @@ dependencies: - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test override: - sudo apt-get update -y - post: - - which clang-${LLVM_VERSION} - - which clang++-${LLVM_VERSION} database: pre: From 68d5cc34f21141636ad0b84cba188e7e34aa79cd Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 13 Jun 2016 12:21:51 -0700 Subject: [PATCH 86/98] upgrade mason to ensure clang v3.8.0 is available --- bootstrap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index e3ee8bc8f..fd877a644 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -10,7 +10,7 @@ todo - shrink icu data ' -MASON_VERSION="3e0cc5a" +MASON_VERSION="b709931" function setup_mason() { if [[ ! -d ./.mason ]]; then @@ -31,7 +31,7 @@ function install() { mason install $1 $2 mason link $1 $2 if [[ ${3:-false} != false ]]; then - LA_FILE=$(${MASON_DIR:-~/.mason}/mason prefix $1 $2)/lib/$3.la + LA_FILE=$(mason prefix $1 $2)/lib/$3.la if [[ -f ${LA_FILE} ]]; then perl -i -p -e 's:\Q$ENV{HOME}/build/mapbox/mason\E:$ENV{PWD}:g' ${LA_FILE} else From 8336e4d43ce23f5c83f4723c38d79705b6ca8873 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 13 Jun 2016 13:07:40 -0700 Subject: [PATCH 87/98] update visual tests to get new gdal tests passing - refs mapnik/mapnik#3430 --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index 047985797..5f0e6f866 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 047985797ab11ea34ac97e469d0871b6220ea4d3 +Subproject commit 5f0e6f86696a2a9a6733e42b1f400ba4ec2f8847 From f9969e7803e07164cb6d16ee4166f2215f55028b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 13 Jun 2016 13:25:00 -0700 Subject: [PATCH 88/98] Add circleci badge [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b58be712a..e99df9825 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ _/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/ ``` [![Build Status Linux](https://api.travis-ci.org/mapnik/mapnik.svg?branch=master)](http://travis-ci.org/mapnik/mapnik) +[![CircleCI](https://circleci.com/gh/mapnik/mapnik.svg?style=svg)](https://circleci.com/gh/mapnik/mapnik) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/hc9l7okdjtucfqqn?branch=master&svg=true)](https://ci.appveyor.com/project/Mapbox/mapnik) [![Coverage Status](https://coveralls.io/repos/mapnik/mapnik/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapnik/mapnik?branch=master) From 56bcc818ddae897bccdeb2c2f46adc178b679b5d Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 14 Jun 2016 12:30:11 +0200 Subject: [PATCH 89/98] update test data --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index 5f0e6f866..047985797 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 5f0e6f86696a2a9a6733e42b1f400ba4ec2f8847 +Subproject commit 047985797ab11ea34ac97e469d0871b6220ea4d3 From d47f8353a9d9cdc9797fa07c37a0f701a5b16456 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 12:00:39 -0700 Subject: [PATCH 90/98] remove tabs in .travis.yml --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index c282a2536..040ae601d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,17 +27,17 @@ matrix: compiler: ": clang" env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" TRIGGER=true addons: - apt: - sources: [ 'ubuntu-toolchain-r-test'] - packages: [ 'libstdc++6'] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6'] - os: linux sudo: false compiler: ": clang-coverage" env: JOBS=8 COVERAGE=true LLVM_VERSION="3.8" _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" addons: - apt: - sources: [ 'ubuntu-toolchain-r-test'] - packages: [ 'libstdc++6','libstdc++-5-dev' ] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6','libstdc++-5-dev' ] - os: osx compiler: ": clang-osx" # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions From 6fd4e974cf17df3c79164afb58310326dfccd59e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 12:04:45 -0700 Subject: [PATCH 91/98] [travis] install clang after mason has been installed --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 040ae601d..6b2085640 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,10 +58,6 @@ before_install: - git_submodule_update --init --depth=10 install: - - ./.mason/mason install clang 3.8.0 - - export PATH=$(./.mason/mason prefix clang 3.8.0)/bin:${PATH} - - which clang++ - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then export CCACHE_READONLY=1; fi - on 'linux' export PYTHONPATH=${PYTHONUSERBASE}/lib/python2.7/site-packages - on 'osx' export PYTHONPATH=${PYTHONUSERBASE}/lib/python/site-packages - on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres @@ -76,6 +72,9 @@ install: before_script: - source bootstrap.sh + - mason install clang 3.8.0 + - export PATH=$(mason prefix clang 3.8.0)/bin:${PATH} + - which clang++ - ccache --version - ccache -p || true - ccache --show-stats || true From 0cec24fe65cf35b4fb4b34f729d723a155fca399 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 21:08:18 -0700 Subject: [PATCH 92/98] debug configure failure on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b2085640..6c76a6f72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,7 +82,7 @@ before_script: script: - export SCONSFLAGS='--debug=time' - - configure BENCHMARK=${BENCH} + - configure BENCHMARK=${BENCH} || cat config.log - make - make test - enabled ${COVERAGE} coverage From 07f34f03de2e46d46e4beeff7ec79057e4967d88 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 21:12:42 -0700 Subject: [PATCH 93/98] scons: don't recommend now oldish compilers [skip ci] --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 694d494fb..0523e184d 100644 --- a/SConstruct +++ b/SConstruct @@ -1355,7 +1355,7 @@ if not preconfigured: # test for C++11 support, which is required if not env['HOST'] and not conf.supports_cxx11(): - color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler to at least g++ 4.7 (ideally 4.8)") + color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler") Exit(1) if not env['HOST']: From de88b47ded1af9cfd36ee673088ef464b2dec0d1 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 21:15:50 -0700 Subject: [PATCH 94/98] [travis] further debug configure failure --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6c76a6f72..86d35c1a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,7 +82,8 @@ before_script: script: - export SCONSFLAGS='--debug=time' - - configure BENCHMARK=${BENCH} || cat config.log + - configure BENCHMARK=${BENCH} + - cat config.log - make - make test - enabled ${COVERAGE} coverage From 915062c6a34873ee8daabb83948cc7883b8a33f8 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 21:25:33 -0700 Subject: [PATCH 95/98] [travis] fix apt package installs --- .travis.yml | 16 ++++++++-------- scripts/travis-common.sh | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 86d35c1a2..bcea120fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,17 +27,17 @@ matrix: compiler: ": clang" env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" TRIGGER=true addons: - apt: - sources: [ 'ubuntu-toolchain-r-test'] - packages: [ 'libstdc++6'] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6', 'libstdc++-5-dev'] - os: linux sudo: false compiler: ": clang-coverage" - env: JOBS=8 COVERAGE=true LLVM_VERSION="3.8" _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" + env: JOBS=8 COVERAGE=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" addons: - apt: - sources: [ 'ubuntu-toolchain-r-test'] - packages: [ 'libstdc++6','libstdc++-5-dev' ] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6','libstdc++-5-dev' ] - os: osx compiler: ": clang-osx" # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions @@ -86,7 +86,7 @@ script: - cat config.log - make - make test - - enabled ${COVERAGE} coverage + - enabled ${COVERAGE} export LLVM_COV="$(mason prefix clang 3.8.0)/bin/llvm-cov" && coverage - enabled ${BENCH} make bench after_success: diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh index 0899df1ce..9cee676dc 100644 --- a/scripts/travis-common.sh +++ b/scripts/travis-common.sh @@ -92,7 +92,7 @@ configure () { coverage () { ./mason_packages/.link/bin/cpp-coveralls \ - --gcov /usr/bin/llvm-cov-${LLVM_VERSION} \ + --gcov ${LLVM_COV} \ --build-root . --gcov-options '\-lp' \ --exclude mason_packages \ --exclude .sconf_temp --exclude benchmark --exclude deps \ From 8955e3b1896605b52a7c9c5b7a82768c4a2f0404 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 21:58:32 -0700 Subject: [PATCH 96/98] [travis] attempt to fix coverage --- .travis.yml | 12 ++++++++---- scripts/travis-common.sh | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index bcea120fa..967786acd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,9 +72,13 @@ install: before_script: - source bootstrap.sh - - mason install clang 3.8.0 - - export PATH=$(mason prefix clang 3.8.0)/bin:${PATH} - - which clang++ + - | + 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" + fi - ccache --version - ccache -p || true - ccache --show-stats || true @@ -86,7 +90,7 @@ script: - cat config.log - make - make test - - enabled ${COVERAGE} export LLVM_COV="$(mason prefix clang 3.8.0)/bin/llvm-cov" && coverage + - enabled ${COVERAGE} coverage - enabled ${BENCH} make bench after_success: diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh index 9cee676dc..2d4b03cc6 100644 --- a/scripts/travis-common.sh +++ b/scripts/travis-common.sh @@ -93,7 +93,7 @@ configure () { coverage () { ./mason_packages/.link/bin/cpp-coveralls \ --gcov ${LLVM_COV} \ - --build-root . --gcov-options '\-lp' \ + --build-root . \ --exclude mason_packages \ --exclude .sconf_temp --exclude benchmark --exclude deps \ --exclude scons --exclude test --exclude demo --exclude docs \ From b9e72964608a42c817ef9a58e857d3e33986aa77 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 22:02:53 -0700 Subject: [PATCH 97/98] update to latest visual test data --- test/data-visual | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data-visual b/test/data-visual index 047985797..5f0e6f866 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 047985797ab11ea34ac97e469d0871b6220ea4d3 +Subproject commit 5f0e6f86696a2a9a6733e42b1f400ba4ec2f8847 From b17dae8381d482aadfa64ebd462bb45498584664 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 14 Jun 2016 22:26:17 -0700 Subject: [PATCH 98/98] [travis][coverage] llvm-3.8 does not support --object-directory option --- scripts/travis-common.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh index 2d4b03cc6..40d18374e 100644 --- a/scripts/travis-common.sh +++ b/scripts/travis-common.sh @@ -93,7 +93,6 @@ configure () { coverage () { ./mason_packages/.link/bin/cpp-coveralls \ --gcov ${LLVM_COV} \ - --build-root . \ --exclude mason_packages \ --exclude .sconf_temp --exclude benchmark --exclude deps \ --exclude scons --exclude test --exclude demo --exclude docs \