Merge commit '00517a507f68237874630dae1821c8a2c844bc3d' into harfbuzz

Conflicts:
	tests/visual_tests/test.py
This commit is contained in:
Hermann Kraus 2013-03-16 12:34:59 +01:00
commit ad905f1ff8
41 changed files with 382 additions and 264 deletions

View file

@ -53,6 +53,7 @@ struct MAPNIK_DECL image_reader
{ {
virtual unsigned width() const=0; virtual unsigned width() const=0;
virtual unsigned height() 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 void read(unsigned x,unsigned y,image_data_32& image)=0;
virtual ~image_reader() {} virtual ~image_reader() {}
}; };

View file

@ -26,7 +26,7 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp> #include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp> #include <mapnik/util/container_adapter.hpp>
// boost // boost
@ -137,14 +137,14 @@ struct geometry_generator_grammar :
using boost::spirit::karma::_r1; using boost::spirit::karma::_r1;
using boost::spirit::karma::eps; using boost::spirit::karma::eps;
using boost::spirit::karma::string; using boost::spirit::karma::string;
coordinates = point | linestring | polygon coordinates = point | linestring | polygon
; ;
point = &uint_(mapnik::Point)[_1 = _type(_val)] point = &uint_(mapnik::Point)[_1 = _type(_val)]
<< point_coord [_1 = _first(_val)] << point_coord [_1 = _first(_val)]
; ;
linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] linestring = &uint_(mapnik::LineString)[_1 = _type(_val)]
<< lit('[') << lit('[')
<< coords << coords
@ -156,13 +156,13 @@ struct geometry_generator_grammar :
<< coords2 << coords2
<< lit("]]") << lit("]]")
; ;
point_coord = &uint_ point_coord = &uint_
<< lit('[') << lit('[')
<< coord_type << lit(',') << coord_type << coord_type << lit(',') << coord_type
<< lit("]") << lit("]")
; ;
polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1]
<< string[ if_ (_r1 > 1) [_1 = "],["] << string[ if_ (_r1 > 1) [_1 = "],["]
.else_[_1 = '[' ]] | &uint_ << lit(',')) .else_[_1 = '[' ]] | &uint_ << lit(','))
@ -170,25 +170,25 @@ struct geometry_generator_grammar :
<< lit(',') << lit(',')
<< coord_type << lit(']') << coord_type << lit(']')
; ;
coords2 %= *polygon_coord(_a) coords2 %= *polygon_coord(_a)
; ;
coords = point_coord % lit(',') coords = point_coord % lit(',')
; ;
} }
// rules // rules
karma::rule<OutputIterator, geometry_type const& ()> coordinates; karma::rule<OutputIterator, geometry_type const& ()> coordinates;
karma::rule<OutputIterator, geometry_type const& ()> point; karma::rule<OutputIterator, geometry_type const& ()> point;
karma::rule<OutputIterator, geometry_type const& ()> linestring; karma::rule<OutputIterator, geometry_type const& ()> linestring;
karma::rule<OutputIterator, geometry_type const& ()> polygon; karma::rule<OutputIterator, geometry_type const& ()> polygon;
karma::rule<OutputIterator, geometry_type const& ()> coords; karma::rule<OutputIterator, geometry_type const& ()> coords;
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2; karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2;
karma::rule<OutputIterator, geometry_type::value_type ()> point_coord; karma::rule<OutputIterator, geometry_type::value_type ()> point_coord;
karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord; karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord;
// phoenix functions // phoenix functions
phoenix::function<get_type > _type; phoenix::function<get_type > _type;
phoenix::function<get_first> _first; phoenix::function<get_first> _first;
@ -200,7 +200,7 @@ struct geometry_generator_grammar :
template <typename OutputIterator> template <typename OutputIterator>
struct multi_geometry_generator_grammar : struct multi_geometry_generator_grammar :
karma::grammar<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >, karma::grammar<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >,
geometry_container const& ()> geometry_container const& ()>
{ {
@ -223,36 +223,36 @@ struct multi_geometry_generator_grammar :
(mapnik::LineString + 3,"\"MultiLineString\"") (mapnik::LineString + 3,"\"MultiLineString\"")
(mapnik::Polygon + 3,"\"MultiPolygon\"") (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\":[") << lit("{\"type\":\"GeometryCollection\",\"geometries\":[")
<< geometry_collection << lit("]}") << geometry_collection << lit("]}")
| |
geometry) geometry)
; ;
geometry_collection = -(geometry2 % lit(',')) geometry_collection = -(geometry2 % lit(','))
; ;
geometry = (lit("{\"type\":") geometry = (lit("{\"type\":")
<< geometry_types[_1 = phoenix::at_c<0>(_a)][_a = _multi_type(_val)] << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = _multi_type(_val)]
<< lit(",\"coordinates\":") << lit(",\"coordinates\":")
<< string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = '[']] << string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = '[']]
<< coordinates << coordinates
<< string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']']] << 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)] << geometry_types[_1 = _a][_a = type_(_val)]
<< lit(",\"coordinates\":") << lit(",\"coordinates\":")
<< path << path
<< lit('}') << lit('}')
; ;
coordinates %= path % lit(',') coordinates %= path % lit(',')
; ;
} }
// rules // rules
karma::rule<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >, karma::rule<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >,

