diff --git a/.travis.yml b/.travis.yml index b0b3090be..f5a8d2981 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,7 @@ before_install: - export COVERAGE=${COVERAGE:-false} - export MASON_PUBLISH=${MASON_PUBLISH:-false} - if [[ ${TRAVIS_BRANCH} != 'master' ]]; then export MASON_PUBLISH=false; fi + - if [[ ${TRAVIS_PULL_REQUEST} != 'false' ]]; then export MASON_PUBLISH=false; fi install: - if [[ $(uname -s) == 'Linux' ]]; then diff --git a/deps/agg/include/agg_color_gray.h b/deps/agg/include/agg_color_gray.h index 2fc01bd71..f2cd0ff9c 100644 --- a/deps/agg/include/agg_color_gray.h +++ b/deps/agg/include/agg_color_gray.h @@ -330,8 +330,8 @@ struct gray8T //-------------------------------------------------------------------- self_type& opacity(double a_) { - if (a_ < 0) a_ = 0; - else if (a_ > 1) a_ = 1; + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; else a = (value_type)uround(a_ * double(base_mask)); return *this; } diff --git a/deps/agg/include/agg_color_rgba.h b/deps/agg/include/agg_color_rgba.h index 2950467e4..b4e3f76d8 100644 --- a/deps/agg/include/agg_color_rgba.h +++ b/deps/agg/include/agg_color_rgba.h @@ -80,8 +80,8 @@ struct rgba //-------------------------------------------------------------------- rgba& opacity(double a_) { - if (a_ < 0) a_ = 0; - else if (a_ > 1) a_ = 1; + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; else a = a_; return *this; } @@ -472,8 +472,8 @@ struct rgba8T //-------------------------------------------------------------------- self_type& opacity(double a_) { - if (a_ < 0) a_ = 0; - else if (a_ > 1) a_ = 1; + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; else a = (value_type)uround(a_ * double(base_mask)); return *this; } @@ -882,8 +882,8 @@ struct rgba16 //-------------------------------------------------------------------- AGG_INLINE self_type& opacity(double a_) { - if (a_ < 0) a_ = 0; - if (a_ > 1) a_ = 1; + if (a_ < 0) a = 0; + if (a_ > 1) a = 1; a = value_type(uround(a_ * double(base_mask))); return *this; } @@ -1238,8 +1238,8 @@ struct rgba32 //-------------------------------------------------------------------- AGG_INLINE self_type& opacity(double a_) { - if (a_ < 0) a_ = 0; - else if (a_ > 1) a_ = 1; + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; else a = value_type(a_); return *this; } diff --git a/docs/contributing.markdown b/docs/contributing.markdown index e899c2ad7..e7f327977 100644 --- a/docs/contributing.markdown +++ b/docs/contributing.markdown @@ -18,8 +18,6 @@ Developers with commit access can update test data like: git remote set-url origin git@github.com:mapnik/test-data git commit -a -m "update test data" git push origin HEAD:master - cd ../../ - git commit test/data -m "update test-data submodule" And the visual test data can up updated like: @@ -27,6 +25,7 @@ And the visual test data can up updated like: git remote set-url origin git@github.com:mapnik/test-data-visual git add styles/* images/* git commit -a -m "add more visual tests" + git push origin HEAD:master After updating the test data you can then do: @@ -35,7 +34,7 @@ After updating the test data you can then do: # the submodule should be marked dirty git status # now commit the changes to the submodule - git commit -a -m "update visual tests and data" + git commit test/data test/data-visual -m "update visual tests and data" ## Community diff --git a/include/mapnik/global.hpp b/include/mapnik/global.hpp index f9b3d3a5a..4526f052c 100644 --- a/include/mapnik/global.hpp +++ b/include/mapnik/global.hpp @@ -48,8 +48,6 @@ namespace mapnik (((std::uint64_t) ((std::uint8_t) (A)[1])) << 48) | \ (((std::uint64_t) ((std::uint8_t) (A)[0])) << 56)) -using byte = std::uint8_t; - #define float8net(V,M) do { double def_temp; \ ((std::uint8_t*) &def_temp)[0]=(M)[7]; \ ((std::uint8_t*) &def_temp)[1]=(M)[6]; \ diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index 868784270..d98f9e2f1 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -98,7 +98,7 @@ class hextree : private util::noncopyable // penalty of using this node as color double reduce_cost; // number of !=0 positions in children_ array - byte children_count; + std::uint8_t children_count; }; // highest reduce_cost first @@ -184,7 +184,7 @@ public: } // process alpha value based on trans_mode_ - byte preprocessAlpha(byte a) const + std::uint8_t preprocessAlpha(std::uint8_t a) const { switch(trans_mode_) { @@ -199,7 +199,7 @@ public: void insert(T const& data) { - byte a = preprocessAlpha(data.a); + std::uint8_t a = preprocessAlpha(data.a); unsigned level = 0; node * cur_node = root_.get(); if (a < InsertPolicy::MIN_ALPHA) @@ -238,7 +238,7 @@ public: // return color index in returned earlier palette int quantize(unsigned val) const { - byte a = preprocessAlpha(U2ALPHA(val)); + std::uint8_t a = preprocessAlpha(U2ALPHA(val)); unsigned ind=0; if (a < InsertPolicy::MIN_ALPHA || colors_ == 0) { @@ -396,12 +396,12 @@ private: if (itr->count != 0) { unsigned count = itr->count; - byte a = byte(itr->alphas/float(count)); + std::uint8_t a = std::uint8_t(itr->alphas/float(count)); if (a > InsertPolicy::MAX_ALPHA) a = 255; if (a < InsertPolicy::MIN_ALPHA) a = 0; - palette.push_back(rgba((byte)round(gamma(itr->reds / count, gamma_)), - (byte)round(gamma(itr->greens / count, gamma_)), - (byte)round(gamma(itr->blues / count, gamma_)), a)); + palette.push_back(rgba((std::uint8_t)round(gamma(itr->reds / count, gamma_)), + (std::uint8_t)round(gamma(itr->greens / count, gamma_)), + (std::uint8_t)round(gamma(itr->blues / count, gamma_)), a)); } for (unsigned idx=0; idx < 16; ++idx) { diff --git a/include/mapnik/image.hpp b/include/mapnik/image.hpp index d9ea2c56a..7567bfc9c 100644 --- a/include/mapnik/image.hpp +++ b/include/mapnik/image.hpp @@ -39,7 +39,10 @@ struct MAPNIK_DECL buffer ~buffer(); buffer& operator=(buffer rhs); - bool operator!() const; + inline bool operator!() const + { + return (data_ == nullptr)? true : false; + } void swap(buffer & rhs); unsigned char* data(); diff --git a/include/mapnik/image_options.hpp b/include/mapnik/image_options.hpp new file mode 100644 index 000000000..fc8f9f1a5 --- /dev/null +++ b/include/mapnik/image_options.hpp @@ -0,0 +1,38 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_IMAGE_OPTIONS_HPP +#define MAPNIK_IMAGE_OPTIONS_HPP + +#include +#include +#include + +namespace mapnik { + +using image_options_map = std::map >; +inline std::string to_string(boost::optional const& val) { return val ? *val : "";} +image_options_map parse_image_options(std::string const& options); + +} + +#endif // MAPNIK_IMAGE_OPTIONS_HPP diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index 9cabef117..21b5cd0b7 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -26,11 +26,6 @@ // mapnik #include #include -//#include -//#include -//#include -//#include -//#include // boost #pragma GCC diagnostic push @@ -53,15 +48,15 @@ struct image_view_any; template class image_view; class color; -class ImageWriterException : public std::exception +class image_writer_exception : public std::exception { private: std::string message_; public: - ImageWriterException(std::string const& message) + image_writer_exception(std::string const& message) : message_(message) {} - ~ImageWriterException() throw() {} + ~image_writer_exception() throw() {} virtual const char* what() const throw() { @@ -420,7 +415,6 @@ void add_border(T & image) image(image.width()-1,y) = 0xffff0000; // blue } } - } #endif // MAPNIK_IMAGE_UTIL_HPP diff --git a/include/mapnik/layer.hpp b/include/mapnik/layer.hpp index 7d0e3bf31..4b4e9f87c 100644 --- a/include/mapnik/layer.hpp +++ b/include/mapnik/layer.hpp @@ -97,24 +97,24 @@ public: std::vector& styles(); /*! - * @param min_zoom The minimum zoom level to set + * @param minimum_scale_denom The minimum scale denominator */ - void set_min_zoom(double min_zoom); + void set_minimum_scale_denominator(double minimum_scale_denom); /*! - * @param max_zoom The maximum zoom level to set + * @param maximum_scale_denom The maximum scale denominator */ - void set_max_zoom(double max_zoom); + void set_maximum_scale_denominator(double maximum_scale_denom); /*! * @return the minimum zoom level of the layer. */ - double min_zoom() const; + double minimum_scale_denominator() const; /*! * @return the maximum zoom level of the layer. */ - double max_zoom() const; + double maximum_scale_denominator() const; /*! * @brief Set whether this layer is active and will be rendered. @@ -137,18 +137,18 @@ public: bool queryable() const; /*! - * @brief Get the visability for a specific scale. + * @brief Get the visibility for a specific scale denominator. * - * @param scale Accepts an integer or float input. + * @param scale_denom Accepts an integer or float input. * - * @return true if this layer's data is active and visible at a given scale. + * @return true if this layer's data is active and visible at a given scale denominator. * Otherwise returns False. * false if: - * scale >= minzoom - 1e-6 + * scale_denominator >= minimum_scale_denominator - 1e-6 * or - * scale < maxzoom + 1e-6 + * scale_denominator < maximum_scale_denominator + 1e-6 */ - bool visible(double scale) const; + bool visible(double scale_denom) const; /*! * @param clear_cache Set whether this layer's labels are cached. @@ -207,8 +207,8 @@ public: private: std::string name_; std::string srs_; - double min_zoom_; - double max_zoom_; + double minimum_scale_denom_; + double maximum_scale_denom_; bool active_; bool queryable_; bool clear_label_cache_; diff --git a/include/mapnik/marker.hpp b/include/mapnik/marker.hpp index 901fb8fb1..3eaaebec8 100644 --- a/include/mapnik/marker.hpp +++ b/include/mapnik/marker.hpp @@ -25,25 +25,22 @@ // mapnik #include -#include #include -#include #include -#include #include // agg #include "agg_array.h" -// boost -#include - // stl #include namespace mapnik { +struct image_any; +namespace svg { struct path_attributes; } + using attr_storage = agg::pod_bvector; using svg_storage_type = mapnik::svg::svg_storage; using svg_path_ptr = std::shared_ptr; diff --git a/include/mapnik/marker_cache.hpp b/include/mapnik/marker_cache.hpp index 43719c4f5..d685cc94b 100644 --- a/include/mapnik/marker_cache.hpp +++ b/include/mapnik/marker_cache.hpp @@ -31,7 +31,6 @@ // boost #include #include -#include namespace mapnik { diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 1457cdcf9..15dca626d 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -23,39 +23,32 @@ #ifndef MAPNIK_MARKER_HELPERS_HPP #define MAPNIK_MARKER_HELPERS_HPP -#include #include +#include #include #include #include #include -#include -#include -#include #include #include // for svg_storage_type #include #include #include -#include #include -#include #include // agg #include "agg_trans_affine.h" -// boost -#include // stl #include -#include // remove_reference -#include namespace mapnik { struct clip_poly_tag; +namespace svg { struct path_attributes; } + using svg_attribute_type = agg::pod_bvector; template diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index d4b15d0e1..37cda8457 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -23,13 +23,19 @@ #ifndef MAPNIK_MARKERS_PLACEMENTS_POINT_HPP #define MAPNIK_MARKERS_PLACEMENTS_POINT_HPP +#include #include #include #include +#include +#include +#include #include "agg_basics.h" #include "agg_trans_affine.h" +#include + namespace mapnik { struct markers_placement_params diff --git a/include/mapnik/octree.hpp b/include/mapnik/octree.hpp index 6119bd6cb..ea813c89e 100644 --- a/include/mapnik/octree.hpp +++ b/include/mapnik/octree.hpp @@ -88,8 +88,8 @@ class octree : private util::noncopyable unsigned count; double reduce_cost; unsigned count_cum; - byte children_count; - byte index; + std::uint8_t children_count; + std::uint8_t index; }; struct node_cmp { @@ -297,9 +297,9 @@ public: if (itr->count != 0) { unsigned count = itr->count; - palette.push_back(rgb(byte(itr->reds/float(count)), - byte(itr->greens/float(count)), - byte(itr->blues/float(count)))); + palette.push_back(rgb(std::uint8_t(itr->reds/float(count)), + std::uint8_t(itr->greens/float(count)), + std::uint8_t(itr->blues/float(count)))); itr->index = static_cast(palette.size()) - 1; } for (unsigned i=0; i < 8 ;++i) diff --git a/include/mapnik/palette.hpp b/include/mapnik/palette.hpp index 5dc3a4cdf..cf21338ac 100644 --- a/include/mapnik/palette.hpp +++ b/include/mapnik/palette.hpp @@ -51,11 +51,11 @@ namespace mapnik { struct rgba; struct MAPNIK_DECL rgb { - byte r; - byte g; - byte b; + std::uint8_t r; + std::uint8_t g; + std::uint8_t b; - inline rgb(byte r_, byte g_, byte b_) : r(r_), g(g_), b(b_) {} + inline rgb(std::uint8_t r_, std::uint8_t g_, std::uint8_t b_) : r(r_), g(g_), b(b_) {} rgb(rgba const& c); inline bool operator==(const rgb& y) const @@ -66,12 +66,12 @@ struct MAPNIK_DECL rgb { struct MAPNIK_DECL rgba { - byte r; - byte g; - byte b; - byte a; + std::uint8_t r; + std::uint8_t g; + std::uint8_t b; + std::uint8_t a; - inline rgba(byte r_, byte g_, byte b_, byte a_) + inline rgba(std::uint8_t r_, std::uint8_t g_, std::uint8_t b_, std::uint8_t a_) : r(r_), g(g_), b(b_), diff --git a/include/mapnik/png_io.hpp b/include/mapnik/png_io.hpp index cde57df08..01d5b17bc 100644 --- a/include/mapnik/png_io.hpp +++ b/include/mapnik/png_io.hpp @@ -182,7 +182,7 @@ void reduce_8(T const& in, for (unsigned x = 0; x < width; ++x) { unsigned val = row[x]; - byte index = 0; + std::uint8_t index = 0; int idx = -1; for(int j=levels-1; j>0; j--) { @@ -233,7 +233,7 @@ void reduce_4(T const& in, for (unsigned x = 0; x < width; ++x) { unsigned val = row[x]; - byte index = 0; + std::uint8_t index = 0; int idx=-1; for(int j=levels-1; j>0; j--) { @@ -642,7 +642,7 @@ void save_as_png8(T1 & file, { mapnik::image_rgba8::pixel_type const * row = image.get_row(y); mapnik::image_gray8::pixel_type * row_out = reduced_image.get_row(y); - byte index = 0; + std::uint8_t index = 0; for (unsigned x = 0; x < width; ++x) { diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index 66e2392e3..c072ca5db 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -25,8 +25,7 @@ // mapnik #include -#include -#include +#include #include #include #include diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp index 79d09cee0..3bc1f314c 100644 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_markers_symbolizer.hpp @@ -23,7 +23,6 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP -#include #include #include #include diff --git a/include/mapnik/tiff_io.hpp b/include/mapnik/tiff_io.hpp index c08304c9b..fd3a7534b 100644 --- a/include/mapnik/tiff_io.hpp +++ b/include/mapnik/tiff_io.hpp @@ -190,7 +190,7 @@ struct tag_setter void operator() (T const&) const { // Assume this would be null type - throw ImageWriterException("Could not write TIFF - unknown image type provided"); + throw image_writer_exception("Could not write TIFF - unknown image type provided"); } inline void operator() (image_rgba8 const& data) const @@ -358,7 +358,7 @@ struct tag_setter inline void operator() (image_null const&) const { // Assume this would be null type - throw ImageWriterException("Could not write TIFF - Null image provided"); + throw image_writer_exception("Could not write TIFF - Null image provided"); } private: @@ -406,7 +406,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config) tiff_dummy_unmap_proc); if (! output) { - throw ImageWriterException("Could not write TIFF"); + throw image_writer_exception("Could not write TIFF"); } TIFFSetField(output, TIFFTAG_IMAGEWIDTH, width); @@ -453,7 +453,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config) } if (TIFFWriteEncodedStrip(output, TIFFComputeStrip(output, y, 0), strip_buffer.get(), strip_size * sizeof(pixel_type)) == -1) { - throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed"); + throw image_writer_exception("Could not write TIFF - TIFF Tile Write failed"); } } } @@ -504,7 +504,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config) } if (TIFFWriteEncodedTile(output, TIFFComputeTile(output, x, y, 0, 0), image_out.get(), tile_size * sizeof(pixel_type)) == -1) { - throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed"); + throw image_writer_exception("Could not write TIFF - TIFF Tile Write failed"); } } } diff --git a/include/mapnik/vertex_cache.hpp b/include/mapnik/vertex_cache.hpp index e557d4b30..094101a85 100644 --- a/include/mapnik/vertex_cache.hpp +++ b/include/mapnik/vertex_cache.hpp @@ -208,7 +208,7 @@ vertex_cache::vertex_cache(T & path) current_subpath_->add_segment(new_x, new_y, 0); first = false; } - if (agg::is_line_to(cmd)) + else if (agg::is_line_to(cmd)) { if (first) { @@ -220,6 +220,14 @@ vertex_cache::vertex_cache(T & path) double segment_length = std::sqrt(dx*dx + dy*dy); current_subpath_->add_segment(new_x, new_y, segment_length); } + else if (agg::is_closed(cmd) && !current_subpath_->vector.empty()) + { + segment const & first_segment = current_subpath_->vector[0]; + double dx = old_x - first_segment.pos.x; + double dy = old_y - first_segment.pos.y; + double segment_length = std::sqrt(dx*dx + dy*dy); + current_subpath_->add_segment(first_segment.pos.x, first_segment.pos.y, segment_length); + } old_x = new_x; old_y = new_y; } diff --git a/include/mapnik/view_strategy.hpp b/include/mapnik/view_strategy.hpp index cdc9204f8..a984dc4d9 100644 --- a/include/mapnik/view_strategy.hpp +++ b/include/mapnik/view_strategy.hpp @@ -24,9 +24,12 @@ #define MAPNIK_VIEW_STRATEGY_HPP // mapnik -#include -#include -#include +#include + +// boost +#include +#include +#include namespace mapnik { diff --git a/localize.sh b/localize.sh index 628c1b2f8..ee62e5987 100755 --- a/localize.sh +++ b/localize.sh @@ -5,4 +5,17 @@ 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} -fi \ No newline at end of file +fi + +export PATH=$(pwd)/utils/nik2img/:${PATH} + +# mapnik-settings.env is an optional file to store +# environment variables that should be used before +# running tests like PROJ_LIB, GDAL_DATA, and ICU_DATA +# These do not normally need to be set except when +# building against binary versions of dependencies like +# done via bootstrap.sh +if [[ -f mapnik-settings.env ]]; then + echo "Inheriting from mapnik-settings.env" + source mapnik-settings.env +fi diff --git a/plugins/input/geojson/geojson_datasource.cpp b/plugins/input/geojson/geojson_datasource.cpp index 1dc5a084e..1d3dfd876 100644 --- a/plugins/input/geojson/geojson_datasource.cpp +++ b/plugins/input/geojson/geojson_datasource.cpp @@ -27,8 +27,13 @@ #include // boost +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-local-typedef" #include #include +#pragma GCC diagnostic pop + // mapnik #include #include diff --git a/plugins/input/pgraster/pgraster_featureset.cpp b/plugins/input/pgraster/pgraster_featureset.cpp index 84ba0a898..3ab87bba4 100644 --- a/plugins/input/pgraster/pgraster_featureset.cpp +++ b/plugins/input/pgraster/pgraster_featureset.cpp @@ -47,7 +47,6 @@ #include #include -using mapnik::byte; using mapnik::feature_factory; using mapnik::context_ptr; diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 7cb528bac..acb9655d3 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -154,10 +154,6 @@ postgis_datasource::postgis_datasource(parameters const& params) schema_ = geometry_table_.substr(0, idx); geometry_table_ = geometry_table_.substr(idx + 1); } - else - { - geometry_table_ = geometry_table_.substr(0); - } // NOTE: geometry_table_ how should ideally be a table name, but // there are known edge cases where this will break down and @@ -234,6 +230,10 @@ postgis_datasource::postgis_datasource(parameters const& params) s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM "; if (!geometry_table_.empty()) { + if (!schema_.empty()) + { + s << schema_ << '.'; + } s << geometry_table_; } else diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 56c3749c9..d256e86f8 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -41,7 +41,6 @@ #include #include -using mapnik::byte; using mapnik::geometry_utils; using mapnik::feature_factory; using mapnik::context_ptr; diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index bceab9492..67723d064 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -53,8 +53,9 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_span_image_filter_rgba.h" + // boost -#include +#include // stl #include @@ -415,8 +416,6 @@ struct agg_render_marker_visitor using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; using renderer_base = agg::renderer_base; - using renderer_type = agg::renderer_scanline_aa_solid; - using svg_attribute_type = agg::pod_bvector; ras_ptr_->reset(); if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0) @@ -574,7 +573,7 @@ void agg_renderer::debug_draw_box(R& buf, box2d const& box, renderer_base renb(pixf); renderer_type ren(renb); - // compute tranformation matrix + // compute transformation matrix agg::trans_affine tr = agg::trans_affine_rotation(angle).translate(x, y); // prepare path agg::path_storage pbox; diff --git a/src/build.py b/src/build.py index d63523236..f48a90960 100644 --- a/src/build.py +++ b/src/build.py @@ -181,6 +181,7 @@ source = Split( image_view.cpp image_view_any.cpp image_any.cpp + image_options.cpp image_util.cpp image_util_jpeg.cpp image_util_png.cpp diff --git a/src/cairo_io.cpp b/src/cairo_io.cpp index 0eefa2e89..d8e965584 100644 --- a/src/cairo_io.cpp +++ b/src/cairo_io.cpp @@ -55,7 +55,7 @@ void save_to_cairo_file(mapnik::Map const& map, std::string const& filename, dou { save_to_cairo_file(map,filename,*type,scale_factor,scale_denominator); } - else throw ImageWriterException("Could not write file to " + filename ); + else throw image_writer_exception("Could not write file to " + filename ); } void save_to_cairo_file(mapnik::Map const& map, @@ -75,7 +75,7 @@ void save_to_cairo_file(mapnik::Map const& map, #ifdef CAIRO_HAS_PDF_SURFACE surface = cairo_surface_ptr(cairo_pdf_surface_create(filename.c_str(),width,height),cairo_surface_closer()); #else - throw ImageWriterException("PDFSurface not supported in the cairo backend"); + throw image_writer_exception("PDFSurface not supported in the cairo backend"); #endif } #ifdef CAIRO_HAS_SVG_SURFACE @@ -102,7 +102,7 @@ void save_to_cairo_file(mapnik::Map const& map, #endif else { - throw ImageWriterException("unknown file type: " + type); + throw image_writer_exception("unknown file type: " + type); } //cairo_t * ctx = cairo_create(surface); diff --git a/src/image.cpp b/src/image.cpp index 528a035a7..408b29c84 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -71,11 +71,6 @@ void buffer::swap(buffer & rhs) std::swap(data_, rhs.data_); } -inline bool buffer::operator!() const -{ - return (data_ == nullptr)? false : true; -} - unsigned char* buffer::data() { return data_; diff --git a/src/image_options.cpp b/src/image_options.cpp new file mode 100644 index 000000000..0c102aeb1 --- /dev/null +++ b/src/image_options.cpp @@ -0,0 +1,73 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include + +namespace mapnik { namespace detail { + +namespace qi = boost::spirit::qi; + +template +struct image_options_grammar + : qi::grammar +{ + using pair_type = std::pair>; + image_options_grammar() + : image_options_grammar::base_type(start) + { + qi::lit_type lit; + qi::char_type char_; + start = pair >> *(lit(':') >> pair) + ; + pair = key >> -('=' >> value) + ; + key = char_("a-zA-Z_") >> *char_("a-zA-Z_0-9\\.\\-") + ; + value = +char_("a-zA-Z_0-9\\.\\-") + ; + } + + qi::rule start; + qi::rule pair; + qi::rule key, value; +}; + +} // ns detail + +image_options_map parse_image_options(std::string const& str) +{ + auto const begin = str.begin(); + auto const end = str.end(); + boost::spirit::ascii::space_type space; + mapnik::detail::image_options_grammar g; + image_options_map options; + bool success = boost::spirit::qi::phrase_parse(begin, end, g, space, options); + if (!success) + { + throw std::runtime_error("Can't parse image options: " + str); + } + return options; // RVO +} + +} // ns mapnik diff --git a/src/image_util.cpp b/src/image_util.cpp index 59040e0f7..16e60ffc4 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -54,14 +54,13 @@ // boost #include +namespace mapnik +{ using boost::numeric_cast; using boost::numeric::positive_overflow; using boost::numeric::negative_overflow; -namespace mapnik -{ - template MAPNIK_DECL std::string save_to_string(T const& image, std::string const& type, @@ -92,7 +91,7 @@ MAPNIK_DECL void save_to_file(T const& image, { save_to_stream(image, file, type, palette); } - else throw ImageWriterException("Could not write file to " + filename ); + else throw image_writer_exception("Could not write file to " + filename ); } template @@ -105,7 +104,7 @@ MAPNIK_DECL void save_to_file(T const& image, { save_to_stream(image, file, type); } - else throw ImageWriterException("Could not write file to " + filename ); + else throw image_writer_exception("Could not write file to " + filename ); } template @@ -125,15 +124,15 @@ MAPNIK_DECL void save_to_stream(T const& image, } else if (boost::algorithm::starts_with(t, "tif")) { - throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)"); + throw image_writer_exception("palettes are not currently supported when writing to tiff format (yet)"); } else if (boost::algorithm::starts_with(t, "jpeg")) { - throw ImageWriterException("palettes are not currently supported when writing to jpeg format"); + throw image_writer_exception("palettes are not currently supported when writing to jpeg format"); } - else throw ImageWriterException("unknown file type: " + type); + else throw image_writer_exception("unknown file type: " + type); } - else throw ImageWriterException("Could not write to empty stream" ); + else throw image_writer_exception("Could not write to empty stream" ); } // This can be removed once image_any and image_view_any are the only @@ -156,15 +155,15 @@ MAPNIK_DECL void save_to_stream(image_rgba8 const& image, } else if (boost::algorithm::starts_with(t, "tif")) { - throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)"); + throw image_writer_exception("palettes are not currently supported when writing to tiff format (yet)"); } else if (boost::algorithm::starts_with(t, "jpeg")) { - throw ImageWriterException("palettes are not currently supported when writing to jpeg format"); + throw image_writer_exception("palettes are not currently supported when writing to jpeg format"); } - else throw ImageWriterException("unknown file type: " + type); + else throw image_writer_exception("unknown file type: " + type); } - else throw ImageWriterException("Could not write to empty stream" ); + else throw image_writer_exception("Could not write to empty stream" ); } // This can be removed once image_any and image_view_any are the only @@ -187,15 +186,15 @@ MAPNIK_DECL void save_to_stream(image_view_rgba8 const& image, } else if (boost::algorithm::starts_with(t, "tif")) { - throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)"); + throw image_writer_exception("palettes are not currently supported when writing to tiff format (yet)"); } else if (boost::algorithm::starts_with(t, "jpeg")) { - throw ImageWriterException("palettes are not currently supported when writing to jpeg format"); + throw image_writer_exception("palettes are not currently supported when writing to jpeg format"); } - else throw ImageWriterException("unknown file type: " + type); + else throw image_writer_exception("unknown file type: " + type); } - else throw ImageWriterException("Could not write to empty stream" ); + else throw image_writer_exception("Could not write to empty stream" ); } template @@ -227,9 +226,9 @@ MAPNIK_DECL void save_to_stream(T const& image, webp_saver visitor(stream, t); util::apply_visitor(visitor, image); } - else throw ImageWriterException("unknown file type: " + type); + else throw image_writer_exception("unknown file type: " + type); } - else throw ImageWriterException("Could not write to empty stream" ); + else throw image_writer_exception("Could not write to empty stream" ); } // This can be removed once image_any and image_view_any are the only @@ -267,9 +266,9 @@ MAPNIK_DECL void save_to_stream(image_rgba8 const& image, visitor(image); //util::apply_visitor(visitor, image); } - else throw ImageWriterException("unknown file type: " + type); + else throw image_writer_exception("unknown file type: " + type); } - else throw ImageWriterException("Could not write to empty stream" ); + else throw image_writer_exception("Could not write to empty stream" ); } // This can be removed once image_any and image_view_any are the only @@ -307,9 +306,9 @@ MAPNIK_DECL void save_to_stream(image_view_rgba8 const& image, visitor(image); //util::apply_visitor(visitor, image); } - else throw ImageWriterException("unknown file type: " + type); + else throw image_writer_exception("unknown file type: " + type); } - else throw ImageWriterException("Could not write to empty stream" ); + else throw image_writer_exception("Could not write to empty stream" ); } template @@ -320,7 +319,7 @@ MAPNIK_DECL void save_to_file(T const& image, std::string const& filename) { save_to_file(image, filename, *type); } - else throw ImageWriterException("Could not write file to " + filename ); + else throw image_writer_exception("Could not write file to " + filename ); } template @@ -331,7 +330,7 @@ MAPNIK_DECL void save_to_file(T const& image, std::string const& filename, rgba_ { save_to_file(image, filename, *type, palette); } - else throw ImageWriterException("Could not write file to " + filename ); + else throw image_writer_exception("Could not write file to " + filename ); } // image_rgba8 @@ -410,18 +409,18 @@ namespace detail { struct is_solid_visitor { - bool operator() (image_view_null const&) + bool operator() (image_view_null const&) const { return true; } - bool operator() (image_null const&) + bool operator() (image_null const&) const { return true; } template - bool operator() (T const & data) + bool operator() (T const & data) const { using pixel_type = typename T::pixel_type; if (data.width() > 0 && data.height() > 0) @@ -492,7 +491,7 @@ namespace detail { struct premultiply_visitor { - bool operator() (image_rgba8 & data) + bool operator() (image_rgba8 & data) const { if (!data.get_premultiplied()) { @@ -506,7 +505,7 @@ struct premultiply_visitor } template - bool operator() (T &) + bool operator() (T &) const { return false; } @@ -514,7 +513,7 @@ struct premultiply_visitor struct demultiply_visitor { - bool operator() (image_rgba8 & data) + bool operator() (image_rgba8 & data) const { if (data.get_premultiplied()) { @@ -528,7 +527,7 @@ struct demultiply_visitor } template - bool operator() (T &) + bool operator() (T &) const { return false; } @@ -540,12 +539,12 @@ struct set_premultiplied_visitor : status_(status) {} template - void operator() (T & data) + void operator() (T & data) const { data.set_premultiplied(status_); } private: - bool status_; + bool const status_; }; } // end detail ns @@ -624,23 +623,24 @@ template MAPNIK_DECL void set_premultiplied_alpha(image_gray64f &, bool); namespace detail { +namespace { + +template +inline T clamp(T d, T min, T max) +{ + T const t = d < min ? min : d; + return t > max ? max : t; +} + +} struct visitor_set_alpha { visitor_set_alpha(float opacity) - : opacity_(opacity) {} + : opacity_(clamp(opacity, 0.0f, 1.0f)) {} - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using pixel_type = image_rgba8::pixel_type; - if (opacity_ > 1.0) - { - opacity_ = 1.0; - } - if (opacity_ < 0.0) - { - opacity_ = 0.0; - } - pixel_type a1 = static_cast(255.0 * opacity_); for (unsigned int y = 0; y < data.height(); ++y) { @@ -649,7 +649,6 @@ struct visitor_set_alpha { pixel_type rgba = row_to[x]; pixel_type a0 = (rgba >> 24) & 0xff; - //unsigned a1 = opacity; if (a0 == a1) continue; pixel_type r = rgba & 0xff; @@ -662,14 +661,13 @@ struct visitor_set_alpha } template - void operator() (T & data) + void operator() (T & data) const { throw std::runtime_error("Error: set_alpha with " + std::string(typeid(data).name()) + " is not supported"); } private: - float opacity_; - + float const opacity_; }; } // end detail ns @@ -715,9 +713,9 @@ namespace detail { struct visitor_multiply_alpha { visitor_multiply_alpha(float opacity) - : opacity_(opacity) {} + : opacity_(clamp(opacity, 0.0f, 1.0f)) {} - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using pixel_type = image_rgba8::pixel_type; for (unsigned int y = 0; y < data.height(); ++y) @@ -726,40 +724,23 @@ struct visitor_multiply_alpha for (unsigned int x = 0; x < data.width(); ++x) { pixel_type rgba = row_to[x]; - pixel_type a0 = (rgba >> 24) & 0xff; - pixel_type a1; - try - { - a1 = numeric_cast(((rgba >> 24) & 0xff) * opacity_); - } - catch(negative_overflow&) - { - a1 = std::numeric_limits::min(); - } - catch(positive_overflow&) - { - a1 = std::numeric_limits::max(); - } - //unsigned a1 = opacity; - if (a0 == a1) continue; - + pixel_type a = static_cast(((rgba >> 24) & 0xff) * opacity_); pixel_type r = rgba & 0xff; pixel_type g = (rgba >> 8 ) & 0xff; pixel_type b = (rgba >> 16) & 0xff; - - row_to[x] = (a1 << 24)| (b << 16) | (g << 8) | (r) ; + row_to[x] = (a << 24) | (b << 16) | (g << 8) | (r); } } } template - void operator() (T & data) + void operator() (T & data) const { throw std::runtime_error("Error: multiply_alpha with " + std::string(typeid(data).name()) + " is not supported"); } - private: - float opacity_; + private: + float const opacity_; }; @@ -805,7 +786,7 @@ namespace detail { struct visitor_set_grayscale_to_alpha { - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using pixel_type = image_rgba8::pixel_type; for (unsigned int y = 0; y < data.height(); ++y) @@ -827,7 +808,7 @@ struct visitor_set_grayscale_to_alpha } template - void operator() (T & data) + void operator() (T & data) const { MAPNIK_LOG_WARN(image_util) << "Warning: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported, image was not modified"; } @@ -838,7 +819,7 @@ struct visitor_set_grayscale_to_alpha_c visitor_set_grayscale_to_alpha_c(color const& c) : c_(c) {} - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using pixel_type = image_rgba8::pixel_type; for (unsigned int y = 0; y < data.height(); ++y) @@ -860,7 +841,7 @@ struct visitor_set_grayscale_to_alpha_c } template - void operator() (T & data) + void operator() (T & data) const { MAPNIK_LOG_WARN(image_util) << "Warning: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported, image was not modified"; } @@ -950,7 +931,7 @@ struct visitor_set_color_to_alpha visitor_set_color_to_alpha(color const& c) : c_(c) {} - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using pixel_type = image_rgba8::pixel_type; for (unsigned y = 0; y < data.height(); ++y) @@ -971,7 +952,7 @@ struct visitor_set_color_to_alpha } template - void operator() (T & data) + void operator() (T & data) const { throw std::runtime_error("Error: set_color_to_alpha with " + std::string(typeid(data).name()) + " is not supported"); } @@ -1029,7 +1010,7 @@ struct visitor_fill : val_(val) {} template - void operator() (T2 & data) + void operator() (T2 & data) const { using pixel_type = typename T2::pixel_type; pixel_type val; @@ -1058,7 +1039,7 @@ struct visitor_fill visitor_fill(color const& val) : val_(val) {} - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using pixel_type = image_rgba8::pixel_type; pixel_type val = static_cast(val_.rgba()); @@ -1067,7 +1048,7 @@ struct visitor_fill } template - void operator() (T2 & data) + void operator() (T2 & data) const { using pixel_type = typename T2::pixel_type; pixel_type val = static_cast(val_.rgba()); @@ -1314,7 +1295,7 @@ struct visitor_set_rectangle visitor_set_rectangle(image_any const & src, int x0, int y0) : src_(src), x0_(x0), y0_(y0) {} - void operator()(image_rgba8 & dst) + void operator()(image_rgba8 & dst) const { using pixel_type = image_rgba8::pixel_type; image_rgba8 src = util::get(src_); @@ -1340,13 +1321,13 @@ struct visitor_set_rectangle } } - void operator() (image_null &) + void operator() (image_null &) const { throw std::runtime_error("Set rectangle not support for null images"); } template - void operator() (T & dst) + void operator() (T & dst) const { using pixel_type = typename T::pixel_type; T src = util::get(src_); @@ -1408,14 +1389,14 @@ struct visitor_composite_pixel // Obviously c variable would only work for rgba8 currently, but didn't want to // make this a template class until new rgba types exist. visitor_composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity) - : opacity_(opacity), + : opacity_(clamp(opacity, 0.0, 1.0)), op_(op), x_(x), y_(y), c_(c), cover_(cover) {} - void operator() (image_rgba8 & data) + void operator() (image_rgba8 & data) const { using color_type = agg::rgba8; using value_type = color_type::value_type; @@ -1424,29 +1405,29 @@ struct visitor_composite_pixel if (mapnik::check_bounds(data, x_, y_)) { - unsigned rgba = data(x_,y_); - unsigned ca = (unsigned)(((c_ >> 24) & 0xff) * opacity_); - unsigned cb = (c_ >> 16 ) & 0xff; - unsigned cg = (c_ >> 8) & 0xff; - unsigned cr = (c_ & 0xff); - blender_type::blend_pix(op_, (value_type*)&rgba, cr, cg, cb, ca, cover_); + image_rgba8::pixel_type rgba = data(x_,y_); + value_type ca = static_cast(((c_ >> 24) & 0xff) * opacity_); + value_type cb = (c_ >> 16 ) & 0xff; + value_type cg = (c_ >> 8) & 0xff; + value_type cr = (c_ & 0xff); + blender_type::blend_pix(op_, reinterpret_cast(&rgba), cr, cg, cb, ca, cover_); data(x_,y_) = rgba; } } template - void operator() (T & data) + void operator() (T & data) const { throw std::runtime_error("Composite pixel is not supported for this data type"); } private: - double opacity_; + double const opacity_; unsigned op_; - int x_; - int y_; - int c_; - unsigned cover_; + int const x_; + int const y_; + int const c_; + unsigned const cover_; }; @@ -1485,7 +1466,7 @@ struct visitor_set_pixel : val_(val), x_(x), y_(y) {} template - void operator() (T2 & data) + void operator() (T2 & data) const { using pixel_type = typename T2::pixel_type; pixel_type val; @@ -1509,8 +1490,8 @@ struct visitor_set_pixel private: T1 const& val_; - std::size_t x_; - std::size_t y_; + std::size_t const x_; + std::size_t const y_; }; template<> @@ -1520,7 +1501,7 @@ struct visitor_set_pixel : val_(val), x_(x), y_(y) {} template - void operator() (T2 & data) + void operator() (T2 & data) const { using pixel_type = typename T2::pixel_type; pixel_type val; @@ -1548,8 +1529,8 @@ struct visitor_set_pixel private: color const& val_; - std::size_t x_; - std::size_t y_; + std::size_t const x_; + std::size_t const y_; }; } // end detail ns @@ -1790,8 +1771,9 @@ struct visitor_get_pixel : x_(x), y_(y) {} template - T1 operator() (T2 const& data) + T1 operator() (T2 const& data) const { + using pixel_type = T1; if (check_bounds(data, x_, y_)) { T1 val; @@ -1816,8 +1798,8 @@ struct visitor_get_pixel } private: - std::size_t x_; - std::size_t y_; + std::size_t const x_; + std::size_t const y_; }; template<> @@ -1827,7 +1809,7 @@ struct visitor_get_pixel : x_(x), y_(y) {} template - color operator() (T2 const& data) + color operator() (T2 const& data) const { if (check_bounds(data, x_, y_)) { @@ -1840,8 +1822,8 @@ struct visitor_get_pixel } private: - std::size_t x_; - std::size_t y_; + std::size_t const x_; + std::size_t const y_; }; } // end detail ns @@ -2338,22 +2320,22 @@ struct visitor_create_view visitor_create_view(unsigned x,unsigned y, unsigned w, unsigned h) : x_(x), y_(y), w_(w), h_(h) {} - image_view_any operator() (image_null const&) + image_view_any operator() (image_null const&) const { throw std::runtime_error("Can not make a view from a null image"); } template - image_view_any operator() (T const& data) + image_view_any operator() (T const& data) const { image_view view(x_,y_,w_,h_,data); return image_view_any(view); } private: - unsigned x_; - unsigned y_; - unsigned w_; - unsigned h_; + unsigned const x_; + unsigned const y_; + unsigned const w_; + unsigned const h_; }; } // end detail ns @@ -2428,8 +2410,8 @@ MAPNIK_DECL unsigned compare(image_rgba8 const& im1, image_rgba8 co { for (unsigned int y = 0; y < im1.height(); ++y) { - const std::uint32_t * row_from = im1.get_row(y); - const std::uint32_t * row_from2 = im2.get_row(y); + const pixel_type * row_from = im1.get_row(y); + const pixel_type * row_from2 = im2.get_row(y); int x = 0; for (; x < ROUND_DOWN(im1.width(),4); x +=4 ) { @@ -2462,8 +2444,8 @@ MAPNIK_DECL unsigned compare(image_rgba8 const& im1, image_rgba8 co __m128i m_thres = _mm_set1_epi8(thres); for (unsigned int y = 0; y < im1.height(); ++y) { - const std::uint32_t * row_from = im1.get_row(y); - const std::uint32_t * row_from2 = im2.get_row(y); + const pixel_type * row_from = im1.get_row(y); + const pixel_type * row_from2 = im2.get_row(y); int x = 0; for (; x < ROUND_DOWN(im1.width(),4); x +=4 ) { @@ -2512,8 +2494,8 @@ MAPNIK_DECL unsigned compare(image_rgba8 const& im1, image_rgba8 co #else for (unsigned int y = 0; y < im1.height(); ++y) { - const std::uint32_t * row_from = im1.get_row(y); - const std::uint32_t * row_from2 = im2.get_row(y); + const pixel_type * row_from = im1.get_row(y); + const pixel_type * row_from2 = im2.get_row(y); for (unsigned int x = 0; x < im1.width(); ++x) { unsigned rgba = row_from[x]; @@ -2550,10 +2532,12 @@ namespace detail struct visitor_compare { visitor_compare(image_any const& im2, double threshold, bool alpha) - : im2_(im2), threshold_(threshold), alpha_(alpha) {} + : im2_(im2), + threshold_(threshold), + alpha_(alpha) {} template - unsigned operator() (T const & im1) + unsigned operator() (T const & im1) const { if (!im2_.is()) { @@ -2564,8 +2548,8 @@ struct visitor_compare private: image_any const& im2_; - double threshold_; - bool alpha_; + double const threshold_; + bool const alpha_; }; } // end detail ns diff --git a/src/image_util_jpeg.cpp b/src/image_util_jpeg.cpp index e85971de9..1c00c8467 100644 --- a/src/image_util_jpeg.cpp +++ b/src/image_util_jpeg.cpp @@ -29,11 +29,9 @@ #include #include #include +#include #include -// boost -#include - // stl #include @@ -48,25 +46,22 @@ void process_rgba8_jpeg(T const& image, std::string const& type, std::ostream & { #if defined(HAVE_JPEG) int quality = 85; - //std::string val = type.substr(4); if (type != "jpeg") { - boost::char_separator sep(":"); - boost::tokenizer< boost::char_separator > tokens(type, sep); - for (auto const& t : tokens) + for (auto const& kv : parse_image_options(type)) { - if (t == "jpeg") + auto const& key = kv.first; + auto const& val = kv.second; + + if ( key == "jpeg" ) continue; + + if ( key == "quality") { - continue; - } - else if (boost::algorithm::starts_with(t, "quality=")) - { - std::string val = t.substr(8); - if (!val.empty()) + if (val && ! (*val).empty()) { - if (!mapnik::util::string2int(val,quality) || quality < 0 || quality > 100) + if (!mapnik::util::string2int(*val, quality) || quality < 0 || quality > 100) { - throw ImageWriterException("invalid jpeg quality: '" + val + "'"); + throw image_writer_exception("invalid jpeg quality: '" + *val + "'"); } } } @@ -74,7 +69,7 @@ void process_rgba8_jpeg(T const& image, std::string const& type, std::ostream & } save_as_jpeg(stream, quality, image); #else - throw ImageWriterException("jpeg output is not enabled in your build of Mapnik"); + throw image_writer_exception("jpeg output is not enabled in your build of Mapnik"); #endif } @@ -93,19 +88,19 @@ void jpeg_saver::operator() (image_view_rgba8 const& image) co template<> void jpeg_saver::operator() (image_null const& image) const { - throw ImageWriterException("Can not save a null image to jpeg"); + throw image_writer_exception("Can not save a null image to jpeg"); } template<> void jpeg_saver::operator() (image_view_null const& image) const { - throw ImageWriterException("Can not save a null image to jpeg"); + throw image_writer_exception("Can not save a null image to jpeg"); } template void jpeg_saver::operator() (T const& image) const { - throw ImageWriterException("Mapnik does not support jpeg grayscale images"); + throw image_writer_exception("Mapnik does not support jpeg grayscale images"); } template void jpeg_saver::operator() (image_rgba8 const& image) const; diff --git a/src/image_util_png.cpp b/src/image_util_png.cpp index 9b1f6c911..7e4dd0ab7 100644 --- a/src/image_util_png.cpp +++ b/src/image_util_png.cpp @@ -37,11 +37,9 @@ extern "C" #include #include #include +#include #include -// boost -#include - // stl #include #include @@ -64,75 +62,70 @@ void handle_png_options(std::string const& type, opts.paletted = true; return; } - boost::char_separator sep(":"); - boost::tokenizer< boost::char_separator > tokens(type, sep); + bool set_colors = false; bool set_gamma = false; - for (std::string const& t : tokens) + + for (auto const& kv : parse_image_options(type)) { - if (t == "png8" || t == "png256") + auto const& key = kv.first; + auto const& val = kv.second; + if (key == "png8" || key == "png256") { opts.paletted = true; } - else if (t == "png" || t == "png24" || t == "png32") + else if (key == "png" || key == "png24" || key == "png32") { opts.paletted = false; } - else if (t == "m=o") + else if (key == "m" && val) { - opts.quantization = png_options::OCTTREE; + if (*val == "o") opts.quantization = png_options::OCTTREE; + else if (*val == "h") opts.quantization = png_options::HEXTREE; + else if (*val == "iq") opts.quantization = png_options::IMGQUANT; } - else if (t == "m=h") + else if (key == "iqs") { - opts.quantization = png_options::HEXTREE; - } - else if (t == "m=iq") - { - opts.quantization = png_options::IMGQUANT; - - } - else if (boost::algorithm::starts_with(t, "iqs=")) - { - if (!mapnik::util::string2int(t.substr(4), opts.iq_speed) || opts.iq_speed < 1 || opts.iq_speed > 10) + if (!val || !mapnik::util::string2int(*val, opts.iq_speed) || opts.iq_speed < 1 || opts.iq_speed > 10) { - throw ImageWriterException("invalid iq speed parameter: " + t.substr(4)); + throw ImageWriterException("invalid iq speed parameter: " + to_string(val)); } } - else if (boost::algorithm::starts_with(t, "iqd=")) + else if (key == "iqd") { - if (!mapnik::util::string2double(t.substr(4), opts.iq_dither) || opts.iq_dither < 0 || opts.iq_dither > 1) + if (!val || !mapnik::util::string2double(*val, opts.iq_dither) || opts.iq_dither < 0 || opts.iq_dither > 1) { - throw ImageWriterException("invalid iq dithering parameter: " + t.substr(4)); + throw ImageWriterException("invalid iq dithering parameter: " + to_string(val)); } } - else if (t == "e=miniz") + else if (key == "e" && val && *val == "miniz") { opts.use_miniz = true; } - else if (boost::algorithm::starts_with(t, "c=")) + else if (key == "c") { set_colors = true; - if (!mapnik::util::string2int(t.substr(2),opts.colors) || opts.colors < 1 || opts.colors > 256) + if (!val || !mapnik::util::string2int(*val, opts.colors) || opts.colors < 1 || opts.colors > 256) { - throw ImageWriterException("invalid color parameter: " + t.substr(2)); + throw image_writer_exception("invalid color parameter: " + to_string(val)); } } - else if (boost::algorithm::starts_with(t, "t=")) + else if (key == "t") { - if (!mapnik::util::string2int(t.substr(2),opts.trans_mode) || opts.trans_mode < 0 || opts.trans_mode > 2) + if (!val || !mapnik::util::string2int(*val,opts.trans_mode) || opts.trans_mode < 0 || opts.trans_mode > 2) { - throw ImageWriterException("invalid trans_mode parameter: " + t.substr(2)); + throw image_writer_exception("invalid trans_mode parameter: " + to_string(val)); } } - else if (boost::algorithm::starts_with(t, "g=")) + else if (key == "g") { set_gamma = true; - if (!mapnik::util::string2double(t.substr(2),opts.gamma) || opts.gamma < 0) + if (!val || !mapnik::util::string2double(*val, opts.gamma) || opts.gamma < 0) { - throw ImageWriterException("invalid gamma parameter: " + t.substr(2)); + throw image_writer_exception("invalid gamma parameter: " + to_string(val)); } } - else if (boost::algorithm::starts_with(t, "z=")) + else if (key == "z") { /* #define Z_NO_COMPRESSION 0 @@ -140,58 +133,59 @@ void handle_png_options(std::string const& type, #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) */ - if (!mapnik::util::string2int(t.substr(2),opts.compression) + if (!val || !mapnik::util::string2int(*val, opts.compression) || opts.compression < Z_DEFAULT_COMPRESSION || opts.compression > 10) // use 10 here rather than Z_BEST_COMPRESSION (9) to allow for MZ_UBER_COMPRESSION { - throw ImageWriterException("invalid compression parameter: " + t.substr(2) + " (only -1 through 10 are valid)"); + throw image_writer_exception("invalid compression parameter: " + to_string(val) + " (only -1 through 10 are valid)"); } } - else if (boost::algorithm::starts_with(t, "s=")) + else if (key == "s") { - std::string s = t.substr(2); - if (s == "default") + if (!val) throw image_writer_exception("invalid compression parameter: "); + + if (*val == "default") { opts.strategy = Z_DEFAULT_STRATEGY; } - else if (s == "filtered") + else if (*val == "filtered") { opts.strategy = Z_FILTERED; } - else if (s == "huff") + else if (*val == "huff") { opts.strategy = Z_HUFFMAN_ONLY; } - else if (s == "rle") + else if (*val == "rle") { opts.strategy = Z_RLE; } - else if (s == "fixed") + else if (*val == "fixed") { opts.strategy = Z_FIXED; } else { - throw ImageWriterException("invalid compression strategy parameter: " + s); + throw image_writer_exception("invalid compression strategy parameter: " + *val); } } else { - throw ImageWriterException("unhandled png option: " + t); + throw image_writer_exception("unhandled png option: " + key); } } // validation if (!opts.paletted && set_colors) { - throw ImageWriterException("invalid color parameter: unavailable for true color (non-paletted) images"); + throw image_writer_exception("invalid color parameter: unavailable for true color (non-paletted) images"); } if (!opts.paletted && set_gamma) { - throw ImageWriterException("invalid gamma parameter: unavailable for true color (non-paletted) images"); + throw image_writer_exception("invalid gamma parameter: unavailable for true color (non-paletted) images"); } if ((opts.use_miniz == false) && opts.compression > Z_BEST_COMPRESSION) { - throw ImageWriterException("invalid compression value: (only -1 through 9 are valid)"); + throw image_writer_exception("invalid compression value: (only -1 through 9 are valid)"); } } #endif @@ -205,29 +199,29 @@ png_saver_pal::png_saver_pal(std::ostream & stream, std::string const& t, rgba_p template<> void png_saver::operator() (image_null const& image) const { - throw ImageWriterException("null images not supported for png"); + throw image_writer_exception("null images not supported for png"); } template<> void png_saver_pal::operator() (image_null const& image) const { - throw ImageWriterException("null images not supported for png"); + throw image_writer_exception("null images not supported for png"); } template<> void png_saver::operator() (image_view_null const& image) const { - throw ImageWriterException("null image views not supported for png"); + throw image_writer_exception("null image views not supported for png"); } template<> void png_saver_pal::operator() (image_view_null const& image) const { - throw ImageWriterException("null image views not supported for png"); + throw image_writer_exception("null image views not supported for png"); } template -void process_rgba8_png_pal(T const& image, +void process_rgba8_png_pal(T const& image, std::string const& t, std::ostream & stream, rgba_palette const& pal) @@ -261,12 +255,12 @@ void process_rgba8_png_pal(T const& image, save_as_png(stream, image, opts); } #else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); + throw image_writer_exception("png output is not enabled in your build of Mapnik"); #endif } template -void process_rgba8_png(T const& image, +void process_rgba8_png(T const& image, std::string const& t, std::ostream & stream) { @@ -293,7 +287,7 @@ void process_rgba8_png(T const& image, save_as_png(stream, image, opts); } #else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); + throw image_writer_exception("png output is not enabled in your build of Mapnik"); #endif } @@ -325,12 +319,12 @@ template void png_saver::operator() (T const& image) const { #if defined(HAVE_PNG) - throw ImageWriterException("Mapnik does not support grayscale images for png"); + throw image_writer_exception("Mapnik does not support grayscale images for png"); //png_options opts; //handle_png_options(t_, opts); //save_as_png(stream_, image, opts); #else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); + throw image_writer_exception("png output is not enabled in your build of Mapnik"); #endif } @@ -338,12 +332,12 @@ template void png_saver_pal::operator() (T const& image) const { #if defined(HAVE_PNG) - throw ImageWriterException("Mapnik does not support grayscale images for png"); + throw image_writer_exception("Mapnik does not support grayscale images for png"); //png_options opts; //handle_png_options(t_, opts); //save_as_png(stream_, image, opts); #else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); + throw image_writer_exception("png output is not enabled in your build of Mapnik"); #endif } diff --git a/src/image_util_tiff.cpp b/src/image_util_tiff.cpp index fb611ca58..5c1e48684 100644 --- a/src/image_util_tiff.cpp +++ b/src/image_util_tiff.cpp @@ -29,11 +29,9 @@ #include #include #include +#include #include -// boost -#include - // stl #include @@ -50,111 +48,103 @@ void handle_tiff_options(std::string const& type, } if (type.length() > 4) { - boost::char_separator sep(":"); - boost::tokenizer< boost::char_separator > tokens(type, sep); - for (auto const& t : tokens) + + for (auto const& kv : parse_image_options(type)) { - if (t == "tiff") + auto const& key = kv.first; + auto const& val = kv.second; + if (key == "tiff") continue; + if (key == "compression") { - continue; - } - else if (boost::algorithm::starts_with(t, "compression=")) - { - std::string val = t.substr(12); - if (!val.empty()) + if (val && !(*val).empty()) { - if (val == "deflate") + if (*val == "deflate") { config.compression = COMPRESSION_DEFLATE; } - else if (val == "adobedeflate") + else if (*val == "adobedeflate") { config.compression = COMPRESSION_ADOBE_DEFLATE; } - else if (val == "lzw") + else if (*val == "lzw") { config.compression = COMPRESSION_LZW; } - else if (val == "none") - { + else if (*val == "none") + { config.compression = COMPRESSION_NONE; } else { - throw ImageWriterException("invalid tiff compression: '" + val + "'"); + throw image_writer_exception("invalid tiff compression: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "method=")) + else if (key == "method") { - std::string val = t.substr(7); - if (!val.empty()) + if (val && !(*val).empty()) { - if (val == "scanline") + if (*val == "scanline") { config.method = TIFF_WRITE_SCANLINE; } - else if (val == "strip" || val == "stripped") + else if (*val == "strip" || *val == "stripped") { config.method = TIFF_WRITE_STRIPPED; } - else if (val == "tiled") + else if (*val == "tiled") { config.method = TIFF_WRITE_TILED; } else { - throw ImageWriterException("invalid tiff method: '" + val + "'"); + throw image_writer_exception("invalid tiff method: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "zlevel=")) + else if (key == "zlevel") { - std::string val = t.substr(7); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9) + if (!mapnik::util::string2int(*val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9) { - throw ImageWriterException("invalid tiff zlevel: '" + val + "'"); + throw image_writer_exception("invalid tiff zlevel: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "tile_height=")) + else if (key == "tile_height") { - std::string val = t.substr(12); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.tile_height) || config.tile_height < 0 ) + if (!mapnik::util::string2int(*val,config.tile_height) || config.tile_height < 0 ) { - throw ImageWriterException("invalid tiff tile_height: '" + val + "'"); + throw image_writer_exception("invalid tiff tile_height: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "tile_width=")) + else if (key == "tile_width") { - std::string val = t.substr(11); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.tile_width) || config.tile_width < 0 ) + if (!mapnik::util::string2int(*val,config.tile_width) || config.tile_width < 0 ) { - throw ImageWriterException("invalid tiff tile_width: '" + val + "'"); + throw image_writer_exception("invalid tiff tile_width: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "rows_per_strip=")) + else if (key == "rows_per_strip") { - std::string val = t.substr(15); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.rows_per_strip) || config.rows_per_strip < 0 ) + if (!mapnik::util::string2int(*val,config.rows_per_strip) || config.rows_per_strip < 0 ) { - throw ImageWriterException("invalid tiff rows_per_strip: '" + val + "'"); + throw image_writer_exception("invalid tiff rows_per_strip: '" + *val + "'"); } } } else { - throw ImageWriterException("unhandled tiff option: " + t); + throw image_writer_exception("unhandled tiff option: " + key); } } } @@ -167,13 +157,13 @@ tiff_saver::tiff_saver(std::ostream & stream, std::string const& t): template<> void tiff_saver::operator() (image_null const& image) const { - throw ImageWriterException("null images not supported"); + throw image_writer_exception("null images not supported"); } template<> void tiff_saver::operator() (image_view_null const& image) const { - throw ImageWriterException("null image views not supported"); + throw image_writer_exception("null image views not supported"); } template @@ -184,7 +174,7 @@ void tiff_saver::operator() (T const& image) const handle_tiff_options(t_, opts); save_as_tiff(stream_, image, opts); #else - throw ImageWriterException("tiff output is not enabled in your build of Mapnik"); + throw image_writer_exception("tiff output is not enabled in your build of Mapnik"); #endif } diff --git a/src/image_util_webp.cpp b/src/image_util_webp.cpp index eb1075a45..c21a637ea 100644 --- a/src/image_util_webp.cpp +++ b/src/image_util_webp.cpp @@ -30,11 +30,9 @@ #include #include #include +#include #include -// boost -#include - // stl #include #include @@ -51,48 +49,45 @@ void handle_webp_options(std::string const& type, { return; } - if (type.length() > 4){ - boost::char_separator sep(":"); - boost::tokenizer< boost::char_separator > tokens(type, sep); - for (auto const& t : tokens) + if (type.length() > 4) + { + for (auto const& kv : parse_image_options(type)) { - if (t == "webp") + auto const& key = kv.first; + auto const& val = kv.second; + + if (key == "webp") continue; + + if (key == "quality") { - continue; - } - else if (boost::algorithm::starts_with(t, "quality=")) - { - std::string val = t.substr(8); - if (!val.empty()) + if (val && !(*val).empty()) { double quality = 90; - if (!mapnik::util::string2double(val,quality) || quality < 0.0 || quality > 100.0) + if (!mapnik::util::string2double(*val,quality) || quality < 0.0 || quality > 100.0) { - throw ImageWriterException("invalid webp quality: '" + val + "'"); + throw image_writer_exception("invalid webp quality: '" + *val + "'"); } config.quality = static_cast(quality); } } - else if (boost::algorithm::starts_with(t, "method=")) + else if (key == "method") { - std::string val = t.substr(7); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.method) || config.method < 0 || config.method > 6) + if (!mapnik::util::string2int(*val,config.method) || config.method < 0 || config.method > 6) { - throw ImageWriterException("invalid webp method: '" + val + "'"); + throw image_writer_exception("invalid webp method: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "lossless=")) + else if (key == "lossless") { - std::string val = t.substr(9); - if (!val.empty()) + if (val && !(*val).empty()) { #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - if (!mapnik::util::string2int(val,config.lossless) || config.lossless < 0 || config.lossless > 1) + if (!mapnik::util::string2int(*val,config.lossless) || config.lossless < 0 || config.lossless > 1) { - throw ImageWriterException("invalid webp lossless: '" + val + "'"); + throw image_writer_exception("invalid webp lossless: '" + *val + "'"); } #else #ifdef _MSC_VER @@ -100,20 +95,19 @@ void handle_webp_options(std::string const& type, #else #warning "compiling against webp that does not support the lossless flag" #endif - throw ImageWriterException("your webp version does not support the lossless option"); + throw image_writer_exception("your webp version does not support the lossless option"); #endif } } - else if (boost::algorithm::starts_with(t, "image_hint=")) + else if (key == "image_hint") { - std::string val = t.substr(11); - if (!val.empty()) + if (val && !(*val).empty()) { #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 int image_hint = 0; - if (!mapnik::util::string2int(val,image_hint) || image_hint < 0 || image_hint > 3) + if (!mapnik::util::string2int(*val,image_hint) || image_hint < 0 || image_hint > 3) { - throw ImageWriterException("invalid webp image_hint: '" + val + "'"); + throw image_writer_exception("invalid webp image_hint: '" + *val + "'"); } config.image_hint = static_cast(image_hint); #else @@ -122,131 +116,120 @@ void handle_webp_options(std::string const& type, #else #warning "compiling against webp that does not support the image_hint flag" #endif - throw ImageWriterException("your webp version does not support the image_hint option"); + throw image_writer_exception("your webp version does not support the image_hint option"); #endif } } - else if (boost::algorithm::starts_with(t, "alpha=")) + else if (key == "alpha") { - std::string val = t.substr(6); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2bool(val,alpha)) + if (!mapnik::util::string2bool(*val,alpha)) { - throw ImageWriterException("invalid webp alpha: '" + val + "'"); + throw image_writer_exception("invalid webp alpha: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "target_size=")) + else if (key == "target_size") { - std::string val = t.substr(12); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.target_size)) + if (!mapnik::util::string2int(*val,config.target_size)) { - throw ImageWriterException("invalid webp target_size: '" + val + "'"); + throw image_writer_exception("invalid webp target_size: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "target_psnr=")) + else if (key == "target_psnr") { - std::string val = t.substr(12); - if (!val.empty()) + if (val && !(*val).empty()) { double psnr = 0; - if (!mapnik::util::string2double(val,psnr)) + if (!mapnik::util::string2double(*val,psnr)) { - throw ImageWriterException("invalid webp target_psnr: '" + val + "'"); + throw image_writer_exception("invalid webp target_psnr: '" + *val + "'"); } config.target_PSNR = psnr; } } - else if (boost::algorithm::starts_with(t, "segments=")) + else if (key == "segments") { - std::string val = t.substr(9); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.segments)) + if (!mapnik::util::string2int(*val,config.segments)) { - throw ImageWriterException("invalid webp segments: '" + val + "'"); + throw image_writer_exception("invalid webp segments: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "sns_strength=")) + else if (key == "sns_strength") { - std::string val = t.substr(13); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.sns_strength)) + if (!mapnik::util::string2int(*val,config.sns_strength)) { - throw ImageWriterException("invalid webp sns_strength: '" + val + "'"); + throw image_writer_exception("invalid webp sns_strength: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "filter_strength=")) + else if (key == "filter_strength") { - std::string val = t.substr(16); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.filter_strength)) + if (!mapnik::util::string2int(*val,config.filter_strength)) { - throw ImageWriterException("invalid webp filter_strength: '" + val + "'"); + throw image_writer_exception("invalid webp filter_strength: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "filter_sharpness=")) + else if (key == "filter_sharpness") { - std::string val = t.substr(17); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.filter_sharpness)) + if (!mapnik::util::string2int(*val,config.filter_sharpness)) { - throw ImageWriterException("invalid webp filter_sharpness: '" + val + "'"); + throw image_writer_exception("invalid webp filter_sharpness: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "filter_type=")) + else if (key == "filter_type") { - std::string val = t.substr(12); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.filter_type)) + if (!mapnik::util::string2int(*val,config.filter_type)) { - throw ImageWriterException("invalid webp filter_type: '" + val + "'"); + throw image_writer_exception("invalid webp filter_type: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "autofilter=")) + else if (key == "autofilter") { - std::string val = t.substr(11); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.autofilter)) + if (!mapnik::util::string2int(*val,config.autofilter)) { - throw ImageWriterException("invalid webp autofilter: '" + val + "'"); + throw image_writer_exception("invalid webp autofilter: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "alpha_compression=")) + else if (key == "alpha_compression") { - std::string val = t.substr(18); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.alpha_compression)) + if (!mapnik::util::string2int(*val,config.alpha_compression)) { - throw ImageWriterException("invalid webp alpha_compression: '" + val + "'"); + throw image_writer_exception("invalid webp alpha_compression: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "alpha_filtering=")) + else if (key == "alpha_filtering") { - std::string val = t.substr(16); - if (!val.empty()) + if (val && !(*val).empty()) { #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - if (!mapnik::util::string2int(val,config.alpha_filtering)) + if (!mapnik::util::string2int(*val,config.alpha_filtering)) { - throw ImageWriterException("invalid webp alpha_filtering: '" + val + "'"); + throw image_writer_exception("invalid webp alpha_filtering: '" + *val + "'"); } #else #ifdef _MSC_VER @@ -254,19 +237,18 @@ void handle_webp_options(std::string const& type, #else #warning "compiling against webp that does not support the alpha_filtering flag" #endif - throw ImageWriterException("your webp version does not support the alpha_filtering option"); + throw image_writer_exception("your webp version does not support the alpha_filtering option"); #endif } } - else if (boost::algorithm::starts_with(t, "alpha_quality=")) + else if (key == "alpha_quality") { - std::string val = t.substr(14); - if (!val.empty()) + if (val && !(*val).empty()) { #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - if (!mapnik::util::string2int(val,config.alpha_quality)) + if (!mapnik::util::string2int(*val,config.alpha_quality)) { - throw ImageWriterException("invalid webp alpha_quality: '" + val + "'"); + throw image_writer_exception("invalid webp alpha_quality: '" + *val + "'"); } #else #ifdef _MSC_VER @@ -274,57 +256,53 @@ void handle_webp_options(std::string const& type, #else #warning "compiling against webp that does not support the alpha_quality flag" #endif - throw ImageWriterException("your webp version does not support the alpha_quality option"); + throw image_writer_exception("your webp version does not support the alpha_quality option"); #endif } } - else if (boost::algorithm::starts_with(t, "pass=")) + else if (key == "pass") { - std::string val = t.substr(5); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.pass)) + if (!mapnik::util::string2int(*val,config.pass)) { - throw ImageWriterException("invalid webp pass: '" + val + "'"); + throw image_writer_exception("invalid webp pass: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "preprocessing=")) + else if (key == "preprocessing") { - std::string val = t.substr(14); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.preprocessing)) + if (!mapnik::util::string2int(*val,config.preprocessing)) { - throw ImageWriterException("invalid webp preprocessing: '" + val + "'"); + throw image_writer_exception("invalid webp preprocessing: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "partitions=")) + else if (key == "partitions") { - std::string val = t.substr(11); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.partitions)) + if (!mapnik::util::string2int(*val,config.partitions)) { - throw ImageWriterException("invalid webp partitions: '" + val + "'"); + throw image_writer_exception("invalid webp partitions: '" + *val + "'"); } } } - else if (boost::algorithm::starts_with(t, "partition_limit=")) + else if (key == "partition_limit") { - std::string val = t.substr(16); - if (!val.empty()) + if (val && !(*val).empty()) { - if (!mapnik::util::string2int(val,config.partition_limit)) + if (!mapnik::util::string2int(*val,config.partition_limit)) { - throw ImageWriterException("invalid webp partition_limit: '" + val + "'"); + throw image_writer_exception("invalid webp partition_limit: '" + *val + "'"); } } } else { - throw ImageWriterException("unhandled webp option: " + t); + throw image_writer_exception("unhandled webp option: " + key); } } } @@ -337,13 +315,13 @@ webp_saver::webp_saver(std::ostream & stream, std::string const& t): template<> void webp_saver::operator() (image_null const& image) const { - throw ImageWriterException("null images not supported"); + throw image_writer_exception("null images not supported"); } template<> void webp_saver::operator() (image_view_null const& image) const { - throw ImageWriterException("null image views not supported"); + throw image_writer_exception("null image views not supported"); } template @@ -361,7 +339,7 @@ void process_rgba8_webp(T const& image, std::string const& t, std::ostream & str handle_webp_options(t,config,alpha); save_as_webp(stream,image,config,alpha); #else - throw ImageWriterException("webp output is not enabled in your build of Mapnik"); + throw image_writer_exception("webp output is not enabled in your build of Mapnik"); #endif } @@ -380,7 +358,7 @@ void webp_saver::operator() (image_view_rgba8 const& image) co template void webp_saver::operator() (T const& image) const { - throw ImageWriterException("Mapnik does not support webp grayscale images"); + throw image_writer_exception("Mapnik does not support webp grayscale images"); } template void webp_saver::operator() (image_rgba8 const& image) const; diff --git a/src/layer.cpp b/src/layer.cpp index a5180a7d8..1a9cf8387 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -34,8 +34,8 @@ namespace mapnik layer::layer(std::string const& name, std::string const& srs) : name_(name), srs_(srs), - min_zoom_(0), - max_zoom_(std::numeric_limits::max()), + minimum_scale_denom_(0), + maximum_scale_denom_(std::numeric_limits::max()), active_(true), queryable_(false), clear_label_cache_(false), @@ -49,8 +49,8 @@ layer::layer(std::string const& name, std::string const& srs) layer::layer(layer const& rhs) : name_(rhs.name_), srs_(rhs.srs_), - min_zoom_(rhs.min_zoom_), - max_zoom_(rhs.max_zoom_), + minimum_scale_denom_(rhs.minimum_scale_denom_), + maximum_scale_denom_(rhs.maximum_scale_denom_), active_(rhs.active_), queryable_(rhs.queryable_), clear_label_cache_(rhs.clear_label_cache_), @@ -64,8 +64,8 @@ layer::layer(layer const& rhs) layer::layer(layer && rhs) : name_(std::move(rhs.name_)), srs_(std::move(rhs.srs_)), - min_zoom_(std::move(rhs.min_zoom_)), - max_zoom_(std::move(rhs.max_zoom_)), + minimum_scale_denom_(std::move(rhs.minimum_scale_denom_)), + maximum_scale_denom_(std::move(rhs.maximum_scale_denom_)), active_(std::move(rhs.active_)), queryable_(std::move(rhs.queryable_)), clear_label_cache_(std::move(rhs.clear_label_cache_)), @@ -81,8 +81,8 @@ layer& layer::operator=(layer rhs) using std::swap; std::swap(this->name_,rhs.name_); std::swap(this->srs_, rhs.srs_); - std::swap(this->min_zoom_, rhs.min_zoom_); - std::swap(this->max_zoom_,rhs.max_zoom_); + std::swap(this->minimum_scale_denom_, rhs.minimum_scale_denom_); + std::swap(this->maximum_scale_denom_,rhs.maximum_scale_denom_); std::swap(this->active_, rhs.active_); std::swap(this->queryable_, rhs.queryable_); std::swap(this->clear_label_cache_, rhs.clear_label_cache_); @@ -99,8 +99,8 @@ bool layer::operator==(layer const& rhs) const { return (name_ == rhs.name_) && (srs_ == rhs.srs_) && - (min_zoom_ == rhs.min_zoom_) && - (max_zoom_ == rhs.max_zoom_) && + (minimum_scale_denom_ == rhs.minimum_scale_denom_) && + (maximum_scale_denom_ == rhs.maximum_scale_denom_) && (active_ == rhs.active_) && (queryable_ == rhs.queryable_) && (clear_label_cache_ == rhs.clear_label_cache_) && @@ -149,24 +149,24 @@ std::vector & layer::styles() return styles_; } -void layer::set_min_zoom(double min_zoom) +void layer::set_minimum_scale_denominator(double minimum_scale_denom) { - min_zoom_=min_zoom; + minimum_scale_denom_=minimum_scale_denom; } -void layer::set_max_zoom(double max_zoom) +void layer::set_maximum_scale_denominator(double maximum_scale_denom) { - max_zoom_=max_zoom; + maximum_scale_denom_=maximum_scale_denom; } -double layer::min_zoom() const +double layer::minimum_scale_denominator() const { - return min_zoom_; + return minimum_scale_denom_; } -double layer::max_zoom() const +double layer::maximum_scale_denominator() const { - return max_zoom_; + return maximum_scale_denom_; } void layer::set_active(bool active) @@ -179,9 +179,9 @@ bool layer::active() const return active_; } -bool layer::visible(double scale) const +bool layer::visible(double scale_denom) const { - return active() && scale >= min_zoom_ - 1e-6 && scale < max_zoom_ + 1e-6; + return active() && scale_denom >= minimum_scale_denom_ - 1e-6 && scale_denom < maximum_scale_denom_ + 1e-6; } void layer::set_queryable(bool queryable) diff --git a/src/load_map.cpp b/src/load_map.cpp index 9e2cacd58..b6fc25977 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -587,17 +587,34 @@ void map_parser::parse_layer(Map & map, xml_node const& node) lyr.set_active(* status); } - optional min_zoom = node.get_opt_attr("minzoom"); - if (min_zoom) + optional minimum_scale_denom = node.get_opt_attr("minimum-scale-denominator"); + if (minimum_scale_denom) { - lyr.set_min_zoom(* min_zoom); + lyr.set_minimum_scale_denominator(* minimum_scale_denom); + } + else // back compatibility: remove at Mapnik 4.x + { + optional min_zoom = node.get_opt_attr("minzoom"); + if (min_zoom) + { + MAPNIK_LOG_ERROR(markers_symbolizer) << "'minzoom' is deprecated and will be removed in Mapnik 4.x, use 'minimum-scale-denominator' instead (encountered in layer " << name << ")"; + lyr.set_minimum_scale_denominator(* min_zoom); + } } - - optional max_zoom = node.get_opt_attr("maxzoom"); - if (max_zoom) + optional maximum_scale_denom = node.get_opt_attr("maximum-scale-denominator"); + if (maximum_scale_denom) { - lyr.set_max_zoom(* max_zoom); + lyr.set_maximum_scale_denominator(* maximum_scale_denom); + } + else // back compatibility: remove at Mapnik 4.x + { + optional max_zoom = node.get_opt_attr("maxzoom"); + if (max_zoom) + { + MAPNIK_LOG_ERROR(markers_symbolizer) << "'maxzoom' is deprecated and will be removed in Mapnik 4.x, use 'maximum-scale-denominator' instead (encountered in layer " << name << ")"; + lyr.set_maximum_scale_denominator(* max_zoom); + } } optional queryable = node.get_opt_attr("queryable"); diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 7931e9123..b2cb37de9 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -264,16 +264,32 @@ bool proj_transform::forward (box2d & box) const if (is_source_equal_dest_) return true; - double minx = box.minx(); - double miny = box.miny(); - double maxx = box.maxx(); - double maxy = box.maxy(); + 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 (!forward(minx,miny,z)) + if (!forward(llx,lly,z)) return false; - if (!forward(maxx,maxy,z)) + if (!forward(lrx,lry,z)) return false; - box.init(minx,miny,maxx,maxy); + if (!forward(ulx,uly,z)) + return false; + if (!forward(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); + box.init(minx, + miny, + maxx, + maxy); return true; } @@ -282,16 +298,31 @@ bool proj_transform::backward (box2d & box) const if (is_source_equal_dest_) return true; - double minx = box.minx(); - double miny = box.miny(); - double maxx = box.maxx(); - double maxy = box.maxy(); + 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(minx,miny,z)) + if (!backward(llx,lly,z)) return false; - if (!backward(maxx,maxy,z)) + if (!backward(lrx,lry,z)) return false; - box.init(minx,miny,maxx,maxy); + 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); + box.init(minx, + miny, + maxx, + maxy); return true; } diff --git a/src/save_map.cpp b/src/save_map.cpp index 620f4ab13..42314d011 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -531,14 +531,14 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau set_attr/**/( layer_node, "clear-label-cache", layer.clear_label_cache() ); } - if ( layer.min_zoom() ) + if ( layer.minimum_scale_denominator() ) { - set_attr( layer_node, "minzoom", layer.min_zoom() ); + set_attr( layer_node, "minimum_scale_denominator", layer.minimum_scale_denominator() ); } - if ( layer.max_zoom() != std::numeric_limits::max() ) + if ( layer.maximum_scale_denominator() != std::numeric_limits::max() ) { - set_attr( layer_node, "maxzoom", layer.max_zoom() ); + set_attr( layer_node, "maximum_scale_denominator", layer.maximum_scale_denominator() ); } if ( layer.queryable() || explicit_defaults ) diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index d3c2622a9..ff44147d2 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -88,7 +88,6 @@ bool placement_finder::next_position() horizontal_alignment_ = layout->horizontal_alignment(); return true; } - MAPNIK_LOG_WARN(placement_finder) << "next_position() called while last call already returned false!\n"; return false; } @@ -239,10 +238,9 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or double last_cluster_angle = 999; int current_cluster = -1; pixel_position cluster_offset; - double angle; + double angle = 0; rotation rot; - double last_glyph_spacing = 0.; - + double last_glyph_spacing = 0.0; for (auto const& glyph : line) { if (current_cluster != static_cast(glyph.char_index)) @@ -250,13 +248,17 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or if (adjust) { if (!off_pp.move(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing))) + { return false; + } last_glyph_spacing = adjust_character_spacing; } else { if (!off_pp.move_to_distance(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing))) + { return false; + } last_glyph_spacing = glyph.format->character_spacing * scale_factor_; } current_cluster = glyph.char_index; @@ -274,7 +276,10 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or last_cluster_angle = angle; } - if (std::abs(angle) > M_PI/2) ++upside_down_glyph_count; + if (std::abs(angle) > M_PI/2) + { + ++upside_down_glyph_count; + } pixel_position pos = off_pp.current_position() + cluster_offset; // Center the text on the line diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index 7761ed8b0..7b1559976 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -318,6 +318,40 @@ placements_list const& text_symbolizer_helper::get() const return finder_.placements(); } +class apply_line_placement_visitor +{ +public: + apply_line_placement_visitor(vertex_converter_type & converter, + placement_finder_adapter const & adapter) + : converter_(converter), adapter_(adapter) + { + } + + bool operator()(geometry::line_string const & geo) const + { + geometry::line_string_vertex_adapter va(geo); + converter_.apply(va, adapter_); + return adapter_.status(); + } + + bool operator()(geometry::polygon const & geo) const + { + geometry::polygon_vertex_adapter va(geo); + converter_.apply(va, adapter_); + return adapter_.status(); + } + + template + bool operator()(T const & geo) const + { + return false; + } + +private: + vertex_converter_type & converter_; + placement_finder_adapter const & adapter_; +}; + bool text_symbolizer_helper::next_line_placement() const { while (!geometries_to_process_.empty()) @@ -331,17 +365,11 @@ bool text_symbolizer_helper::next_line_placement() const continue; //Reexecute size check } - if (geo_itr_->is()) // line_string + if (mapnik::util::apply_visitor(apply_line_placement_visitor(converter_, adapter_), *geo_itr_)) { - auto const& line = util::get const>(*geo_itr_); - geometry::line_string_vertex_adapter va(line); - converter_.apply(va, adapter_); - if (adapter_.status()) - { - //Found a placement - geo_itr_ = geometries_to_process_.erase(geo_itr_); - return true; - } + //Found a placement + geo_itr_ = geometries_to_process_.erase(geo_itr_); + return true; } // No placement for this geometry. Keep it in geometries_to_process_ for next try. diff --git a/src/text/text_layout.cpp b/src/text/text_layout.cpp index fbaebe958..fd2fdc56d 100644 --- a/src/text/text_layout.cpp +++ b/src/text/text_layout.cpp @@ -224,7 +224,9 @@ void text_layout::break_line_icu(std::pair && line_limits) double wrap_at; double string_width = line.width(); double string_height = line.line_height(); - for (double i = 1.0; ((wrap_at = string_width/i)/(string_height*i)) > text_ratio_ && (string_width/i) > scaled_wrap_width; i += 1.0) ; + for (double i = 1.0; + ((wrap_at = string_width/i)/(string_height*i)) > text_ratio_ && (string_width/i) > scaled_wrap_width; + i += 1.0) ; scaled_wrap_width = wrap_at; } @@ -243,10 +245,9 @@ void text_layout::break_line_icu(std::pair && line_limits) } breakitr->setText(text); - double current_line_length = 0; int last_break_position = static_cast(line.first_char()); - for (unsigned i=line.first_char(); i < line.last_char(); ++i) + for (unsigned i = line.first_char(); i < line.last_char(); ++i) { // TODO: character_spacing std::map::const_iterator width_itr = width_map_.find(i); @@ -256,7 +257,7 @@ void text_layout::break_line_icu(std::pair && line_limits) } if (current_line_length <= scaled_wrap_width) continue; - int break_position = wrap_before_ ? breakitr->preceding(i) : breakitr->following(i); + int break_position = wrap_before_ ? breakitr->preceding(i + 1) : breakitr->following(i); // following() returns a break position after the last word. So DONE should only be returned // when calling preceding. if (break_position <= last_break_position || break_position == static_cast(BreakIterator::DONE)) @@ -280,15 +281,18 @@ void text_layout::break_line_icu(std::pair && line_limits) { break_position = line.last_char(); } + bool adjust_for_space_character = break_position > 0 && text[break_position - 1] == 0x0020; - text_line new_line(last_break_position, break_position); - clear_cluster_widths(last_break_position, break_position); + text_line new_line(last_break_position, adjust_for_space_character ? break_position - 1 : break_position); + clear_cluster_widths(last_break_position, adjust_for_space_character ? break_position - 1 : break_position); shape_text(new_line); add_line(std::move(new_line)); + last_break_position = break_position; i = break_position - 1; current_line_length = 0; } + if (last_break_position == static_cast(line.first_char())) { // No line breaks => no reshaping required @@ -365,7 +369,7 @@ void text_layout::break_line(std::pair && line_limits) } if (current_line_length <= scaled_wrap_width) continue; - int break_position = wrap_before_ ? breaker.preceding(i) : breaker.following(i); + int break_position = wrap_before_ ? breaker.preceding(i + 1) : breaker.following(i); if (break_position <= last_break_position || break_position == static_cast(BreakIterator::DONE)) { break_position = breaker.following(i); diff --git a/test/data b/test/data index d51e1cffa..6802b2795 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit d51e1cffaf450148397dd68886edaf4936abb37d +Subproject commit 6802b27950218d7f620ffb7e73c5213aa003ea3c diff --git a/test/data-visual b/test/data-visual index 7fd9b1954..034075190 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 7fd9b1954e87105c69bb0670db486147e2284ff5 +Subproject commit 03407519069c6510da49b130ea03fba4fc22161c diff --git a/test/run b/test/run index f0d4a8c47..47b8f5500 100755 --- a/test/run +++ b/test/run @@ -11,16 +11,6 @@ function run_substep { >&2 echo -e "\033[1m\033[36m* $1\033[0m"; } function run_success { >&2 echo -e "\033[1m\033[32m* $1\033[0m"; } run_step "Starting Mapnik tests" -# mapnik-settings.env is an optional file to store -# environment variables that should be used before -# running tests like PROJ_LIB, GDAL_DATA, and ICU_DATA -# These do not normally need to be set except when -# building against binary versions of dependencies like -# done via bootstrap.sh -if [[ -f mapnik-settings.env ]]; then - run_substep "Inheriting from mapnik-settings.env" - source mapnik-settings.env -fi run_substep "Running C++ Unit tests..." ./test/unit/run diff --git a/test/unit/geometry/geometry_equal.hpp b/test/unit/geometry/geometry_equal.hpp index 9222c33ce..6b5dc6861 100644 --- a/test/unit/geometry/geometry_equal.hpp +++ b/test/unit/geometry/geometry_equal.hpp @@ -3,9 +3,14 @@ // boost #include #include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-local-typedef" #include #include #include +#pragma GCC diagnostic pop // helper namespace to ensure correct functionality namespace aux{ diff --git a/test/unit/imaging/image.cpp b/test/unit/imaging/image.cpp new file mode 100644 index 000000000..d2c908ed1 --- /dev/null +++ b/test/unit/imaging/image.cpp @@ -0,0 +1,292 @@ +#include "catch.hpp" + +// mapnik +#include +#include +#include +#include + +TEST_CASE("image class") { + +SECTION("test gray16") { + + const mapnik::image_gray16 im(4,4); + mapnik::image_gray16 im2(im); + mapnik::image_gray16 im3(5,5); + + CHECK(im == im); + CHECK_FALSE(im == im2); + CHECK_FALSE(im2 == im3); + CHECK(im < im3); + CHECK_FALSE(im < im2); + + // Check that width is correct + CHECK(im.width() == 4); + CHECK(im2.width() == 4); + + // Check that height is correct + CHECK(im.height() == 4); + CHECK(im2.height() == 4); + + CHECK(im(0,0) == 0); + CHECK(im2(0,0) == 0); + im2(0,0) = 1; + CHECK(im2(0,0) == 1); + im2.set(514); + CHECK(im2(0,0) == 514); + CHECK(im2(1,1) == 514); + + // Check that size is correct + CHECK(im.size() == 32); + CHECK(im2.size() == 32); + + // Check that row_size is correct + CHECK(im.row_size() == 8); + CHECK(im2.row_size() == 8); + + // Check that get_premultiplied is correct + CHECK_FALSE(im.get_premultiplied()); + CHECK_FALSE(im2.get_premultiplied()); + + // Check that set premultiplied works + im2.set_premultiplied(true); + CHECK(im2.get_premultiplied()); + + // Check that painted is correct + CHECK_FALSE(im.painted()); + CHECK_FALSE(im2.painted()); + + // Check that set premultiplied works + im2.painted(true); + CHECK(im2.painted()); + + // Check that offset is correct + CHECK(im.get_offset() == 0.0); + CHECK(im2.get_offset() == 0.0); + + // Check that set offset works + im2.set_offset(2.3); + CHECK(im2.get_offset() == 2.3); + + // Check that scaling is correct + CHECK(im.get_scaling() == 1.0); + CHECK(im2.get_scaling() == 1.0); + + // Check that set scaling works + im2.set_scaling(1.1); + CHECK(im2.get_scaling() == 1.1); + + // CHECK that image dtype is correct + CHECK(im.get_dtype() == mapnik::image_dtype_gray16); + CHECK(im2.get_dtype() == mapnik::image_dtype_gray16); + + using pixel_type = mapnik::image_view_gray16::pixel_type; + pixel_type expected_val; + // Check that all data in the view is correct + // IM + expected_val = 0; + pixel_type const* data_im = im.data(); + CHECK(*data_im == expected_val); + unsigned char const* data_b = im.bytes(); + CHECK(*data_b == 0); + for (std::size_t y = 0; y < im.height(); ++y) + { + std::size_t width = im.width(); + pixel_type const* data_1 = im.get_row(y); + pixel_type const* data_2 = im.get_row(y, 1); + for (std::size_t x = 0; x < width; ++x) + { + CHECK(*data_1 == expected_val); + ++data_1; + } + for (std::size_t x = 1; x < width; ++x) + { + CHECK(*data_2 == expected_val); + ++data_2; + } + } + // IM2 + expected_val = 514; + pixel_type * data_im2 = im2.data(); + CHECK(*data_im2 == expected_val); + unsigned char * data_b2 = im2.bytes(); + CHECK(*data_b2 == 2); + ++data_b; + CHECK(*data_b2 == 2); + for (std::size_t y = 0; y < im2.height(); ++y) + { + std::size_t width = im2.width(); + pixel_type const* data_1 = im2.get_row(y); + pixel_type const* data_2 = im2.get_row(y, 1); + for (std::size_t x = 0; x < width; ++x) + { + CHECK(*data_1 == expected_val); + ++data_1; + } + for (std::size_t x = 1; x < width; ++x) + { + CHECK(*data_2 == expected_val); + ++data_2; + } + } + + // Test set row + std::vector v1(im2.width(), 30); + std::vector v2(im2.width()-1, 50); + im2.set_row(0, v1.data(), v1.size()); + im2.set_row(1, 1, v2.size(), v2.data()); + + CHECK(im2(0,0) == 30); + CHECK(im2(0,1) == 514); + CHECK(im2(1,1) == 50); + +} // END SECTION + +SECTION("image_null") +{ + mapnik::image_null im_null; + const mapnik::image_null im_null2(2,2); // Actually doesn't really set any size + mapnik::image_null im_null3(im_null2); + mapnik::image_null im_null4(std::move(im_null3)); + + // All nulls are equal + CHECK(im_null == im_null4); + CHECK(im_null == im_null2); + + // No null is greater + CHECK_FALSE(im_null < im_null4); + CHECK_FALSE(im_null < im_null2); + + // Check defaults + CHECK(im_null.width() == 0); + CHECK(im_null.height() == 0); + CHECK(im_null.size() == 0); + CHECK(im_null.row_size() == 0); + // Setting offset does nothing + im_null.set_offset(10000000.0); + CHECK(im_null.get_offset() == 0.0); + // Setting scaling does nothing + im_null.set_scaling(123123123.0); + CHECK(im_null.get_scaling() == 1.0); + CHECK(im_null.get_dtype() == mapnik::image_dtype_null); + // Setting premultiplied does nothing + im_null.set_premultiplied(true); + CHECK_FALSE(im_null.get_premultiplied()); + // Setting painted does nothing + im_null.painted(true); + CHECK_FALSE(im_null.painted()); + + // Should throw if we try to access or setdata. + REQUIRE_THROWS(im_null(0,0)); + REQUIRE_THROWS(im_null2(0,0)); + REQUIRE_THROWS(im_null(0,0) = 1); + + unsigned char const* e1 = im_null.bytes(); + unsigned char * e2 = im_null.bytes(); + CHECK(e1 == nullptr); + CHECK(e2 == nullptr); + +} // END SECTION + +SECTION("image any") +{ + mapnik::image_null null_im; + const mapnik::image_any im_any_null(null_im); + CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null); + CHECK(im_any_null.bytes() == nullptr); + + mapnik::image_gray16 im(4,4); + mapnik::fill(im, 514); + mapnik::image_any im_any(im); + + CHECK(im_any.get_dtype() == mapnik::image_dtype_gray16); + unsigned char * foo = im_any.bytes(); + CHECK(*foo == 2); + ++foo; + CHECK(*foo == 2); + CHECK(im_any.width() == 4); + CHECK(im_any.height() == 4); + CHECK(im_any.size() == 32); + CHECK(im_any.row_size() == 8); + CHECK_FALSE(im_any.get_premultiplied()); + im_any.set_offset(10.0); + CHECK(im_any.get_offset() == 10.0); + im_any.set_scaling(2.1); + CHECK(im_any.get_scaling() == 2.1); + CHECK_FALSE(im_any.painted()); + +} // END SECTION + + +SECTION("test image_any initialization") +{ + { + mapnik::image_any im(4,4); + CHECK(im.get_dtype() == mapnik::image_dtype_rgba8); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_null); + CHECK(im.get_dtype() == mapnik::image_dtype_null); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray8); + CHECK(im.get_dtype() == mapnik::image_dtype_gray8); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray8s); + CHECK(im.get_dtype() == mapnik::image_dtype_gray8s); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray16); + CHECK(im.get_dtype() == mapnik::image_dtype_gray16); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray16s); + CHECK(im.get_dtype() == mapnik::image_dtype_gray16s); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray32); + CHECK(im.get_dtype() == mapnik::image_dtype_gray32); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray32s); + CHECK(im.get_dtype() == mapnik::image_dtype_gray32s); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray32f); + CHECK(im.get_dtype() == mapnik::image_dtype_gray32f); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray64); + CHECK(im.get_dtype() == mapnik::image_dtype_gray64); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray64s); + CHECK(im.get_dtype() == mapnik::image_dtype_gray64s); + } + { + mapnik::image_any im(4, 4, mapnik::image_dtype_gray64f); + CHECK(im.get_dtype() == mapnik::image_dtype_gray64f); + } + +} // END SECTION + +SECTION("Image Buffer") +{ + mapnik::detail::buffer buf_zero(0); + CHECK(buf_zero.size() == 0); + CHECK(!buf_zero); + mapnik::detail::buffer buf(10); + CHECK(buf.size() == 10); + CHECK_FALSE(!buf); + unsigned char * d = buf.data(); + *d = 9; + const mapnik::detail::buffer buf2 = buf; + CHECK(buf2.size() == 10); + unsigned char const* d2 = buf2.data(); + CHECK(*d2 == 9); + +} // END SECTION + +} // END TEST CASE + diff --git a/test/unit/imaging/image_multiply_alpha.cpp b/test/unit/imaging/image_multiply_alpha.cpp index f4d26f376..20bee304a 100644 --- a/test/unit/imaging/image_multiply_alpha.cpp +++ b/test/unit/imaging/image_multiply_alpha.cpp @@ -13,7 +13,7 @@ SECTION("test rgba8") { mapnik::image_rgba8 im2(4,4,true,true); // Initialize as already premultiplied mapnik::image_any im_any(mapnik::image_rgba8(4,4)); mapnik::image_any im2_any(mapnik::image_rgba8(4,4,true,true)); - + // Fill the images with meaningfull values mapnik::color c1(57,70,128,128); // This color is not premultiplied mapnik::color c2(57,70,128,128, true); // This color is premultiplied @@ -21,12 +21,12 @@ SECTION("test rgba8") { mapnik::fill(im_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied mapnik::fill(im2, c2); // Because c1 is premultiplied it will make the image premultiplied mapnik::fill(im2_any, c2); // Because c1 is premultiplied it will make the image premultiplied - + mapnik::multiply_alpha(im, 0.75); mapnik::multiply_alpha(im_any, 0.75); mapnik::multiply_alpha(im2, 0.75); mapnik::multiply_alpha(im2_any, 0.75); - + mapnik::color out; // This should have only changed the alpha, as it was not premultipleid out = mapnik::get_pixel(im, 0, 0); @@ -54,30 +54,35 @@ SECTION("test rgba8") { } // END SECTION SECTION("test rgba8 overflow") { - + mapnik::image_rgba8 im(4,4); mapnik::color c(128,128,128,128); // This color is premultiplied mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied - - mapnik::multiply_alpha(im, 2.5); - mapnik::color out; out = mapnik::get_pixel(im, 0, 0); CHECK(static_cast(out.red()) == 128); CHECK(static_cast(out.green()) == 128); CHECK(static_cast(out.blue()) == 128); - CHECK(static_cast(out.alpha()) == 255); + CHECK(static_cast(out.alpha()) == 128); + + mapnik::multiply_alpha(im, 2.5); + + out = mapnik::get_pixel(im, 0, 0); + CHECK(static_cast(out.red()) == 128); + CHECK(static_cast(out.green()) == 128); + CHECK(static_cast(out.blue()) == 128); + CHECK(static_cast(out.alpha()) == 128); } // END SECTION SECTION("test rgba8 underflow") { - + mapnik::image_rgba8 im(4,4); mapnik::color c(128,128,128,128); // This color is premultiplied mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied - + mapnik::multiply_alpha(im, -2.5); - + mapnik::color out; out = mapnik::get_pixel(im, 0, 0); CHECK(static_cast(out.red()) == 128); @@ -88,13 +93,12 @@ SECTION("test rgba8 underflow") { } // END SECTION SECTION("test gray8") { - + mapnik::image_gray8 im(4,4); mapnik::image_any im_any(mapnik::image_gray8(4,4)); - + CHECK_THROWS(mapnik::multiply_alpha(im, 0.25)); CHECK_THROWS(mapnik::multiply_alpha(im_any, 0.25)); } // END SECTION } // END TEST_CASE - diff --git a/test/unit/imaging/image_view.cpp b/test/unit/imaging/image_view.cpp index 4290ef251..dac76449b 100644 --- a/test/unit/imaging/image_view.cpp +++ b/test/unit/imaging/image_view.cpp @@ -50,6 +50,8 @@ SECTION("test rgba8") { CHECK(view_all == view_yellow); CHECK(view_all == view_red); + CHECK(view_all.data() == im); + // Check that view_all and view_all_2 are not the same underlying data CHECK_FALSE(view_all == view_all_2); CHECK(view_all < view_all_2); diff --git a/test/unit/pixel/palette.cpp b/test/unit/pixel/palette.cpp new file mode 100644 index 000000000..c45d06815 --- /dev/null +++ b/test/unit/pixel/palette.cpp @@ -0,0 +1,89 @@ +#include "catch.hpp" + +#include +#include +#include +#include +#include + +std::string get_file_contents(std::string const& filename) +{ + std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary); + if (in) + { + std::ostringstream contents; + contents << in.rdbuf(); + in.close(); + return(contents.str()); + } + throw(errno); +} + +TEST_CASE("palette") +{ + +SECTION("rgb") +{ + mapnik::rgb a(1,2,3); + mapnik::rgba b_(1,2,3,4); + mapnik::rgb b(b_); + mapnik::rgb c(3,4,5); + CHECK(a == b); + CHECK_FALSE(a == c); + +} // END SECTION + + +SECTION("rgba") +{ + mapnik::rgba a(1,2,3,4); + mapnik::rgba a_copy(1,2,3,4); + mapnik::rgba b(255,255,255,255); + mapnik::rgba c(4,3,2,1); + mapnik::rgb d_(1,2,3); + mapnik::rgba d(d_); + + mapnik::rgba e(16909060); + + CHECK(e.r == 4); + CHECK(e.g == 3); + CHECK(e.b == 2); + CHECK(e.a == 1); + + CHECK(a == a_copy); + CHECK_FALSE(a == c); + CHECK(c == e); + + mapnik::rgba::mean_sort_cmp msc; + + CHECK_FALSE(msc(a,a_copy)); + CHECK(msc(a,b)); + CHECK_FALSE(msc(a,c)); + CHECK(msc(a,d)); + +} // END SECTION + +SECTION("rgba palette - exceptions and bad palettes") +{ + REQUIRE_THROWS(mapnik::rgba_palette("foo")); + REQUIRE_THROWS(mapnik::rgba_palette("fooo", mapnik::rgba_palette::PALETTE_RGB)); + REQUIRE_THROWS(mapnik::rgba_palette("foo", mapnik::rgba_palette::PALETTE_ACT)); +} // END SECTION + +SECTION("rgba palette - act pal_64") +{ + std::string pal_64 = get_file_contents("./test/data/palettes/palette64.act"); + mapnik::rgba_palette rgba_pal(pal_64, mapnik::rgba_palette::PALETTE_ACT); + CHECK(rgba_pal.to_string() == "[Palette 64 colors #494746 #c37631 #89827c #d1955c #7397b9 #fc9237 #a09f9c #fbc147 #9bb3ce #b7c9a1 #b5d29c #c4b9aa #cdc4a5 #d5c8a3 #c1d7aa #ccc4b6 #dbd19c #b2c4d5 #eae487 #c9c8c6 #e4db99 #c9dcb5 #dfd3ac #cbd2c2 #d6cdbc #dbd2b6 #c0ceda #ece597 #f7ef86 #d7d3c3 #dfcbc3 #d1d0cd #d1e2bf #d3dec1 #dbd3c4 #e6d8b6 #f4ef91 #d3d3cf #cad5de #ded7c9 #dfdbce #fcf993 #ffff8a #dbd9d7 #dbe7cd #d4dce2 #e4ded3 #ebe3c9 #e0e2e2 #f4edc3 #fdfcae #e9e5dc #f4edda #eeebe4 #fefdc5 #e7edf2 #edf4e5 #f2efe9 #f6ede7 #fefedd #f6f4f0 #f1f5f8 #fbfaf8 #ffffff]"); + +} // END SECTION + +SECTION("rgba palette - act pal_256") +{ + std::string pal_ = get_file_contents("./test/data/palettes/palette256.act"); + mapnik::rgba_palette rgba_pal(pal_, mapnik::rgba_palette::PALETTE_ACT); + CHECK(rgba_pal.to_string() == "[Palette 256 colors #272727 #3c3c3c #484847 #564b41 #605243 #6a523e #555555 #785941 #5d5d5d #746856 #676767 #956740 #ba712e #787777 #cb752a #c27c3d #b68049 #dc8030 #df9e10 #878685 #e1a214 #928b82 #a88a70 #ea8834 #e7a81d #cb8d55 #909090 #94938c #e18f48 #f68d36 #6f94b7 #e1ab2e #8e959b #c79666 #999897 #ff9238 #ef9447 #a99a88 #f1b32c #919ca6 #a1a09f #f0b04b #8aa4bf #f8bc39 #b3ac8f #d1a67a #e3b857 #a8a8a7 #ffc345 #a2adb9 #afaeab #f9ab69 #afbba4 #c4c48a #b4b2af #dec177 #9ab2cf #a3bebb #d7b491 #b6cd9e #b5d29c #b9c8a2 #f1c969 #c5c79e #bbbab9 #cabdaa #a6bcd1 #cec4a7 #e7cc89 #dad98a #d5c9a3 #fabd8a #c1d7aa #cec5b4 #d1d1a5 #d9cf9f #c5c4c3 #d3c7b5 #ddd59d #b4c6d6 #d1cbb4 #d1c7ba #d7d1aa #e1c6ab #cbc7c2 #dbd0a9 #e8e58a #fee178 #d3cbba #dfd7a3 #d2cfb9 #c9ddb5 #d2cbbe #c3cbce #d7cbba #dcceb2 #dfd3aa #e5dd9a #dbd3b1 #ceccc6 #d7cbbe #d7cfba #dfc3be #dfd3ae #cbcbcb #cbd3c3 #d3cfc0 #e0d8aa #d7cfbe #dbd3b8 #ebe596 #dfd8b0 #c0ceda #f1ee89 #decfbc #d7cfc4 #d7d3c3 #d1d0cd #d2dfc0 #dbd3c3 #e7c7c3 #e7d7b3 #f2ed92 #d1e2bf #dad7c3 #fef383 #d3d3cf #dbd3c7 #e0d3c2 #dfd7c0 #ebe4a8 #dbd7c7 #dfd3c7 #f7f38f #c9d4de #dcdcc5 #dfd7c7 #e7d5c2 #d6d5d4 #faf78e #d7dfca #fbfb8a #fffb86 #dfd7cb #e5ddc0 #dad7d2 #ecd6c1 #cfd7de #e8d0cc #fbfb8e #fffb8a #eae3b8 #e3d7cd #dfdbce #fffb8e #ffff8a #f5efa6 #dae6cc #e3dbcf #edddc3 #dddbd6 #d5dbdf #ffff91 #e3dbd3 #fefc99 #e7dbd2 #eaddcd #e3dfd3 #ebd7d3 #dddddd #d4dee6 #e2dfd7 #fcdcc0 #e7dbd7 #e7dfd3 #ebe4cb #f4eeb8 #e3dfdb #e7dfd7 #ebded5 #e7e3d7 #fefea6 #e1ecd6 #ece5d3 #e7e3db #dee3e5 #ebe3db #efdfdb #efe3d8 #f4efc9 #e6ecdb #ebe3df #ebe7db #f0ecd3 #e5e6e5 #efe7da #ebe7df #efe3df #fefeb8 #dfe7ef #ebe7e3 #edebde #efe7e0 #e8efe0 #e7f3df #ebebe3 #e7ebe8 #f5edd9 #efebe3 #e3ebf1 #e9efe7 #ebebea #efebe7 #f0efe2 #ecf3e5 #fefdc9 #efefe7 #f3efe7 #f5f3e1 #f2efe9 #e9eef4 #ffeddf #efefef #f3efeb #f3f3eb #f0f7eb #fbf7e1 #fefed8 #f3f3ef #f7f3eb #eef3f7 #f7f7ea #f3f3f3 #f3f7ef #f7f3ef #f3f3f7 #f7f3f3 #f7f7ef #fffee3 #f3f7f7 #f7f7f3 #fcf7ee #f7f7f7 #f7fbf4 #f5f7fb #fbf7f6 #fffeef #f7fbfb #fbfbf7 #fbfbfb #fbfbff #fbfffb #fffbfb #fbffff #fffffb #ffffff]"); + +} // END SECTION + +} // END TEST CASE diff --git a/test/unit/projection/proj_transform.cpp b/test/unit/projection/proj_transform.cpp new file mode 100644 index 000000000..618b57de5 --- /dev/null +++ b/test/unit/projection/proj_transform.cpp @@ -0,0 +1,38 @@ +#include "catch.hpp" + +#include +#include +#include + +TEST_CASE("projection transform") +{ + +SECTION("Test bounding box transforms - 4326 to 3857") +{ + mapnik::projection proj_4326("+init=epsg:4326"); + mapnik::projection proj_3857("+init=epsg:3857"); + mapnik::proj_transform prj_trans(proj_4326, proj_3857); + + double minx = -45.0; + double miny = 55.0; + double maxx = -40.0; + double maxy = 75.0; + + mapnik::box2d bbox(minx, miny, maxx, maxy); + + prj_trans.forward(bbox); + INFO(bbox.to_string()); + CHECK(bbox.minx() == Approx(-5009377.085697311)); + CHECK(bbox.miny() == Approx(7361866.1130511891)); + CHECK(bbox.maxx() == Approx(-4452779.631730943)); + CHECK(bbox.maxy() == Approx(12932243.1119920239)); + + prj_trans.backward(bbox); + CHECK(bbox.minx() == Approx(minx)); + CHECK(bbox.miny() == Approx(miny)); + CHECK(bbox.maxx() == Approx(maxx)); + CHECK(bbox.maxy() == Approx(maxy)); + +} // END SECTION + +} // END TEST CASE diff --git a/test/visual/renderer.hpp b/test/visual/renderer.hpp index 6c8d234e2..045e41f3e 100644 --- a/test/visual/renderer.hpp +++ b/test/visual/renderer.hpp @@ -31,6 +31,7 @@ // mapnik #include +#include #include #if defined(HAVE_CAIRO) #include @@ -117,15 +118,16 @@ public: { typename Renderer::image_type image(ren.render(map, scale_factor)); boost::filesystem::path reference = reference_dir / image_file_name(name, map.width(), map.height(), scale_factor, true); + bool reference_exists = mapnik::util::exists(reference.string()); result res; - res.state = STATE_OK; + res.state = reference_exists ? STATE_OK : STATE_OVERWRITE; res.name = name; res.renderer_name = Renderer::name; res.scale_factor = scale_factor; res.size = map_size(map.width(), map.height()); res.reference_image_path = reference; - res.diff = ren.compare(image, reference); + res.diff = reference_exists ? ren.compare(image, reference) : 0; if (res.diff) { @@ -134,12 +136,12 @@ public: res.actual_image_path = path; res.state = STATE_FAIL; ren.save(image, path); + } - if (overwrite) - { - ren.save(image, reference); - res.state = STATE_OVERWRITE; - } + if ((res.diff && overwrite) || !reference_exists) + { + ren.save(image, reference); + res.state = STATE_OVERWRITE; } return res; diff --git a/utils/nik2img/nik2img.cpp b/utils/nik2img/nik2img.cpp index 1d11358df..e223cf086 100644 --- a/utils/nik2img/nik2img.cpp +++ b/utils/nik2img/nik2img.cpp @@ -11,7 +11,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedef" -#include #include #include #pragma GCC diagnostic pop @@ -135,7 +134,7 @@ int main (int argc,char** argv) vars[name] = tr.transcode(param.second.get().c_str()); } } - } + } } mapnik::agg_renderer ren(map,req,vars,im,scale_factor,0,0); ren.apply(); diff --git a/utils/ogrindex/ogrindex.cpp b/utils/ogrindex/ogrindex.cpp index 66c94c192..7e34a656f 100644 --- a/utils/ogrindex/ogrindex.cpp +++ b/utils/ogrindex/ogrindex.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include diff --git a/utils/shapeindex/shapeindex.cpp b/utils/shapeindex/shapeindex.cpp index 2390cd4a6..bcf4a57cf 100644 --- a/utils/shapeindex/shapeindex.cpp +++ b/utils/shapeindex/shapeindex.cpp @@ -32,7 +32,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedef" -#include #include #include #pragma GCC diagnostic pop