+ implement cairo_context wrapper and remove unnecessary dependencies

( cairomm, libsigc++)
This commit is contained in:
artemp 2013-01-09 17:00:30 +00:00
parent 0121f53f56
commit f25d4d9279
17 changed files with 1187 additions and 973 deletions

View file

@ -49,7 +49,7 @@ SCONF_TEMP_DIR = '.sconf_temp'
# auto-search directories for boost libs/headers # auto-search directories for boost libs/headers
BOOST_SEARCH_PREFIXES = ['/usr/local','/opt/local','/sw','/usr',] BOOST_SEARCH_PREFIXES = ['/usr/local','/opt/local','/sw','/usr',]
BOOST_MIN_VERSION = '1.47' BOOST_MIN_VERSION = '1.47'
CAIROMM_MIN_VERSION = '1.8.0' #CAIROMM_MIN_VERSION = '1.8.0'
DEFAULT_LINK_PRIORITY = ['internal','other','frameworks','user','system'] DEFAULT_LINK_PRIORITY = ['internal','other','frameworks','user','system']
@ -60,8 +60,8 @@ pretty_dep_names = {
'ogr':'OGR-enabled GDAL C++ Library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki//OGR', 'ogr':'OGR-enabled GDAL C++ Library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki//OGR',
'geos_c':'GEOS Simple Geometry Specification C Library | configured with GEOS_LIB & GEOS_INCLUDE | more info: https://github.com/mapnik/mapnik/wiki//GEOS', 'geos_c':'GEOS Simple Geometry Specification C Library | configured with GEOS_LIB & GEOS_INCLUDE | more info: https://github.com/mapnik/mapnik/wiki//GEOS',
'cairo':'Cairo C library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option', 'cairo':'Cairo C library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'cairomm':'Cairomm C++ bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option', #'cairomm':'Cairomm C++ bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'cairomm-version':'Cairomm version is too old (so cairo renderer will not be built), you need at least %s' % CAIROMM_MIN_VERSION, #'cairomm-version':'Cairomm version is too old (so cairo renderer will not be built), you need at least %s' % CAIROMM_MIN_VERSION,
'pycairo':'Python bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option', 'pycairo':'Python bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'proj':'Proj.4 C Projections library | configure with PROJ_LIBS & PROJ_INCLUDES | more info: http://trac.osgeo.org/proj/', 'proj':'Proj.4 C Projections library | configure with PROJ_LIBS & PROJ_INCLUDES | more info: http://trac.osgeo.org/proj/',
'pg':'Postgres C Library requiered for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki//PostGIS', 'pg':'Postgres C Library requiered for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki//PostGIS',
@ -333,8 +333,8 @@ opts.AddVariables(
# Note: cairo, cairomm, and pycairo all optional but configured automatically through pkg-config # Note: cairo, cairomm, and pycairo all optional but configured automatically through pkg-config
# Therefore, we use a single boolean for whether to attempt to build cairo support. # Therefore, we use a single boolean for whether to attempt to build cairo support.
BoolVariable('CAIRO', 'Attempt to build with Cairo rendering support', 'True'), BoolVariable('CAIRO', 'Attempt to build with Cairo rendering support', 'True'),
PathVariable('CAIRO_INCLUDES', 'Search path for cairo/cairomm include files', '',PathVariable.PathAccept), PathVariable('CAIRO_INCLUDES', 'Search path for cairo include files', '',PathVariable.PathAccept),
PathVariable('CAIRO_LIBS', 'Search path for cairo/cairomm library files','',PathVariable.PathAccept), PathVariable('CAIRO_LIBS', 'Search path for cairo library files','',PathVariable.PathAccept),
('GDAL_CONFIG', 'The path to the gdal-config executable for finding gdal and ogr details.', 'gdal-config'), ('GDAL_CONFIG', 'The path to the gdal-config executable for finding gdal and ogr details.', 'gdal-config'),
('PG_CONFIG', 'The path to the pg_config executable.', 'pg_config'), ('PG_CONFIG', 'The path to the pg_config executable.', 'pg_config'),
PathVariable('OCCI_INCLUDES', 'Search path for OCCI include files', '/usr/lib/oracle/10.2.0.3/client/include', PathVariable.PathAccept), PathVariable('OCCI_INCLUDES', 'Search path for OCCI include files', '/usr/lib/oracle/10.2.0.3/client/include', PathVariable.PathAccept),
@ -1277,17 +1277,17 @@ if not preconfigured:
c_inc = os.path.dirname(c_inc) c_inc = os.path.dirname(c_inc)
env["CAIROMM_CPPPATHS"].extend( env["CAIROMM_CPPPATHS"].extend(
[ [
os.path.join(c_inc,'include/cairomm-1.0'), #os.path.join(c_inc,'include/cairomm-1.0'),
os.path.join(c_inc,'lib/cairomm-1.0/include'), #os.path.join(c_inc,'lib/cairomm-1.0/include'),
os.path.join(c_inc,'include/cairo'), os.path.join(c_inc,'include/cairo'),
os.path.join(c_inc,'include/sigc++-2.0'), #os.path.join(c_inc,'include/sigc++-2.0'),
os.path.join(c_inc,'lib/sigc++-2.0/include'), #os.path.join(c_inc,'lib/sigc++-2.0/include'),
os.path.join(c_inc,'include/pixman-1'), os.path.join(c_inc,'include/pixman-1'),
#os.path.join(c_inc,'include/freetype2'), #os.path.join(c_inc,'include/freetype2'),
#os.path.join(c_inc,'include/libpng'), #os.path.join(c_inc,'include/libpng'),
] ]
) )
env["CAIROMM_LINKFLAGS"] = ['cairo','cairomm-1.0'] env["CAIROMM_LINKFLAGS"] = ['cairo']
if env['RUNTIME_LINK'] == 'static': if env['RUNTIME_LINK'] == 'static':
env["CAIROMM_LINKFLAGS"].extend( env["CAIROMM_LINKFLAGS"].extend(
['sigc-2.0','pixman-1','expat','fontconfig','iconv'] ['sigc-2.0','pixman-1','expat','fontconfig','iconv']
@ -1299,40 +1299,40 @@ if not preconfigured:
env['HAS_CAIRO'] = False env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('pkg-config') env['SKIPPED_DEPS'].append('pkg-config')
env['SKIPPED_DEPS'].append('cairo') env['SKIPPED_DEPS'].append('cairo')
env['SKIPPED_DEPS'].append('cairomm') #env['SKIPPED_DEPS'].append('cairomm')
elif not conf.CheckPKG('cairo'): elif not conf.CheckPKG('cairo'):
env['HAS_CAIRO'] = False env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('cairo') env['SKIPPED_DEPS'].append('cairo')
elif not conf.CheckPKG('cairomm-1.0'): #elif not conf.CheckPKG('cairomm-1.0'):
env['HAS_CAIRO'] = False # env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('cairomm') # env['SKIPPED_DEPS'].append('cairomm')
elif not conf.CheckPKGVersion('cairomm-1.0',CAIROMM_MIN_VERSION): #elif not conf.CheckPKGVersion('cairomm-1.0',CAIROMM_MIN_VERSION):
env['HAS_CAIRO'] = False # env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('cairomm-version') # env['SKIPPED_DEPS'].append('cairomm-version')
else: #else:
print 'Checking for cairo/cairomm lib and include paths... ', # print 'Checking for cairo/cairomm lib and include paths... ',
cmd = 'pkg-config --libs --cflags cairomm-1.0' # cmd = 'pkg-config --libs --cflags cairomm-1.0'
if env['RUNTIME_LINK'] == 'static': # if env['RUNTIME_LINK'] == 'static':
cmd += ' --static' # cmd += ' --static'
cairo_env = env.Clone() # cairo_env = env.Clone()
try: # try:
cairo_env.ParseConfig(cmd) # cairo_env.ParseConfig(cmd)
for lib in cairo_env['LIBS']: # for lib in cairo_env['LIBS']:
if not lib in env['LIBS']: # if not lib in env['LIBS']:
env["CAIROMM_LINKFLAGS"].append(lib) # env["CAIROMM_LINKFLAGS"].append(lib)
for lpath in cairo_env['LIBPATH']: # for lpath in cairo_env['LIBPATH']:
if not lpath in env['LIBPATH']: # if not lpath in env['LIBPATH']:
env["CAIROMM_LIBPATHS"].append(lpath) # env["CAIROMM_LIBPATHS"].append(lpath)
for inc in cairo_env['CPPPATH']: # for inc in cairo_env['CPPPATH']:
if not inc in env['CPPPATH']: # if not inc in env['CPPPATH']:
env["CAIROMM_CPPPATHS"].append(inc) # env["CAIROMM_CPPPATHS"].append(inc)
env['HAS_CAIRO'] = True # env['HAS_CAIRO'] = True
print 'yes' # print 'yes'
except OSError,e: # except OSError,e:
color_print(1,'no') # color_print(1,'no')
env['SKIPPED_DEPS'].append('cairo') # env['SKIPPED_DEPS'].append('cairo')
env['SKIPPED_DEPS'].append('cairomm') # env['SKIPPED_DEPS'].append('cairomm')
color_print(1,'pkg-config reported: %s' % e) # color_print(1,'pkg-config reported: %s' % e)
else: else:
color_print(4,'Not building with cairo support, pass CAIRO=True to enable') color_print(4,'Not building with cairo support, pass CAIRO=True to enable')

View file

@ -46,7 +46,7 @@ extern "C"
// cairo // cairo
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <cairomm/surface.h> #include <mapnik/cairo_context.hpp>
#include <pycairo.h> #include <pycairo.h>
#endif #endif
@ -158,17 +158,16 @@ void blend (image_32 & im, unsigned x, unsigned y, image_32 const& im2, float op
im.set_rectangle_alpha2(im2.data(),x,y,opacity); im.set_rectangle_alpha2(im2.data(),x,y,opacity);
} }
void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, float opacity) void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, float opacity)
{ {
mapnik::composite(dst.data(),src.data(),mode,opacity,0,0,false); mapnik::composite(dst.data(),src.data(),mode,opacity,0,0,false);
} }
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
boost::shared_ptr<image_32> from_cairo(PycairoSurface* surface) boost::shared_ptr<image_32> from_cairo(PycairoSurface* py_surface)
{ {
Cairo::RefPtr<Cairo::ImageSurface> s(new Cairo::ImageSurface(surface->surface)); mapnik::cairo_surface_ptr surface(py_surface->surface, mapnik::cairo_surface_closer());
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(s); boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(surface);
return image_ptr; return image_ptr;
} }
#endif #endif

View file

@ -163,92 +163,92 @@ void render_layer2(const mapnik::Map& map,
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
void render3(const mapnik::Map& map, void render3(const mapnik::Map& map,
PycairoSurface* surface, PycairoSurface* py_surface,
double scale_factor = 1.0, double scale_factor = 1.0,
unsigned offset_x = 0, unsigned offset_x = 0,
unsigned offset_y = 0) unsigned offset_y = 0)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface)); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,scale_factor,offset_x,offset_y); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface,scale_factor,offset_x,offset_y);
ren.apply(); ren.apply();
} }
void render4(const mapnik::Map& map, PycairoSurface* surface) void render4(const mapnik::Map& map, PycairoSurface* py_surface)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface)); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<Cairo::Surface> ren(map,s); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface);
ren.apply(); ren.apply();
} }
void render5(const mapnik::Map& map, void render5(const mapnik::Map& map,
PycairoContext* context, PycairoContext* py_context,
double scale_factor = 1.0, double scale_factor = 1.0,
unsigned offset_x = 0, unsigned offset_x = 0,
unsigned offset_y = 0) unsigned offset_y = 0)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx)); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<Cairo::Context> ren(map,c,scale_factor,offset_x, offset_y); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,scale_factor,offset_x, offset_y);
ren.apply(); ren.apply();
} }
void render6(const mapnik::Map& map, PycairoContext* context) void render6(const mapnik::Map& map, PycairoContext* py_context)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx)); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<Cairo::Context> ren(map,c); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context);
ren.apply(); ren.apply();
} }
void render_with_detector2( void render_with_detector2(
const mapnik::Map& map, const mapnik::Map& map,
PycairoContext* context, PycairoContext* py_context,
boost::shared_ptr<mapnik::label_collision_detector4> detector) boost::shared_ptr<mapnik::label_collision_detector4> detector)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx)); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<Cairo::Context> ren(map,c,detector); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector);
ren.apply(); ren.apply();
} }
void render_with_detector3( void render_with_detector3(
const mapnik::Map& map, const mapnik::Map& map,
PycairoContext* context, PycairoContext* py_context,
boost::shared_ptr<mapnik::label_collision_detector4> detector, boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0, double scale_factor = 1.0,
unsigned offset_x = 0u, unsigned offset_x = 0u,
unsigned offset_y = 0u) unsigned offset_y = 0u)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx)); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<Cairo::Context> ren(map,c,detector,scale_factor,offset_x,offset_y); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector,scale_factor,offset_x,offset_y);
ren.apply(); ren.apply();
} }
void render_with_detector4( void render_with_detector4(
const mapnik::Map& map, const mapnik::Map& map,
PycairoSurface* surface, PycairoSurface* py_surface,
boost::shared_ptr<mapnik::label_collision_detector4> detector) boost::shared_ptr<mapnik::label_collision_detector4> detector)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface)); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,detector); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector);
ren.apply(); ren.apply();
} }
void render_with_detector5( void render_with_detector5(
const mapnik::Map& map, const mapnik::Map& map,
PycairoSurface* surface, PycairoSurface* py_surface,
boost::shared_ptr<mapnik::label_collision_detector4> detector, boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0, double scale_factor = 1.0,
unsigned offset_x = 0u, unsigned offset_x = 0u,
unsigned offset_y = 0u) unsigned offset_y = 0u)
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface)); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,detector,scale_factor,offset_x,offset_y); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector, scale_factor, offset_x, offset_y);
ren.apply(); ren.apply();
} }