View file

@ -32,11 +32,13 @@ struct raster
{ {
box2d<double> ext_; box2d<double> ext_;
image_data_32 data_; image_data_32 data_;
raster(box2d<double> const& ext,image_data_32 const& data) bool premultiplied_alpha_;
raster(box2d<double> const& ext,image_data_32 const& data, bool premultiplied_alpha = false)
: ext_(ext), : ext_(ext),
data_(data) {} data_(data),
premultiplied_alpha_(premultiplied_alpha)
{}
}; };
} }
#endif // MAPNIK_RASTER_HPP #endif // MAPNIK_RASTER_HPP

View file

@ -17,7 +17,8 @@
namespace mapnik namespace mapnik
{ {
struct weighted_vertex : private boost::noncopyable { struct weighted_vertex : private boost::noncopyable
{
vertex2d coord; vertex2d coord;
double weight; double weight;
weighted_vertex *prev; weighted_vertex *prev;
@ -27,20 +28,23 @@ struct weighted_vertex : private boost::noncopyable {
coord(coord_), coord(coord_),
weight(std::numeric_limits<double>::infinity()), weight(std::numeric_limits<double>::infinity()),
prev(NULL), prev(NULL),
next(NULL) { } next(NULL) {}
double nominalWeight() { double nominalWeight()
{
if (prev == NULL || next == NULL || coord.cmd != SEG_LINETO) { if (prev == NULL || next == NULL || coord.cmd != SEG_LINETO) {
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
} }
vertex2d& A = prev->coord; vertex2d const& A = prev->coord;
vertex2d& B = next->coord; vertex2d const& B = next->coord;
vertex2d& C = 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; 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 { struct ascending_sort
bool operator() (const weighted_vertex *a, const weighted_vertex *b) { {
bool operator() (const weighted_vertex *a, const weighted_vertex *b)
{
return b->weight > a->weight; return b->weight > a->weight;
} }
}; };
@ -97,10 +101,11 @@ struct MAPNIK_DECL simplify_converter
{ {
public: public:
simplify_converter(Geometry& geom) simplify_converter(Geometry& geom)
: geom_(geom) : geom_(geom),
, tolerance_(0.0) tolerance_(0.0),
, status_(initial) status_(initial),
, algorithm_(radial_distance) algorithm_(radial_distance),
pos_(0)
{} {}
enum status enum status
@ -117,8 +122,10 @@ public:
return algorithm_; return algorithm_;
} }
void set_simplify_algorithm(simplify_algorithm_e value) { void set_simplify_algorithm(simplify_algorithm_e value)
if (algorithm_ != value) { {
if (algorithm_ != value)
{
algorithm_ = value; algorithm_ = value;
reset(); reset();
} }
@ -145,7 +152,7 @@ public:
pos_ = 0; pos_ = 0;
} }
void rewind(unsigned int) void rewind(unsigned int) const
{ {
pos_ = 0; pos_ = 0;
} }
@ -360,7 +367,8 @@ private:
} }
} }
status init_vertices_visvalingam_whyatt() { status init_vertices_visvalingam_whyatt()
{
typedef std::set<weighted_vertex *, weighted_vertex::ascending_sort> VertexSet; typedef std::set<weighted_vertex *, weighted_vertex::ascending_sort> VertexSet;
typedef std::vector<weighted_vertex *> VertexList; typedef std::vector<weighted_vertex *> VertexList;
@ -371,13 +379,13 @@ private:
v_list.push_back(new weighted_vertex(vtx)); v_list.push_back(new weighted_vertex(vtx));
} }
if (!v_list.size()) { if (v_list.empty()) {
return status_ = process; return status_ = process;
} }
// Connect the vertices in a linked list and insert them into the set. // Connect the vertices in a linked list and insert them into the set.
VertexSet v; 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)->prev = i == v_list.begin() ? NULL : *(i - 1);
(*i)->next = i + 1 == v_list.end() ? NULL : *(i + 1); (*i)->next = i + 1 == v_list.end() ? NULL : *(i + 1);
@ -415,9 +423,10 @@ private:
v.clear(); v.clear();
// Traverse the remaining list and insert them into the vertex cache. // 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); vertices_.push_back((*i)->coord);
} }
delete *i; delete *i;
@ -431,10 +440,10 @@ private:
double tolerance_; double tolerance_;
status status_; status status_;
simplify_algorithm_e algorithm_; simplify_algorithm_e algorithm_;
size_t pos_;
std::deque<vertex2d> vertices_; std::deque<vertex2d> vertices_;
std::deque<vertex2d> sleeve_cont_; std::deque<vertex2d> sleeve_cont_;
vertex2d previous_vertex_; vertex2d previous_vertex_;
mutable size_t pos_;
}; };

