Merge commit '88360c365f2ea288740db51e65588f839fc67bba' into harfbuzz
Conflicts: include/mapnik/cairo_renderer.hpp
This commit is contained in:
commit
346ce07117
28 changed files with 709 additions and 166 deletions
16
Makefile
16
Makefile
|
@ -7,26 +7,26 @@ endif
|
|||
|
||||
OS:=$(shell uname -s)
|
||||
|
||||
ifeq ($(NPROCS),)
|
||||
NPROCS:=1
|
||||
ifeq ($(JOBS),)
|
||||
JOBS:=1
|
||||
ifeq ($(OS),Linux)
|
||||
NPROCS:=$(shell grep -c ^processor /proc/cpuinfo)
|
||||
JOBS:=$(shell grep -c ^processor /proc/cpuinfo)
|
||||
endif
|
||||
ifeq ($(OS),Darwin)
|
||||
NPROCS:=$(shell sysctl -n hw.ncpu)
|
||||
JOBS:=$(shell sysctl -n hw.ncpu)
|
||||
endif
|
||||
endif
|
||||
|
||||
all: mapnik
|
||||
|
||||
install:
|
||||
@python scons/scons.py -j$(NPROCS) --config=cache --implicit-cache --max-drift=1 install
|
||||
@python scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1 install
|
||||
|
||||
mapnik:
|
||||
@python scons/scons.py -j$(NPROCS) --config=cache --implicit-cache --max-drift=1
|
||||
@python scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1
|
||||
|
||||
clean:
|
||||
@python scons/scons.py -j$(NPROCS) -c --config=cache --implicit-cache --max-drift=1
|
||||
@python scons/scons.py -j$(JOBS) -c --config=cache --implicit-cache --max-drift=1
|
||||
@if test -e ".sconsign.dblite"; then rm ".sconsign.dblite"; fi
|
||||
@if test -e "config.log"; then rm "config.log"; fi
|
||||
@if test -e ".sconf_temp/"; then rm -r ".sconf_temp/"; fi
|
||||
|
@ -46,7 +46,7 @@ rebuild:
|
|||
make uninstall && make clean && time make && make install
|
||||
|
||||
uninstall:
|
||||
@python scons/scons.py -j$(NPROCS) --config=cache --implicit-cache --max-drift=1 uninstall
|
||||
@python scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1 uninstall
|
||||
|
||||
test:
|
||||
@ ./run_tests
|
||||
|
|
|
@ -460,7 +460,7 @@ HELP_REQUESTED = False
|
|||
if ('-h' in command_line_args) or ('--help' in command_line_args):
|
||||
HELP_REQUESTED = True
|
||||
|
||||
if ('-c' in command_line_args) or ('--clean' in command_line_args):
|
||||
if ('install' not in command_line_args) and ('-c' in command_line_args) or ('--clean' in command_line_args):
|
||||
HELP_REQUESTED = True
|
||||
|
||||
if 'configure' in command_line_args and not HELP_REQUESTED:
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <QtGui>
|
||||
|
||||
#define BOOST_CHRONO_HEADER_ONLY
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
|
@ -502,7 +504,10 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
|
|||
|
||||
try
|
||||
{
|
||||
ren.apply();
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
ren.apply();
|
||||
}
|
||||
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
|
||||
pix = QPixmap::fromImage(image.rgbSwapped());
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
######################################################################
|
||||
TEMPLATE = app
|
||||
QMAKE_CXX = clang++
|
||||
QMAKE_CXXFLAGS += $$system(mapnik-config --cflags)
|
||||
QMAKE_CXXFLAGS += $$system(mapnik-config --cxxflags)
|
||||
QMAKE_LFLAGS += $$system(mapnik-config --libs)
|
||||
QMAKE_LFLAGS += $$system(mapnik-config --ldflags --dep-libs)
|
||||
|
||||
QMAKE_LFLAGS += -lboost_timer
|
||||
# Input
|
||||
|
||||
CONFIG += qt debug_and_release
|
||||
|
@ -19,17 +19,17 @@ HEADERS += mainwindow.hpp \
|
|||
layerwidget.hpp \
|
||||
layerlistmodel.hpp \
|
||||
layerdelegate.hpp \
|
||||
styles_model.hpp
|
||||
styles_model.hpp
|
||||
|
||||
HEADERS += about_dialog.hpp \
|
||||
info_dialog.hpp \
|
||||
layer_info_dialog.hpp
|
||||
|
||||
SOURCES += main.cpp \
|
||||
mainwindow.cpp \
|
||||
mainwindow.cpp \
|
||||
mapwidget.cpp \
|
||||
layerwidget.cpp \
|
||||
layerlistmodel.cpp \
|
||||
layerlistmodel.cpp \
|
||||
layerdelegate.cpp \
|
||||
styles_model.cpp
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <mapnik/ctrans.hpp> // for CoordTransform
|
||||
#include <mapnik/image_compositing.hpp> // for composite_mode_e
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/request.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
@ -70,6 +71,8 @@ public:
|
|||
// create with external placement detector, possibly non-empty
|
||||
agg_renderer(Map const &m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
|
||||
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
// pass in mapnik::request object to provide the mutable things per render
|
||||
agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
~agg_renderer();
|
||||
void start_map_processing(Map const& map);
|
||||
void end_map_processing(Map const& map);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <mapnik/label_collision_detector.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/request.hpp>
|
||||
#include <mapnik/rule.hpp> // for all symbolizers
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
#include <mapnik/cairo_context.hpp>
|
||||
|
@ -58,6 +59,7 @@ class MAPNIK_DECL cairo_renderer_base : private mapnik::noncopyable
|
|||
{
|
||||
protected:
|
||||
cairo_renderer_base(Map const& m, cairo_ptr const& cairo, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
cairo_renderer_base(Map const& m, request const& req, cairo_ptr const& cairo, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
cairo_renderer_base(Map const& m, cairo_ptr const& cairo, boost::shared_ptr<label_collision_detector4> detector, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
public:
|
||||
~cairo_renderer_base();
|
||||
|
@ -138,6 +140,7 @@ class MAPNIK_DECL cairo_renderer : public feature_style_processor<cairo_renderer
|
|||
public:
|
||||
typedef cairo_renderer_base processor_impl_type;
|
||||
cairo_renderer(Map const& m, T const& obj, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
cairo_renderer(Map const& m, request const& req, T const& obj, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
cairo_renderer(Map const& m, T const& obj, boost::shared_ptr<label_collision_detector4> detector, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
void end_map_processing(Map const& map);
|
||||
};
|
||||
|
|
|
@ -52,24 +52,32 @@ class feature_style_processor
|
|||
{
|
||||
struct symbol_dispatch;
|
||||
public:
|
||||
explicit feature_style_processor(Map const& m, double scale_factor = 1.0);
|
||||
explicit feature_style_processor(Map const& m,
|
||||
double scale_factor = 1.0);
|
||||
|
||||
/*!
|
||||
* \brief apply renderer to all map layers.
|
||||
*/
|
||||
void apply();
|
||||
void apply(double scale_denom_override=0.0);
|
||||
|
||||
/*!
|
||||
* \brief apply renderer to a single layer, providing pre-populated set of query attribute names.
|
||||
*/
|
||||
void apply(mapnik::layer const& lyr, std::set<std::string>& names);
|
||||
void apply(mapnik::layer const& lyr,
|
||||
std::set<std::string>& names,
|
||||
double scale_denom_override=0.0);
|
||||
/*!
|
||||
* \brief render a layer given a projection and scale.
|
||||
*/
|
||||
void apply_to_layer(layer const& lay,
|
||||
Processor & p,
|
||||
projection const& proj0,
|
||||
double scale,
|
||||
double scale_denom,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
box2d<double> const& extent,
|
||||
int buffer_size,
|
||||
std::set<std::string>& names);
|
||||
|
||||
private:
|
||||
|
|
|
@ -150,7 +150,7 @@ feature_style_processor<Processor>::feature_style_processor(Map const& m, double
|
|||
}
|
||||
|
||||
template <typename Processor>
|
||||
void feature_style_processor<Processor>::apply()
|
||||
void feature_style_processor<Processor>::apply(double scale_denom)
|
||||
{
|
||||
#if defined(RENDERING_STATS)
|
||||
std::clog << "\n//-- starting rendering timer...\n";
|
||||
|
@ -163,7 +163,8 @@ void feature_style_processor<Processor>::apply()
|
|||
try
|
||||
{
|
||||
projection proj(m_.srs(),true);
|
||||
double scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
|
||||
if (scale_denom <= 0.0)
|
||||
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
|
||||
scale_denom *= scale_factor_;
|
||||
|
||||
BOOST_FOREACH ( layer const& lyr, m_.layers() )
|
||||
|
@ -171,7 +172,17 @@ void feature_style_processor<Processor>::apply()
|
|||
if (lyr.visible(scale_denom))
|
||||
{
|
||||
std::set<std::string> names;
|
||||
apply_to_layer(lyr, p, proj, scale_denom, names);
|
||||
apply_to_layer(lyr,
|
||||
p,
|
||||
proj,
|
||||
m_.scale(),
|
||||
scale_denom,
|
||||
m_.width(),
|
||||
m_.height(),
|
||||
m_.get_current_extent(),
|
||||
m_.buffer_size(),
|
||||
names);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,19 +201,31 @@ void feature_style_processor<Processor>::apply()
|
|||
}
|
||||
|
||||
template <typename Processor>
|
||||
void feature_style_processor<Processor>::apply(mapnik::layer const& lyr, std::set<std::string>& names)
|
||||
void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
|
||||
std::set<std::string>& names,
|
||||
double scale_denom)
|
||||
{
|
||||
Processor & p = static_cast<Processor&>(*this);
|
||||
p.start_map_processing(m_);
|
||||
try
|
||||
{
|
||||
projection proj(m_.srs(),true);
|
||||
double scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
|
||||
if (scale_denom <= 0.0)
|
||||
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
|
||||
scale_denom *= scale_factor_;
|
||||
|
||||
if (lyr.visible(scale_denom))
|
||||
{
|
||||
apply_to_layer(lyr, p, proj, scale_denom, names);
|
||||
apply_to_layer(lyr,
|
||||
p,
|
||||
proj,
|
||||
m_.scale(),
|
||||
scale_denom,
|
||||
m_.width(),
|
||||
m_.height(),
|
||||
m_.get_current_extent(),
|
||||
m_.buffer_size(),
|
||||
names);
|
||||
}
|
||||
}
|
||||
catch (proj_init_error& ex)
|
||||
|
@ -215,7 +238,12 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr, std::se
|
|||
template <typename Processor>
|
||||
void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Processor & p,
|
||||
projection const& proj0,
|
||||
double scale,
|
||||
double scale_denom,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
box2d<double> const& extent,
|
||||
int buffer_size,
|
||||
std::set<std::string>& names)
|
||||
{
|
||||
std::vector<std::string> const& style_names = lay.styles();
|
||||
|
@ -253,20 +281,21 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
|
|||
#endif
|
||||
|
||||
|
||||
box2d<double> query_ext = m_.get_current_extent(); // unbuffered
|
||||
box2d<double> query_ext = extent; // unbuffered
|
||||
box2d<double> buffered_query_ext(query_ext); // buffered
|
||||
|
||||
double buffer_padding = 2.0 * scale;
|
||||
boost::optional<int> layer_buffer_size = lay.buffer_size();
|
||||
if (layer_buffer_size) // if layer overrides buffer size, use this value to compute buffered extent
|
||||
{
|
||||
double extra = 2.0 * m_.scale() * *layer_buffer_size;
|
||||
buffered_query_ext.width(query_ext.width() + extra);
|
||||
buffered_query_ext.height(query_ext.height() + extra);
|
||||
buffer_padding *= *layer_buffer_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffered_query_ext = m_.get_buffered_extent();
|
||||
buffer_padding *= buffer_size;
|
||||
}
|
||||
buffered_query_ext.width(query_ext.width() + buffer_padding);
|
||||
buffered_query_ext.height(query_ext.height() + buffer_padding);
|
||||
|
||||
// clip buffered extent by maximum extent, if supplied
|
||||
boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent();
|
||||
|
@ -363,10 +392,10 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
|
|||
|
||||
double qw = query_ext.width()>0 ? query_ext.width() : 1;
|
||||
double qh = query_ext.height()>0 ? query_ext.height() : 1;
|
||||
query::resolution_type res(m_.width()/qw,
|
||||
m_.height()/qh);
|
||||
query::resolution_type res(width/qw,
|
||||
height/qh);
|
||||
|
||||
query q(layer_ext,res,scale_denom,m_.get_current_extent());
|
||||
query q(layer_ext,res,scale_denom,extent);
|
||||
std::vector<feature_type_style const*> active_styles;
|
||||
attribute_collector collector(names);
|
||||
double filt_factor = 1.0;
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace mapnik {
|
|||
class marker;
|
||||
class proj_transform;
|
||||
struct grid_rasterizer;
|
||||
class request;
|
||||
}
|
||||
|
||||
namespace mapnik {
|
||||
|
@ -67,6 +68,7 @@ public:
|
|||
typedef T buffer_type;
|
||||
typedef grid_renderer<T> processor_impl_type;
|
||||
grid_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
grid_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
~grid_renderer();
|
||||
void start_map_processing(Map const& map);
|
||||
void end_map_processing(Map const& map);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
//mapnik
|
||||
#include <mapnik/image_filter_types.hpp>
|
||||
#include <mapnik/util/hsl.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
@ -403,6 +404,69 @@ void apply_filter(Src & src, agg_stack_blur const& op)
|
|||
agg::stack_blur_rgba32(pixf,op.rx,op.ry);
|
||||
}
|
||||
|
||||
template <typename Src>
|
||||
void apply_filter(Src & src, hsla const& op)
|
||||
{
|
||||
using namespace boost::gil;
|
||||
Tinter tint;
|
||||
tint.h0 = .1;
|
||||
tint.s0 = .3;
|
||||
tint.l1 = .9;
|
||||
bool tinting = !tint.is_identity();
|
||||
bool set_alpha = !tint.is_alpha_identity();
|
||||
// todo - should filters be able to report if they should be run?
|
||||
if (tinting || set_alpha)
|
||||
{
|
||||
rgba8_view_t src_view = rgba8_view(src);
|
||||
for (int y=0; y<src_view.height(); ++y)
|
||||
{
|
||||
rgba8_view_t::x_iterator src_it = src_view.row_begin(y);
|
||||
for (int x=0; x<src_view.width(); ++x)
|
||||
{
|
||||
uint8_t & a = get_color(src_it[x], alpha_t());
|
||||
uint8_t a_original = a;
|
||||
if (set_alpha)
|
||||
{
|
||||
double a2 = tint.a0 + (a/255.0 * (tint.a1 - tint.a0));
|
||||
if (a2 > 1) a2 = 1;
|
||||
if (a2 < 0) a2 = 0;
|
||||
a = static_cast<unsigned>(std::floor(a2 * 255.0));
|
||||
}
|
||||
if (a > 1 && tinting)
|
||||
{
|
||||
double h;
|
||||
double s;
|
||||
double l;
|
||||
uint8_t & r = get_color(src_it[x], red_t());
|
||||
uint8_t & g = get_color(src_it[x], green_t());
|
||||
uint8_t & b = get_color(src_it[x], blue_t());
|
||||
// demultiply
|
||||
r /= a_original;
|
||||
g /= a_original;
|
||||
b /= a_original;
|
||||
rgb2hsl(r,g,b,h,s,l);
|
||||
double h2 = tint.h0 + (h * (tint.h1 - tint.h0));
|
||||
double s2 = tint.s0 + (s * (tint.s1 - tint.s0));
|
||||
double l2 = tint.l0 + (l * (tint.l1 - tint.l0));
|
||||
if (h2 > 1) h2 = 1;
|
||||
else if (h2 < 0) h2 = 0;
|
||||
if (s2 > 1) s2 = 1;
|
||||
else if (s2 < 0) s2 = 0;
|
||||
if (l2 > 1) l2 = 1;
|
||||
else if (l2 < 0) l2 = 0;
|
||||
hsl2rgb(h2,s2,l2,r,g,b);
|
||||
// premultiply
|
||||
// we only work with premultiplied source,
|
||||
// thus all color values must be <= alpha
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Src>
|
||||
void apply_filter(Src & src, gray const& op)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,10 @@ struct image_filter_grammar :
|
|||
{
|
||||
image_filter_grammar();
|
||||
qi::rule<Iterator, ContType(), qi::ascii::space_type> start;
|
||||
qi::rule<Iterator, ContType(), qi::locals<int,int>, qi::ascii::space_type> filter;
|
||||
qi::rule<Iterator, ContType(), qi::ascii::space_type> filter;
|
||||
qi::rule<Iterator, qi::locals<int,int>, void(ContType&), qi::ascii::space_type> agg_blur_filter;
|
||||
qi::rule<Iterator, qi::locals<std::string>, void(ContType&), qi::ascii::space_type> hsla_filter;
|
||||
qi::rule<Iterator, std::string(), qi::ascii::space_type> string_arg;
|
||||
qi::uint_parser< unsigned, 10, 1, 3 > radius_;
|
||||
};
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
// stl
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <iterator> // for std::back_insert_iterator
|
||||
|
@ -55,6 +54,13 @@ struct agg_stack_blur
|
|||
unsigned ry;
|
||||
};
|
||||
|
||||
struct hsla
|
||||
{
|
||||
hsla(std::string const& tint_string)
|
||||
: tinter(tint_string) {}
|
||||
std::string tinter;
|
||||
};
|
||||
|
||||
typedef boost::variant<filter::blur,
|
||||
filter::gray,
|
||||
filter::agg_stack_blur,
|
||||
|
@ -64,7 +70,8 @@ typedef boost::variant<filter::blur,
|
|||
filter::sobel,
|
||||
filter::x_gradient,
|
||||
filter::y_gradient,
|
||||
filter::invert> filter_type;
|
||||
filter::invert,
|
||||
filter::hsla> filter_type;
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& os, blur)
|
||||
{
|
||||
|
@ -80,7 +87,13 @@ inline std::ostream& operator<< (std::ostream& os, gray)
|
|||
|
||||
inline std::ostream& operator<< (std::ostream& os, agg_stack_blur const& filter)
|
||||
{
|
||||
os << "agg-stack-blur:" << filter.rx << ',' << filter.ry;
|
||||
os << "agg-stack-blur(" << filter.rx << ',' << filter.ry << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& os, hsla const& filter)
|
||||
{
|
||||
os << "hsla(" << filter.tinter << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
60
include/mapnik/request.hpp
Normal file
60
include/mapnik/request.hpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2013 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_REQUEST_HPP
|
||||
#define MAPNIK_REQUEST_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional/optional.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
class MAPNIK_DECL request
|
||||
{
|
||||
public:
|
||||
request(unsigned width,
|
||||
unsigned height,
|
||||
box2d<double> const& extent);
|
||||
unsigned width() const;
|
||||
unsigned height() const;
|
||||
void set_buffer_size(int buffer_size);
|
||||
int buffer_size() const;
|
||||
box2d<double> const& extent() const;
|
||||
void set_extent(box2d<double> const& box);
|
||||
box2d<double> get_buffered_extent() const;
|
||||
double scale() const;
|
||||
~request();
|
||||
private:
|
||||
unsigned width_;
|
||||
unsigned height_;
|
||||
box2d<double> extent_;
|
||||
int buffer_size_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_REQUEST_HPP
|
108
include/mapnik/util/hsl.hpp
Normal file
108
include/mapnik/util/hsl.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2013 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_HSL_HPP
|
||||
#define MAPNIK_HSL_HPP
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
struct Tinter {
|
||||
double h0;
|
||||
double h1;
|
||||
double s0;
|
||||
double s1;
|
||||
double l0;
|
||||
double l1;
|
||||
double a0;
|
||||
double a1;
|
||||
|
||||
Tinter() :
|
||||
h0(0),
|
||||
h1(1),
|
||||
s0(0),
|
||||
s1(1),
|
||||
l0(0),
|
||||
l1(1),
|
||||
a0(0),
|
||||
a1(1) { }
|
||||
|
||||
bool is_identity() {
|
||||
return (h0 == 0 &&
|
||||
h1 == 1 &&
|
||||
s0 == 0 &&
|
||||
s1 == 1 &&
|
||||
l0 == 0 &&
|
||||
l1 == 1);
|
||||
}
|
||||
|
||||
bool is_alpha_identity() {
|
||||
return (a0 == 0 &&
|
||||
a1 == 1);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void rgb2hsl(unsigned char red, unsigned char green, unsigned char blue,
|
||||
double & h, double & s, double & l) {
|
||||
double r = red/255.0;
|
||||
double g = green/255.0;
|
||||
double b = blue/255.0;
|
||||
double max = std::max(r,std::max(g,b));
|
||||
double min = std::min(r,std::min(g,b));
|
||||
double delta = max - min;
|
||||
double gamma = max + min;
|
||||
h = s = l = gamma / 2.0;
|
||||
if (delta > 0.0) {
|
||||
s = l > 0.5 ? delta / (2.0 - gamma) : delta / gamma;
|
||||
if (max == r && max != g) h = (g - b) / delta + (g < b ? 6.0 : 0.0);
|
||||
else if (max == g && max != b) h = (b - r) / delta + 2.0;
|
||||
else if (max == b && max != r) h = (r - g) / delta + 4.0;
|
||||
h /= 6.0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double hueToRGB(double m1, double m2, double h) {
|
||||
// poor mans fmod
|
||||
if(h < 0) h += 1;
|
||||
if(h > 1) h -= 1;
|
||||
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
|
||||
if (h * 2 < 1) return m2;
|
||||
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
|
||||
return m1;
|
||||
}
|
||||
|
||||
static inline void hsl2rgb(double h, double s, double l,
|
||||
unsigned char & r, unsigned char & g, unsigned char & b) {
|
||||
if (!s) {
|
||||
r = g = b = static_cast<unsigned char>(l * 255);
|
||||
}
|
||||
double m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
|
||||
double m1 = l * 2 - m2;
|
||||
r = static_cast<unsigned char>(hueToRGB(m1, m2, h + 0.33333) * 255);
|
||||
g = static_cast<unsigned char>(hueToRGB(m1, m2, h) * 255);
|
||||
b = static_cast<unsigned char>(hueToRGB(m1, m2, h - 0.33333) * 255);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end MAPNIK_HSL_HPP
|
|
@ -84,6 +84,25 @@ agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, double scale_factor, uns
|
|||
setup(m);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
agg_renderer<T>::agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<agg_renderer>(m, scale_factor),
|
||||
pixmap_(pixmap),
|
||||
internal_buffer_(),
|
||||
current_buffer_(&pixmap),
|
||||
style_level_compositing_(false),
|
||||
width_(pixmap_.width()),
|
||||
height_(pixmap_.height()),
|
||||
scale_factor_(scale_factor),
|
||||
t_(req.width(),req.height(),req.extent(),offset_x,offset_y),
|
||||
font_engine_(),
|
||||
font_manager_(font_engine_),
|
||||
detector_(boost::make_shared<label_collision_detector4>(box2d<double>(-req.buffer_size(), -req.buffer_size(), req.width() + req.buffer_size() ,req.height() + req.buffer_size()))),
|
||||
ras_ptr(new rasterizer)
|
||||
{
|
||||
setup(m);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
|
||||
double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
|
|
|
@ -109,6 +109,7 @@ else: # unix, non-macos
|
|||
|
||||
source = Split(
|
||||
"""
|
||||
request.cpp
|
||||
well_known_srs.cpp
|
||||
params.cpp
|
||||
image_filter_types.cpp
|
||||
|
|
|
@ -210,7 +210,7 @@ void cairo_context::set_dash(dash_array const &dashes, double scale_factor)
|
|||
d[index++] = itr->second * scale_factor;
|
||||
}
|
||||
|
||||
cairo_set_dash(cairo_.get() , &d[0], dashes.size(), 0/*offset*/);
|
||||
cairo_set_dash(cairo_.get() , &d[0], d.size(), 0/*offset*/);
|
||||
check_object_status_and_throw_exception(*this);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,6 +139,28 @@ cairo_renderer_base::cairo_renderer_base(Map const& m,
|
|||
setup(m);
|
||||
}
|
||||
|
||||
cairo_renderer_base::cairo_renderer_base(Map const& m,
|
||||
request const& req,
|
||||
cairo_ptr const& cairo,
|
||||
double scale_factor,
|
||||
unsigned offset_x,
|
||||
unsigned offset_y)
|
||||
: m_(m),
|
||||
context_(cairo),
|
||||
width_(req.width()),
|
||||
height_(req.height()),
|
||||
scale_factor_(scale_factor),
|
||||
t_(req.width(),req.height(),req.extent(),offset_x,offset_y),
|
||||
font_engine_(boost::make_shared<freetype_engine>()),
|
||||
font_manager_(*font_engine_),
|
||||
face_manager_(font_engine_),
|
||||
detector_(boost::make_shared<label_collision_detector4>(
|
||||
box2d<double>(-req.buffer_size(), -req.buffer_size(),
|
||||
req.width() + req.buffer_size(), req.height() + req.buffer_size())))
|
||||
{
|
||||
setup(m);
|
||||
}
|
||||
|
||||
cairo_renderer_base::cairo_renderer_base(Map const& m,
|
||||
cairo_ptr const& cairo,
|
||||
boost::shared_ptr<label_collision_detector4> detector,
|
||||
|
@ -169,6 +191,16 @@ cairo_renderer<cairo_surface_ptr>::cairo_renderer(Map const& m, cairo_surface_pt
|
|||
: feature_style_processor<cairo_renderer>(m,scale_factor),
|
||||
cairo_renderer_base(m,create_context(surface),scale_factor,offset_x,offset_y) {}
|
||||
|
||||
template <>
|
||||
cairo_renderer<cairo_ptr>::cairo_renderer(Map const& m, request const& req, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<cairo_renderer>(m,scale_factor),
|
||||
cairo_renderer_base(m,req,cairo,scale_factor,offset_x,offset_y) {}
|
||||
|
||||
template <>
|
||||
cairo_renderer<cairo_surface_ptr>::cairo_renderer(Map const& m, request const& req, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<cairo_renderer>(m,scale_factor),
|
||||
cairo_renderer_base(m,req, create_context(surface),scale_factor,offset_x,offset_y) {}
|
||||
|
||||
template <>
|
||||
cairo_renderer<cairo_ptr>::cairo_renderer(Map const& m, cairo_ptr const& cairo, boost::shared_ptr<label_collision_detector4> detector, double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<cairo_renderer>(m,scale_factor),
|
||||
|
|
|
@ -152,6 +152,24 @@ bool string2float(const char * iter, const char * end, float & result)
|
|||
return r && (iter == end);
|
||||
}
|
||||
|
||||
// double conversion - here we use sprintf over karma to work
|
||||
// around https://github.com/mapnik/mapnik/issues/1741
|
||||
bool to_string(std::string & s, double val)
|
||||
{
|
||||
s.resize(s.capacity());
|
||||
while (true)
|
||||
{
|
||||
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%g", val));
|
||||
if (n2 <= s.size())
|
||||
{
|
||||
s.resize(n2);
|
||||
break;
|
||||
}
|
||||
s.resize(n2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MAPNIK_KARMA_TO_STRING
|
||||
|
||||
bool to_string(std::string & str, int value)
|
||||
|
@ -184,95 +202,6 @@ bool to_string(std::string & str, bool value)
|
|||
return karma::generate(sink, value);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct double_policy : boost::spirit::karma::real_policies<T>
|
||||
{
|
||||
typedef boost::spirit::karma::real_policies<T> base_type;
|
||||
|
||||
static int floatfield(T n) {
|
||||
using namespace boost::spirit; // for traits
|
||||
|
||||
if (traits::test_zero(n))
|
||||
return base_type::fmtflags::fixed;
|
||||
|
||||
T abs_n = traits::get_absolute_value(n);
|
||||
return (abs_n >= 1e16 || abs_n < 1e-4)
|
||||
? base_type::fmtflags::scientific : base_type::fmtflags::fixed;
|
||||
}
|
||||
|
||||
static unsigned precision(T n) {
|
||||
if ( n == 0.0 ) return 0;
|
||||
using namespace boost::spirit; // for traits
|
||||
return static_cast<unsigned>(15 - boost::math::trunc(log10(traits::get_absolute_value(n))));
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
static bool dot(OutputIterator& sink, T n, unsigned precision) {
|
||||
if (n == 0.0) return true; // avoid trailing zeroes
|
||||
return base_type::dot(sink, n, precision);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
static bool fraction_part (OutputIterator& sink, T n
|
||||
, unsigned precision_, unsigned precision)
|
||||
{
|
||||
// NOTE: copied from karma only to avoid trailing zeroes
|
||||
// (maybe a bug ?)
|
||||
|
||||
// allow for ADL to find the correct overload for floor and log10
|
||||
using namespace std;
|
||||
|
||||
using namespace boost::spirit; // for traits
|
||||
using namespace boost::spirit::karma; // for char_inserter
|
||||
|
||||
if ( traits::test_zero(n) ) return true; // this part added to karma
|
||||
|
||||
// The following is equivalent to:
|
||||
// generate(sink, right_align(precision, '0')[ulong], n);
|
||||
// but it's spelled out to avoid inter-modular dependencies.
|
||||
|
||||
typename boost::remove_const<T>::type digits =
|
||||
(traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
|
||||
bool r = true;
|
||||
for (/**/; r && digits < precision_; digits = digits + 1)
|
||||
r = char_inserter<>::call(sink, '0');
|
||||
if (precision && r)
|
||||
r = int_inserter<10>::call(sink, n);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename CharEncoding, typename Tag, typename OutputIterator>
|
||||
static bool exponent (OutputIterator& sink, long n)
|
||||
{
|
||||
// NOTE: copied from karma to force sign in exponent
|
||||
const bool force_sign = true;
|
||||
|
||||
using namespace boost::spirit; // for traits
|
||||
using namespace boost::spirit::karma; // for char_inserter, sign_inserter
|
||||
|
||||
unsigned long abs_n = traits::get_absolute_value(n);
|
||||
bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
|
||||
sign_inserter::call(sink, traits::test_zero(n)
|
||||
, traits::test_negative(n), force_sign);
|
||||
|
||||
// the C99 Standard requires at least two digits in the exponent
|
||||
if (r && abs_n < 10)
|
||||
r = char_inserter<CharEncoding, Tag>::call(sink, '0');
|
||||
return r && int_inserter<10>::call(sink, abs_n);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
bool to_string(std::string & str, double value)
|
||||
{
|
||||
namespace karma = boost::spirit::karma;
|
||||
typedef karma::real_generator<double, detail::double_policy<double> > double_type;
|
||||
std::back_insert_iterator<std::string> sink(str);
|
||||
return karma::generate(sink, double_type(), value);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool to_string(std::string & s, int val)
|
||||
|
@ -332,22 +261,6 @@ bool to_string(std::string & s, bool val)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool to_string(std::string & s, double val)
|
||||
{
|
||||
s.resize(s.capacity());
|
||||
while (true)
|
||||
{
|
||||
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%g", val));
|
||||
if (n2 <= s.size())
|
||||
{
|
||||
s.resize(n2);
|
||||
break;
|
||||
}
|
||||
s.resize(n2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace util
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <mapnik/font_set.hpp>
|
||||
#include <mapnik/parse_path.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/request.hpp>
|
||||
#include <mapnik/svg/svg_converter.hpp>
|
||||
#include <mapnik/svg/svg_renderer_agg.hpp>
|
||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||
|
@ -71,6 +72,24 @@ grid_renderer<T>::grid_renderer(Map const& m, T & pixmap, double scale_factor, u
|
|||
setup(m);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
grid_renderer<T>::grid_renderer(Map const& m, request const& req, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<grid_renderer>(m, scale_factor),
|
||||
pixmap_(pixmap),
|
||||
width_(pixmap_.width()),
|
||||
height_(pixmap_.height()),
|
||||
scale_factor_(scale_factor),
|
||||
// NOTE: can change this to m dims instead of pixmap_ if render-time
|
||||
// resolution support is dropped from grid_renderer python interface
|
||||
t_(pixmap_.width(),pixmap_.height(),req.extent(),offset_x,offset_y),
|
||||
font_engine_(),
|
||||
font_manager_(font_engine_),
|
||||
detector_(boost::make_shared<label_collision_detector4>(box2d<double>(-req.buffer_size(), -req.buffer_size(), req.width() + req.buffer_size() ,req.height() + req.buffer_size()))),
|
||||
ras_ptr(new grid_rasterizer)
|
||||
{
|
||||
setup(m);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::setup(Map const& m)
|
||||
{
|
||||
|
|
|
@ -44,8 +44,11 @@ image_filter_grammar<Iterator,ContType>::image_filter_grammar()
|
|||
using qi::_1;
|
||||
using qi::_a;
|
||||
using qi::_b;
|
||||
using qi::_r1;
|
||||
using qi::eps;
|
||||
using qi::char_;
|
||||
using qi::lexeme;
|
||||
using boost::spirit::ascii::string;
|
||||
using phoenix::push_back;
|
||||
using phoenix::construct;
|
||||
|
||||
|
@ -75,15 +78,26 @@ image_filter_grammar<Iterator,ContType>::image_filter_grammar()
|
|||
|
|
||||
lit("y-gradient")[push_back(_val,construct<mapnik::filter::y_gradient>())]
|
||||
|
|
||||
(lit("agg-stack-blur")[_a = 1, _b = 1]
|
||||
>> -( lit('(') >> radius_[_a = _1]
|
||||
>> lit(',')
|
||||
>> radius_[_b = _1]
|
||||
>> lit(')'))
|
||||
[push_back(_val,construct<mapnik::filter::agg_stack_blur>(_a,_b))])
|
||||
|
|
||||
lit("invert")[push_back(_val,construct<mapnik::filter::invert>())]
|
||||
|
|
||||
agg_blur_filter(_val)
|
||||
|
|
||||
hsla_filter(_val)
|
||||
;
|
||||
|
||||
agg_blur_filter = (lit("agg-stack-blur")[_a = 1, _b = 1]
|
||||
>> -( lit('(') >> radius_[_a = _1]
|
||||
>> lit(',')
|
||||
>> radius_[_b = _1]
|
||||
>> lit(')')))
|
||||
[push_back(_r1,construct<mapnik::filter::agg_stack_blur>(_a,_b))]
|
||||
;
|
||||
|
||||
hsla_filter = (lit("hsla") >> lit('(') >> string_arg[_a = _1] >> lit(')'))
|
||||
[push_back(_r1,construct<mapnik::filter::hsla>(_a))]
|
||||
;
|
||||
|
||||
string_arg = +~char_(')');
|
||||
}
|
||||
|
||||
template struct mapnik::image_filter_grammar<std::string::const_iterator,std::vector<mapnik::filter::filter_type> >;
|
||||
|
|
85
src/request.cpp
Normal file
85
src/request.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2013 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/request.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
request::request(unsigned width,
|
||||
unsigned height,
|
||||
box2d<double> const& extent)
|
||||
: width_(width),
|
||||
height_(height),
|
||||
extent_(extent),
|
||||
buffer_size_(0) {}
|
||||
|
||||
request::~request() {}
|
||||
|
||||
unsigned request::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned request::height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
void request::set_buffer_size(int buffer_size)
|
||||
{
|
||||
buffer_size_ = buffer_size;
|
||||
}
|
||||
|
||||
int request::buffer_size() const
|
||||
{
|
||||
return buffer_size_;
|
||||
}
|
||||
|
||||
void request::set_extent(box2d<double> const& box)
|
||||
{
|
||||
extent_ = box;
|
||||
}
|
||||
|
||||
box2d<double> const& request::extent() const
|
||||
{
|
||||
return extent_;
|
||||
}
|
||||
|
||||
box2d<double> request::get_buffered_extent() const
|
||||
{
|
||||
double extra = 2.0 * scale() * buffer_size_;
|
||||
box2d<double> ext(extent_);
|
||||
ext.width(extent_.width() + extra);
|
||||
ext.height(extent_.height() + extra);
|
||||
return ext;
|
||||
}
|
||||
|
||||
double request::scale() const
|
||||
{
|
||||
if (width_>0)
|
||||
return extent_.width()/width_;
|
||||
return extent_.width();
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,12 @@ test_env.AppendUnique(LIBS='mapnik')
|
|||
test_env.AppendUnique(LIBS='sqlite3')
|
||||
test_env.AppendUnique(CXXFLAGS='-g')
|
||||
|
||||
test_env['CXXFLAGS'] = copy(test_env['LIBMAPNIK_CXXFLAGS'])
|
||||
|
||||
if test_env['HAS_CAIRO']:
|
||||
test_env.PrependUnique(CPPPATH=test_env['CAIRO_CPPPATHS'])
|
||||
test_env.Append(CXXFLAGS = '-DHAVE_CAIRO')
|
||||
|
||||
for cpp_test in glob.glob('*_test.cpp'):
|
||||
name = cpp_test.replace('.cpp','-bin')
|
||||
source_files = [cpp_test]
|
||||
|
|
|
@ -65,11 +65,6 @@ int main( int, char*[] )
|
|||
BOOST_TEST_EQ( out, "-0.0001" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.0001234567890123456));
|
||||
// TODO: https://github.com/mapnik/mapnik/issues/1676
|
||||
BOOST_TEST_EQ( out, "0.000123457" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.0001));
|
||||
BOOST_TEST_EQ( out, "0.0001" );
|
||||
out.clear();
|
||||
|
@ -98,6 +93,23 @@ int main( int, char*[] )
|
|||
BOOST_TEST_EQ( out, "1e-10" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(-1.234e+16));
|
||||
BOOST_TEST_EQ( out, "-1.234e+16" );
|
||||
out.clear();
|
||||
|
||||
// critical failure when karam is used
|
||||
// https://github.com/mapnik/mapnik/issues/1741
|
||||
// https://github.com/mapbox/tilemill/issues/1456
|
||||
to_string(out, double(8.3));
|
||||
BOOST_TEST_EQ( out, "8.3" );
|
||||
out.clear();
|
||||
|
||||
// non-critical failures if karma is used
|
||||
to_string(out, double(0.0001234567890123456));
|
||||
// TODO: https://github.com/mapnik/mapnik/issues/1676
|
||||
BOOST_TEST_EQ( out, "0.000123457" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.00000000001));
|
||||
BOOST_TEST_EQ( out, "1e-11" );
|
||||
out.clear();
|
||||
|
@ -185,15 +197,7 @@ int main( int, char*[] )
|
|||
to_string(out, double(1.234e+16));
|
||||
BOOST_TEST_EQ( out, "1.234e+16" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(-1.234e+16));
|
||||
BOOST_TEST_EQ( out, "-1.234e+16" );
|
||||
out.clear();
|
||||
// https://github.com/mapbox/tilemill/issues/1456
|
||||
to_string(out, double(8.3));
|
||||
BOOST_TEST_EQ( out, "8.3" );
|
||||
out.clear();
|
||||
|
||||
|
||||
// int
|
||||
to_string(out, int(2));
|
||||
BOOST_TEST_EQ( out, "2" );
|
||||
|
|
152
tests/cpp_tests/map_request_test.cpp
Normal file
152
tests/cpp_tests/map_request_test.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
#include <boost/version.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/load_map.hpp>
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
#if defined(HAVE_CAIRO)
|
||||
#include <mapnik/cairo_renderer.hpp>
|
||||
#include <mapnik/cairo_context.hpp>
|
||||
#endif
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/datasource_cache.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/image_data.hpp>
|
||||
#include <mapnik/image_reader.hpp>
|
||||
#include <mapnik/scale_denominator.hpp>
|
||||
#include <mapnik/feature_style_processor.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
bool compare_images(std::string const& src_fn,std::string const& dest_fn)
|
||||
{
|
||||
using namespace mapnik;
|
||||
std::auto_ptr<mapnik::image_reader> reader1(mapnik::get_image_reader(dest_fn,"png"));
|
||||
if (!reader1.get())
|
||||
{
|
||||
throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
|
||||
}
|
||||
boost::shared_ptr<image_32> image_ptr1 = boost::make_shared<image_32>(reader1->width(),reader1->height());
|
||||
reader1->read(0,0,image_ptr1->data());
|
||||
|
||||
std::auto_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn,"png"));
|
||||
if (!reader2.get())
|
||||
{
|
||||
throw mapnik::image_reader_exception("Failed to load: " + src_fn);
|
||||
}
|
||||
boost::shared_ptr<image_32> image_ptr2 = boost::make_shared<image_32>(reader2->width(),reader2->height());
|
||||
reader2->read(0,0,image_ptr2->data());
|
||||
|
||||
image_data_32 const& dest = image_ptr1->data();
|
||||
image_data_32 const& src = image_ptr2->data();
|
||||
|
||||
unsigned int width = src.width();
|
||||
unsigned int height = src.height();
|
||||
if ((width != dest.width()) || height != dest.height()) return false;
|
||||
for (unsigned int y = 0; y < height; ++y)
|
||||
{
|
||||
const unsigned int* row_from = src.getRow(y);
|
||||
const unsigned int* row_to = dest.getRow(y);
|
||||
for (unsigned int x = 0; x < width; ++x)
|
||||
{
|
||||
if (row_from[x] != row_to[x]) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int, char*[] )
|
||||
{
|
||||
std::string expected("./tests/cpp_tests/support/map-request-marker-text-line-expected.png");
|
||||
std::string expected_cairo("./tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png");
|
||||
try {
|
||||
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
|
||||
mapnik::freetype_engine::register_fonts("./fonts", true );
|
||||
mapnik::Map m(256,256);
|
||||
mapnik::load_map(m,"./tests/data/good_maps/marker-text-line.xml",false);
|
||||
m.zoom_all();
|
||||
mapnik::image_32 im(m.width(),m.height());
|
||||
double scale_factor = 1.2;
|
||||
|
||||
// render normally with apply() and just map and image
|
||||
mapnik::agg_renderer<mapnik::image_32> renderer1(m,im,scale_factor);
|
||||
renderer1.apply();
|
||||
std::string actual1("/tmp/map-request-marker-text-line-actual1.png");
|
||||
//mapnik::save_to_file(im,expected);
|
||||
mapnik::save_to_file(im,actual1);
|
||||
BOOST_TEST(compare_images(actual1,expected));
|
||||
|
||||
// reset image
|
||||
im.clear();
|
||||
|
||||
// set up a mapnik::request object
|
||||
mapnik::request req(m.width(),m.height(),m.get_current_extent());
|
||||
req.set_buffer_size(m.buffer_size());
|
||||
|
||||
// render using apply() and mapnik::request
|
||||
mapnik::agg_renderer<mapnik::image_32> renderer2(m,req,im,scale_factor);
|
||||
renderer2.apply();
|
||||
std::string actual2("/tmp/map-request-marker-text-line-actual2.png");
|
||||
mapnik::save_to_file(im,actual2);
|
||||
BOOST_TEST(compare_images(actual2,expected));
|
||||
|
||||
// reset image
|
||||
im.clear();
|
||||
|
||||
// render with apply_to_layer api and mapnik::request params passed to apply_to_layer
|
||||
mapnik::agg_renderer<mapnik::image_32> renderer3(m,req,im,scale_factor);
|
||||
renderer3.start_map_processing(m);
|
||||
mapnik::projection map_proj(m.srs(),true);
|
||||
double scale_denom = mapnik::scale_denominator(req.scale(),map_proj.is_geographic());
|
||||
scale_denom *= scale_factor;
|
||||
BOOST_FOREACH ( mapnik::layer const& lyr, m.layers() )
|
||||
{
|
||||
if (lyr.visible(scale_denom))
|
||||
{
|
||||
std::set<std::string> names;
|
||||
renderer3.apply_to_layer(lyr,
|
||||
renderer3,
|
||||
map_proj,
|
||||
req.scale(),
|
||||
scale_denom,
|
||||
req.width(),
|
||||
req.height(),
|
||||
req.extent(),
|
||||
req.buffer_size(),
|
||||
names);
|
||||
|
||||
}
|
||||
}
|
||||
renderer3.end_map_processing(m);
|
||||
std::string actual3("/tmp/map-request-marker-text-line-actual3.png");
|
||||
mapnik::save_to_file(im,actual3);
|
||||
BOOST_TEST(compare_images(actual3,expected));
|
||||
|
||||
// also test cairo
|
||||
#if defined(HAVE_CAIRO)
|
||||
mapnik::cairo_surface_ptr image_surface(
|
||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,req.width(),req.height()),
|
||||
mapnik::cairo_surface_closer());
|
||||
mapnik::cairo_ptr image_context = (mapnik::create_context(image_surface));
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> png_render(m,req,image_context,scale_factor);
|
||||
png_render.apply();
|
||||
//cairo_surface_write_to_png(&*image_surface, expected_cairo.c_str());
|
||||
std::string actual_cairo("/tmp/map-request-marker-text-line-actual4.png");
|
||||
cairo_surface_write_to_png(&*image_surface, actual_cairo.c_str());
|
||||
BOOST_TEST(compare_images(actual_cairo,expected_cairo));
|
||||
#endif
|
||||
// TODO - test grid_renderer
|
||||
|
||||
} catch (std::exception const& ex) {
|
||||
std::clog << ex.what() << "\n";
|
||||
}
|
||||
if (!::boost::detail::test_errors()) {
|
||||
std::clog << "C++ Map Request rendering hook: \x1b[1;32m✓ \x1b[0m\n";
|
||||
#if BOOST_VERSION >= 104600
|
||||
::boost::detail::report_errors_remind().called_report_errors_function = true;
|
||||
#endif
|
||||
} else {
|
||||
return ::boost::report_errors();
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
|
@ -1,4 +1,4 @@
|
|||
<Map>
|
||||
<Map srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
|
||||
<Style name="ellipse">
|
||||
<Rule>
|
||||
<MarkersSymbolizer
|
||||
|
|
|
@ -27,7 +27,7 @@ Known values for OPTION are:
|
|||
--libs print library linking information
|
||||
--dep-libs print library linking information for Mapnik dependencies
|
||||
--ldflags print library paths (-L) information
|
||||
--cflags print pre-processor and compiler flags
|
||||
--cxxflags print pre-processor and compiler flags
|
||||
--fonts print default fonts directory
|
||||
--input-plugins print default input plugins directory
|
||||
--json print all config options as json object
|
||||
|
@ -89,7 +89,7 @@ while test $# -gt 0; do
|
|||
echo ${CONFIG_INPUT_PLUGINS}
|
||||
;;
|
||||
|
||||
--cflags)
|
||||
--cxxflags)
|
||||
echo -I${CONFIG_MAPNIK_INCLUDE} -I${CONFIG_MAPNIK_AGG_INCLUDE} ${CONFIG_OTHER_INCLUDES}
|
||||
;;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue