diff --git a/include/mapnik/image_reader.hpp b/include/mapnik/image_reader.hpp index bb8d30198..bda9b735e 100644 --- a/include/mapnik/image_reader.hpp +++ b/include/mapnik/image_reader.hpp @@ -53,6 +53,7 @@ struct MAPNIK_DECL image_reader { virtual unsigned width() const=0; virtual unsigned height() const=0; + virtual bool premultiplied_alpha() const=0; virtual void read(unsigned x,unsigned y,image_data_32& image)=0; virtual ~image_reader() {} }; diff --git a/include/mapnik/json/geometry_generator_grammar.hpp b/include/mapnik/json/geometry_generator_grammar.hpp index a1915b062..408bbf212 100644 --- a/include/mapnik/json/geometry_generator_grammar.hpp +++ b/include/mapnik/json/geometry_generator_grammar.hpp @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include #include // boost @@ -137,14 +137,14 @@ struct geometry_generator_grammar : using boost::spirit::karma::_r1; using boost::spirit::karma::eps; using boost::spirit::karma::string; - + coordinates = point | linestring | polygon ; - + point = &uint_(mapnik::Point)[_1 = _type(_val)] << point_coord [_1 = _first(_val)] ; - + linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] << lit('[') << coords @@ -156,13 +156,13 @@ struct geometry_generator_grammar : << coords2 << lit("]]") ; - - point_coord = &uint_ - << lit('[') + + point_coord = &uint_ + << lit('[') << coord_type << lit(',') << coord_type << lit("]") ; - + polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] << string[ if_ (_r1 > 1) [_1 = "],["] .else_[_1 = '[' ]] | &uint_ << lit(',')) @@ -170,25 +170,25 @@ struct geometry_generator_grammar : << lit(',') << coord_type << lit(']') ; - + coords2 %= *polygon_coord(_a) ; - + coords = point_coord % lit(',') ; - + } // rules karma::rule coordinates; karma::rule point; karma::rule linestring; karma::rule polygon; - + karma::rule coords; karma::rule, geometry_type const& ()> coords2; karma::rule point_coord; karma::rule polygon_coord; - + // phoenix functions phoenix::function _type; phoenix::function _first; @@ -200,7 +200,7 @@ struct geometry_generator_grammar : template struct multi_geometry_generator_grammar : - karma::grammar >, + karma::grammar >, geometry_container const& ()> { @@ -223,36 +223,36 @@ struct multi_geometry_generator_grammar : (mapnik::LineString + 3,"\"MultiLineString\"") (mapnik::Polygon + 3,"\"MultiPolygon\"") ; - - start %= ( eps(phoenix::at_c<1>(_a))[_a = _multi_type(_val)] + + start %= ( eps(phoenix::at_c<1>(_a))[_a = _multi_type(_val)] << lit("{\"type\":\"GeometryCollection\",\"geometries\":[") << geometry_collection << lit("]}") | - geometry) + geometry) ; - + geometry_collection = -(geometry2 % lit(',')) ; - - geometry = (lit("{\"type\":") - << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = _multi_type(_val)] + + geometry = (lit("{\"type\":") + << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = _multi_type(_val)] << lit(",\"coordinates\":") << string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = '[']] << coordinates << string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']']] - << lit('}')) | lit("null") + << lit('}')) | lit("null") ; - - geometry2 = lit("{\"type\":") + + geometry2 = lit("{\"type\":") << geometry_types[_1 = _a][_a = type_(_val)] << lit(",\"coordinates\":") << path - << lit('}') + << lit('}') ; - + coordinates %= path % lit(',') ; - + } // rules karma::rule >, diff --git a/include/mapnik/raster.hpp b/include/mapnik/raster.hpp index d48cf6bd0..2a9951966 100644 --- a/include/mapnik/raster.hpp +++ b/include/mapnik/raster.hpp @@ -32,11 +32,13 @@ struct raster { box2d ext_; image_data_32 data_; - raster(box2d const& ext,image_data_32 const& data) + bool premultiplied_alpha_; + raster(box2d const& ext,image_data_32 const& data, bool premultiplied_alpha = false) : ext_(ext), - data_(data) {} + data_(data), + premultiplied_alpha_(premultiplied_alpha) + {} }; } #endif // MAPNIK_RASTER_HPP - diff --git a/include/mapnik/simplify_converter.hpp b/include/mapnik/simplify_converter.hpp index 83e9a0235..2476311d2 100644 --- a/include/mapnik/simplify_converter.hpp +++ b/include/mapnik/simplify_converter.hpp @@ -17,7 +17,8 @@ namespace mapnik { -struct weighted_vertex : private boost::noncopyable { +struct weighted_vertex : private boost::noncopyable +{ vertex2d coord; double weight; weighted_vertex *prev; @@ -27,20 +28,23 @@ struct weighted_vertex : private boost::noncopyable { coord(coord_), weight(std::numeric_limits::infinity()), prev(NULL), - next(NULL) { } + next(NULL) {} - double nominalWeight() { + double nominalWeight() + { if (prev == NULL || next == NULL || coord.cmd != SEG_LINETO) { return std::numeric_limits::infinity(); } - vertex2d& A = prev->coord; - vertex2d& B = next->coord; - vertex2d& C = coord; + vertex2d const& A = prev->coord; + vertex2d const& B = next->coord; + vertex2d const& C = coord; return std::abs((double)((A.x - C.x) * (B.y - A.y) - (A.x - B.x) * (C.y - A.y))) / 2.0; } - struct ascending_sort { - bool operator() (const weighted_vertex *a, const weighted_vertex *b) { + struct ascending_sort + { + bool operator() (const weighted_vertex *a, const weighted_vertex *b) + { return b->weight > a->weight; } }; @@ -97,10 +101,11 @@ struct MAPNIK_DECL simplify_converter { public: simplify_converter(Geometry& geom) - : geom_(geom) - , tolerance_(0.0) - , status_(initial) - , algorithm_(radial_distance) + : geom_(geom), + tolerance_(0.0), + status_(initial), + algorithm_(radial_distance), + pos_(0) {} enum status @@ -117,8 +122,10 @@ public: return algorithm_; } - void set_simplify_algorithm(simplify_algorithm_e value) { - if (algorithm_ != value) { + void set_simplify_algorithm(simplify_algorithm_e value) + { + if (algorithm_ != value) + { algorithm_ = value; reset(); } @@ -145,7 +152,7 @@ public: pos_ = 0; } - void rewind(unsigned int) + void rewind(unsigned int) const { pos_ = 0; } @@ -360,7 +367,8 @@ private: } } - status init_vertices_visvalingam_whyatt() { + status init_vertices_visvalingam_whyatt() + { typedef std::set VertexSet; typedef std::vector VertexList; @@ -371,13 +379,13 @@ private: v_list.push_back(new weighted_vertex(vtx)); } - if (!v_list.size()) { + if (v_list.empty()) { return status_ = process; } // Connect the vertices in a linked list and insert them into the set. VertexSet v; - for (VertexList::iterator i = v_list.begin(); i != v_list.end(); i++) + for (VertexList::iterator i = v_list.begin(); i != v_list.end(); ++i) { (*i)->prev = i == v_list.begin() ? NULL : *(i - 1); (*i)->next = i + 1 == v_list.end() ? NULL : *(i + 1); @@ -415,9 +423,10 @@ private: v.clear(); // Traverse the remaining list and insert them into the vertex cache. - for (VertexList::iterator i = v_list.begin(); i != v_list.end(); i++) + for (VertexList::iterator i = v_list.begin(); i != v_list.end(); ++i) { - if ((*i)->weight >= tolerance_) { + if ((*i)->weight >= tolerance_) + { vertices_.push_back((*i)->coord); } delete *i; @@ -431,10 +440,10 @@ private: double tolerance_; status status_; simplify_algorithm_e algorithm_; - size_t pos_; std::deque vertices_; std::deque sleeve_cont_; vertex2d previous_vertex_; + mutable size_t pos_; }; diff --git a/include/mapnik/util/container_adapter.hpp b/include/mapnik/util/container_adapter.hpp index 2cac51f28..ae985a837 100644 --- a/include/mapnik/util/container_adapter.hpp +++ b/include/mapnik/util/container_adapter.hpp @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // boost #include @@ -40,26 +40,26 @@ struct is_container : mpl::true_ {} ; template <> struct container_iterator { - typedef mapnik::util::vertex_iterator type; + typedef mapnik::util::path_iterator type; }; template <> struct begin_container { - static mapnik::util::vertex_iterator + static mapnik::util::path_iterator call (mapnik::geometry_type const& g) { - return mapnik::util::vertex_iterator(g.data()); + return mapnik::util::path_iterator(g); } }; template <> struct end_container { - static mapnik::util::vertex_iterator + static mapnik::util::path_iterator call (mapnik::geometry_type const& g) { - return mapnik::util::vertex_iterator(); + return mapnik::util::path_iterator(); } }; diff --git a/include/mapnik/util/geometry_svg_generator.hpp b/include/mapnik/util/geometry_svg_generator.hpp index 11a7994b0..b229e73c1 100644 --- a/include/mapnik/util/geometry_svg_generator.hpp +++ b/include/mapnik/util/geometry_svg_generator.hpp @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include #include // boost diff --git a/include/mapnik/util/geometry_to_svg.hpp b/include/mapnik/util/geometry_to_svg.hpp index 018545cc9..d65d14d6c 100644 --- a/include/mapnik/util/geometry_to_svg.hpp +++ b/include/mapnik/util/geometry_to_svg.hpp @@ -26,7 +26,6 @@ // mapnik #include #include -#include #include // boost diff --git a/include/mapnik/util/geometry_to_wkb.hpp b/include/mapnik/util/geometry_to_wkb.hpp index 3b0159345..ee3686568 100644 --- a/include/mapnik/util/geometry_to_wkb.hpp +++ b/include/mapnik/util/geometry_to_wkb.hpp @@ -126,8 +126,8 @@ namespace mapnik { namespace util { ss.write(reinterpret_cast(&byte_order),1); int type = static_cast(mapnik::Point); write(ss,type,4,byte_order); - double x(0); - double y(0); + double x = 0; + double y = 0; g.vertex(0,&x,&y); write(ss,x,8,byte_order); write(ss,y,8,byte_order); @@ -146,8 +146,8 @@ namespace mapnik { namespace util { int type = static_cast(mapnik::LineString); write(ss,type,4,byte_order); write(ss,num_points,4,byte_order); - double x(0); - double y(0); + double x = 0; + double y = 0; for (unsigned i=0; i< num_points; ++i) { g.vertex(i,&x,&y); @@ -167,8 +167,8 @@ namespace mapnik { namespace util { typedef std::vector linear_ring; boost::ptr_vector rings; - double x(0); - double y(0); + double x = 0; + double y = 0; std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings for (unsigned i=0; i< num_points; ++i) { diff --git a/include/mapnik/util/geometry_to_wkt.hpp b/include/mapnik/util/geometry_to_wkt.hpp index bd7e0268b..e49423ece 100644 --- a/include/mapnik/util/geometry_to_wkt.hpp +++ b/include/mapnik/util/geometry_to_wkt.hpp @@ -26,7 +26,6 @@ // mapnik #include #include -#include #include // boost @@ -40,7 +39,7 @@ bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom) { typedef std::back_insert_iterator sink_type; sink_type sink(wkt); - wkt_generator generator(true); + wkt_generator generator(true); bool result = karma::generate(sink, generator, geom); return result; } @@ -49,7 +48,7 @@ bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom) { typedef std::back_insert_iterator sink_type; sink_type sink(wkt); - wkt_multi_generator generator; + wkt_multi_generator generator; bool result = karma::generate(sink, generator, geom); return result; } diff --git a/include/mapnik/util/geometry_wkt_generator.hpp b/include/mapnik/util/geometry_wkt_generator.hpp index e2c4eb220..ee75c3dbd 100644 --- a/include/mapnik/util/geometry_wkt_generator.hpp +++ b/include/mapnik/util/geometry_wkt_generator.hpp @@ -25,7 +25,6 @@ // mapnik #include -#include // boost #include @@ -36,7 +35,7 @@ #include #include #include - +#include //#define BOOST_SPIRIT_USE_PHOENIX_V3 1 @@ -50,7 +49,6 @@ struct is_container }}} - namespace mapnik { namespace util { namespace karma = boost::spirit::karma; @@ -58,34 +56,41 @@ namespace phoenix = boost::phoenix; namespace detail { +template struct get_type { template struct result { typedef int type; }; - int operator() (geometry_type const& geom) const + int operator() (Geometry const& geom) const { return static_cast(geom.type()); } }; +template struct get_first { - template - struct result { typedef geometry_type::value_type const type; }; + typedef T geometry_type; - geometry_type::value_type const operator() (geometry_type const& geom) const + template + struct result { typedef typename geometry_type::value_type const type; }; + + typename geometry_type::value_type const operator() (geometry_type const& geom) const { - geometry_type::value_type coord; - boost::get<0>(coord) = geom.vertex(0,&boost::get<1>(coord),&boost::get<2>(coord)); + typename geometry_type::value_type coord; + geom.rewind(0); + boost::get<0>(coord) = geom.vertex(&boost::get<1>(coord),&boost::get<2>(coord)); return coord; } }; - +template struct multi_geometry_ { - template + typedef T geometry_container; + + template struct result { typedef bool type; }; bool operator() (geometry_container const& geom) const @@ -94,9 +99,12 @@ struct multi_geometry_ } }; +template struct multi_geometry_type { - template + typedef T geometry_container; + + template struct result { typedef boost::tuple type; }; boost::tuple operator() (geometry_container const& geom) const; @@ -113,10 +121,13 @@ struct wkt_coordinate_policy : karma::real_policies } -template +template struct wkt_generator : - karma::grammar + karma::grammar { + typedef Geometry geometry_type; + typedef typename boost::remove_pointer::type coord_type; + wkt_generator(bool single = false); // rules karma::rule wkt; @@ -126,33 +137,35 @@ struct wkt_generator : karma::rule coords; karma::rule, geometry_type const& ()> coords2; - karma::rule point_coord; - karma::rule polygon_coord; + karma::rule point_coord; + karma::rule polygon_coord; // phoenix functions - phoenix::function _type; - phoenix::function _first; + phoenix::function > _type; + phoenix::function > _first; // - karma::real_generator > coord_type; + karma::real_generator > coordinate; }; -template +template struct wkt_multi_generator : - karma::grammar >, geometry_container const& ()> + karma::grammar >, GeometryContainer const& ()> { + typedef GeometryContainer geometry_contaner; + typedef boost::remove_pointer::type geometry_type; wkt_multi_generator(); // rules - karma::rule >, geometry_container const& ()> wkt; - karma::rule geometry; + karma::rule >, GeometryContainer const& ()> wkt; + karma::rule geometry; karma::rule single_geometry; - karma::rule multi_geometry; - wkt_generator path; + karma::rule multi_geometry; + wkt_generator path; // phoenix - phoenix::function is_multi; - phoenix::function _multi_type; - phoenix::function _type; + phoenix::function > is_multi; + phoenix::function > _multi_type; + phoenix::function > _type; // karma::symbols geometry_types; }; diff --git a/include/mapnik/util/path_iterator.hpp b/include/mapnik/util/path_iterator.hpp new file mode 100644 index 000000000..f62624ab5 --- /dev/null +++ b/include/mapnik/util/path_iterator.hpp @@ -0,0 +1,85 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 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_VERTEX_ITERATOR_HPP +#define MAPNIK_VERTEX_ITERATOR_HPP + +// mapnik +#include + +// boost +#include +#include + +namespace mapnik { namespace util { + +template +class path_iterator + : public boost::iterator_facade< path_iterator, + boost::tuple const, + boost::forward_traversal_tag + > +{ + +public: + typedef T path_type; + typedef typename boost::tuple value_type; + + path_iterator() + : v_(mapnik::SEG_END,0,0), + vertices_() + {} + + explicit path_iterator(path_type const& vertices) + : vertices_(&vertices) + { + vertices_->rewind(0); + increment(); + } + +private: + friend class boost::iterator_core_access; + + void increment() + { + boost::get<0>(v_) = vertices_->vertex( &boost::get<1>(v_), &boost::get<2>(v_)); + } + + bool equal( path_iterator const& other) const + { + return boost::get<0>(v_) == boost::get<0>(other.v_); + } + + value_type const& dereference() const + { + return v_; + } + + value_type v_; + const path_type *vertices_; + unsigned pos_; +}; + +}} + + +#endif // MAPNIK_VERTEX_ITERATOR_HPP diff --git a/include/mapnik/util/vertex_iterator.hpp b/include/mapnik/util/vertex_iterator.hpp deleted file mode 100644 index 5cc794078..000000000 --- a/include/mapnik/util/vertex_iterator.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2011 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_VERTEX_ITERATOR_HPP -#define MAPNIK_VERTEX_ITERATOR_HPP - -// mapnik -#include -#include - -// boost -#include -#include - -namespace mapnik { namespace util { - - template - class vertex_iterator - : public boost::iterator_facade< vertex_iterator, - typename boost::tuple const, - boost::forward_traversal_tag - > - { - - public: - typedef typename boost::tuple value_type; - typedef vertex_vector container_type; - - vertex_iterator() - : v_(SEG_END,0,0), - vertices_(), - pos_(0) - {} - - explicit vertex_iterator(container_type const& vertices) - : vertices_(&vertices), - pos_(0) - { - increment(); - } - - private: - friend class boost::iterator_core_access; - - void increment() - { - boost::get<0>(v_) = vertices_->get_vertex(pos_++, &boost::get<1>(v_), &boost::get<2>(v_)); - } - - bool equal( vertex_iterator const& other) const - { - return boost::get<0>(v_) == boost::get<0>(other.v_); - } - - value_type const& dereference() const - { - return v_; - } - - value_type v_; - container_type const *vertices_; - unsigned pos_; - }; - - }} - - -#endif // MAPNIK_VERTEX_ITERATOR_HPP diff --git a/plugins/input/raster/raster_featureset.cpp b/plugins/input/raster/raster_featureset.cpp index affe873be..9d7c0b4d1 100644 --- a/plugins/input/raster/raster_featureset.cpp +++ b/plugins/input/raster/raster_featureset.cpp @@ -113,7 +113,7 @@ feature_ptr raster_featureset::next() image_data_32 image(width,height); reader->read(x_off, y_off, image); - feature->set_raster(boost::make_shared(intersect, image)); + feature->set_raster(boost::make_shared(intersect, image,reader->premultiplied_alpha())); } } } diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 1b769af53..f662efb2f 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -524,7 +524,7 @@ boost::optional sqlite_datasource::get_geometry_ if (data) { boost::ptr_vector paths; - if (mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto)) + if (mapnik::geometry_utils::from_wkb(paths, data, size, format_)) { mapnik::util::to_ds_type(paths,result); if (result) diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index 2830b2564..d8f145a7d 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -96,7 +96,9 @@ void agg_renderer::process(raster_symbolizer const& sym, filter_radius); } } - composite(current_buffer_->data(), target.data_, sym.comp_op(), sym.get_opacity(), start_x, start_y, true); + composite(current_buffer_->data(), target.data_, + sym.comp_op(), sym.get_opacity(), + start_x, start_y, !source->premultiplied_alpha_); } } } diff --git a/src/jpeg_reader.cpp b/src/jpeg_reader.cpp index c98dddb49..df03314f9 100644 --- a/src/jpeg_reader.cpp +++ b/src/jpeg_reader.cpp @@ -50,6 +50,7 @@ public: ~JpegReader(); unsigned width() const; unsigned height() const; + inline bool premultiplied_alpha() const { return true ;} void read(unsigned x,unsigned y,image_data_32& image); private: void init(); diff --git a/src/png_reader.cpp b/src/png_reader.cpp index 0cde465f5..dde14ed70 100644 --- a/src/png_reader.cpp +++ b/src/png_reader.cpp @@ -46,6 +46,7 @@ public: ~png_reader(); unsigned width() const; unsigned height() const; + bool premultiplied_alpha() const { return false; } //http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html void read(unsigned x,unsigned y,image_data_32& image); private: void init(); diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index effb6551b..8cf5f89ae 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -64,7 +64,7 @@ private: int tile_width_; int tile_height_; tiff_ptr tif_; - + bool premultiplied_alpha_; public: enum TiffType { generic=1, @@ -75,6 +75,7 @@ public: virtual ~tiff_reader(); unsigned width() const; unsigned height() const; + bool premultiplied_alpha() const; void read(unsigned x,unsigned y,image_data_32& image); private: tiff_reader(const tiff_reader&); @@ -103,7 +104,8 @@ tiff_reader::tiff_reader(std::string const& file_name) height_(0), rows_per_strip_(0), tile_width_(0), - tile_height_(0) + tile_height_(0), + premultiplied_alpha_(false) { init(); } @@ -132,6 +134,16 @@ void tiff_reader::init() { read_method_=stripped; } + //TIFFTAG_EXTRASAMPLES + uint16 extrasamples; + uint16* sampleinfo; + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, + &extrasamples, &sampleinfo); + if (extrasamples == 1 && + sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA) + { + premultiplied_alpha_ = true; + } } else { @@ -156,6 +168,10 @@ unsigned tiff_reader::height() const return height_; } +bool tiff_reader::premultiplied_alpha() const +{ + return premultiplied_alpha_; +} void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) { diff --git a/src/wkt/wkt_generator.cpp b/src/wkt/wkt_generator.cpp index f9d82efb6..9e04640b1 100644 --- a/src/wkt/wkt_generator.cpp +++ b/src/wkt/wkt_generator.cpp @@ -24,19 +24,22 @@ #if BOOST_VERSION >= 104700 +#include #include -#include +#include #include namespace mapnik { namespace util { -boost::tuple detail::multi_geometry_type::operator() (geometry_container const& geom) const +template +boost::tuple detail::multi_geometry_type::operator() (T const& geom) const { + typedef T geometry_container; unsigned type = 0u; bool collection = false; - geometry_container::const_iterator itr = geom.begin(); - geometry_container::const_iterator end = geom.end(); + typename geometry_container::const_iterator itr = geom.begin(); + typename geometry_container::const_iterator end = geom.end(); for ( ; itr != end; ++itr) { @@ -50,8 +53,8 @@ boost::tuple detail::multi_geometry_type::operator() (geometry_co return boost::tuple(type, collection); } -template -wkt_generator::wkt_generator(bool single) +template +wkt_generator::wkt_generator(bool single) : wkt_generator::base_type(wkt) { using boost::spirit::karma::uint_; @@ -62,50 +65,50 @@ wkt_generator::wkt_generator(bool single) using boost::spirit::karma::_r1; using boost::spirit::karma::eps; using boost::spirit::karma::string; - + wkt = point | linestring | polygon ; - + point = &uint_(mapnik::Point)[_1 = _type(_val)] << string[ phoenix::if_ (single) [_1 = "Point("] .else_[_1 = "("]] << point_coord [_1 = _first(_val)] << lit(')') ; - + linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] << string[ phoenix::if_ (single) [_1 = "LineString("] .else_[_1 = "("]] << coords << lit(')') ; - + polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)] << string[ phoenix::if_ (single) [_1 = "Polygon("] .else_[_1 = "("]] << coords2 << lit("))") ; - - point_coord = &uint_ << coord_type << lit(' ') << coord_type + + point_coord = &uint_ << coordinate << lit(' ') << coordinate ; - + polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] << string[ if_ (_r1 > 1) [_1 = "),("] .else_[_1 = "("] ] | &uint_ << ",") - << coord_type + << coordinate << lit(' ') - << coord_type + << coordinate ; - + coords2 %= *polygon_coord(_a) ; - + coords = point_coord % lit(',') ; } -template -wkt_multi_generator::wkt_multi_generator() +template +wkt_multi_generator::wkt_multi_generator() : wkt_multi_generator::base_type(wkt) { using boost::spirit::karma::lit; @@ -138,10 +141,10 @@ wkt_multi_generator::wkt_multi_generator() } -template struct mapnik::util::wkt_generator >; -template struct mapnik::util::wkt_multi_generator >; +template struct mapnik::util::wkt_generator, mapnik::geometry_type>; +template struct mapnik::util::wkt_multi_generator, mapnik::geometry_container >; }} -#endif \ No newline at end of file +#endif diff --git a/tests/data/raster/river.tiff b/tests/data/raster/river.tiff new file mode 100644 index 000000000..1f68f396d Binary files /dev/null and b/tests/data/raster/river.tiff differ diff --git a/tests/data/raster/river_merc.tiff b/tests/data/raster/river_merc.tiff new file mode 100644 index 000000000..447263f4b Binary files /dev/null and b/tests/data/raster/river_merc.tiff differ diff --git a/tests/data/raster/river_wgs.tiff b/tests/data/raster/river_wgs.tiff new file mode 100644 index 000000000..60fe5577f Binary files /dev/null and b/tests/data/raster/river_wgs.tiff differ diff --git a/tests/data/raster/white-alpha-assoc-alpha-correct.tiff b/tests/data/raster/white-alpha-assoc-alpha-correct.tiff new file mode 100644 index 000000000..2085393c4 Binary files /dev/null and b/tests/data/raster/white-alpha-assoc-alpha-correct.tiff differ diff --git a/tests/data/raster/white-alpha.tiff b/tests/data/raster/white-alpha-assoc-alpha-wrong.tiff similarity index 100% rename from tests/data/raster/white-alpha.tiff rename to tests/data/raster/white-alpha-assoc-alpha-wrong.tiff diff --git a/tests/python_tests/multi_tile_raster_test.py b/tests/python_tests/multi_tile_raster_test.py index ce2854f31..fff685487 100644 --- a/tests/python_tests/multi_tile_raster_test.py +++ b/tests/python_tests/multi_tile_raster_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from nose.tools import * -from utilities import execution_path, save_data, contains_word +from utilities import execution_path, contains_word import os, mapnik @@ -40,8 +40,6 @@ def test_multi_tile_policy(): im = mapnik.Image(_map.width, _map.height) mapnik.render(_map, im) - save_data('test_multi_tile_policy.png', im.tostring('png')) - # test green chunk eq_(im.view(0,64,1,1).tostring(), '\x00\xff\x00\xff') eq_(im.view(127,64,1,1).tostring(), '\x00\xff\x00\xff') diff --git a/tests/python_tests/raster_symbolizer_test.py b/tests/python_tests/raster_symbolizer_test.py index f285c615f..9e7870703 100644 --- a/tests/python_tests/raster_symbolizer_test.py +++ b/tests/python_tests/raster_symbolizer_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from nose.tools import * -from utilities import execution_path, save_data, contains_word +from utilities import execution_path, contains_word import os, mapnik @@ -51,8 +51,6 @@ def test_dataraster_coloring(): im = mapnik.Image(_map.width,_map.height) mapnik.render(_map, im) - # save a png somewhere so we can see it - save_data('test_dataraster_coloring.png', im.tostring('png')) imdata = im.tostring() # we have some values in the [20,30) interval so check that they're colored assert contains_word('\xff\xff\x00\xff', imdata) @@ -135,8 +133,6 @@ def test_raster_with_alpha_blends_correctly_with_background(): mim = mapnik.Image(WIDTH, HEIGHT) mapnik.render(map, mim) - save_data('test_raster_with_alpha_blends_correctly_with_background.png', - mim.tostring('png')) imdata = mim.tostring() # All white is expected assert contains_word('\xff\xff\xff\xff', imdata) @@ -166,8 +162,6 @@ def test_raster_warping(): im = mapnik.Image(_map.width,_map.height) mapnik.render(_map, im) - # save a png somewhere so we can see it - save_data('test_raster_warping.png', im.tostring('png')) imdata = im.tostring() assert contains_word('\xff\xff\x00\xff', imdata) @@ -195,9 +189,6 @@ def test_raster_warping_does_not_overclip_source(): im = mapnik.Image(_map.width,_map.height) mapnik.render(_map, im) - # save a png somewhere so we can see it - save_data('test_raster_warping_does_not_overclip_source.png', - im.tostring('png')) assert im.view(0,200,1,1).tostring()=='\xff\xff\x00\xff' if __name__ == "__main__": diff --git a/tests/python_tests/utilities.py b/tests/python_tests/utilities.py index f76c5e54a..b47df7be4 100644 --- a/tests/python_tests/utilities.py +++ b/tests/python_tests/utilities.py @@ -15,20 +15,6 @@ class TodoPlugin(ErrorClassPlugin): todo = ErrorClass(Todo, label='TODO', isfailure=False) -def save_data(filename, data, key='MAPNIK_TEST_DATA_DIR'): - """Saves bytestring 'data' into os.environ[key]/filename if - key in os.environ""" - if key in os.environ: - dir = os.environ[key] - if not os.path.exists(dir): - os.makedirs(dir) - fname = os.path.join(dir, filename) - f = open(fname, 'w') - try: - f.write(data) - finally: - f.close() - def contains_word(word, bytestring_): """ Checks that a bytestring contains a given word. len(bytestring) should be diff --git a/tests/visual_tests/compare.py b/tests/visual_tests/compare.py index 43bd251d9..d2f05b08d 100644 --- a/tests/visual_tests/compare.py +++ b/tests/visual_tests/compare.py @@ -24,6 +24,10 @@ def compare_pixels(pixel1, pixel2): else: return False +def fail(actual,expected,message): + global errors + errors.append((message, actual, expected)) + # compare two images and return number of different pixels def compare(actual, expected): global errors @@ -52,11 +56,14 @@ def compare(actual, expected): def summary(generate=False): global errors global passed - print "-"*80 - print "Visual text rendering summary:", + if len(errors) != 0: - for error in errors: - if (error[0] is None): + msg = "Visual text rendering: %s failures" % len(errors) + print "-"*len(msg) + print msg + print "-"*len(msg) + for idx,error in enumerate(errors): + if error[0] is None: if generate: actual = open(error[1],'r').read() open(error[2],'wb').write(actual) @@ -64,9 +71,14 @@ def summary(generate=False): continue else: print "Could not verify %s: No reference image found!" % error[1] - else: - print "Failed: %d different pixels:\n\t%s (actual)\n\t%s (expected)" % error + elif isinstance(error[0],int): + print str(idx+1) + ") \x1b[34m%s different pixels\x1b[0m:\n\t%s (\x1b[31mactual\x1b[0m)\n\t%s (\x1b[32mexpected\x1b[0m)" % error + elif isinstance(error[0],str): + print str(idx+1) + ") \x1b[31mfailure to run test:\x1b[0m %s" % error[0] sys.exit(1) else: - print 'All %s tests passed: \x1b[1;32m✓ \x1b[0m' % passed + msg = 'All %s visual tests passed: \x1b[1;32m✓ \x1b[0m' % passed + print "-"*len(msg) + print msg + print "-"*len(msg) sys.exit(0) diff --git a/tests/visual_tests/images/tiff-alpha-broken-assoc-alpha-gdal-600-reference.png b/tests/visual_tests/images/tiff-alpha-broken-assoc-alpha-gdal-600-reference.png new file mode 100644 index 000000000..3c79bb304 Binary files /dev/null and b/tests/visual_tests/images/tiff-alpha-broken-assoc-alpha-gdal-600-reference.png differ diff --git a/tests/visual_tests/images/tiff-alpha-broken-assoc-alpha-raster-600-reference.png b/tests/visual_tests/images/tiff-alpha-broken-assoc-alpha-raster-600-reference.png new file mode 100644 index 000000000..3c79bb304 Binary files /dev/null and b/tests/visual_tests/images/tiff-alpha-broken-assoc-alpha-raster-600-reference.png differ diff --git a/tests/visual_tests/images/tiff-alpha-gdal-600-reference.png b/tests/visual_tests/images/tiff-alpha-gdal-600-reference.png index 3c79bb304..0bb7ff1cf 100644 Binary files a/tests/visual_tests/images/tiff-alpha-gdal-600-reference.png and b/tests/visual_tests/images/tiff-alpha-gdal-600-reference.png differ diff --git a/tests/visual_tests/images/tiff-alpha-raster-600-reference.png b/tests/visual_tests/images/tiff-alpha-raster-600-reference.png index 3c79bb304..0bb7ff1cf 100644 Binary files a/tests/visual_tests/images/tiff-alpha-raster-600-reference.png and b/tests/visual_tests/images/tiff-alpha-raster-600-reference.png differ diff --git a/tests/visual_tests/images/tiff-opaque-edge-gdal-256-reference.png b/tests/visual_tests/images/tiff-opaque-edge-gdal-256-reference.png new file mode 100644 index 000000000..cb90dea1d Binary files /dev/null and b/tests/visual_tests/images/tiff-opaque-edge-gdal-256-reference.png differ diff --git a/tests/visual_tests/images/tiff-opaque-edge-raster-256-reference.png b/tests/visual_tests/images/tiff-opaque-edge-raster-256-reference.png new file mode 100644 index 000000000..cb90dea1d Binary files /dev/null and b/tests/visual_tests/images/tiff-opaque-edge-raster-256-reference.png differ diff --git a/tests/visual_tests/styles/tiff-alpha-broken-assoc-alpha-gdal.xml b/tests/visual_tests/styles/tiff-alpha-broken-assoc-alpha-gdal.xml new file mode 100644 index 000000000..358a2260b --- /dev/null +++ b/tests/visual_tests/styles/tiff-alpha-broken-assoc-alpha-gdal.xml @@ -0,0 +1,21 @@ + + + + + + + white + + + + ../../data/raster/white-alpha-assoc-alpha-wrong.tiff + gdal + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/tiff-alpha-broken-assoc-alpha-raster.xml b/tests/visual_tests/styles/tiff-alpha-broken-assoc-alpha-raster.xml new file mode 100644 index 000000000..61cdb9c47 --- /dev/null +++ b/tests/visual_tests/styles/tiff-alpha-broken-assoc-alpha-raster.xml @@ -0,0 +1,22 @@ + + + + + + + white + + + + ../../data/raster/white-alpha-assoc-alpha-wrong.tiff + raster + 1001859.9561,5922814.94334,1021141.75555,5942096.74279 + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/tiff-alpha-gdal.xml b/tests/visual_tests/styles/tiff-alpha-gdal.xml index e7fe88453..ce42b1a3f 100644 --- a/tests/visual_tests/styles/tiff-alpha-gdal.xml +++ b/tests/visual_tests/styles/tiff-alpha-gdal.xml @@ -11,7 +11,7 @@ srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"> white - ../../data/raster/white-alpha.tiff + ../../data/raster/white-alpha-assoc-alpha-correct.tiff gdal diff --git a/tests/visual_tests/styles/tiff-alpha-raster.xml b/tests/visual_tests/styles/tiff-alpha-raster.xml index ce9e2fb6c..a86c7603d 100644 --- a/tests/visual_tests/styles/tiff-alpha-raster.xml +++ b/tests/visual_tests/styles/tiff-alpha-raster.xml @@ -11,7 +11,7 @@ srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"> white - ../../data/raster/white-alpha.tiff + ../../data/raster/white-alpha-assoc-alpha-correct.tiff raster 1001859.9561,5922814.94334,1021141.75555,5942096.74279 diff --git a/tests/visual_tests/styles/tiff-opaque-edge-gdal.xml b/tests/visual_tests/styles/tiff-opaque-edge-gdal.xml new file mode 100644 index 000000000..5d62e2d8b --- /dev/null +++ b/tests/visual_tests/styles/tiff-opaque-edge-gdal.xml @@ -0,0 +1,17 @@ + + + + + + test + + ../../data/raster/river.tiff + gdal + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/tiff-opaque-edge-raster.xml b/tests/visual_tests/styles/tiff-opaque-edge-raster.xml new file mode 100644 index 000000000..ec5519725 --- /dev/null +++ b/tests/visual_tests/styles/tiff-opaque-edge-raster.xml @@ -0,0 +1,18 @@ + + + + + + test + + ../../data/raster/river.tiff + raster + 0,0,256,210 + + + + \ No newline at end of file diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 34007ced2..12938df55 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -2,9 +2,11 @@ # -*- coding: utf-8 -*- import mapnik +mapnik.logger.set_severity(mapnik.severity_type.None) + import sys import os.path -from compare import compare, summary +from compare import compare, summary, fail defaults = { 'sizes': [(500, 100)] @@ -51,12 +53,16 @@ files = [ {'name': "line-offset", 'sizes':[(900, 250)],'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)}, {'name': "tiff-alpha-gdal", 'sizes':[(600,400)]}, {'name': "tiff-alpha-raster", 'sizes':[(600,400)]}, + {'name': "tiff-alpha-broken-assoc-alpha-gdal", 'sizes':[(600,400)]}, + {'name': "tiff-alpha-broken-assoc-alpha-raster", 'sizes':[(600,400)]}, {'name': "tiff-alpha-gradient-gdal", 'sizes':[(600,400)]}, {'name': "tiff-nodata-edge-gdal", 'sizes':[(600,400)]}, {'name': "tiff-nodata-edge-raster", 'sizes':[(600,400)]}, + {'name': "tiff-opaque-edge-gdal", 'sizes':[(256,256)]}, + {'name': "tiff-opaque-edge-raster", 'sizes':[(256,256)]}, {'name': "shieldsymbolizer-2"}, {'name': "shieldsymbolizer-3"}, - {'name': "shieldsymbolizer-4"}, + {'name': "shieldsymbolizer-4"}, {'name': "orientation", 'sizes': [(800, 200)]}, {'name': "hb-fontsets", 'sizes': [(800, 200)]}, {'name': "charspacing", 'sizes': [(200, 400)]}, @@ -65,25 +71,28 @@ files = [ def render(filename, width, height, bbox, quiet=False): if not quiet: - print "Rendering style \"%s\" with size %dx%d ... \x1b[1;32m✓ \x1b[0m" % (filename, width, height) - print "-"*80 + print "\"%s\" with size %dx%d ..." % (filename, width, height), m = mapnik.Map(width, height) - mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False) - if bbox is not None: - m.zoom_to_box(bbox) - else: - m.zoom_all() expected = os.path.join(dirname, "images", '%s-%d-reference.png' % (filename, width)) - if not os.path.exists('/tmp/mapnik-visual-images'): - os.makedirs('/tmp/mapnik-visual-images') actual = os.path.join("/tmp/mapnik-visual-images", '%s-%d-agg.png' % (filename, width)) - mapnik.render_to_file(m, actual) - diff = compare(actual, expected) - if diff > 0: - print "-"*80 - print '\x1b[33mError:\x1b[0m %u different pixels' % diff - print "-"*80 - + try: + mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False) + if bbox is not None: + m.zoom_to_box(bbox) + else: + m.zoom_all() + if not os.path.exists('/tmp/mapnik-visual-images'): + os.makedirs('/tmp/mapnik-visual-images') + mapnik.render_to_file(m, actual) + diff = compare(actual, expected) + if not quiet: + if diff > 0: + print '\x1b[31m✘\x1b[0m (\x1b[34m%u different pixels\x1b[0m)' % diff + else: + print '\x1b[32m✓\x1b[0m' + except Exception, e: + sys.stderr.write(e.message + '\n') + fail(actual,expected,str(e.message)) return m if __name__ == "__main__":