View file

@ -26,7 +26,7 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp> #include <mapnik/util/path_iterator.hpp>
// boost // boost
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
@ -40,26 +40,26 @@ struct is_container<mapnik::geometry_type const> : mpl::true_ {} ;
template <> template <>
struct container_iterator<mapnik::geometry_type const> struct container_iterator<mapnik::geometry_type const>
{ {
typedef mapnik::util::vertex_iterator<double> type; typedef mapnik::util::path_iterator<mapnik::geometry_type> type;
}; };
template <> template <>
struct begin_container<mapnik::geometry_type const> struct begin_container<mapnik::geometry_type const>
{ {
static mapnik::util::vertex_iterator<double> static mapnik::util::path_iterator<mapnik::geometry_type>
call (mapnik::geometry_type const& g) call (mapnik::geometry_type const& g)
{ {
return mapnik::util::vertex_iterator<double>(g.data()); return mapnik::util::path_iterator<mapnik::geometry_type>(g);
} }
}; };
template <> template <>
struct end_container<mapnik::geometry_type const> struct end_container<mapnik::geometry_type const>
{ {
static mapnik::util::vertex_iterator<double> static mapnik::util::path_iterator<mapnik::geometry_type>
call (mapnik::geometry_type const& g) call (mapnik::geometry_type const& g)
{ {
return mapnik::util::vertex_iterator<double>(); return mapnik::util::path_iterator<mapnik::geometry_type>();
} }
}; };

View file

@ -26,7 +26,7 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp> #include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp> #include <mapnik/util/container_adapter.hpp>
// boost // boost

View file

@ -26,7 +26,6 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/geometry_svg_generator.hpp> #include <mapnik/util/geometry_svg_generator.hpp>
// boost // boost

View file

