Merge commit 'f25d4d9279fc99650b88d980a8c579a6b541d4b5' into harfbuzz
Conflicts: src/cairo_renderer.cpp
This commit is contained in:
commit
04c0fa0767
17 changed files with 1174 additions and 959 deletions
82
SConstruct
82
SConstruct
|
@ -49,7 +49,7 @@ SCONF_TEMP_DIR = '.sconf_temp'
|
|||
# auto-search directories for boost libs/headers
|
||||
BOOST_SEARCH_PREFIXES = ['/usr/local','/opt/local','/sw','/usr',]
|
||||
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']
|
||||
|
||||
|
@ -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',
|
||||
'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',
|
||||
'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':'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,
|
||||
'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/',
|
||||
'pg':'Postgres C Library requiered for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki//PostGIS',
|
||||
|
@ -337,8 +337,8 @@ opts.AddVariables(
|
|||
# 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.
|
||||
BoolVariable('CAIRO', 'Attempt to build with Cairo rendering support', 'True'),
|
||||
PathVariable('CAIRO_INCLUDES', 'Search path for cairo/cairomm include files', '',PathVariable.PathAccept),
|
||||
PathVariable('CAIRO_LIBS', 'Search path for cairo/cairomm library files','',PathVariable.PathAccept),
|
||||
PathVariable('CAIRO_INCLUDES', 'Search path for cairo include 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'),
|
||||
('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),
|
||||
|
@ -1282,17 +1282,17 @@ if not preconfigured:
|
|||
c_inc = os.path.dirname(c_inc)
|
||||
env["CAIROMM_CPPPATHS"].extend(
|
||||
[
|
||||
os.path.join(c_inc,'include/cairomm-1.0'),
|
||||
os.path.join(c_inc,'lib/cairomm-1.0/include'),
|
||||
#os.path.join(c_inc,'include/cairomm-1.0'),
|
||||
#os.path.join(c_inc,'lib/cairomm-1.0/include'),
|
||||
os.path.join(c_inc,'include/cairo'),
|
||||
os.path.join(c_inc,'include/sigc++-2.0'),
|
||||
os.path.join(c_inc,'lib/sigc++-2.0/include'),
|
||||
#os.path.join(c_inc,'include/sigc++-2.0'),
|
||||
#os.path.join(c_inc,'lib/sigc++-2.0/include'),
|
||||
os.path.join(c_inc,'include/pixman-1'),
|
||||
#os.path.join(c_inc,'include/freetype2'),
|
||||
#os.path.join(c_inc,'include/libpng'),
|
||||
]
|
||||
)
|
||||
env["CAIROMM_LINKFLAGS"] = ['cairo','cairomm-1.0']
|
||||
env["CAIROMM_LINKFLAGS"] = ['cairo']
|
||||
if env['RUNTIME_LINK'] == 'static':
|
||||
env["CAIROMM_LINKFLAGS"].extend(
|
||||
['sigc-2.0','pixman-1','expat','fontconfig','iconv']
|
||||
|
@ -1304,40 +1304,40 @@ if not preconfigured:
|
|||
env['HAS_CAIRO'] = False
|
||||
env['SKIPPED_DEPS'].append('pkg-config')
|
||||
env['SKIPPED_DEPS'].append('cairo')
|
||||
env['SKIPPED_DEPS'].append('cairomm')
|
||||
#env['SKIPPED_DEPS'].append('cairomm')
|
||||
elif not conf.CheckPKG('cairo'):
|
||||
env['HAS_CAIRO'] = False
|
||||
env['SKIPPED_DEPS'].append('cairo')
|
||||
elif not conf.CheckPKG('cairomm-1.0'):
|
||||
env['HAS_CAIRO'] = False
|
||||
env['SKIPPED_DEPS'].append('cairomm')
|
||||
elif not conf.CheckPKGVersion('cairomm-1.0',CAIROMM_MIN_VERSION):
|
||||
env['HAS_CAIRO'] = False
|
||||
env['SKIPPED_DEPS'].append('cairomm-version')
|
||||
else:
|
||||
print 'Checking for cairo/cairomm lib and include paths... ',
|
||||
cmd = 'pkg-config --libs --cflags cairomm-1.0'
|
||||
if env['RUNTIME_LINK'] == 'static':
|
||||
cmd += ' --static'
|
||||
cairo_env = env.Clone()
|
||||
try:
|
||||
cairo_env.ParseConfig(cmd)
|
||||
for lib in cairo_env['LIBS']:
|
||||
if not lib in env['LIBS']:
|
||||
env["CAIROMM_LINKFLAGS"].append(lib)
|
||||
for lpath in cairo_env['LIBPATH']:
|
||||
if not lpath in env['LIBPATH']:
|
||||
env["CAIROMM_LIBPATHS"].append(lpath)
|
||||
for inc in cairo_env['CPPPATH']:
|
||||
if not inc in env['CPPPATH']:
|
||||
env["CAIROMM_CPPPATHS"].append(inc)
|
||||
env['HAS_CAIRO'] = True
|
||||
print 'yes'
|
||||
except OSError,e:
|
||||
color_print(1,'no')
|
||||
env['SKIPPED_DEPS'].append('cairo')
|
||||
env['SKIPPED_DEPS'].append('cairomm')
|
||||
color_print(1,'pkg-config reported: %s' % e)
|
||||
#elif not conf.CheckPKG('cairomm-1.0'):
|
||||
# env['HAS_CAIRO'] = False
|
||||
# env['SKIPPED_DEPS'].append('cairomm')
|
||||
#elif not conf.CheckPKGVersion('cairomm-1.0',CAIROMM_MIN_VERSION):
|
||||
# env['HAS_CAIRO'] = False
|
||||
# env['SKIPPED_DEPS'].append('cairomm-version')
|
||||
#else:
|
||||
# print 'Checking for cairo/cairomm lib and include paths... ',
|
||||
# cmd = 'pkg-config --libs --cflags cairomm-1.0'
|
||||
# if env['RUNTIME_LINK'] == 'static':
|
||||
# cmd += ' --static'
|
||||
# cairo_env = env.Clone()
|
||||
# try:
|
||||
# cairo_env.ParseConfig(cmd)
|
||||
# for lib in cairo_env['LIBS']:
|
||||
# if not lib in env['LIBS']:
|
||||
# env["CAIROMM_LINKFLAGS"].append(lib)
|
||||
# for lpath in cairo_env['LIBPATH']:
|
||||
# if not lpath in env['LIBPATH']:
|
||||
# env["CAIROMM_LIBPATHS"].append(lpath)
|
||||
# for inc in cairo_env['CPPPATH']:
|
||||
# if not inc in env['CPPPATH']:
|
||||
# env["CAIROMM_CPPPATHS"].append(inc)
|
||||
# env['HAS_CAIRO'] = True
|
||||
# print 'yes'
|
||||
# except OSError,e:
|
||||
# color_print(1,'no')
|
||||
# env['SKIPPED_DEPS'].append('cairo')
|
||||
# env['SKIPPED_DEPS'].append('cairomm')
|
||||
# color_print(1,'pkg-config reported: %s' % e)
|
||||
|
||||
else:
|
||||
color_print(4,'Not building with cairo support, pass CAIRO=True to enable')
|
||||
|
|
|
@ -46,7 +46,7 @@ extern "C"
|
|||
|
||||
// cairo
|
||||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
#include <cairomm/surface.h>
|
||||
#include <mapnik/cairo_context.hpp>
|
||||
#include <pycairo.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#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));
|
||||
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(s);
|
||||
mapnik::cairo_surface_ptr surface(py_surface->surface, mapnik::cairo_surface_closer());
|
||||
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(surface);
|
||||
return image_ptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -163,92 +163,92 @@ void render_layer2(const mapnik::Map& map,
|
|||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
|
||||
void render3(const mapnik::Map& map,
|
||||
PycairoSurface* surface,
|
||||
PycairoSurface* py_surface,
|
||||
double scale_factor = 1.0,
|
||||
unsigned offset_x = 0,
|
||||
unsigned offset_y = 0)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
|
||||
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,scale_factor,offset_x,offset_y);
|
||||
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface,scale_factor,offset_x,offset_y);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render4(const mapnik::Map& map, PycairoSurface* surface)
|
||||
void render4(const mapnik::Map& map, PycairoSurface* py_surface)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
|
||||
mapnik::cairo_renderer<Cairo::Surface> ren(map,s);
|
||||
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render5(const mapnik::Map& map,
|
||||
PycairoContext* context,
|
||||
PycairoContext* py_context,
|
||||
double scale_factor = 1.0,
|
||||
unsigned offset_x = 0,
|
||||
unsigned offset_y = 0)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
|
||||
mapnik::cairo_renderer<Cairo::Context> ren(map,c,scale_factor,offset_x, offset_y);
|
||||
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,scale_factor,offset_x, offset_y);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render6(const mapnik::Map& map, PycairoContext* context)
|
||||
void render6(const mapnik::Map& map, PycairoContext* py_context)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
|
||||
mapnik::cairo_renderer<Cairo::Context> ren(map,c);
|
||||
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render_with_detector2(
|
||||
const mapnik::Map& map,
|
||||
PycairoContext* context,
|
||||
PycairoContext* py_context,
|
||||
boost::shared_ptr<mapnik::label_collision_detector4> detector)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
|
||||
mapnik::cairo_renderer<Cairo::Context> ren(map,c,detector);
|
||||
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render_with_detector3(
|
||||
const mapnik::Map& map,
|
||||
PycairoContext* context,
|
||||
PycairoContext* py_context,
|
||||
boost::shared_ptr<mapnik::label_collision_detector4> detector,
|
||||
double scale_factor = 1.0,
|
||||
unsigned offset_x = 0u,
|
||||
unsigned offset_y = 0u)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
|
||||
mapnik::cairo_renderer<Cairo::Context> ren(map,c,detector,scale_factor,offset_x,offset_y);
|
||||
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector,scale_factor,offset_x,offset_y);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render_with_detector4(
|
||||
const mapnik::Map& map,
|
||||
PycairoSurface* surface,
|
||||
PycairoSurface* py_surface,
|
||||
boost::shared_ptr<mapnik::label_collision_detector4> detector)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
|
||||
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,detector);
|
||||
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
void render_with_detector5(
|
||||
const mapnik::Map& map,
|
||||
PycairoSurface* surface,
|
||||
PycairoSurface* py_surface,
|
||||
boost::shared_ptr<mapnik::label_collision_detector4> detector,
|
||||
double scale_factor = 1.0,
|
||||
unsigned offset_x = 0u,
|
||||
unsigned offset_y = 0u)
|
||||
{
|
||||
python_unblock_auto_block b;
|
||||
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
|
||||
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,detector,scale_factor,offset_x,offset_y);
|
||||
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector, scale_factor, offset_x, offset_y);
|
||||
ren.apply();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#ifdef HAVE_CAIRO
|
||||
// cairo
|
||||
#include <mapnik/cairo_renderer.hpp>
|
||||
#include <cairomm/surface.h>
|
||||
#endif
|
||||
|
||||
#include "mapwidget.hpp"
|
||||
|
@ -567,12 +566,10 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
|
|||
{
|
||||
|
||||
#ifdef HAVE_CAIRO
|
||||
Cairo::RefPtr<Cairo::ImageSurface> image_surface =
|
||||
Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, map.width(),map.height());
|
||||
|
||||
mapnik::cairo_renderer<Cairo::Surface> png_render(map, image_surface, scaling_factor);
|
||||
png_render.apply();
|
||||
|
||||
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_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);
|
||||
renderer.apply();
|
||||
image_32 buf(image_surface);
|
||||
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
|
||||
pix = QPixmap::fromImage(image.rgbSwapped());
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "styles_model.hpp"
|
||||
#include <mapnik/expression_string.hpp>
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
#include <mapnik/rule.hpp>
|
||||
#include <mapnik/feature_type_style.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/concept_check.hpp>
|
||||
|
@ -162,6 +164,18 @@ struct symbolizer_info : public boost::static_visitor<QString>
|
|||
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>
|
||||
QString operator() (T const& ) const
|
||||
{
|
||||
|
|
426
include/mapnik/cairo_context.hpp
Normal file
426
include/mapnik/cairo_context.hpp
Normal file
|
@ -0,0 +1,426 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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>
|
||||
#include <mapnik/text/placements_list.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, pixel_position const pos);
|
||||
void glyph_path(unsigned long index, pixel_position const pos);
|
||||
void add_text(glyph_position_ptr pos,
|
||||
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
|
|
@ -34,10 +34,10 @@
|
|||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/rule.hpp> // for all symbolizers
|
||||
#include <mapnik/noncopyable.hpp>
|
||||
#include <mapnik/cairo_context.hpp>
|
||||
|
||||
// cairo
|
||||
#include <cairomm/context.h>
|
||||
#include <cairomm/surface.h>
|
||||
#include <cairo.h>
|
||||
|
||||
// boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
@ -54,27 +54,11 @@ namespace mapnik {
|
|||
|
||||
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
|
||||
{
|
||||
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::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, 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();
|
||||
void start_map_processing(Map const& map);
|
||||
|
@ -133,9 +117,9 @@ public:
|
|||
void render_box(box2d<double> const& b);
|
||||
protected:
|
||||
|
||||
|
||||
Map const& m_;
|
||||
Cairo::RefPtr<Cairo::Context> context_;
|
||||
//Cairo::RefPtr<Cairo::Context> context_;
|
||||
cairo_context context_;
|
||||
unsigned width_;
|
||||
unsigned height_;
|
||||
double scale_factor_;
|
||||
|
@ -153,8 +137,8 @@ class MAPNIK_DECL cairo_renderer : public feature_style_processor<cairo_renderer
|
|||
{
|
||||
public:
|
||||
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, 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, 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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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, mapnik::expression_grammar<std::string::const_iterator> const& g);
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_EXPRESSION_HPP
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
// cairo
|
||||
#ifdef HAVE_CAIRO
|
||||
#include <cairomm/surface.h>
|
||||
#include <mapnik/cairo_context.hpp>
|
||||
#endif
|
||||
|
||||
// boost
|
||||
|
@ -58,7 +58,7 @@ public:
|
|||
image_32(int width,int height);
|
||||
image_32(image_32 const& rhs);
|
||||
#ifdef HAVE_CAIRO
|
||||
image_32(Cairo::RefPtr<Cairo::ImageSurface> rhs);
|
||||
explicit image_32(cairo_surface_ptr const& surface);
|
||||
#endif
|
||||
~image_32();
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// boost
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
// mapnik
|
||||
#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::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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -210,6 +210,7 @@ if env['HAS_CAIRO']:
|
|||
libmapnik_cxxflags.append('-DHAVE_CAIRO')
|
||||
lib_env.PrependUnique(CPPPATH=copy(env['CAIROMM_CPPPATHS']))
|
||||
source.insert(0,'cairo_renderer.cpp')
|
||||
source.insert(0,'cairo_context.cpp')
|
||||
|
||||
if env['JPEG']:
|
||||
source += Split(
|
||||
|
|
438
src/cairo_context.cpp
Normal file
438
src/cairo_context.cpp
Normal file
|
@ -0,0 +1,438 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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, pixel_position const pos)
|
||||
{
|
||||
cairo_glyph_t glyph;
|
||||
glyph.index = index;
|
||||
glyph.x = pos.x;
|
||||
glyph.y = pos.y;
|
||||
|
||||
cairo_show_glyphs(cairo_.get(), &glyph, 1);
|
||||
check_object_status_and_throw_exception(*this);
|
||||
}
|
||||
|
||||
void cairo_context::glyph_path(unsigned long index, pixel_position const pos)
|
||||
{
|
||||
cairo_glyph_t glyph;
|
||||
glyph.index = index;
|
||||
glyph.x = pos.x;
|
||||
glyph.y = pos.y;
|
||||
|
||||
cairo_glyph_path(cairo_.get(), &glyph, 1);
|
||||
check_object_status_and_throw_exception(*this);
|
||||
}
|
||||
|
||||
void cairo_context::add_text(glyph_position_ptr pos,
|
||||
cairo_face_manager & manager,
|
||||
face_manager<freetype_engine> & font_manager,
|
||||
double scale_factor)
|
||||
{
|
||||
pixel_position const& base = pos->get_base_point();
|
||||
|
||||
glyph_positions::const_iterator itr = pos->begin(), end = pos->end();
|
||||
for (; itr != end; itr++)
|
||||
{
|
||||
glyph_info const& glyph = *(itr->glyph);
|
||||
double text_size = glyph.format->text_size * scale_factor;
|
||||
glyph.face->set_character_sizes(text_size);
|
||||
|
||||
Cairo::Matrix matrix;
|
||||
matrix.xx = text_size * itr->rot.cos;
|
||||
matrix.xy = text_size * itr->rot.sin;
|
||||
matrix.yx = text_size * -itr->rot.sin;
|
||||
matrix.yy = text_size * itr->rot.cos;
|
||||
matrix.x0 = 0;
|
||||
matrix.y0 = 0;
|
||||
|
||||
set_font_matrix(matrix);
|
||||
set_font_face(manager, glyph.face);
|
||||
|
||||
glyph_path(glyph.glyph_index, base + itr->pos);
|
||||
set_line_width(2.0 * glyph.format->halo_radius * scale_factor);
|
||||
set_line_join(ROUND_JOIN);
|
||||
set_color(glyph.format->halo_fill);
|
||||
stroke();
|
||||
set_color(glyph.format->fill);
|
||||
show_glyph(glyph.glyph_index, base + itr->pos);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -28,8 +28,7 @@
|
|||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
#if defined(HAVE_CAIRO)
|
||||
#include <cairomm/context.h>
|
||||
#include <cairomm/surface.h>
|
||||
#include <cairo.h>
|
||||
#include <mapnik/cairo_renderer.hpp>
|
||||
#endif
|
||||
|
||||
|
@ -41,8 +40,8 @@ namespace mapnik
|
|||
{
|
||||
|
||||
#if defined(HAVE_CAIRO)
|
||||
template class feature_style_processor<cairo_renderer<Cairo::Context> >;
|
||||
template class feature_style_processor<cairo_renderer<Cairo::Surface> >;
|
||||
template class feature_style_processor<cairo_renderer<cairo_ptr> >;
|
||||
template class feature_style_processor<cairo_renderer<cairo_surface_ptr> >;
|
||||
#endif
|
||||
|
||||
#if defined(SVG_RENDERER)
|
||||
|
|
|
@ -31,14 +31,14 @@
|
|||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
|
||||
// cairo
|
||||
#ifdef HAVE_CAIRO
|
||||
#include <cairomm/surface.h>
|
||||
#endif
|
||||
|
||||
// boost
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
// cairo
|
||||
#ifdef HAVE_CAIRO
|
||||
#include <mapnik/cairo_context.hpp>
|
||||
#endif
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
image_32::image_32(int width,int height)
|
||||
|
@ -54,22 +54,22 @@ image_32::image_32(const image_32& rhs)
|
|||
painted_(rhs.painted_) {}
|
||||
|
||||
#ifdef HAVE_CAIRO
|
||||
image_32::image_32(Cairo::RefPtr<Cairo::ImageSurface> rhs)
|
||||
:width_(rhs->get_width()),
|
||||
height_(rhs->get_height()),
|
||||
data_(rhs->get_width(),rhs->get_height())
|
||||
image_32::image_32(cairo_surface_ptr const& surface)
|
||||
:width_(cairo_image_surface_get_width(&*surface)),
|
||||
height_(cairo_image_surface_get_height(&*surface)),
|
||||
data_(width_, height_)
|
||||
{
|
||||
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";
|
||||
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_]);
|
||||
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)
|
||||
{
|
||||
|
@ -142,7 +142,6 @@ void image_32::set_color_to_alpha(const color& c)
|
|||
|
||||
void image_32::set_alpha(float opacity)
|
||||
{
|
||||
{
|
||||
for (unsigned int y = 0; y < height_; ++y)
|
||||
{
|
||||
unsigned int* row_to = data_.getRow(y);
|
||||
|
@ -176,8 +175,6 @@ void image_32::set_alpha(float opacity)
|
|||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void image_32::set_background(const color& c)
|
||||
|
|
|
@ -43,7 +43,17 @@ extern "C"
|
|||
|
||||
#ifdef HAVE_CAIRO
|
||||
#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
|
||||
|
||||
// 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);
|
||||
if (file)
|
||||
{
|
||||
Cairo::RefPtr<Cairo::Surface> surface;
|
||||
cairo_surface_ptr surface;
|
||||
unsigned width = map.width();
|
||||
unsigned height = map.height();
|
||||
if (type == "pdf")
|
||||
{
|
||||
#if defined(CAIRO_HAS_PDF_SURFACE)
|
||||
surface = Cairo::PdfSurface::create(filename,width,height);
|
||||
#ifdef CAIRO_HAS_PDF_SURFACE
|
||||
surface = cairo_surface_ptr(cairo_pdf_surface_create(filename.c_str(),width,height),cairo_surface_closer());
|
||||
#else
|
||||
throw ImageWriterException("PDFSurface not supported in the cairo backend");
|
||||
#endif
|
||||
}
|
||||
#if defined(CAIRO_HAS_SVG_SURFACE)
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
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
|
||||
#if defined(CAIRO_HAS_PS_SURFACE)
|
||||
#ifdef CAIRO_HAS_PS_SURFACE
|
||||
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
|
||||
#if defined(CAIRO_HAS_IMAGE_SURFACE)
|
||||
#ifdef CAIRO_HAS_IMAGE_SURFACE
|
||||
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")
|
||||
{
|
||||
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
|
||||
else
|
||||
|
@ -422,7 +432,7 @@ void save_to_cairo_file(mapnik::Map const& map,
|
|||
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
|
||||
/*
|
||||
|
@ -432,15 +442,14 @@ void save_to_cairo_file(mapnik::Map const& map,
|
|||
}
|
||||
*/
|
||||
|
||||
|
||||
mapnik::cairo_renderer<Cairo::Context> ren(map, context, scale_factor);
|
||||
mapnik::cairo_renderer<cairo_ptr> ren(map, create_context(surface), scale_factor);
|
||||
ren.apply();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,34 +36,9 @@ namespace mapnik {
|
|||
|
||||
namespace params_detail {
|
||||
|
||||
// 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_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct converter
|
||||
{
|
||||
template <typename T>
|
||||
struct converter
|
||||
{
|
||||
typedef boost::optional<T> return_type;
|
||||
static return_type extract(parameters const& params,
|
||||
std::string const& name,
|
||||
|
@ -77,7 +52,7 @@ namespace params_detail {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
};
|
||||
} // end namespace params_detail
|
||||
|
||||
// parameters
|
||||
|
|
Loading…
Reference in a new issue