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 height() const=0;
virtual bool premultiplied_alpha() const=0;
virtual void read(unsigned x,unsigned y,image_data_32& image)=0;
virtual ~image_reader() {}
};

View file

@ -26,7 +26,7 @@
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp>
// 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<OutputIterator, geometry_type const& ()> coordinates;
karma::rule<OutputIterator, geometry_type const& ()> point;
karma::rule<OutputIterator, geometry_type const& ()> linestring;
karma::rule<OutputIterator, geometry_type const& ()> polygon;
karma::rule<OutputIterator, geometry_type const& ()> coords;
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 (unsigned& )> polygon_coord;
// phoenix functions
phoenix::function<get_type > _type;
phoenix::function<get_first> _first;
@ -200,7 +200,7 @@ struct geometry_generator_grammar :
template <typename OutputIterator>
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& ()>
{
@ -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<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >,

View file

@ -32,11 +32,13 @@ struct raster
{
box2d<double> ext_;
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),
data_(data) {}
data_(data),
premultiplied_alpha_(premultiplied_alpha)
{}
};
}
#endif // MAPNIK_RASTER_HPP

View file

@ -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<double>::infinity()),
prev(NULL),
next(NULL) { }
next(NULL) {}
double nominalWeight() {
double nominalWeight()
{
if (prev == NULL || next == NULL || coord.cmd != SEG_LINETO) {
return std::numeric_limits<double>::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<weighted_vertex *, weighted_vertex::ascending_sort> VertexSet;
typedef std::vector<weighted_vertex *> 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<vertex2d> vertices_;
std::deque<vertex2d> sleeve_cont_;
vertex2d previous_vertex_;
mutable size_t pos_;
};

View file

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

View file

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

View file

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

View file

@ -126,8 +126,8 @@ namespace mapnik { namespace util {
ss.write(reinterpret_cast<char*>(&byte_order),1);
int type = static_cast<int>(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<int>(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<point_type> linear_ring;
boost::ptr_vector<linear_ring> 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)
{

View file

@ -26,7 +26,6 @@
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/geometry_wkt_generator.hpp>
// 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;
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);
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;
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);
return result;
}

View file

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

View file

@ -96,7 +96,9 @@ void agg_renderer<T>::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_);
}
}
}

View file

@ -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();

View file

@ -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();

View file

@ -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)
{

View file

@ -24,19 +24,22 @@
#if BOOST_VERSION >= 104700
#include <mapnik/geometry.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>
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;
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<unsigned,bool> detail::multi_geometry_type::operator() (geometry_co
return boost::tuple<unsigned,bool>(type, collection);
}
template <typename OutputIterator>
wkt_generator<OutputIterator>::wkt_generator(bool single)
template <typename OutputIterator, typename Geometry>
wkt_generator<OutputIterator, Geometry>::wkt_generator(bool single)
: wkt_generator::base_type(wkt)
{
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::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 <typename OutputIterator>
wkt_multi_generator<OutputIterator>::wkt_multi_generator()
template <typename OutputIterator, typename GeometryContainer>
wkt_multi_generator<OutputIterator, GeometryContainer>::wkt_multi_generator()
: wkt_multi_generator::base_type(wkt)
{
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_multi_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>, 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
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')

View file

@ -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__":

View file

@ -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

View file

@ -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)

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">
<StyleName>white</StyleName>
<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>
</Datasource>
</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">
<StyleName>white</StyleName>
<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="extent">1001859.9561,5922814.94334,1021141.75555,5942096.74279</Parameter>
</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 -*-
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__":