@ -126,8 +126,8 @@ namespace mapnik { namespace util {
ss.write(reinterpret_cast<char*>(&byte_order),1); ss.write(reinterpret_cast<char*>(&byte_order),1);
int type = static_cast<int>(mapnik::Point); int type = static_cast<int>(mapnik::Point);
write(ss,type,4,byte_order); write(ss,type,4,byte_order);
double x(0); double x = 0;
double y(0); double y = 0;
g.vertex(0,&x,&y); g.vertex(0,&x,&y);
write(ss,x,8,byte_order); write(ss,x,8,byte_order);
write(ss,y,8,byte_order); write(ss,y,8,byte_order);
@ -146,8 +146,8 @@ namespace mapnik { namespace util {
int type = static_cast<int>(mapnik::LineString); int type = static_cast<int>(mapnik::LineString);
write(ss,type,4,byte_order); write(ss,type,4,byte_order);
write(ss,num_points,4,byte_order); write(ss,num_points,4,byte_order);
double x(0); double x = 0;
double y(0); double y = 0;
for (unsigned i=0; i< num_points; ++i) for (unsigned i=0; i< num_points; ++i)
{ {
g.vertex(i,&x,&y); g.vertex(i,&x,&y);
@ -167,8 +167,8 @@ namespace mapnik { namespace util {
typedef std::vector<point_type> linear_ring; typedef std::vector<point_type> linear_ring;
boost::ptr_vector<linear_ring> rings; boost::ptr_vector<linear_ring> rings;
double x(0); double x = 0;
double y(0); double y = 0;
std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings
for (unsigned i=0; i< num_points; ++i) for (unsigned i=0; i< num_points; ++i)
{ {

View file

@ -26,7 +26,6 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/geometry_wkt_generator.hpp> #include <mapnik/util/geometry_wkt_generator.hpp>
// boost // boost
@ -40,7 +39,7 @@ bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom)
{ {
typedef std::back_insert_iterator<std::string> sink_type; typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt); sink_type sink(wkt);
wkt_generator<sink_type> generator(true); wkt_generator<sink_type, mapnik::geometry_type> generator(true);
bool result = karma::generate(sink, generator, geom); bool result = karma::generate(sink, generator, geom);
return result; return result;
} }
@ -49,7 +48,7 @@ bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom)
{ {
typedef std::back_insert_iterator<std::string> sink_type; typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt); sink_type sink(wkt);
wkt_multi_generator<sink_type> generator; wkt_multi_generator<sink_type, mapnik::geometry_container> generator;
bool result = karma::generate(sink, generator, geom); bool result = karma::generate(sink, generator, geom);
return result; return result;
} }

View file

@ -25,7 +25,6 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
// boost // boost
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
@ -36,7 +35,7 @@
#include <boost/spirit/include/phoenix_function.hpp> #include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/home/phoenix/statement/if.hpp> #include <boost/spirit/home/phoenix/statement/if.hpp>
#include <boost/fusion/include/boost_tuple.hpp> #include <boost/fusion/include/boost_tuple.hpp>
#include <boost/type_traits/remove_pointer.hpp>
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1 //#define BOOST_SPIRIT_USE_PHOENIX_V3 1
@ -50,7 +49,6 @@ struct is_container<mapnik::geometry_container>
}}} }}}
namespace mapnik { namespace util { namespace mapnik { namespace util {
namespace karma = boost::spirit::karma; namespace karma = boost::spirit::karma;
@ -58,34 +56,41 @@ namespace phoenix = boost::phoenix;
namespace detail { namespace detail {
template <typename Geometry>
struct get_type struct get_type
{ {
template <typename T> template <typename T>
struct result { typedef int type; }; struct result { typedef int type; };
int operator() (geometry_type const& geom) const int operator() (Geometry const& geom) const
{ {
return static_cast<int>(geom.type()); return static_cast<int>(geom.type());
} }
}; };
template <typename T>
struct get_first struct get_first
{ {
template <typename T> typedef T geometry_type;
struct result { typedef geometry_type::value_type const type; };
geometry_type::value_type const operator() (geometry_type const& geom) const template <typename U>
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; typename geometry_type::value_type coord;
boost::get<0>(coord) = geom.vertex(0,&boost::get<1>(coord),&boost::get<2>(coord)); geom.rewind(0);
boost::get<0>(coord) = geom.vertex(&boost::get<1>(coord),&boost::get<2>(coord));
return coord; return coord;
} }
}; };
template <typename T>
struct multi_geometry_ struct multi_geometry_
{ {
template <typename T> typedef T geometry_container;
template <typename U>
struct result { typedef bool type; }; struct result { typedef bool type; };
bool operator() (geometry_container const& geom) const bool operator() (geometry_container const& geom) const
@ -94,9 +99,12 @@ struct multi_geometry_
} }
}; };
template <typename T>
struct multi_geometry_type struct multi_geometry_type
{ {
template <typename T> typedef T geometry_container;
template <typename U>
struct result { typedef boost::tuple<unsigned,bool> type; }; struct result { typedef boost::tuple<unsigned,bool> type; };
boost::tuple<unsigned,bool> operator() (geometry_container const& geom) const; boost::tuple<unsigned,bool> operator() (geometry_container const& geom) const;
@ -113,10 +121,13 @@ struct wkt_coordinate_policy : karma::real_policies<T>
} }
template <typename OutputIterator> template <typename OutputIterator, typename Geometry>
struct wkt_generator : struct wkt_generator :
karma::grammar<OutputIterator, geometry_type const& ()> karma::grammar<OutputIterator, Geometry const& ()>
{ {
typedef Geometry geometry_type;
typedef typename boost::remove_pointer<typename geometry_type::value_type>::type coord_type;
wkt_generator(bool single = false); wkt_generator(bool single = false);
// rules // rules
karma::rule<OutputIterator, geometry_type const& ()> wkt; karma::rule<OutputIterator, geometry_type const& ()> wkt;
@ -126,33 +137,35 @@ struct wkt_generator :
karma::rule<OutputIterator, geometry_type const& ()> coords; karma::rule<OutputIterator, geometry_type const& ()> coords;
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2; karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2;
karma::rule<OutputIterator, geometry_type::value_type ()> point_coord; karma::rule<OutputIterator, coord_type ()> point_coord;
karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord; karma::rule<OutputIterator, coord_type (unsigned& )> polygon_coord;
// phoenix functions // phoenix functions
phoenix::function<detail::get_type > _type; phoenix::function<detail::get_type<geometry_type> > _type;
phoenix::function<detail::get_first> _first; phoenix::function<detail::get_first<geometry_type> > _first;
// //
karma::real_generator<double, detail::wkt_coordinate_policy<double> > coord_type; karma::real_generator<double, detail::wkt_coordinate_policy<double> > coordinate;
}; };
template <typename OutputIterator> template <typename OutputIterator, typename GeometryContainer>
struct wkt_multi_generator : struct wkt_multi_generator :
karma::grammar<OutputIterator, karma::locals< boost::tuple<unsigned,bool> >, geometry_container const& ()> karma::grammar<OutputIterator, karma::locals< boost::tuple<unsigned,bool> >, GeometryContainer const& ()>
{ {
typedef GeometryContainer geometry_contaner;
typedef boost::remove_pointer<typename geometry_container::value_type>::type geometry_type;
wkt_multi_generator(); wkt_multi_generator();
// rules // rules
karma::rule<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >, geometry_container const& ()> wkt; karma::rule<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >, GeometryContainer const& ()> wkt;
karma::rule<OutputIterator, geometry_container const& ()> geometry; karma::rule<OutputIterator, GeometryContainer const& ()> geometry;
karma::rule<OutputIterator, geometry_type const& ()> single_geometry; karma::rule<OutputIterator, geometry_type const& ()> single_geometry;
karma::rule<OutputIterator, geometry_container const& ()> multi_geometry; karma::rule<OutputIterator, GeometryContainer const& ()> multi_geometry;
wkt_generator<OutputIterator> path; wkt_generator<OutputIterator, geometry_type > path;
// phoenix // phoenix
phoenix::function<detail::multi_geometry_> is_multi; phoenix::function<detail::multi_geometry_<GeometryContainer> > is_multi;
phoenix::function<detail::multi_geometry_type> _multi_type; phoenix::function<detail::multi_geometry_type<GeometryContainer> > _multi_type;
phoenix::function<detail::get_type > _type; phoenix::function<detail::get_type<geometry_type> > _type;
// //
karma::symbols<unsigned, char const*> geometry_types; karma::symbols<unsigned, char const*> geometry_types;
}; };

View file

@ -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 <mapnik/global.hpp>
// boost
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/iterator_facade.hpp>
namespace mapnik { namespace util {
template <typename T>
class path_iterator
: public boost::iterator_facade< path_iterator<T>,
boost::tuple<unsigned,double,double> const,
boost::forward_traversal_tag
>
{
public:
typedef T path_type;
typedef typename boost::tuple<unsigned, double, double> 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

View file

@ -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 <mapnik/global.hpp>
#include <mapnik/vertex_vector.hpp>
// boost
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/iterator_facade.hpp>
namespace mapnik { namespace util {
template <typename T>
class vertex_iterator
: public boost::iterator_facade< vertex_iterator<T>,
typename boost::tuple<unsigned,T,T> const,
boost::forward_traversal_tag
>
{
public:
typedef typename boost::tuple<unsigned, T, T> value_type;
typedef vertex_vector<T> 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

View file

@ -113,7 +113,7 @@ feature_ptr raster_featureset<LookupPolicy>::next()
image_data_32 image(width,height); image_data_32 image(width,height);
reader->read(x_off, y_off, image); reader->read(x_off, y_off, image);
feature->set_raster(boost::make_shared<raster>(intersect, image)); feature->set_raster(boost::make_shared<raster>(intersect, image,reader->premultiplied_alpha()));
} }
} }
} }

View file

@ -524,7 +524,7 @@ boost::optional<mapnik::datasource::geometry_t> sqlite_datasource::get_geometry_
if (data) if (data)
{ {
boost::ptr_vector<mapnik::geometry_type> paths; boost::ptr_vector<mapnik::geometry_type> 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); mapnik::util::to_ds_type(paths,result);
if (result) if (result)

View file

@ -96,7 +96,9 @@ void agg_renderer<T>::process(raster_symbolizer const& sym,
filter_radius); 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_);
} }
} }
} }