View file

@ -37,7 +37,6 @@
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
// cairo // cairo
#include <mapnik/cairo_renderer.hpp> #include <mapnik/cairo_renderer.hpp>
#include <cairomm/surface.h>
#endif #endif
#include "mapwidget.hpp" #include "mapwidget.hpp"
@ -567,12 +566,10 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{ {
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
Cairo::RefPtr<Cairo::ImageSurface> image_surface = mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,map.width(),map.height()),
Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, map.width(),map.height()); mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> renderer(map, image_surface, scaling_factor);
mapnik::cairo_renderer<Cairo::Surface> png_render(map, image_surface, scaling_factor); renderer.apply();
png_render.apply();
image_32 buf(image_surface); image_32 buf(image_surface);
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32); QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped()); pix = QPixmap::fromImage(image.rgbSwapped());

View file

@ -21,6 +21,8 @@
#include "styles_model.hpp" #include "styles_model.hpp"
#include <mapnik/expression_string.hpp> #include <mapnik/expression_string.hpp>
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/feature_type_style.hpp>
// boost // boost
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
@ -162,6 +164,18 @@ struct symbolizer_info : public boost::static_visitor<QString>
return QString("ShieldSymbolizer"); return QString("ShieldSymbolizer");
} }
QString operator() (mapnik::markers_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("MarkersSymbolizer");
}
QString operator() (mapnik::building_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("BuildingSymbolizer");
}
template <typename T> template <typename T>
QString operator() (T const& ) const QString operator() (T const& ) const
{ {
@ -223,7 +237,7 @@ class symbolizer_node
{ {
public: public:
symbolizer_node(mapnik::symbolizer const & sym) symbolizer_node(mapnik::symbolizer const & sym)
: sym_(sym) {} : sym_(sym) {}
~symbolizer_node(){} ~symbolizer_node(){}
QString name() const QString name() const

View file

@ -0,0 +1,425 @@
/*****************************************************************************
*
* 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_CAIRO_CONTEXT_HPP
#define MAPNIK_CAIRO_CONTEXT_HPP
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/color.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/text_path.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/gradient.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
// cairo
#include <cairo.h>
#include <cairo-ft.h>
// stl
#include <valarray>
// agg
#include "agg_basics.h"
namespace mapnik {
typedef cairo_status_t ErrorStatus;
/// Throws the appropriate exception, if exceptions are enabled.
inline void throw_exception(ErrorStatus status)
{
throw std::runtime_error("cairo: fixme");
}
//We inline this because it is called so often.
inline void check_status_and_throw_exception(ErrorStatus status)
{
if(status != CAIRO_STATUS_SUCCESS)
throw_exception(status);
}
template<class T>
void check_object_status_and_throw_exception(const T& object)
{
check_status_and_throw_exception(object.get_status());
}
class cairo_face : private mapnik::noncopyable
{
public:
cairo_face(boost::shared_ptr<freetype_engine> const& engine, face_ptr const& face)
: face_(face)
{
static cairo_user_data_key_t key;
c_face_ = cairo_ft_font_face_create_for_ft_face(face->get_face(), FT_LOAD_NO_HINTING);
cairo_font_face_set_user_data(c_face_, &key, new handle(engine, face), destroy);
}
~cairo_face()
{
if (c_face_) cairo_font_face_destroy(c_face_);
}
cairo_font_face_t * face() const
{
return c_face_;
}
private:
class handle
{
public:
handle(boost::shared_ptr<freetype_engine> const& engine, face_ptr const& face)
: engine_(engine), face_(face) {}
private:
boost::shared_ptr<freetype_engine> engine_;
face_ptr face_;
};
static void destroy(void *data)
{
handle *h = static_cast<handle *>(data);
delete h;
}
private:
face_ptr face_;
cairo_font_face_t *c_face_;
};
typedef boost::shared_ptr<cairo_face> cairo_face_ptr;
class cairo_face_manager : private mapnik::noncopyable
{
public:
cairo_face_manager(boost::shared_ptr<freetype_engine> engine);
cairo_face_ptr get_face(face_ptr face);
private:
typedef std::map<face_ptr,cairo_face_ptr> cairo_face_cache;
boost::shared_ptr<freetype_engine> font_engine_;
cairo_face_cache cache_;
};
class cairo_pattern : private mapnik::noncopyable
{
public:
cairo_pattern(image_data_32 const& data)
{
int pixels = data.width() * data.height();
const unsigned int *in_ptr = data.getData();
const unsigned int *in_end = in_ptr + pixels;
unsigned int *out_ptr;
surface_ = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, data.width(), data.height());
out_ptr = reinterpret_cast<unsigned int *>(cairo_image_surface_get_data(surface_));
while (in_ptr < in_end)
{
unsigned int in = *in_ptr++;
unsigned int r = (in >> 0) & 0xff;
unsigned int g = (in >> 8) & 0xff;
unsigned int b = (in >> 16) & 0xff;
unsigned int a = (in >> 24) & 0xff;
//r = r * a / 255;
//g = g * a / 255;
//b = b * a / 255;
*out_ptr++ = (a << 24) | (r << 16) | (g << 8) | b;
}
// mark the surface as dirty as we've modified it behind cairo's back
cairo_surface_mark_dirty(surface_);
pattern_ = cairo_pattern_create_for_surface(surface_);
}
~cairo_pattern()
{
if (surface_) cairo_surface_destroy(surface_);
if (pattern_) cairo_pattern_destroy(pattern_);
}
void set_matrix(cairo_matrix_t const& matrix)
{
cairo_pattern_set_matrix(pattern_, &matrix);
}
void set_origin(double x, double y)
{
cairo_matrix_t matrix;
cairo_pattern_get_matrix(pattern_,&matrix);
matrix.x0 = -x;
matrix.y0 = -y;
cairo_pattern_set_matrix(pattern_,&matrix);
}
void set_extend(cairo_extend_t extend)
{
cairo_pattern_set_extend(pattern_, extend);
}
void set_filter(cairo_filter_t filter)
{
cairo_pattern_set_filter(pattern_, filter);
}
cairo_pattern_t * pattern() const
{
return pattern_;
}
private:
cairo_surface_t * surface_;
cairo_pattern_t * pattern_;
};
class cairo_gradient : private mapnik::noncopyable
{
public:
cairo_gradient(const mapnik::gradient &grad, double opacity=1.0)
{
double x1,x2,y1,y2,rad;
grad.get_control_points(x1,y1,x2,y2,rad);
if (grad.get_gradient_type() == LINEAR)
{
pattern_ = cairo_pattern_create_linear(x1, y1, x2, y2);
}
else if (grad.get_gradient_type() == RADIAL)
{
pattern_ = cairo_pattern_create_radial(x1, y1, 0, x2, y2, rad);
}
units_ = grad.get_units();
BOOST_FOREACH ( mapnik::stop_pair const& st, grad.get_stop_array() )
{
mapnik::color const& stop_color = st.second;
double r= static_cast<double> (stop_color.red())/255.0;
double g= static_cast<double> (stop_color.green())/255.0;
double b= static_cast<double> (stop_color.blue())/255.0;
double a= static_cast<double> (stop_color.alpha())/255.0;
cairo_pattern_add_color_stop_rgba(pattern_,st.first, r, g, b, a*opacity);
}
double m[6];
agg::trans_affine tr = grad.get_transform();
tr.invert();
tr.store_to(m);
cairo_matrix_t matrix;
cairo_matrix_init(&matrix,m[0],m[1],m[2],m[3],m[4],m[5]);
cairo_pattern_set_matrix(pattern_, &matrix);
}
~cairo_gradient()
{
if (pattern_)
cairo_pattern_destroy(pattern_);
}
cairo_pattern_t * gradient() const
{
return pattern_;
}
gradient_unit_e units() const
{
return units_;
}
private:
cairo_pattern_t * pattern_;
gradient_unit_e units_;
};
struct cairo_closer
{
void operator() (cairo_t * obj)
{
if (obj) cairo_destroy(obj);
}
};
struct cairo_surface_closer
{
void operator() (cairo_surface_t * surface)
{
if (surface) cairo_surface_destroy(surface);
}
};
typedef boost::shared_ptr<cairo_t> cairo_ptr;
typedef boost::shared_ptr<cairo_surface_t> cairo_surface_ptr;
inline cairo_ptr create_context(cairo_surface_ptr const& surface)
{
return cairo_ptr(cairo_create(&*surface),cairo_closer());
}
class cairo_context : private mapnik::noncopyable
{
public:
cairo_context(cairo_ptr const& cairo);
inline ErrorStatus get_status() const
{
return cairo_status(cairo_.get());
}
void clip();
void show_page();
void set_color(color const &color, double opacity = 1.0);
void set_color(double r, double g, double b, double opacity = 1.0);
void set_operator(composite_mode_e comp_op);
void set_line_join(line_join_e join);
void set_line_cap(line_cap_e cap);
void set_miter_limit(double limit);
void set_line_width(double width);
void set_dash(dash_array const &dashes, double scale_factor);
void set_fill_rule(cairo_fill_rule_t fill_rule);
void move_to(double x, double y);
void curve_to(double ct1_x, double ct1_y, double ct2_x, double ct2_y, double end_x, double end_y);
void close_path();
void line_to(double x, double y);
void rectangle(double x, double y, double w, double h);
void stroke();
void fill();
void paint();
void set_pattern(cairo_pattern const& pattern);
void set_gradient(cairo_gradient const& pattern, const box2d<double> &bbox);
void add_image(double x, double y, image_data_32 & data, double opacity = 1.0);
void add_image(agg::trans_affine const& tr, image_data_32 & data, double opacity = 1.0);
void set_font_face(cairo_face_manager & manager, face_ptr face);
void set_font_matrix(cairo_matrix_t const& matrix);
void set_matrix(cairo_matrix_t const& matrix);
void transform(cairo_matrix_t const& matrix);
void translate(double x, double y);
void save();
void restore();
void show_glyph(unsigned long index, double x, double y);
void glyph_path(unsigned long index, double x, double y);
void add_text(text_path const& path,
cairo_face_manager & manager,
face_manager<freetype_engine> & font_manager,
double scale_factor = 1.0);
template <typename T>
void add_path(T& path, unsigned start_index = 0)
{
double x, y;
path.rewind(start_index);
for (unsigned cm = path.vertex(&x, &y); cm != SEG_END; cm = path.vertex(&x, &y))
{
if (cm == SEG_MOVETO)
{
move_to(x, y);
}
else if (cm == SEG_LINETO)
{
line_to(x, y);
}
else if (cm == SEG_CLOSE)
{
close_path();
}
}
}
template <typename T>
void add_agg_path(T& path, unsigned start_index = 0)
{
double x=0;
double y=0;
path.rewind(start_index);
for (unsigned cm = path.vertex(&x, &y); !agg::is_stop(cm); cm = path.vertex(&x, &y))
{
if (agg::is_move_to(cm))
{
move_to(x, y);
}
else if (agg::is_drawing(cm))
{
if (agg::is_curve3(cm))
{
double end_x=0;
double end_y=0;
MAPNIK_LOG_WARN(cairo_renderer) << "Curve 3 not implemented";
path.vertex(&end_x, &end_y);
curve_to(x,y,x,y,end_x,end_y);
}
else if (agg::is_curve4(cm))
{
double ct2_x=0;
double ct2_y=0;
double end_x=0;
double end_y=0;
path.vertex(&ct2_x, &ct2_y);
path.vertex(&end_x, &end_y);
curve_to(x,y,ct2_x,ct2_y,end_x,end_y);
}
else if (agg::is_line_to(cm))
{
line_to(x, y);
}
else
{
MAPNIK_LOG_WARN(cairo_renderer) << "Unimplemented drawing command: " << cm;
move_to(x, y);
}
}
else if (agg::is_close(cm))
{
close_path();
}
else
{
MAPNIK_LOG_WARN(cairo_renderer) << "Unimplemented path command: " << cm;
}
}
}
private:
cairo_ptr cairo_;
};
}
#endif // MAPNIK_CAIRO_CONTEXT_HPP

View file

@ -33,10 +33,10 @@
#include <mapnik/map.hpp> #include <mapnik/map.hpp>
#include <mapnik/rule.hpp> // for all symbolizers #include <mapnik/rule.hpp> // for all symbolizers
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
#include <mapnik/cairo_context.hpp>
// cairo // cairo
#include <cairomm/context.h> #include <cairo.h>
#include <cairomm/surface.h>
// boost // boost
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
@ -53,27 +53,11 @@ namespace mapnik {
class marker; class marker;
class cairo_face;
typedef boost::shared_ptr<cairo_face> cairo_face_ptr;
class cairo_face_manager : private mapnik::noncopyable
{
public:
cairo_face_manager(boost::shared_ptr<freetype_engine> engine);
cairo_face_ptr get_face(face_ptr face);
private:
typedef std::map<face_ptr,cairo_face_ptr> cairo_face_cache;
boost::shared_ptr<freetype_engine> font_engine_;
cairo_face_cache cache_;
};
class MAPNIK_DECL cairo_renderer_base : private mapnik::noncopyable class MAPNIK_DECL cairo_renderer_base : private mapnik::noncopyable
{ {
protected: protected:
cairo_renderer_base(Map const& m, Cairo::RefPtr<Cairo::Context> const& context, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); 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, Cairo::RefPtr<Cairo::Context> const& context, boost::shared_ptr<label_collision_detector4> detector, 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: public:
~cairo_renderer_base(); ~cairo_renderer_base();
void start_map_processing(Map const& map); void start_map_processing(Map const& map);
@ -132,9 +116,9 @@ public:
void render_box(box2d<double> const& b); void render_box(box2d<double> const& b);
protected: protected:
Map const& m_; Map const& m_;
Cairo::RefPtr<Cairo::Context> context_; //Cairo::RefPtr<Cairo::Context> context_;
cairo_context context_;
unsigned width_; unsigned width_;
unsigned height_; unsigned height_;
double scale_factor_; double scale_factor_;
@ -152,8 +136,8 @@ class MAPNIK_DECL cairo_renderer : public feature_style_processor<cairo_renderer
{ {
public: public:
typedef cairo_renderer_base processor_impl_type; typedef cairo_renderer_base processor_impl_type;
cairo_renderer(Map const& m, Cairo::RefPtr<T> const& surface, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); 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, Cairo::RefPtr<T> const& surface, boost::shared_ptr<label_collision_detector4> detector, 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); void end_map_processing(Map const& map);
}; };
} }

View file

@ -45,7 +45,6 @@ typedef std::set<expression_ptr> expression_set;
MAPNIK_DECL expression_ptr parse_expression (std::string const& wkt, std::string const& encoding = "UTF8"); MAPNIK_DECL expression_ptr parse_expression (std::string const& wkt, std::string const& encoding = "UTF8");
MAPNIK_DECL expression_ptr parse_expression (std::string const& wkt, mapnik::expression_grammar<std::string::const_iterator> const& g); MAPNIK_DECL expression_ptr parse_expression (std::string const& wkt, mapnik::expression_grammar<std::string::const_iterator> const& g);
} }
#endif // MAPNIK_EXPRESSION_HPP #endif // MAPNIK_EXPRESSION_HPP

View file

@ -37,7 +37,7 @@
// cairo // cairo
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
#include <cairomm/surface.h> #include <mapnik/cairo_context.hpp>
#endif #endif
// boost // boost
@ -58,7 +58,7 @@ public:
image_32(int width,int height); image_32(int width,int height);
image_32(image_32 const& rhs); image_32(image_32 const& rhs);
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
image_32(Cairo::RefPtr<Cairo::ImageSurface> rhs); explicit image_32(cairo_surface_ptr const& surface);
#endif #endif
~image_32(); ~image_32();
@ -184,9 +184,9 @@ public:
#endif #endif
} }
} }
void composite_pixel(unsigned op, int x,int y,unsigned c, unsigned cover, double opacity); void composite_pixel(unsigned op, int x,int y,unsigned c, unsigned cover, double opacity);
inline unsigned width() const inline unsigned width() const
{ {
return width_; return width_;

View file

@ -26,7 +26,7 @@
// boost // boost
#include <boost/variant/variant.hpp> #include <boost/variant/variant.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
// mapnik // mapnik
#include <mapnik/value_types.hpp> #include <mapnik/value_types.hpp>
@ -40,6 +40,31 @@ typedef boost::variant<value_null,value_integer,value_double,std::string> value_
typedef std::pair<std::string, value_holder> parameter; typedef std::pair<std::string, value_holder> parameter;
typedef std::map<std::string, value_holder> param_map; typedef std::map<std::string, value_holder> param_map;
// TODO - rewrite to avoid usage of lexical_cast
template <typename T>
struct value_extractor_visitor : public boost::static_visitor<>
{
value_extractor_visitor(boost::optional<T> & var)
:var_(var) {}
void operator () (T val) const
{
var_ = val;
}
template <typename T1>
void operator () (T1 val) const
{
try
{
var_ = boost::lexical_cast<T>(val);
}
catch (boost::bad_lexical_cast & ) {}
}
boost::optional<T> & var_;
};
class parameters : public param_map class parameters : public param_map
{ {
public: public:

View file

@ -17,7 +17,7 @@
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# #
# #
import os import os
@ -204,6 +204,7 @@ if env['HAS_CAIRO']:
libmapnik_cxxflags.append('-DHAVE_CAIRO') libmapnik_cxxflags.append('-DHAVE_CAIRO')
lib_env.PrependUnique(CPPPATH=copy(env['CAIROMM_CPPPATHS'])) lib_env.PrependUnique(CPPPATH=copy(env['CAIROMM_CPPPATHS']))
source.insert(0,'cairo_renderer.cpp') source.insert(0,'cairo_renderer.cpp')
source.insert(0,'cairo_context.cpp')
if env['JPEG']: if env['JPEG']:
source += Split( source += Split(

451
src/cairo_context.cpp Normal file
View file

@ -0,0 +1,451 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#include <mapnik/cairo_context.hpp>
namespace mapnik {
cairo_context::cairo_context(cairo_ptr const& cairo)
: cairo_(cairo)
{}
void cairo_context::clip()
{
cairo_clip(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::show_page()
{
cairo_show_page(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_color(color const &color, double opacity)
{
set_color(color.red()/255.0, color.green()/255.0, color.blue()/255.0, color.alpha() * opacity / 255.0);
}
void cairo_context::set_color(double r, double g, double b, double opacity)
{
cairo_set_source_rgb(cairo_.get(), r, g, b);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_operator(composite_mode_e comp_op)
{
switch (comp_op)
{
case clear:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_CLEAR);
break;
case src:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_SOURCE);
break;
case dst:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DEST);
break;
case src_over:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_OVER);
break;
case dst_over:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DEST_OVER);
break;
case src_in:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_IN);
break;
case dst_in:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DEST_IN);
break;
case src_out:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_OUT);
break;
case dst_out:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DEST_OUT);
break;
case src_atop:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_ATOP);
break;
case dst_atop:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DEST_ATOP);
break;
case _xor:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_XOR);
break;
case plus:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_ADD);
break;
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
case multiply:
cairo_set_operator(cairo_.get(), CAIRO_OPERATOR_MULTIPLY);
break;
case screen:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_SCREEN);
break;
case overlay:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_OVERLAY);
break;
case darken:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DARKEN);
break;
case lighten:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_LIGHTEN);
break;
case color_dodge:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_COLOR_DODGE);
break;
case color_burn:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_COLOR_BURN);
break;
case hard_light:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_HARD_LIGHT);
break;
case soft_light:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_SOFT_LIGHT);
break;
case difference:
cairo_set_operator(cairo_.get(),CAIRO_OPERATOR_DIFFERENCE);
break;
case exclusion:
cairo_set_operator(cairo_.get(), CAIRO_OPERATOR_EXCLUSION);
break;
#else
#warning building against cairo older that 1.10.0, some compositing options are disabled
case multiply:
case screen:
case overlay:
case darken:
case lighten:
case color_dodge:
case color_burn:
case hard_light:
case soft_light:
case difference:
case exclusion:
break;
#endif
case contrast:
case minus:
case invert:
case invert_rgb:
case grain_merge:
case grain_extract:
case hue:
case saturation:
case _color:
case _value:
//case colorize_alpha:
break;
}
//
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_line_join(line_join_e join)
{
if (join == MITER_JOIN)
cairo_set_line_join(cairo_.get(), CAIRO_LINE_JOIN_MITER);
else if (join == MITER_REVERT_JOIN)
cairo_set_line_join(cairo_.get(), CAIRO_LINE_JOIN_MITER);
else if (join == ROUND_JOIN)
cairo_set_line_join(cairo_.get(), CAIRO_LINE_JOIN_ROUND);
else
cairo_set_line_join(cairo_.get(), CAIRO_LINE_JOIN_BEVEL);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_line_cap(line_cap_e cap)
{
if (cap == BUTT_CAP)
cairo_set_line_cap(cairo_.get(), CAIRO_LINE_CAP_BUTT);
else if (cap == SQUARE_CAP)
cairo_set_line_cap(cairo_.get(), CAIRO_LINE_CAP_SQUARE);
else
cairo_set_line_cap(cairo_.get(), CAIRO_LINE_CAP_ROUND);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_miter_limit(double limit)
{
cairo_set_miter_limit(cairo_.get(), limit);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_line_width(double width)
{
cairo_set_line_width(cairo_.get(), width);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_dash(dash_array const &dashes, double scale_factor)
{
std::valarray<double> d(dashes.size() * 2);
dash_array::const_iterator itr = dashes.begin();
dash_array::const_iterator end = dashes.end();
int index = 0;
for (; itr != end; ++itr)
{
d[index++] = itr->first * scale_factor;
d[index++] = itr->second * scale_factor;
}
cairo_set_dash(cairo_.get() , &d[0], dashes.size(), 0/*offset*/);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_fill_rule(cairo_fill_rule_t fill_rule)
{
cairo_set_fill_rule(cairo_.get(),fill_rule);
check_object_status_and_throw_exception(*this);
}
void cairo_context::move_to(double x, double y)
{
#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 6, 0)
if (x < -32767.0) x = -32767.0;
else if (x > 32767.0) x = 32767.0;
if (y < -32767.0) y = -32767.0;
else if (y > 32767.0) y = 32767.0;
#endif
cairo_move_to(cairo_.get(), x, y);
check_object_status_and_throw_exception(*this);
}
void cairo_context::curve_to(double ct1_x, double ct1_y, double ct2_x, double ct2_y, double end_x, double end_y)
{
cairo_curve_to(cairo_.get(), ct1_x,ct1_y,ct2_x,ct2_y,end_x,end_y);
check_object_status_and_throw_exception(*this);
}
void cairo_context::close_path()
{
cairo_close_path(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::line_to(double x, double y)
{
#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 6, 0)
if (x < -32767.0) x = -32767.0;
else if (x > 32767.0) x = 32767.0;
if (y < -32767.0) y = -32767.0;
else if (y > 32767.0) y = 32767.0;
#endif
cairo_line_to(cairo_.get(), x, y);
check_object_status_and_throw_exception(*this);
}
void cairo_context::rectangle(double x, double y, double w, double h)
{
cairo_rectangle(cairo_.get(), x, y, w, h);
check_object_status_and_throw_exception(*this);
}
void cairo_context::stroke()
{
cairo_stroke(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::fill()
{
cairo_fill(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::paint()
{
cairo_paint(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_pattern(cairo_pattern const& pattern)
{
cairo_set_source(cairo_.get(), pattern.pattern());
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_gradient(cairo_gradient const& pattern, const box2d<double> &bbox)
{
cairo_pattern_t * gradient = pattern.gradient();
double bx1=bbox.minx();
double by1=bbox.miny();
double bx2=bbox.maxx();
double by2=bbox.maxy();
if (pattern.units() != USER_SPACE_ON_USE)
{
if (pattern.units() == OBJECT_BOUNDING_BOX)
{
cairo_path_extents(cairo_.get(), &bx1, &by1, &bx2, &by2);
}
cairo_matrix_t cairo_matrix;
cairo_pattern_get_matrix(gradient, &cairo_matrix);
cairo_matrix_scale(&cairo_matrix,1.0/(bx2-bx1),1.0/(by2-by1));
cairo_matrix_translate(&cairo_matrix, -bx1,-by1);
cairo_pattern_set_matrix(gradient, &cairo_matrix);
}
cairo_set_source(cairo_.get(), const_cast<cairo_pattern_t*>(gradient));
check_object_status_and_throw_exception(*this);
}
void cairo_context::add_image(double x, double y, image_data_32 & data, double opacity)
{
cairo_pattern pattern(data);
pattern.set_origin(x, y);
cairo_save(cairo_.get());
cairo_set_source(cairo_.get(), const_cast<cairo_pattern_t*>(pattern.pattern()));
cairo_paint_with_alpha(cairo_.get(), opacity);
cairo_restore(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::add_image(agg::trans_affine const& tr, image_data_32 & data, double opacity)
{
cairo_pattern pattern(data);
if (!tr.is_identity())
{
double m[6];
tr.store_to(m);
cairo_matrix_t cairo_matrix;
cairo_matrix_init(&cairo_matrix,m[0],m[1],m[2],m[3],m[4],m[5]);
cairo_matrix_invert(&cairo_matrix);
pattern.set_matrix(cairo_matrix);
}
cairo_save(cairo_.get());
cairo_set_source(cairo_.get(), const_cast<cairo_pattern_t*>(pattern.pattern()));
cairo_paint_with_alpha(cairo_.get(), opacity);
cairo_restore(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_font_face(cairo_face_manager & manager, face_ptr face)
{
cairo_set_font_face(cairo_.get(), manager.get_face(face)->face());
}
void cairo_context::set_font_matrix(cairo_matrix_t const& matrix)
{
cairo_set_font_matrix(cairo_.get(), &matrix);
check_object_status_and_throw_exception(*this);
}
void cairo_context::set_matrix(cairo_matrix_t const& matrix)
{
cairo_set_matrix(cairo_.get(), &matrix);
check_object_status_and_throw_exception(*this);
}
void cairo_context::transform(cairo_matrix_t const& matrix)
{
cairo_transform(cairo_.get(), &matrix);
check_object_status_and_throw_exception(*this);
}
void cairo_context::translate(double x, double y)
{
cairo_translate(cairo_.get(), x, y);
check_object_status_and_throw_exception(*this);
}
void cairo_context::save()
{
cairo_save(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::restore()
{
cairo_restore(cairo_.get());
check_object_status_and_throw_exception(*this);
}
void cairo_context::show_glyph(unsigned long index, double x, double y)
{
cairo_glyph_t glyph;
glyph.index = index;
glyph.x = x;
glyph.y = y;
cairo_show_glyphs(cairo_.get(), &glyph, 1);
check_object_status_and_throw_exception(*this);
}
void cairo_context::glyph_path(unsigned long index, double x, double y)
{
cairo_glyph_t glyph;
glyph.index = index;
glyph.x = x;
glyph.y = y;
cairo_glyph_path(cairo_.get(), &glyph, 1);
check_object_status_and_throw_exception(*this);
}
void cairo_context::add_text(text_path const& path,
cairo_face_manager & manager,
face_manager<freetype_engine> & font_manager,
double scale_factor)
{
double sx = path.center.x;
double sy = path.center.y;
path.rewind();
for (int iii = 0; iii < path.num_nodes(); iii++)
{
char_info_ptr c;
double x, y, angle;
path.vertex(&c, &x, &y, &angle);
face_set_ptr faces = font_manager.get_face_set(c->format->face_name, c->format->fontset);
double text_size = c->format->text_size * scale_factor;
faces->set_character_sizes(text_size);
glyph_ptr glyph = faces->get_glyph(c->c);
if (glyph)
{
cairo_matrix_t matrix;
matrix.xx = text_size * cos(angle);
matrix.xy = text_size * sin(angle);
matrix.yx = text_size * -sin(angle);
matrix.yy = text_size * cos(angle);
matrix.x0 = 0;
matrix.y0 = 0;
set_font_matrix(matrix);
set_font_face(manager, glyph->get_face());
glyph_path(glyph->get_index(), sx + x, sy - y);
set_line_width(2.0 * c->format->halo_radius * scale_factor);
set_line_join(ROUND_JOIN);
set_color(c->format->halo_fill);
stroke();
set_color(c->format->fill);
show_glyph(glyph->get_index(), sx + x, sy - y);
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -28,8 +28,7 @@
#include <mapnik/grid/grid.hpp> #include <mapnik/grid/grid.hpp>
#if defined(HAVE_CAIRO) #if defined(HAVE_CAIRO)
#include <cairomm/context.h> #include <cairo.h>
#include <cairomm/surface.h>
#include <mapnik/cairo_renderer.hpp> #include <mapnik/cairo_renderer.hpp>
#endif #endif
@ -41,8 +40,8 @@ namespace mapnik
{ {
#if defined(HAVE_CAIRO) #if defined(HAVE_CAIRO)
template class feature_style_processor<cairo_renderer<Cairo::Context> >; template class feature_style_processor<cairo_renderer<cairo_ptr> >;
template class feature_style_processor<cairo_renderer<Cairo::Surface> >; template class feature_style_processor<cairo_renderer<cairo_surface_ptr> >;
#endif #endif
#if defined(SVG_RENDERER) #if defined(SVG_RENDERER)

View file

@ -31,14 +31,14 @@
#include "agg_rendering_buffer.h" #include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h" #include "agg_pixfmt_rgba.h"
// cairo
#ifdef HAVE_CAIRO
#include <cairomm/surface.h>
#endif
// boost // boost
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
// cairo
#ifdef HAVE_CAIRO
#include <mapnik/cairo_context.hpp>
#endif
namespace mapnik namespace mapnik
{ {
image_32::image_32(int width,int height) image_32::image_32(int width,int height)
@ -54,22 +54,22 @@ image_32::image_32(const image_32& rhs)
painted_(rhs.painted_) {} painted_(rhs.painted_) {}
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
image_32::image_32(Cairo::RefPtr<Cairo::ImageSurface> rhs) image_32::image_32(cairo_surface_ptr const& surface)
:width_(rhs->get_width()), :width_(cairo_image_surface_get_width(&*surface)),
height_(rhs->get_height()), height_(cairo_image_surface_get_height(&*surface)),
data_(rhs->get_width(),rhs->get_height()) data_(width_, height_)
{ {
painted_ = true; painted_ = true;
if (rhs->get_format() != Cairo::FORMAT_ARGB32) if ( cairo_image_surface_get_format(&*surface) != CAIRO_FORMAT_ARGB32)
{ {
MAPNIK_LOG_WARN(graphics) << "Unable to convert this Cairo format"; MAPNIK_LOG_WARN(graphics) << "Unable to convert this Cairo format";
return; // throw exception ?? throw;
} }
int stride = rhs->get_stride() / 4; int stride = cairo_image_surface_get_stride(&*surface) / 4;
boost::scoped_array<unsigned int> out_row(new unsigned int[width_]); boost::scoped_array<unsigned int> out_row(new unsigned int[width_]);
const unsigned int *in_row = (const unsigned int *)rhs->get_data(); const unsigned int *in_row = (const unsigned int *)cairo_image_surface_get_data(&*surface);
for (unsigned int row = 0; row < height_; row++, in_row += stride) for (unsigned int row = 0; row < height_; row++, in_row += stride)
{ {
@ -142,42 +142,39 @@ void image_32::set_color_to_alpha(const color& c)
void image_32::set_alpha(float opacity) void image_32::set_alpha(float opacity)
{ {
for (unsigned int y = 0; y < height_; ++y)
{ {
for (unsigned int y = 0; y < height_; ++y) unsigned int* row_to = data_.getRow(y);
for (unsigned int x = 0; x < width_; ++x)
{ {
unsigned int* row_to = data_.getRow(y); unsigned rgba = row_to[x];
for (unsigned int x = 0; x < width_; ++x)
{
unsigned rgba = row_to[x];
#ifdef MAPNIK_BIG_ENDIAN #ifdef MAPNIK_BIG_ENDIAN
unsigned a0 = (rgba & 0xff); unsigned a0 = (rgba & 0xff);
unsigned a1 = int( (rgba & 0xff) * opacity ); unsigned a1 = int( (rgba & 0xff) * opacity );
if (a0 == a1) continue; if (a0 == a1) continue;
unsigned r = (rgba >> 24) & 0xff; unsigned r = (rgba >> 24) & 0xff;
unsigned g = (rgba >> 16 ) & 0xff; unsigned g = (rgba >> 16 ) & 0xff;
unsigned b = (rgba >> 8) & 0xff; unsigned b = (rgba >> 8) & 0xff;
row_to[x] = (a1) | (b << 8) | (g << 16) | (r << 24) ; row_to[x] = (a1) | (b << 8) | (g << 16) | (r << 24) ;
#else #else
unsigned a0 = (rgba >> 24) & 0xff; unsigned a0 = (rgba >> 24) & 0xff;
unsigned a1 = int( ((rgba >> 24) & 0xff) * opacity ); unsigned a1 = int( ((rgba >> 24) & 0xff) * opacity );
//unsigned a1 = opacity; //unsigned a1 = opacity;
if (a0 == a1) continue; if (a0 == a1) continue;
unsigned r = rgba & 0xff; unsigned r = rgba & 0xff;
unsigned g = (rgba >> 8 ) & 0xff; unsigned g = (rgba >> 8 ) & 0xff;
unsigned b = (rgba >> 16) & 0xff; unsigned b = (rgba >> 16) & 0xff;
row_to[x] = (a1 << 24)| (b << 16) | (g << 8) | (r) ; row_to[x] = (a1 << 24)| (b << 16) | (g << 8) | (r) ;
#endif #endif
}
} }
} }
} }
void image_32::set_background(const color& c) void image_32::set_background(const color& c)
@ -211,7 +208,7 @@ void image_32::composite_pixel(unsigned op, int x,int y, unsigned c, unsigned co
typedef color_type::value_type value_type; typedef color_type::value_type value_type;
typedef agg::order_rgba order_type; typedef agg::order_rgba order_type;
typedef agg::comp_op_adaptor_rgba<color_type,order_type> blender_type; typedef agg::comp_op_adaptor_rgba<color_type,order_type> blender_type;
if (checkBounds(x,y)) if (checkBounds(x,y))
{ {
unsigned rgba = data_(x,y); unsigned rgba = data_(x,y);
@ -219,8 +216,8 @@ void image_32::composite_pixel(unsigned op, int x,int y, unsigned c, unsigned co
unsigned cb = (c >> 16 ) & 0xff; unsigned cb = (c >> 16 ) & 0xff;
unsigned cg = (c >> 8) & 0xff; unsigned cg = (c >> 8) & 0xff;
unsigned cr = (c & 0xff); unsigned cr = (c & 0xff);
blender_type::blend_pix(op, (value_type*)&rgba, cr, cg, cb, ca, cover); blender_type::blend_pix(op, (value_type*)&rgba, cr, cg, cb, ca, cover);
data_(x,y) = rgba; data_(x,y) = rgba;
} }
} }

View file

@ -43,7 +43,17 @@ extern "C"
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
#include <mapnik/cairo_renderer.hpp> #include <mapnik/cairo_renderer.hpp>
#include <cairo-features.h> #include <cairo.h>
#ifdef CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
#endif // CAIRO_HAS_PDF_SURFACE
#ifdef CAIRO_HAS_PS_SURFACE
#include <cairo-ps.h>
#endif // CAIRO_HAS_PS_SURFACE
#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
#endif // CAIRO_HAS_SVG_SURFACE
#endif #endif
// boost // boost
@ -384,37 +394,37 @@ void save_to_cairo_file(mapnik::Map const& map,
std::ofstream file (filename.c_str(), std::ios::out|std::ios::trunc|std::ios::binary); std::ofstream file (filename.c_str(), std::ios::out|std::ios::trunc|std::ios::binary);
if (file) if (file)
{ {
Cairo::RefPtr<Cairo::Surface> surface; cairo_surface_ptr surface;
unsigned width = map.width(); unsigned width = map.width();
unsigned height = map.height(); unsigned height = map.height();
if (type == "pdf") if (type == "pdf")
{ {
#if defined(CAIRO_HAS_PDF_SURFACE) #ifdef CAIRO_HAS_PDF_SURFACE
surface = Cairo::PdfSurface::create(filename,width,height); surface = cairo_surface_ptr(cairo_pdf_surface_create(filename.c_str(),width,height),cairo_surface_closer());
#else #else
throw ImageWriterException("PDFSurface not supported in the cairo backend"); throw ImageWriterException("PDFSurface not supported in the cairo backend");
#endif #endif
} }
#if defined(CAIRO_HAS_SVG_SURFACE) #ifdef CAIRO_HAS_SVG_SURFACE
else if (type == "svg") else if (type == "svg")
{ {
surface = Cairo::SvgSurface::create(filename,width,height); surface = cairo_surface_ptr(cairo_svg_surface_create(filename.c_str(),width,height),cairo_surface_closer());
} }
#endif #endif
#if defined(CAIRO_HAS_PS_SURFACE) #ifdef CAIRO_HAS_PS_SURFACE
else if (type == "ps") else if (type == "ps")
{ {
surface = Cairo::PsSurface::create(filename,width,height); surface = cairo_surface_ptr(cairo_ps_surface_create(filename.c_str(),width,height),cairo_surface_closer());
} }
#endif #endif
#if defined(CAIRO_HAS_IMAGE_SURFACE) #ifdef CAIRO_HAS_IMAGE_SURFACE
else if (type == "ARGB32") else if (type == "ARGB32")
{ {
surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32,width,height); surface = cairo_surface_ptr(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,width,height),cairo_surface_closer());
} }
else if (type == "RGB24") else if (type == "RGB24")
{ {
surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24,width,height); surface = cairo_surface_ptr(cairo_image_surface_create(CAIRO_FORMAT_RGB24,width,height),cairo_surface_closer());
} }
#endif #endif
else else
@ -422,7 +432,7 @@ void save_to_cairo_file(mapnik::Map const& map,
throw ImageWriterException("unknown file type: " + type); throw ImageWriterException("unknown file type: " + type);
} }
Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(surface); //cairo_t * ctx = cairo_create(surface);
// TODO - expose as user option // TODO - expose as user option
/* /*
@ -432,15 +442,14 @@ void save_to_cairo_file(mapnik::Map const& map,
} }
*/ */
mapnik::cairo_renderer<cairo_ptr> ren(map, create_context(surface), scale_factor);
mapnik::cairo_renderer<Cairo::Context> ren(map, context, scale_factor);
ren.apply(); ren.apply();
if (type == "ARGB32" || type == "RGB24") if (type == "ARGB32" || type == "RGB24")
{ {
surface->write_to_png(filename); cairo_surface_write_to_png(&*surface, filename.c_str());
} }
surface->finish(); cairo_surface_finish(&*surface);
} }
} }

View file

@ -36,48 +36,23 @@ namespace mapnik {
namespace params_detail { namespace params_detail {
// TODO - rewrite to avoid usage of lexical_cast template <typename T>
template <typename T> struct converter
struct value_extractor_visitor : public boost::static_visitor<> {
typedef boost::optional<T> return_type;
static return_type extract(parameters const& params,
std::string const& name,
boost::optional<T> const& default_opt_value)
{ {
value_extractor_visitor(boost::optional<T> & var) boost::optional<T> result(default_opt_value);
:var_(var) {} parameters::const_iterator itr = params.find(name);
if (itr != params.end())
void operator () (T val) const
{ {
var_ = val; boost::apply_visitor(value_extractor_visitor<T>(result),itr->second);
} }
return result;
template <typename T1> }
void operator () (T1 val) const };
{
try
{
var_ = boost::lexical_cast<T>(val);
}
catch (boost::bad_lexical_cast & ) {}
}
boost::optional<T> & var_;
};
template <typename T>
struct converter
{
typedef boost::optional<T> return_type;
static return_type extract(parameters const& params,
std::string const& name,
boost::optional<T> const& default_opt_value)
{
boost::optional<T> result(default_opt_value);
parameters::const_iterator itr = params.find(name);
if (itr != params.end())
{
boost::apply_visitor(value_extractor_visitor<T>(result),itr->second);
}
return result;
}
};
} // end namespace params_detail } // end namespace params_detail
// parameters // parameters