View file

@ -50,6 +50,7 @@ public:
~JpegReader(); ~JpegReader();
unsigned width() const; unsigned width() const;
unsigned height() const; unsigned height() const;
inline bool premultiplied_alpha() const { return true ;}
void read(unsigned x,unsigned y,image_data_32& image); void read(unsigned x,unsigned y,image_data_32& image);
private: private:
void init(); void init();

View file

@ -46,6 +46,7 @@ public:
~png_reader(); ~png_reader();
unsigned width() const; unsigned width() const;
unsigned height() 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); void read(unsigned x,unsigned y,image_data_32& image);
private: private:
void init(); void init();

View file

@ -64,7 +64,7 @@ private:
int tile_width_; int tile_width_;
int tile_height_; int tile_height_;
tiff_ptr tif_; tiff_ptr tif_;
bool premultiplied_alpha_;
public: public:
enum TiffType { enum TiffType {
generic=1, generic=1,
@ -75,6 +75,7 @@ public:
virtual ~tiff_reader(); virtual ~tiff_reader();
unsigned width() const; unsigned width() const;
unsigned height() const; unsigned height() const;
bool premultiplied_alpha() const;
void read(unsigned x,unsigned y,image_data_32& image); void read(unsigned x,unsigned y,image_data_32& image);
private: private:
tiff_reader(const tiff_reader&); tiff_reader(const tiff_reader&);
@ -103,7 +104,8 @@ tiff_reader::tiff_reader(std::string const& file_name)
height_(0), height_(0),
rows_per_strip_(0), rows_per_strip_(0),
tile_width_(0), tile_width_(0),
tile_height_(0) tile_height_(0),
premultiplied_alpha_(false)
{ {
init(); init();
} }
@ -132,6 +134,16 @@ void tiff_reader::init()
{ {
read_method_=stripped; 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 else
{ {
@ -156,6 +168,10 @@ unsigned tiff_reader::height() const
return height_; return height_;
} }
bool tiff_reader::premultiplied_alpha() const
{
return premultiplied_alpha_;
}
void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) void tiff_reader::read(unsigned x,unsigned y,image_data_32& image)
{ {

View file

@ -24,19 +24,22 @@
#if BOOST_VERSION >= 104700 #if BOOST_VERSION >= 104700
#include <mapnik/geometry.hpp>
#include <mapnik/util/geometry_wkt_generator.hpp> #include <mapnik/util/geometry_wkt_generator.hpp>
#include <mapnik/util/vertex_iterator.hpp> #include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp> #include <mapnik/util/container_adapter.hpp>
namespace mapnik { namespace util { namespace mapnik { namespace util {
boost::tuple<unsigned,bool> detail::multi_geometry_type::operator() (geometry_container const& geom) const template <typename T>
boost::tuple<unsigned,bool> detail::multi_geometry_type<T>::operator() (T const& geom) const
{ {
typedef T geometry_container;
unsigned type = 0u; unsigned type = 0u;
bool collection = false; bool collection = false;
geometry_container::const_iterator itr = geom.begin(); typename geometry_container::const_iterator itr = geom.begin();
geometry_container::const_iterator end = geom.end(); typename geometry_container::const_iterator end = geom.end();
for ( ; itr != end; ++itr) for ( ; itr != end; ++itr)
{ {
@ -50,8 +53,8 @@ boost::tuple<unsigned,bool> detail::multi_geometry_type::operator() (geometry_co
return boost::tuple<unsigned,bool>(type, collection); return boost::tuple<unsigned,bool>(type, collection);
} }
template <typename OutputIterator> template <typename OutputIterator, typename Geometry>
wkt_generator<OutputIterator>::wkt_generator(bool single) wkt_generator<OutputIterator, Geometry>::wkt_generator(bool single)
: wkt_generator::base_type(wkt) : wkt_generator::base_type(wkt)
{ {
using boost::spirit::karma::uint_; using boost::spirit::karma::uint_;
@ -62,50 +65,50 @@ wkt_generator<OutputIterator>::wkt_generator(bool single)
using boost::spirit::karma::_r1; using boost::spirit::karma::_r1;
using boost::spirit::karma::eps; using boost::spirit::karma::eps;
using boost::spirit::karma::string; using boost::spirit::karma::string;
wkt = point | linestring | polygon wkt = point | linestring | polygon
; ;
point = &uint_(mapnik::Point)[_1 = _type(_val)] point = &uint_(mapnik::Point)[_1 = _type(_val)]
<< string[ phoenix::if_ (single) [_1 = "Point("] << string[ phoenix::if_ (single) [_1 = "Point("]
.else_[_1 = "("]] .else_[_1 = "("]]
<< point_coord [_1 = _first(_val)] << lit(')') << point_coord [_1 = _first(_val)] << lit(')')
; ;
linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] linestring = &uint_(mapnik::LineString)[_1 = _type(_val)]
<< string[ phoenix::if_ (single) [_1 = "LineString("] << string[ phoenix::if_ (single) [_1 = "LineString("]
.else_[_1 = "("]] .else_[_1 = "("]]
<< coords << coords
<< lit(')') << lit(')')
; ;
polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)] polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)]
<< string[ phoenix::if_ (single) [_1 = "Polygon("] << string[ phoenix::if_ (single) [_1 = "Polygon("]
.else_[_1 = "("]] .else_[_1 = "("]]
<< coords2 << coords2
<< lit("))") << lit("))")
; ;
point_coord = &uint_ << coord_type << lit(' ') << coord_type point_coord = &uint_ << coordinate << lit(' ') << coordinate
; ;
polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1]
<< string[ if_ (_r1 > 1) [_1 = "),("] << string[ if_ (_r1 > 1) [_1 = "),("]
.else_[_1 = "("] ] | &uint_ << ",") .else_[_1 = "("] ] | &uint_ << ",")
<< coord_type << coordinate
<< lit(' ') << lit(' ')
<< coord_type << coordinate
; ;
coords2 %= *polygon_coord(_a) coords2 %= *polygon_coord(_a)
; ;
coords = point_coord % lit(',') coords = point_coord % lit(',')
; ;
} }
template <typename OutputIterator> template <typename OutputIterator, typename GeometryContainer>
wkt_multi_generator<OutputIterator>::wkt_multi_generator() wkt_multi_generator<OutputIterator, GeometryContainer>::wkt_multi_generator()
: wkt_multi_generator::base_type(wkt) : wkt_multi_generator::base_type(wkt)
{ {
using boost::spirit::karma::lit; using boost::spirit::karma::lit;
@ -138,10 +141,10 @@ wkt_multi_generator<OutputIterator>::wkt_multi_generator()
} }
template struct mapnik::util::wkt_generator<std::back_insert_iterator<std::string> >; template struct mapnik::util::wkt_generator<std::back_insert_iterator<std::string>, mapnik::geometry_type>;
template struct mapnik::util::wkt_multi_generator<std::back_insert_iterator<std::string> >; template struct mapnik::util::wkt_multi_generator<std::back_insert_iterator<std::string>, mapnik::geometry_container >;
}} }}
#endif #endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from nose.tools import * from nose.tools import *
from utilities import execution_path, save_data, contains_word from utilities import execution_path, contains_word
import os, mapnik import os, mapnik
@ -40,8 +40,6 @@ def test_multi_tile_policy():
im = mapnik.Image(_map.width, _map.height) im = mapnik.Image(_map.width, _map.height)
mapnik.render(_map, im) mapnik.render(_map, im)
save_data('test_multi_tile_policy.png', im.tostring('png'))
# test green chunk # test green chunk
eq_(im.view(0,64,1,1).tostring(), '\x00\xff\x00\xff') eq_(im.view(0,64,1,1).tostring(), '\x00\xff\x00\xff')
eq_(im.view(127,64,1,1).tostring(), '\x00\xff\x00\xff') eq_(im.view(127,64,1,1).tostring(), '\x00\xff\x00\xff')

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from nose.tools import * from nose.tools import *
from utilities import execution_path, save_data, contains_word from utilities import execution_path, contains_word
import os, mapnik import os, mapnik
@ -51,8 +51,6 @@ def test_dataraster_coloring():
im = mapnik.Image(_map.width,_map.height) im = mapnik.Image(_map.width,_map.height)
mapnik.render(_map, im) 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() imdata = im.tostring()
# we have some values in the [20,30) interval so check that they're colored # we have some values in the [20,30) interval so check that they're colored
assert contains_word('\xff\xff\x00\xff', imdata) 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) mim = mapnik.Image(WIDTH, HEIGHT)
mapnik.render(map, mim) mapnik.render(map, mim)
save_data('test_raster_with_alpha_blends_correctly_with_background.png',
mim.tostring('png'))
imdata = mim.tostring() imdata = mim.tostring()
# All white is expected # All white is expected
assert contains_word('\xff\xff\xff\xff', imdata) assert contains_word('\xff\xff\xff\xff', imdata)
@ -166,8 +162,6 @@ def test_raster_warping():
im = mapnik.Image(_map.width,_map.height) im = mapnik.Image(_map.width,_map.height)
mapnik.render(_map, im) 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() imdata = im.tostring()
assert contains_word('\xff\xff\x00\xff', imdata) 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) im = mapnik.Image(_map.width,_map.height)
mapnik.render(_map, im) 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' assert im.view(0,200,1,1).tostring()=='\xff\xff\x00\xff'
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -15,20 +15,6 @@ class TodoPlugin(ErrorClassPlugin):
todo = ErrorClass(Todo, label='TODO', isfailure=False) 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_): def contains_word(word, bytestring_):
""" """
Checks that a bytestring contains a given word. len(bytestring) should be Checks that a bytestring contains a given word. len(bytestring) should be

View file

@ -24,6 +24,10 @@ def compare_pixels(pixel1, pixel2):
else: else:
return False return False
def fail(actual,expected,message):
global errors
errors.append((message, actual, expected))
# compare two images and return number of different pixels # compare two images and return number of different pixels
def compare(actual, expected): def compare(actual, expected):
global errors global errors
@ -52,11 +56,14 @@ def compare(actual, expected):
def summary(generate=False): def summary(generate=False):
global errors global errors
global passed global passed
print "-"*80
print "Visual text rendering summary:",
if len(errors) != 0: if len(errors) != 0:
for error in errors: msg = "Visual text rendering: %s failures" % len(errors)
if (error[0] is None): print "-"*len(msg)
print msg
print "-"*len(msg)
for idx,error in enumerate(errors):
if error[0] is None:
if generate: if generate:
actual = open(error[1],'r').read() actual = open(error[1],'r').read()
open(error[2],'wb').write(actual) open(error[2],'wb').write(actual)
@ -64,9 +71,14 @@ def summary(generate=False):
continue continue
else: else:
print "Could not verify %s: No reference image found!" % error[1] print "Could not verify %s: No reference image found!" % error[1]
else: elif isinstance(error[0],int):
print "Failed: %d different pixels:\n\t%s (actual)\n\t%s (expected)" % error 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) sys.exit(1)
else: 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) sys.exit(0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" background-color="red">
<Style name="white">
<Rule>
<RasterSymbolizer opacity="1" scaling="bilinear" comp-op="src-over"/>
</Rule>
</Style>
<Layer name="white"
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">
<StyleName>white</StyleName>
<Datasource>
<!-- tiffinfo data/raster/white-alpha-assoc-alpha-wrong.tiff reports 'Extra Samples: 1<assoc-alpha>' which is incorrect -->
<!-- https://github.com/mapnik/mapnik/issues/1511 -->
<Parameter name="file">../../data/raster/white-alpha-assoc-alpha-wrong.tiff</Parameter>
<Parameter name="type">gdal</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" background-color="red">
<Style name="white">
<Rule>
<RasterSymbolizer opacity="1" scaling="bilinear" comp-op="src-over"/>
</Rule>
</Style>
<Layer name="white"
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">
<StyleName>white</StyleName>
<Datasource>
<!-- tiffinfo data/raster/white-alpha-assoc-alpha-wrong.tiff reports 'Extra Samples: 1<assoc-alpha>' which is incorrect -->
<!-- https://github.com/mapnik/mapnik/issues/1511 -->
<Parameter name="file">../../data/raster/white-alpha-assoc-alpha-wrong.tiff</Parameter>
<Parameter name="type">raster</Parameter>
<Parameter name="extent">1001859.9561,5922814.94334,1021141.75555,5942096.74279</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -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"> 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">
<StyleName>white</StyleName> <StyleName>white</StyleName>
<Datasource> <Datasource>
<Parameter name="file">../../data/raster/white-alpha.tiff</Parameter> <Parameter name="file">../../data/raster/white-alpha-assoc-alpha-correct.tiff</Parameter>
<Parameter name="type">gdal</Parameter> <Parameter name="type">gdal</Parameter>
</Datasource> </Datasource>
</Layer> </Layer>

View file

@ -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"> 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">
<StyleName>white</StyleName> <StyleName>white</StyleName>
<Datasource> <Datasource>
<Parameter name="file">../../data/raster/white-alpha.tiff</Parameter> <Parameter name="file">../../data/raster/white-alpha-assoc-alpha-correct.tiff</Parameter>
<Parameter name="type">raster</Parameter> <Parameter name="type">raster</Parameter>
<Parameter name="extent">1001859.9561,5922814.94334,1021141.75555,5942096.74279</Parameter> <Parameter name="extent">1001859.9561,5922814.94334,1021141.75555,5942096.74279</Parameter>
</Datasource> </Datasource>

View file

@ -0,0 +1,17 @@
<Map srs="+init=EPSG:4326" background-color="white">
<Style name="test">
<Rule>
<RasterSymbolizer scaling="bilinear" />
</Rule>
</Style>
<Layer name="test" srs="+init=EPSG:4326">
<StyleName>test</StyleName>
<Datasource>
<Parameter name="file">../../data/raster/river.tiff</Parameter>
<Parameter name="type">gdal</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,18 @@
<Map srs="+init=EPSG:4326" background-color="white">
<Style name="test">
<Rule>
<RasterSymbolizer scaling="bilinear" />
</Rule>
</Style>
<Layer name="test" srs="+init=EPSG:4326">
<StyleName>test</StyleName>
<Datasource>
<Parameter name="file">../../data/raster/river.tiff</Parameter>
<Parameter name="type">raster</Parameter>
<Parameter name="extent">0,0,256,210</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -2,9 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import mapnik import mapnik
mapnik.logger.set_severity(mapnik.severity_type.None)
import sys import sys
import os.path import os.path
from compare import compare, summary from compare import compare, summary, fail
defaults = { defaults = {
'sizes': [(500, 100)] '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': "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-gdal", 'sizes':[(600,400)]},
{'name': "tiff-alpha-raster", '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-alpha-gradient-gdal", 'sizes':[(600,400)]},
{'name': "tiff-nodata-edge-gdal", 'sizes':[(600,400)]}, {'name': "tiff-nodata-edge-gdal", 'sizes':[(600,400)]},
{'name': "tiff-nodata-edge-raster", '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-2"},
{'name': "shieldsymbolizer-3"}, {'name': "shieldsymbolizer-3"},
{'name': "shieldsymbolizer-4"}, {'name': "shieldsymbolizer-4"},
{'name': "orientation", 'sizes': [(800, 200)]}, {'name': "orientation", 'sizes': [(800, 200)]},
{'name': "hb-fontsets", 'sizes': [(800, 200)]}, {'name': "hb-fontsets", 'sizes': [(800, 200)]},
{'name': "charspacing", 'sizes': [(200, 400)]}, {'name': "charspacing", 'sizes': [(200, 400)]},
@ -65,25 +71,28 @@ files = [
def render(filename, width, height, bbox, quiet=False): def render(filename, width, height, bbox, quiet=False):
if not quiet: if not quiet:
print "Rendering style \"%s\" with size %dx%d ... \x1b[1;32m✓ \x1b[0m" % (filename, width, height) print "\"%s\" with size %dx%d ..." % (filename, width, height),
print "-"*80
m = mapnik.Map(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)) 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)) actual = os.path.join("/tmp/mapnik-visual-images", '%s-%d-agg.png' % (filename, width))
mapnik.render_to_file(m, actual) try:
diff = compare(actual, expected) mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False)
if diff > 0: if bbox is not None:
print "-"*80 m.zoom_to_box(bbox)
print '\x1b[33mError:\x1b[0m %u different pixels' % diff else:
print "-"*80 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 return m
if __name__ == "__main__": if __name__ == "__main__":