Merge branch '2.3.x' of github.com:mapnik/mapnik into layer-opacity

Conflicts:
	include/mapnik/agg_renderer.hpp
	src/agg/agg_renderer.cpp
This commit is contained in:
Dane Springmeyer 2013-12-03 09:20:22 -08:00
commit 5d3ee5787e
1081 changed files with 26968 additions and 8574 deletions

View file

@ -1,18 +1,20 @@
language: cpp
compiler: clang
addons:
postgresql: "9.3"
compiler:
- clang
- gcc
before_install:
- echo 'yes' | sudo add-apt-repository ppa:mapnik/boost
- sudo apt-get update -qq
- sudo apt-get install -qq libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev
- sudo apt-get install -qq make libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev postgresql-server-dev*
script:
- ./configure DEMO=False BINDINGS='python' CPP_TESTS=False CAIRO=False INPUT_PLUGINS='' OPTIMIZATION=1 FAST=True && JOBS=2 make
branches:
only:
- master
- ./configure CXX=${CXX} CC=${CC} DEMO=False BINDINGS='python' CPP_TESTS=True CAIRO=True FAST=True && JOBS=2 make
- make test-local
notifications:
irc:

View file

@ -6,13 +6,112 @@ Developers: Please commit along with changes.
For a complete change history, see the git log.
## 2.3.0
Released ...
(Packaged from ...)
Summary: TODO
- Added missing support for `geometry-transform` in `line-pattern` and `polygon-pattern` symbolizers (#2065)
- Dropped support for Sun compiler
- Upgraded unifont to `unifont-6.3.20131020`
- CSV Plugin: added the ability to pass an `extent` in options
- Fixed crash when rendering to cairo context from python (#2031)
- Moved `label-position-tolerance` from unsigned type to double
- Default PNG encoding method when `png` is supplied is now `png8:m=h`, so paletted png using hextree color quantization (#2028)
Use `png32` now for full color png. More details at https://github.com/mapnik/mapnik/wiki/Image-IO.
- Added support for more seamless blurring by rendering to a larger internal image to avoid edge effects (#1478)
- Fixed rendering of large shapes at high zoom levels, which might dissapear due to integer overflow. This
bug was previously fixable when geometries were clipped, but would, until now, re-appear if clipping was turned
off for a symbolizer (#2000)
- Added single color argument support to `colorize-alpha` to allow colorizing alpha with one color.
- Added `color-to-alpha` `image-filter` to allow for applying alpha in proportion to color similiarity (#2023)
- Added Async support to PostGIS plugin - https://github.com/mapnik/mapnik/wiki/PostGIS-Async
- Fixed alpha handling bug with `comp-op:dst-over` (#1995)
- Fixed alpha handling bug with building-fill-opacity (#2011)
- Optimized mapnik.Path.to_wkb
- Python: added `__geo_interface__` to mapnik.Feature and mapnik.Path (#2009)
- Python: Exposed optimized WKTReader for parsing WKT into geometry paths (6bfbb53)
- Optimized expression evaluation of text by avoiding extra copy (1dd1275)
- Added Map level `background-image-comp-op` to control the compositing operation used to blend the
`background-image` onto the `background-color`. Has no meaning if `background-color` or `background-image`
are not set. (#1966)
- Added Map level `background-image-opacity` to dynamically set the opacity of the `background-image` (#1966)
- Removed `RENDERING_STATS` compile option since it should be replaced with a better solution (#1956)
- Added support to experimental `svg_renderer` for grouping layers for inkscape and illustrator (#1917)
- Fixed compile of python bindings against Python 3.x
- Optimized SVG loading by improving color parsing speed (#1918)
- Fixed startup problem when fonts cannot be read due to lacking permissions (#1919)
- Fixed bad behavior when negative image dimensions are requested (#1927)
- Fixed handling of `marker-ignore-placement:true` when `marker-placement:line` (#1931)
- Fixed handling of svg `opacity` in Cairo renderer (#1943)
- Fixed handling of SVG files which contain empty `<g>` (#1944)
- Fixed various 32bit test failures
- Fixed compile against icu when by using `U_NAMESPACE_QUALIFIER`
- Fixed missing support for using PathExpression in `marker-file` (#1952)
- Added support for `line-pattern-offset` (#1991)
- Added support for building on Android (tested with `android-ndk-r9`)
- Added support for compiling with both -ansi (aka -std=c++98) and -std=c++11
- Added support for compiling and linking on OS X against libc++
- Fixed regression in handling `F` type dbf fields, introduced in v2.2.0.
- Added the ability to create a mapnik Feature from a geojson feature with `mapnik.Feature.from_geojson` in python.
- Added to python bindings: `has_tiff`, `has_png`, `has_webp`, `has_proj4`, `has_svg_renderer`, and `has_grid_renderer`
- Made it possible to disable compilation of `grid_renderer` with `./configure GRID_RENDERER=False` (#1962)
- Added `premultiplied` property on mapnik::image_32 / mapnik.Image to enable knowledge of premultiplied status of image buffer.
- Added `webp` image encoding and decoding support (#1955)
- Added `scale-hsla` image-filter that allows scaling colors in HSL color space. RGB is converted to HSL (hue-saturation-lightness) and then each value (and the original alpha value) is stretched based on the specified scaling values. An example syntax is `scale-hsla(0,1,0,1,0,1,0,1)` which means no change because the full range will be kept (0 for lowest, 1 for highest). Other examples are: 1) `scale-hsla(0,0,0,1,0,1,0,1)` which would force all colors to be red in hue in the same way `scale-hsla(1,1,0,1,0,1,0,1)` would, 2) `scale-hsla(0,1,1,1,0,1,0,1)` which would cause all colors to become fully saturated, 3) `scale-hsla(0,1,1,1,0,1,.5,1)` which would force no colors to be any more transparent than half, and 4) `scale-hsla(0,1,1,1,0,1,0,.5)` which would force all colors to be at least half transparent. (#1954)
## 2.2.0
Released ---
Released June 3rd, 2013
(Packaged from ---)
(Packaged from 9231205)
Summary: The 2.2.0 release is the fastest running and most stable release in the history of Mapnik. The code line represents development in the master branch since the release of 2.1.0 in Aug 2012 and therefore includes nearly a year of bugfixes and low level optimizations. Shapefile and PostGIS datasources have benefited from numerous stability fixes, 64 bit integer support has been added to support OSM data, and many rendering fixes have landed for high quality output when using a rendering `scale_factor`. Many critical code paths have been optimized extensively include raster rendering, xml map loading, string to number conversion, vector reprojection when using `epsg:4326` and `epsg:3857`, `hextree` encoding, halo rendering, and rendering when using a custom `gamma`. Mapnik 2.2 also compiles faster than previous releases in the 2.x series and drops several unneeded and hard to install dependencies.
Summary: The 2.2.0 release is primarily a performance and stability release. The code line represents development in the master branch since the release of 2.1.0 in Aug 2012 and therefore includes nearly a year of bug-fixes and optimizations. Nearly 500 new tests have been added bring the total coverage to 925. Shapefile and PostGIS datasources have benefited from numerous stability fixes, 64 bit integer support has been added to support OSM data in the grid renderer and in attribute filtering, and many fixes have landed for higher quality output when using a custom `scale_factor` during rendering. Critical code paths have been optimized include raster rendering, xml map loading, string to number conversion, vector reprojection when using `epsg:4326` and `epsg:3857`, `hextree` encoding, halo rendering, and rendering when using a custom `gamma`. Mapnik 2.2 also compiles faster than previous releases in the 2.x series and drops several unneeded and hard to install dependencies making builds on OS X and Windows easier than any previous release.
- Removed 3 depedencies without loosing any functionality: `ltdl`, `cairomm` and `libsigc++` (#1804,#806,#1681)
@ -22,6 +121,14 @@ Summary: The 2.2.0 release is the fastest running and most stable release in the
- Added faster reprojection support between `epsg:3857` and `epsg:4326` (#1705,#1703,#1579)
- Added `colorize-alpha` image filter that applies user provided color gradients based on level of alpha.
Accepts one or more colors separated by commas. Each color can be paired with an `offset` value separated
by a space that is either `0-100%` or `0.0-1.0`. An `offset` of `0` is implied and the default. For background
on where this design came from see http://www.w3.org/TR/SVG/pservers.html#GradientStops. A simple example
of colorizing alpha into a "rainbow" is `colorize-alpha(blue,cyan,lightgreen, yellow, orange, red)`. An example of
using offsets and the variety of supported color encodings is to produce a ramp which sharp contrast between `blue`
and `cyan` is `colorize-alpha(blue 30%, cyan, yellow 0.7 , rgb(0%,80%,0%) 90%)` (#1371).
- Fixed concurrency problem when using cursors in postgis plugin (#1823,#1588)
- Fixed postgres connection pool leaks when using `persist_connection=false` (#1764)
@ -32,6 +139,12 @@ Summary: The 2.2.0 release is the fastest running and most stable release in the
- Fixed blurry rendering of image and SVG icons (#1316)
- Added detection of invalid srs values when loading xml (#646)
- Added support for specifying a base_path as a third, optional argument to load_xml
- Removed muffling of projection errors while rendering (#646)
- Improved logging system (https://github.com/mapnik/mapnik/wiki/Logging)
- Added support for reading images from in memory streams (#1805)
@ -227,9 +340,9 @@ Released Aug 23, 2012
- Improved logging/debugging system with release logs and file redirection (https://github.com/mapnik/mapnik/wiki/Runtime-Logging) (#937 and partially #986, #467)
- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161)
- GDAL: allow setting `nodata` value on the fly (will override value if `nodata` is set in data) (#1161)
- GDAL: respect nodata for paletted/colormapped images (#1160)
- GDAL: respect `nodata` for paletted/colormapped images (#1160)
- PostGIS: Added a new option called `autodetect_key_field` (by default false) that if true will
trigger autodetection of the table primary key allowing for feature.id() to represent
@ -366,7 +479,7 @@ Released September 26, 2011
cannot possibly be projected into the map srs or the user wishes to control map bounds without
modifying the extents of each layer.
- Support for NODATA values with grey and rgb images in GDAL plugin (#727)
- Support for `nodata` values with grey and rgb images in GDAL plugin (#727)
- Print warning if invalid XML property names are used (#110)

View file

@ -48,31 +48,39 @@ Mapnik Core depends on:
- regex (optionally built with icu regex support)
- program_options (optionally for mapnik command line programs)
* libicuuc >= 4.0 (ideally >= 4.2) - International Components for Unicode
* libpng >= 1.2.x - PNG graphics
* libjpeg - JPEG graphics
* libtiff - TIFF graphics
* libz - Zlib compression
* libfreetype - Freetype2 for font support (Install requires freetype-config)
* libxml2 - XML parsing (Install requires xml2-config)
* libproj - PROJ.4 projection library
Mapnik Core optionally depends on:
* libpng >= 1.2.x - PNG graphics (Default enabled, if found)
* libjpeg - JPEG graphics (Default enabled, if found)
* libtiff - TIFF graphics (Default enabled, if found)
* libwebp - WEBP graphics (Default enabled, if found)
* libproj - PROJ.4 projection library (Default enabled, if found)
Mapnik Python bindings depend on:
* Python 2.5-2.7 or >= 3.2
* Boost python
* simplejson module if using <= 2.5
Note: Python3k is supported, see: https://github.com/mapnik/mapnik/wiki/Python3k
Note: Python 3.x is supported, see: https://github.com/mapnik/mapnik/wiki/Python3k
Optional dependencies:
Additional optional dependencies:
* Cairo >= 1.6.0 - Graphics library for output formats like PDF, PS, and SVG
- pkg-config - Required for building with cairo support
- pycairo - Python bindings for cairo
* libpq - PostgreSQL libraries (For PostGIS plugin support)
* PostgreSQL (for PostGIS plugin support)
- libpq - PostreSQL libraries
- pg_config - PostgreSQL installation capabilities
* libgdal - GDAL/OGR input (For gdal and ogr plugin support)
* libsqlite3 - SQLite input (needs RTree support builtin) (sqlite plugin support)
* libocci - Oracle input plugin support
* libcurl - OSM input plugin support
* librasterlite - Rasterlite input plugin support
Instructions for installing many of these dependencies on
various platforms can be found at the Mapnik Wiki:

View file

@ -68,7 +68,7 @@ check: test-local
demo:
@echo "*** Running rundemo.cpp…"
cd demo/c++; ./rundemo `mapnik-config --prefix`/lib/mapnik
cd demo/c++; ./rundemo `mapnik-config --prefix`
pep8:
# https://gist.github.com/1903033

View file

@ -12,19 +12,18 @@ _/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
# What is Mapnik?
Mapnik is an open source toolkit and API for developing mapping applications. At the core is a C++ shared library providing algorithms and patterns for spatial data access and visualization. High-level bindings for Java, JavaScript, Python, and Ruby facilitate rapid application development in a variety of environments.
Mapnik is an open source toolkit for developing mapping applications. At the core is a C++ shared library providing algorithms and patterns for spatial data access and visualization. High-level bindings for JavaScript, Python, and Ruby facilitate rapid application development in a variety of environments.
# Overview
Mapnik is basically a collection of geographic objects like maps, layers, datasources, features, and geometries. The library doesn't rely on any OS specific "windowing systems" and it can be deployed to any server environment. It is intended to play fair in a multi-threaded environment and is aimed primarily, but not exclusively, at web-based development.
For further information see [http://mapnik.org](http://mapnik.org) and also our [wiki documentation](https://github.com/mapnik/mapnik/wiki) here on GitHub.
# Installation
See [INSTALL.md](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) for installation instructions.
See [INSTALL.md](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides.
# License
Mapnik software is free and is released under LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information.
Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information.

View file

@ -1,6 +1,6 @@
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2009 Artem Pavlenko, Jean-Francois Doyon, Dane Springmeyer
# Copyright (C) 2013 Artem Pavlenko
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@ -36,11 +36,17 @@ except:
LIBDIR_SCHEMA_DEFAULT='lib'
severities = ['debug', 'warn', 'error', 'none']
ICU_INCLUDES_DEFAULT='/usr/include'
ICU_LIBS_DEFAULT='/usr/'
DEFAULT_CC = "gcc"
DEFAULT_CXX = "g++"
if sys.platform == 'darwin':
DEFAULT_CC = "clang"
DEFAULT_CXX = "clang++"
# homebrew default
ICU_INCLUDES_DEFAULT='/usr/local/opt/icu4c/include/'
ICU_LIBS_DEFAULT='/usr/local/opt/icu4c/'
py3 = None
@ -62,17 +68,18 @@ DEFAULT_LINK_PRIORITY = ['internal','other','frameworks','user','system']
pretty_dep_names = {
'ociei':'Oracle database library | configure with OCCI_LIBS & OCCI_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki//OCCI',
'ociei':'Oracle database library | configure with OCCI_LIBS & OCCI_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/OCCI',
'gdal':'GDAL C++ library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki/GDAL',
'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',
'cairo':'Cairo C 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/',
'pg':'Postgres C Library required for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki//PostGIS',
'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki//SQLite',
'pg':'Postgres C Library required for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki/PostGIS',
'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/SQLite',
'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES',
'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES',
'png':'PNG C library | configure with PNG_LIBS & PNG_INCLUDES',
'webp':'WEBP C library | configure with WEBP_LIBS & WEBP_INCLUDES',
'icuuc':'ICU C++ library | configure with ICU_LIBS & ICU_INCLUDES or use ICU_LIB_NAME to specify custom lib name | more info: http://site.icu-project.org/',
'z':'Z compression library | more info: http://www.zlib.net/',
'm':'Basic math library, part of C++ stlib',
@ -82,8 +89,8 @@ pretty_dep_names = {
'libxml2':'libxml2 library | try setting XML2_CONFIG SCons option to point to location of xml2-config program',
'gdal-config':'gdal-config program | try setting GDAL_CONFIG SCons option',
'freetype-config':'freetype-config program | try setting FREETYPE_CONFIG SCons option',
'osm':'more info: https://github.com/mapnik/mapnik/wiki//OsmPlugin',
'curl':'libcurl is required for the "osm" plugin - more info: https://github.com/mapnik/mapnik/wiki//OsmPlugin',
'osm':'more info: https://github.com/mapnik/mapnik/wiki/OsmPlugin',
'curl':'libcurl is required for the "osm" plugin - more info: https://github.com/mapnik/mapnik/wiki/OsmPlugin',
'boost_regex_icu':'libboost_regex built with optional ICU unicode support is needed for unicode regex support in mapnik.',
'sqlite_rtree':'The SQLite plugin requires libsqlite3 built with RTREE support (-DSQLITE_ENABLE_RTREE=1)',
'pgsql2sqlite_rtree':'The pgsql2sqlite program requires libsqlite3 built with RTREE support (-DSQLITE_ENABLE_RTREE=1)'
@ -113,10 +120,17 @@ PLUGINS = { # plugins with external dependencies
}
def init_environment(env):
env.Decider('MD5-timestamp')
env.SourceCode(".", None)
if os.environ.get('RANLIB'):
env['RANLIB'] = os.environ['RANLIB']
if os.environ.get('AR'):
env['AR'] = os.environ['AR']
#### SCons build options and initial setup ####
env = Environment(ENV=os.environ)
env.Decider('MD5-timestamp')
env.SourceCode(".", None)
init_environment(env)
def color_print(color,text,newline=True):
# 1 - red
@ -250,7 +264,7 @@ def pretty_dep(dep):
if pretty:
return '%s (%s)' % (dep,pretty)
elif 'boost' in dep:
return '%s (%s)' % (dep,'more info see: https://github.com/mapnik/mapnik/wiki//MapnikInstallation & http://www.boost.org')
return '%s (%s)' % (dep,'more info see: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation & http://www.boost.org')
return dep
@ -296,7 +310,7 @@ opts.AddVariables(
('PYTHON_PREFIX','Custom install path "prefix" for python bindings (default of no prefix)',''),
('DESTDIR', 'The root directory to install into. Useful mainly for binary package building', '/'),
('PATH', 'A custom path (or multiple paths divided by ":") to append to the $PATH env to prioritize usage of command line programs (if multiple are present on the system)', ''),
('PATH_REMOVE', 'A path prefix to exclude from all known command and compile paths', ''),
('PATH_REMOVE', 'A path prefix to exclude from all known command and compile paths (create multiple excludes separated by :)', ''),
('PATH_REPLACE', 'Two path prefixes (divided with a :) to search/replace from all known command and compile paths', ''),
# Boost variables
@ -312,8 +326,8 @@ opts.AddVariables(
# Variables for required dependencies
('FREETYPE_CONFIG', 'The path to the freetype-config executable.', 'freetype-config'),
('XML2_CONFIG', 'The path to the xml2-config executable.', 'xml2-config'),
PathVariable('ICU_INCLUDES', 'Search path for ICU include files', '/usr/include', PathVariable.PathAccept),
PathVariable('ICU_LIBS','Search path for ICU include files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
PathVariable('ICU_INCLUDES', 'Search path for ICU include files', ICU_INCLUDES_DEFAULT, PathVariable.PathAccept),
PathVariable('ICU_LIBS','Search path for ICU include files',ICU_LIBS_DEFAULT + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc', PathVariable.PathAccept),
BoolVariable('PNG', 'Build Mapnik with PNG read and write support', 'True'),
@ -325,6 +339,9 @@ opts.AddVariables(
BoolVariable('TIFF', 'Build Mapnik with TIFF read and write support', 'True'),
PathVariable('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include', PathVariable.PathAccept),
PathVariable('TIFF_LIBS', 'Search path for libtiff library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
BoolVariable('WEBP', 'Build Mapnik with WEBP read', 'True'),
PathVariable('WEBP_INCLUDES', 'Search path for libwebp include files', '/usr/include', PathVariable.PathAccept),
PathVariable('WEBP_LIBS','Search path for libwebp library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
BoolVariable('PROJ', 'Build Mapnik with proj4 support to enable transformations between many different projections', 'True'),
PathVariable('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/include', PathVariable.PathAccept),
PathVariable('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
@ -332,8 +349,7 @@ opts.AddVariables(
# Variables affecting rendering back-ends
BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'),
BoolVariable('GRID_RENDERER', 'build support for native grid renderer', 'True'),
BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'),
BoolVariable('CPP_TESTS', 'Compile the C++ tests', 'True'),
BoolVariable('BENCHMARK', 'Compile the C++ benchmark scripts', 'False'),
@ -414,7 +430,6 @@ pickle_store = [# Scons internal variables
'BOOST_APPEND',
'LIBDIR_SCHEMA',
'REQUESTED_PLUGINS',
'SUNCC',
'PYTHON_VERSION',
'PYTHON_INCLUDES',
'PYTHON_INSTALL_LOCATION',
@ -445,10 +460,12 @@ pickle_store = [# Scons internal variables
'CAIRO_LIBPATHS',
'CAIRO_ALL_LIBS',
'CAIRO_CPPPATHS',
'GRID_RENDERER',
'SVG_RENDERER',
'SQLITE_LINKFLAGS',
'BOOST_LIB_VERSION_FROM_HEADER',
'BIGINT'
'BIGINT',
'HOST'
]
# Add all other user configurable options to pickle pickle_store
@ -610,6 +627,10 @@ def get_pkg_lib(context, config, lib):
if ret:
try:
value = call(cmd,silent=True)
if ' ' in value:
parts = value.split(' ')
if len(parts) > 1:
value = parts[1]
libnames = re.findall(libpattern,value)
if libnames:
libname = libnames[0]
@ -902,8 +923,7 @@ int main()
def boost_regex_has_icu(context):
if env['RUNTIME_LINK'] == 'static':
context.env.Append(LIBS='icui18n')
context.env.Append(LIBS='icudata')
context.env.AppendUnique(LIBS='icudata')
ret = context.TryRun("""
#include <boost/regex/icu.hpp>
@ -911,7 +931,7 @@ def boost_regex_has_icu(context):
int main()
{
UnicodeString ustr;
U_NAMESPACE_QUALIFIER UnicodeString ustr;
try {
boost::u32regex pattern = boost::make_u32regex(ustr);
}
@ -930,7 +950,7 @@ int main()
return True
return False
def sqlite_has_rtree(context):
def sqlite_has_rtree(context, silent=False):
""" check an sqlite3 install has rtree support.
PRAGMA compile_options;
@ -967,7 +987,10 @@ int main()
}
""", '.c')
context.Message('Checking if SQLite supports RTREE... ')
if not silent:
context.Message('Checking if SQLite supports RTREE... ')
if silent:
context.did_show_result=1
context.Result(ret[0])
if ret[0]:
return True
@ -1021,8 +1044,7 @@ if not preconfigured:
color_print(1,"SCons CONFIG not found: '%s'" % conf)
# Recreate the base environment using modified `opts`
env = Environment(ENV=os.environ,options=opts)
env.Decider('MD5-timestamp')
env.SourceCode(".", None)
init_environment(env)
env['USE_CONFIG'] = True
else:
color_print(4,'SCons USE_CONFIG specified as false, will not inherit variables python config file...')
@ -1120,20 +1142,8 @@ if not preconfigured:
thread_suffix = ''
env.Append(LIBS = 'pthread')
# Solaris & Sun Studio settings (the `SUNCC` flag will only be
# set if the `CXX` option begins with `CC`)
SOLARIS = env['PLATFORM'] == 'SunOS'
env['SUNCC'] = SOLARIS and env['CXX'].startswith('CC')
# If the Sun Studio C++ compiler (`CC`) is used instead of gcc.
if env['SUNCC']:
env['CC'] = 'cc'
# To be compatible w/Boost everything needs to be compiled
# with the `-library=stlport4` flag (which needs to come
# before the `-o` flag).
env['CXX'] = 'CC -library=stlport4'
if env['THREADING'] == 'multi':
env.Append(CXXFLAGS = '-mt')
if env['SHAPE_MEMORY_MAPPED_FILE']:
env.Append(CPPDEFINES = '-DSHAPE_MEMORY_MAPPED_FILE')
# allow for mac osx /usr/lib/libicucore.dylib compatibility
# requires custom supplied headers since Apple does not include them
@ -1175,14 +1185,15 @@ if not preconfigured:
else:
env['MISSING_DEPS'].append('libxml2')
LIBSHEADERS = [
REQUIRED_LIBSHEADERS = [
['z', 'zlib.h', True,'C'],
[env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'],
]
OPTIONAL_LIBSHEADERS = []
if env['JPEG']:
env.Append(CPPDEFINES = '-DHAVE_JPEG')
LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], True,'C'])
OPTIONAL_LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], False,'C','-DHAVE_JPEG'])
inc_path = env['%s_INCLUDES' % 'JPEG']
lib_path = env['%s_LIBS' % 'JPEG']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@ -1191,8 +1202,7 @@ if not preconfigured:
env['SKIPPED_DEPS'].extend(['jpeg'])
if env['PROJ']:
env.Append(CPPDEFINES = '-DMAPNIK_USE_PROJ4')
LIBSHEADERS.append(['proj', 'proj_api.h', True,'C'])
OPTIONAL_LIBSHEADERS.append(['proj', 'proj_api.h', False,'C','-DMAPNIK_USE_PROJ4'])
inc_path = env['%s_INCLUDES' % 'PROJ']
lib_path = env['%s_LIBS' % 'PROJ']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@ -1201,8 +1211,7 @@ if not preconfigured:
env['SKIPPED_DEPS'].extend(['proj'])
if env['PNG']:
env.Append(CPPDEFINES = '-DHAVE_PNG')
LIBSHEADERS.append(['png', 'png.h', True,'C'])
OPTIONAL_LIBSHEADERS.append(['png', 'png.h', False,'C','-DHAVE_PNG'])
inc_path = env['%s_INCLUDES' % 'PNG']
lib_path = env['%s_LIBS' % 'PNG']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@ -1210,9 +1219,17 @@ if not preconfigured:
else:
env['SKIPPED_DEPS'].extend(['png'])
if env['WEBP']:
OPTIONAL_LIBSHEADERS.append(['webp', 'webp/decode.h', False,'C','-DHAVE_WEBP'])
inc_path = env['%s_INCLUDES' % 'WEBP']
lib_path = env['%s_LIBS' % 'WEBP']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
env.AppendUnique(LIBPATH = os.path.realpath(lib_path))
else:
env['SKIPPED_DEPS'].extend(['webp'])
if env['TIFF']:
env.Append(CPPDEFINES = '-DHAVE_TIFF')
LIBSHEADERS.append(['tiff', 'tiff.h', True,'C'])
OPTIONAL_LIBSHEADERS.append(['tiff', 'tiff.h', False,'C','-DHAVE_TIFF'])
inc_path = env['%s_INCLUDES' % 'TIFF']
lib_path = env['%s_LIBS' % 'TIFF']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@ -1225,7 +1242,7 @@ if not preconfigured:
conf.prioritize_paths(silent=True)
if not env['HOST']:
for libname, headers, required, lang in LIBSHEADERS:
for libname, headers, required, lang in REQUIRED_LIBSHEADERS:
if not conf.CheckLibWithHeader(libname, headers, lang):
if required:
color_print(1, 'Could not find required header or shared library for %s' % libname)
@ -1250,134 +1267,184 @@ if not preconfigured:
conf.FindBoost(BOOST_SEARCH_PREFIXES,thread_flag)
env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion()
# The other required boost headers.
BOOST_LIBSHEADERS = [
['system', 'boost/system/system_error.hpp', True],
['filesystem', 'boost/filesystem/operations.hpp', True],
['regex', 'boost/regex.hpp', True],
['program_options', 'boost/program_options.hpp', False]
]
if env['THREADING'] == 'multi':
BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True])
# on solaris the configure checks for boost_thread
# require the -pthreads flag to be able to check for
# threading support, so we add as a global library instead
# of attaching to cxxflags after configure
if env['PLATFORM'] == 'SunOS':
env.Append(CXXFLAGS = '-pthreads')
# if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
if env['PRIORITIZE_LINKING']:
conf.prioritize_paths(silent=True)
has_boost_devel = True
if not env['HOST']:
# if the user is not setting custom boost configuration
# enforce boost version greater than or equal to BOOST_MIN_VERSION
if not conf.CheckBoost(BOOST_MIN_VERSION):
color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION)
if not env['BOOST_VERSION']:
env['MISSING_DEPS'].append('boost version >=%s' % BOOST_MIN_VERSION)
else:
color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
if not conf.CheckHeader(header='boost/version.hpp',language='C++'):
env['MISSING_DEPS'].append('boost development headers')
has_boost_devel = False
if not env['HOST']:
for count, libinfo in enumerate(BOOST_LIBSHEADERS):
if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'):
if libinfo[2]:
color_print(1,'Could not find required header or shared library for boost %s' % libinfo[0])
env['MISSING_DEPS'].append('boost ' + libinfo[0])
else:
color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0])
env['SKIPPED_DEPS'].append('boost ' + libinfo[0])
if has_boost_devel:
if not env['HOST']:
env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion()
if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
# The other required boost headers.
BOOST_LIBSHEADERS = [
['system', 'boost/system/system_error.hpp', True],
['filesystem', 'boost/filesystem/operations.hpp', True],
['regex', 'boost/regex.hpp', True],
['program_options', 'boost/program_options.hpp', False]
]
if env['THREADING'] == 'multi':
BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True])
# on solaris the configure checks for boost_thread
# require the -pthreads flag to be able to check for
# threading support, so we add as a global library instead
# of attaching to cxxflags after configure
if env['PLATFORM'] == 'SunOS':
env.Append(CXXFLAGS = '-pthreads')
# if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
if env['PRIORITIZE_LINKING']:
conf.prioritize_paths(silent=True)
if not env['HOST']:
# if the user is not setting custom boost configuration
# enforce boost version greater than or equal to BOOST_MIN_VERSION
if not conf.CheckBoost(BOOST_MIN_VERSION):
color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION)
if not env['BOOST_VERSION']:
env['MISSING_DEPS'].append('boost version >= %s' % BOOST_MIN_VERSION)
else:
color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
if not env['HOST']:
for count, libinfo in enumerate(BOOST_LIBSHEADERS):
if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'):
if libinfo[2]:
color_print(1,'Could not find required header or shared library for boost %s' % libinfo[0])
env['MISSING_DEPS'].append('boost ' + libinfo[0])
else:
color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0])
env['SKIPPED_DEPS'].append('boost ' + libinfo[0])
if not env['HOST'] and env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
# http://lists.boost.org/Archives/boost/2009/03/150076.php
# we need libicui18n if using static boost libraries, so it is
# important to try this check with the library linked
env.AppendUnique(LIBS='icui18n')
if conf.boost_regex_has_icu():
# TODO - should avoid having this be globally defined...
env.Append(CPPDEFINES = '-DBOOST_REGEX_HAS_ICU')
else:
env['SKIPPED_DEPS'].append('boost_regex_icu')
for libname, headers, required, lang, define in OPTIONAL_LIBSHEADERS:
if not env['HOST']:
if not conf.CheckLibWithHeader(libname, headers, lang):
if required:
color_print(1, 'Could not find required header or shared library for %s' % libname)
env['MISSING_DEPS'].append(libname)
else:
color_print(4, 'Could not find optional header or shared library for %s' % libname)
env['SKIPPED_DEPS'].append(libname)
else:
env.Append(CPPDEFINES = define)
else:
env.Append(CPPDEFINES = define)
env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])]
SQLITE_HAS_RTREE = None
if env['HOST']:
SQLITE_HAS_RTREE = True
CHECK_PKG_CONFIG = conf.CheckPKGConfig('0.15.0')
if len(env['REQUESTED_PLUGINS']):
color_print(4,'Checking for requested plugins dependencies...')
for plugin in env['REQUESTED_PLUGINS']:
details = env['PLUGINS'][plugin]
if plugin == 'gdal':
if conf.parse_config('GDAL_CONFIG',checks='--libs'):
conf.parse_config('GDAL_CONFIG',checks='--cflags')
libname = conf.get_pkg_lib('GDAL_CONFIG','gdal')
if libname:
details['lib'] = libname
elif plugin == 'postgis':
conf.parse_pg_config('PG_CONFIG')
elif plugin == 'ogr':
if conf.ogr_enabled():
if not 'gdal' in env['REQUESTED_PLUGINS']:
conf.parse_config('GDAL_CONFIG',checks='--libs')
if env['HOST']:
for plugin in env['REQUESTED_PLUGINS']:
details = env['PLUGINS'][plugin]
if details['lib']:
env.AppendUnique(LIBS=details['lib'])
else:
color_print(4,'Checking for requested plugins dependencies...')
for plugin in env['REQUESTED_PLUGINS']:
details = env['PLUGINS'][plugin]
if plugin == 'gdal':
if conf.parse_config('GDAL_CONFIG',checks='--libs'):
conf.parse_config('GDAL_CONFIG',checks='--cflags')
libname = conf.get_pkg_lib('GDAL_CONFIG','ogr')
if libname:
details['lib'] = libname
elif details['path'] and details['lib'] and details['inc']:
backup = env.Clone().Dictionary()
# Note, the 'delete_existing' keyword makes sure that these paths are prepended
# to the beginning of the path list even if they already exist
incpath = env['%s_INCLUDES' % details['path']]
libpath = env['%s_LIBS' % details['path']]
env.PrependUnique(CPPPATH = os.path.realpath(incpath),delete_existing=True)
env.PrependUnique(LIBPATH = os.path.realpath(libpath),delete_existing=True)
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
env.Replace(**backup)
env['SKIPPED_DEPS'].append(details['lib'])
if plugin == 'sqlite':
sqlite_backup = env.Clone().Dictionary()
libname = conf.get_pkg_lib('GDAL_CONFIG','gdal')
if libname:
if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']):
env['SKIPPED_DEPS'].append('gdal')
if libname in env['LIBS']:
env['LIBS'].remove(libname)
else:
details['lib'] = libname
elif plugin == 'postgis':
conf.parse_pg_config('PG_CONFIG')
elif plugin == 'ogr':
if conf.ogr_enabled():
if not 'gdal' in env['REQUESTED_PLUGINS']:
conf.parse_config('GDAL_CONFIG',checks='--libs')
conf.parse_config('GDAL_CONFIG',checks='--cflags')
libname = conf.get_pkg_lib('GDAL_CONFIG','ogr')
if libname:
if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']):
if 'gdal' not in env['SKIPPED_DEPS']:
env['SKIPPED_DEPS'].append('gdal')
if libname in env['LIBS']:
env['LIBS'].remove(libname)
else:
details['lib'] = libname
elif details['path'] and details['lib'] and details['inc']:
backup = env.Clone().Dictionary()
# Note, the 'delete_existing' keyword makes sure that these paths are prepended
# to the beginning of the path list even if they already exist
incpath = env['%s_INCLUDES' % details['path']]
libpath = env['%s_LIBS' % details['path']]
env.PrependUnique(CPPPATH = os.path.realpath(incpath),delete_existing=True)
env.PrependUnique(LIBPATH = os.path.realpath(libpath),delete_existing=True)
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
env.Replace(**backup)
env['SKIPPED_DEPS'].append(details['lib'])
if plugin == 'sqlite':
sqlite_backup = env.Clone().Dictionary()
# if statically linking, on linux we likely
# need to link sqlite to pthreads and dl
if env['RUNTIME_LINK'] == 'static':
if CHECK_PKG_CONFIG and conf.CheckPKG('sqlite3'):
sqlite_env = env.Clone()
try:
sqlite_env.ParseConfig('pkg-config --static --libs sqlite3')
for lib in sqlite_env['LIBS']:
if not lib in env['LIBS']:
env["SQLITE_LINKFLAGS"].append(lib)
env.Append(LIBS=lib)
except OSError,e:
pass
SQLITE_HAS_RTREE = conf.sqlite_has_rtree()
if not SQLITE_HAS_RTREE:
env.Replace(**sqlite_backup)
if details['lib'] in env['LIBS']:
env['LIBS'].remove(details['lib'])
env['SKIPPED_DEPS'].append('sqlite_rtree')
else:
env.Replace(**sqlite_backup)
elif details['lib'] and details['inc']:
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
env['SKIPPED_DEPS'].append(details['lib'])
# if statically linking, on linux we likely
# need to link sqlite to pthreads and dl
if env['RUNTIME_LINK'] == 'static':
if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('sqlite3'):
sqlite_env = env.Clone()
try:
sqlite_env.ParseConfig('pkg-config --static --libs sqlite3')
for lib in sqlite_env['LIBS']:
if not lib in env['LIBS']:
env["SQLITE_LINKFLAGS"].append(lib)
env.Append(LIBS=lib)
except OSError,e:
pass
# re-append the local paths for mapnik sources to the beginning of the list
# to make sure they come before any plugins that were 'prepended'
env.PrependUnique(CPPPATH = '#include', delete_existing=True)
env.PrependUnique(CPPPATH = '#', delete_existing=True)
env.PrependUnique(LIBPATH = '#src', delete_existing=True)
if not conf.sqlite_has_rtree():
env.Replace(**sqlite_backup)
if details['lib'] in env['LIBS']:
env['LIBS'].remove(details['lib'])
env['SKIPPED_DEPS'].append('sqlite_rtree')
else:
env.Replace(**sqlite_backup)
elif details['lib'] and details['inc']:
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
env['SKIPPED_DEPS'].append(details['lib'])
# re-append the local paths for mapnik sources to the beginning of the list
# to make sure they come before any plugins that were 'prepended'
env.PrependUnique(CPPPATH = '#include', delete_existing=True)
env.PrependUnique(CPPPATH = '#', delete_existing=True)
env.PrependUnique(LIBPATH = '#src', delete_existing=True)
if env['PGSQL2SQLITE']:
if 'sqlite3' not in env['LIBS']:
env.AppendUnique(LIBS='sqlite3')
env.AppendUnique(CPPPATH = os.path.realpath(env['SQLITE_INCLUDES']))
env.AppendUnique(LIBPATH = os.path.realpath(env['SQLITE_LIBS']))
if not conf.sqlite_has_rtree():
env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree')
env['PGSQL2SQLITE'] = False
if not env['HOST']:
if env['PGSQL2SQLITE']:
if 'sqlite3' not in env['LIBS']:
env.AppendUnique(LIBS='sqlite3')
env.AppendUnique(CPPPATH = os.path.realpath(env['SQLITE_INCLUDES']))
env.AppendUnique(LIBPATH = os.path.realpath(env['SQLITE_LIBS']))
if 'pq' not in env['LIBS']:
if not conf.parse_pg_config('PG_CONFIG'):
env['PGSQL2SQLITE'] = False
if not SQLITE_HAS_RTREE:
env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree')
env['PGSQL2SQLITE'] = False
# we rely on an internal, patched copy of agg with critical fixes
# prepend to make sure we link locally
@ -1409,12 +1476,12 @@ if not preconfigured:
env["CAIRO_ALL_LIBS"] = ['cairo']
if env['RUNTIME_LINK'] == 'static':
env["CAIRO_ALL_LIBS"].extend(
['pixman-1','expat','fontconfig','iconv']
['pixman-1','expat','fontconfig']
)
# todo - run actual checkLib?
env['HAS_CAIRO'] = True
else:
if not conf.CheckPKGConfig('0.15.0'):
if not CHECK_PKG_CONFIG:
env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('pkg-config')
env['SKIPPED_DEPS'].append('cairo')
@ -1515,7 +1582,7 @@ if not preconfigured:
else:
env['PYTHON_IS_64BIT'] = False
if 'python' in env['BINDINGS']:
if has_boost_devel and 'python' in env['BINDINGS']:
if py3 and env['BOOST_PYTHON_LIB'] == 'boost_python':
env['BOOST_PYTHON_LIB'] = 'boost_python3%s' % env['BOOST_APPEND']
elif env['BOOST_PYTHON_LIB'] == 'boost_python':
@ -1526,7 +1593,7 @@ if not preconfigured:
env['MISSING_DEPS'].append('boost python')
if env['CAIRO']:
if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('pycairo'):
if CHECK_PKG_CONFIG and conf.CheckPKG('pycairo'):
env['HAS_PYCAIRO'] = True
else:
env['SKIPPED_DEPS'].extend(['pycairo'])
@ -1548,7 +1615,7 @@ if not preconfigured:
color_print(4," $ sudo python scons/scons.py install")
color_print(4,"\nTo view available path variables:\n $ python scons/scons.py --help or -h")
color_print(4,'\nTo view overall SCons help options:\n $ python scons/scons.py --help-options or -H\n')
color_print(4,'More info: https://github.com/mapnik/mapnik/wiki//MapnikInstallation')
color_print(4,'More info: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation')
if not HELP_REQUESTED:
Exit(1)
else:
@ -1568,15 +1635,18 @@ if not preconfigured:
color_print(4,"Did not use user config file, no custom path variables will be saved...")
if env['SKIPPED_DEPS']:
color_print(3,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']]))
color_print(4,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']]))
print
# fetch the mapnik version header in order to set the
# ABI version used to build libmapnik.so on linux in src/build.py
abi = conf.GetMapnikLibVersion()
abi_fallback = "2.2.0-pre"
abi = None
abi_fallback = "3.0.0-pre"
if not env['HOST']:
abi = conf.GetMapnikLibVersion()
if not abi:
color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback)
if not env['HOST']:
color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback)
abi = abi_fallback
abi_no_pre = abi.replace('-pre','').split('.')
@ -1601,6 +1671,16 @@ if not preconfigured:
debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG']
ndebug_defines = ['-DNDEBUG']
# c++11 support / https://github.com/mapnik/mapnik/issues/1683
# - upgrade to PHOENIX_V3 since that is needed for c++11 compile
if 'c++11' in env['CUSTOM_CXXFLAGS']:
env.Append(CPPDEFINES = '-DBOOST_SPIRIT_USE_PHOENIX_V3=1')
# - workaround boost gil channel_algorithm.hpp narrowing error
# TODO - remove when building against >= 1.55
# https://github.com/mapnik/mapnik/issues/1970
if 'clang++' in env['CXX']:
env.Append(CXXFLAGS = '-Wno-c++11-narrowing')
# Enable logging in debug mode (always) and release mode (when specified)
if env['DEFAULT_LOG_SEVERITY']:
if env['DEFAULT_LOG_SEVERITY'] not in severities:
@ -1638,24 +1718,22 @@ if not preconfigured:
else:
env.Append(CPPDEFINES = ndebug_defines)
if not env['SUNCC']:
# Common flags for g++/clang++ CXX compiler.
# TODO: clean up code more to make -Wsign-conversion -Wconversion -Wshadow viable
common_cxx_flags = '-Wall -Wsign-compare %s %s -ftemplate-depth-300 ' % (env['WARNING_CXXFLAGS'], pthread)
# Common flags for CXX compiler.
common_cxx_flags = '-ansi -Wall %s %s -ftemplate-depth-300 ' % (env['WARNING_CXXFLAGS'], pthread)
# https://github.com/mapnik/mapnik/issues/1835
if sys.platform == 'darwin' and env['CXX'] == 'g++':
common_cxx_flags += '-fpermissive '
# https://github.com/mapnik/mapnik/issues/1835
if sys.platform == 'darwin' and env['CXX'] == 'g++':
common_cxx_flags += '-fpermissive '
if env['DEBUG']:
env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline')
else:
# TODO - add back -fvisibility-inlines-hidden
# https://github.com/mapnik/mapnik/issues/1863
env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION']))
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv')
if env['DEBUG']:
env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline')
else:
# TODO - add back -fvisibility-inlines-hidden
# https://github.com/mapnik/mapnik/issues/1863
env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION']))
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv')
if 'python' in env['BINDINGS'] or 'python' in env['REQUESTED_PLUGINS']:
majver, minver = env['PYTHON_VERSION'].split('.')
@ -1737,14 +1815,14 @@ if not HELP_REQUESTED:
env['ENV']['PATH'] = os.path.realpath(env['PATH']) + ':' + env['ENV']['PATH']
if env['PATH_REMOVE']:
p = env['PATH_REMOVE']
if p in env['ENV']['PATH']:
env['ENV']['PATH'].replace(p,'')
rm_path(p,'LIBPATH',env)
rm_path(p,'CPPPATH',env)
rm_path(p,'CXXFLAGS',env)
rm_path(p,'CAIRO_LIBPATHS',env)
rm_path(p,'CAIRO_CPPPATHS',env)
for p in env['PATH_REMOVE'].split(':'):
if p in env['ENV']['PATH']:
env['ENV']['PATH'].replace(p,'')
rm_path(p,'LIBPATH',env)
rm_path(p,'CPPPATH',env)
rm_path(p,'CXXFLAGS',env)
rm_path(p,'CAIRO_LIBPATHS',env)
rm_path(p,'CAIRO_CPPPATHS',env)
if env['PATH_REPLACE']:
searches,replace = env['PATH_REPLACE'].split(':')
@ -1800,7 +1878,7 @@ if not HELP_REQUESTED:
if env['PLUGIN_LINKING'] == 'static' or plugin not in env['REQUESTED_PLUGINS']:
if os.path.exists('plugins/input/%s.input' % plugin):
os.unlink('plugins/input/%s.input' % plugin)
if plugin in env['REQUESTED_PLUGINS']:
elif plugin in env['REQUESTED_PLUGINS']:
details = env['PLUGINS'][plugin]
if details['lib'] in env['LIBS']:
if env['PLUGIN_LINKING'] == 'shared':
@ -1836,30 +1914,29 @@ if not HELP_REQUESTED:
plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'%s.input' % plugin)
if os.path.exists(plugin_path):
if plugin not in env['REQUESTED_PLUGINS'] or env['PLUGIN_LINKING'] == 'static':
color_print(3,"Notice: removing out of date plugin: '%s'" % plugin_path)
color_print(4,"Notice: removing out of date plugin: '%s'" % plugin_path)
os.unlink(plugin_path)
# Build the c++ rundemo app if requested
if env['DEMO']:
SConscript('demo/c++/build.py')
if not env['HOST']:
if env['DEMO']:
SConscript('demo/c++/build.py')
# Build shapeindex and remove its dependency from the LIBS
if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
if env['SHAPEINDEX']:
SConscript('utils/shapeindex/build.py')
# Build the pgsql2psqlite app if requested
if env['PGSQL2SQLITE']:
SConscript('utils/pgsql2sqlite/build.py')
if env['SVG2PNG']:
SConscript('utils/svg2png/build.py')
# devtools not ready for public
#SConscript('utils/ogrindex/build.py')
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
else :
color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available")
if not env['HOST']:
if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
if env['SHAPEINDEX']:
SConscript('utils/shapeindex/build.py')
# Build the pgsql2psqlite app if requested
if env['PGSQL2SQLITE']:
SConscript('utils/pgsql2sqlite/build.py')
if env['SVG2PNG']:
SConscript('utils/svg2png/build.py')
# devtools not ready for public
#SConscript('utils/ogrindex/build.py')
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
else :
color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available")
# Build the Python bindings
if 'python' in env['BINDINGS']:
@ -1896,7 +1973,7 @@ if not HELP_REQUESTED:
if 'install' in COMMAND_LINE_TARGETS:
plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'hello.input')
if os.path.exists(plugin_path):
color_print(3,"Notice: removing out of date plugin: '%s'" % plugin_path)
color_print(4,"Notice: removing out of date plugin: '%s'" % plugin_path)
os.unlink(plugin_path)
if os.path.exists('plugins/input/templates/hello.input'):
os.unlink('plugins/input/templates/hello.input')

View file

@ -1 +1 @@
MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))
POLYGON ((155 203, 233 454, 315 340, 421 446, 463 324, 559 466, 665 253, 528 178, 394 229, 329 138, 212 134, 183 228, 200 264, 155 203),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343 287, 249 334, 229 191, 313 190))

View file

@ -0,0 +1,14 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="steelblue">
<Style name="style">
<Rule>
<PolygonSymbolizer clip="true"/>
</Rule>
</Style>
<Layer name="world" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<Parameter name="file">../../tests/data/shp/world_merc.shp</Parameter>
<Parameter name="type">shape</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,14 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="steelblue">
<Style name="style">
<Rule>
<PolygonSymbolizer clip="false"/>
</Rule>
</Style>
<Layer name="world" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<Parameter name="file">../../tests/data/shp/world_merc.shp</Parameter>
<Parameter name="type">shape</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -12,6 +12,7 @@
#include <sstream>
#include <cstdio>
#include <set>
#include <stdexcept>
// boost
#include <boost/version.hpp>
@ -27,9 +28,10 @@
using namespace boost::chrono;
using namespace mapnik;
static unsigned test_num = 1;
static bool dry_run = false;
static std::set<int> test_set;
typedef std::set<int> set_type;
static set_type test_set;
static set_type::key_type test_num = 1;
typedef process_cpu_clock clock_type;
typedef clock_type::duration dur;
@ -87,7 +89,7 @@ void benchmark(T & test_runner, std::string const& name)
{
std::clog << "test runner did not complete: " << ex.what() << "\n";
}
test_num++;
++test_num;
}
bool compare_images(std::string const& src_fn,std::string const& dest_fn)
@ -264,7 +266,7 @@ struct test5
s.resize(s.capacity());
while (true)
{
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%g", val_));
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%g", val));
if (n2 <= s.size())
{
s.resize(n2);
@ -407,209 +409,88 @@ struct test8
}
};
#include <mapnik/rule_cache.hpp>
#if BOOST_VERSION >= 105300
#include <boost/container/vector.hpp>
#include <boost/move/utility.hpp>
class rule_cache_move
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(rule_cache_move)
public:
typedef std::vector<rule const*> rule_ptrs;
rule_cache_move()
: if_rules_(),
else_rules_(),
also_rules_() {}
rule_cache_move(BOOST_RV_REF(rule_cache_move) rhs) // move ctor
: if_rules_(boost::move(rhs.if_rules_)),
else_rules_(boost::move(rhs.else_rules_)),
also_rules_(boost::move(rhs.also_rules_))
{}
rule_cache_move& operator=(BOOST_RV_REF(rule_cache_move) rhs) // move assign
{
std::swap(if_rules_, rhs.if_rules_);
std::swap(else_rules_,rhs.else_rules_);
std::swap(also_rules_, rhs.also_rules_);
return *this;
}
void add_rule(rule const& r)
{
if (r.has_else_filter())
{
else_rules_.push_back(&r);
}
else if (r.has_also_filter())
{
also_rules_.push_back(&r);
}
else
{
if_rules_.push_back(&r);
}
}
rule_ptrs const& get_if_rules() const
{
return if_rules_;
}
rule_ptrs const& get_else_rules() const
{
return else_rules_;
}
rule_ptrs const& get_also_rules() const
{
return also_rules_;
}
private:
rule_ptrs if_rules_;
rule_ptrs else_rules_;
rule_ptrs also_rules_;
};
struct test9
{
unsigned iter_;
unsigned threads_;
unsigned num_rules_;
unsigned num_styles_;
std::vector<rule> rules_;
explicit test9(unsigned iterations,
unsigned threads,
unsigned num_rules,
unsigned num_styles) :
iter_(iterations),
threads_(threads),
num_rules_(num_rules),
num_styles_(num_styles),
rules_() {
mapnik::rule r("test");
for (unsigned i=0;i<num_rules_;++i) {
rules_.push_back(r);
}
}
bool validate()
{
return true;
}
void operator()()
{
for (unsigned i=0;i<iter_;++i) {
boost::container::vector<rule_cache_move> rule_caches;
for (unsigned i=0;i<num_styles_;++i) {
rule_cache_move rc;
for (unsigned i=0;i<num_rules_;++i) {
rc.add_rule(rules_[i]);
}
rule_caches.push_back(boost::move(rc));
}
}
}
};
#endif
class rule_cache_heap
{
public:
typedef std::vector<rule const*> rule_ptrs;
rule_cache_heap()
: if_rules_(),
else_rules_(),
also_rules_() {}
void add_rule(rule const& r)
{
if (r.has_else_filter())
{
else_rules_.push_back(&r);
}
else if (r.has_also_filter())
{
also_rules_.push_back(&r);
}
else
{
if_rules_.push_back(&r);
}
}
rule_ptrs const& get_if_rules() const
{
return if_rules_;
}
rule_ptrs const& get_else_rules() const
{
return else_rules_;
}
rule_ptrs const& get_also_rules() const
{
return also_rules_;
}
private:
rule_ptrs if_rules_;
rule_ptrs else_rules_;
rule_ptrs also_rules_;
};
struct test10
{
unsigned iter_;
unsigned threads_;
unsigned num_rules_;
unsigned num_styles_;
std::vector<rule> rules_;
explicit test10(unsigned iterations,
unsigned threads,
unsigned num_rules,
unsigned num_styles) :
iter_(iterations),
threads_(threads),
num_rules_(num_rules),
num_styles_(num_styles),
rules_() {
mapnik::rule r("test");
for (unsigned i=0;i<num_rules_;++i) {
rules_.push_back(r);
}
}
bool validate()
{
return true;
}
void operator()()
{
for (unsigned i=0;i<iter_;++i) {
boost::ptr_vector<rule_cache_heap> rule_caches;
for (unsigned i=0;i<num_styles_;++i) {
std::auto_ptr<rule_cache_heap> rc(new rule_cache_heap);
for (unsigned i=0;i<num_rules_;++i) {
rc->add_rule(rules_[i]);
}
rule_caches.push_back(rc);
}
}
}
};
#include "agg_conv_clip_polygon.h"
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/util/geometry_to_wkt.hpp>
#include <mapnik/geometry.hpp>
#include "agg_conv_clip_polygon.h"
struct test11a
{
unsigned iter_;
unsigned threads_;
std::string wkt_in_;
mapnik::box2d<double> extent_;
typedef agg::conv_clip_polygon<mapnik::geometry_type> conv_clip;
test11a(unsigned iterations,
unsigned threads,
std::string wkt_in,
mapnik::box2d<double> const& extent)
: iter_(iterations),
threads_(threads),
wkt_in_(wkt_in),
extent_(extent) {
}
bool validate()
{
std::string expected_wkt("Polygon((181 286.666667,233 454,315 340,421 446,463 324,559 466,631 321.320755,631 234.386861,528 178,394 229,329 138,212 134,183 228,200 264,181 238.244444),(313 190,440 256,470 248,510 305,533 237,613 263,553 397,455 262,405 378,343 287,249 334,229 191,313 190,313 190))");
boost::ptr_vector<geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
BOOST_FOREACH (geometry_type & geom , paths)
{
conv_clip clipped(geom);
clipped.clip_box(
extent_.minx(),
extent_.miny(),
extent_.maxx(),
extent_.maxy());
unsigned cmd;
double x,y;
mapnik::geometry_type geom2(mapnik::Polygon);
while ((cmd = clipped.vertex(&x, &y)) != SEG_END) {
geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
}
std::string wkt;
bool result = mapnik::util::to_wkt(wkt,geom2);
if (result) {
return (wkt == expected_wkt);
}
}
return false;
}
void operator()()
{
boost::ptr_vector<geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
for (unsigned i=0;i<iter_;++i)
{
BOOST_FOREACH (geometry_type & geom , paths)
{
conv_clip clipped(geom);
clipped.clip_box(
extent_.minx(),
extent_.miny(),
extent_.maxx(),
extent_.maxy());
unsigned cmd;
double x,y;
while ((cmd = clipped.vertex(&x, &y)) != SEG_END) {}
}
}
}
};
#include "agg_conv_clipper.h"
#include "agg_path_storage.h"
#include <mapnik/geometry.hpp>
struct test11
{
@ -631,7 +512,39 @@ struct test11
bool validate()
{
return true;
std::string expected_wkt("Polygon((212 134,329 138,394 229,528 178,631 234.4,631 321.3,559 466,463 324,421 446,315 340,233 454,181 286.7,181 238.2,200 264,183 228),(313 190,229 191,249 334,343 287,405 378,455 262,553 397,613 263,533 237,510 305,470 248,440 256))");
boost::ptr_vector<geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
agg::path_storage ps;
ps.move_to(extent_.minx(), extent_.miny());
ps.line_to(extent_.minx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.miny());
ps.close_polygon();
BOOST_FOREACH (geometry_type & geom , paths)
{
poly_clipper clipped(geom,ps,
agg::clipper_and,
agg::clipper_non_zero,
agg::clipper_non_zero,
1);
clipped.rewind(0);
unsigned cmd;
double x,y;
mapnik::geometry_type geom2(mapnik::Polygon);
while ((cmd = clipped.vertex(&x, &y)) != SEG_END) {
geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
}
std::string wkt;
bool result = mapnik::util::to_wkt(wkt,geom2);
if (result) {
return (wkt == expected_wkt);
}
}
return false;
}
void operator()()
{
@ -646,18 +559,19 @@ struct test11
ps.line_to(extent_.maxx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.miny());
ps.close_polygon();
for (unsigned i=0;i<iter_;++i) {
BOOST_FOREACH( geometry_type & geom, paths)
for (unsigned i=0;i<iter_;++i)
{
BOOST_FOREACH (geometry_type & geom , paths)
{
poly_clipper clipped(geom,ps,
agg::clipper_and,
agg::clipper_non_zero,
agg::clipper_non_zero,
1);
agg::clipper_and,
agg::clipper_non_zero,
agg::clipper_non_zero,
1);
clipped.rewind(0);
unsigned cmd;
double x,y;
while ((cmd = geom.vertex(&x, &y)) != SEG_END) {}
while ((cmd = clipped.vertex(&x, &y)) != SEG_END) {}
}
}
}
@ -670,7 +584,6 @@ struct test12
unsigned iter_;
unsigned threads_;
std::string wkt_in_;
mapnik::box2d<double> extent_;
typedef mapnik::polygon_clipper<mapnik::geometry_type> poly_clipper;
test12(unsigned iterations,
@ -686,7 +599,28 @@ struct test12
bool validate()
{
return true;
std::string expected_wkt("Polygon((181 286.666667,233 454,315 340,421 446,463 324,559 466,631 321.320755,631 234.386861,528 178,394 229,329 138,212 134,183 228,200 264,181 238.244444,181 286.666667),(313 190,440 256,470 248,510 305,533 237,613 263,553 397,455 262,405 378,343 287,249 334,229 191,313 190))");
boost::ptr_vector<geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
BOOST_FOREACH ( geometry_type & geom , paths)
{
poly_clipper clipped(extent_, geom);
unsigned cmd;
double x,y;
mapnik::geometry_type geom2(mapnik::Polygon);
while ((cmd = clipped.vertex(&x, &y)) != SEG_END) {
geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
}
std::string wkt;
bool result = mapnik::util::to_wkt(wkt,geom2);
if (result) {
return (wkt == expected_wkt);
}
}
return false;
}
void operator()()
{
@ -697,12 +631,12 @@ struct test12
}
for (unsigned i=0;i<iter_;++i)
{
BOOST_FOREACH( geometry_type & geom, paths)
BOOST_FOREACH ( geometry_type & geom , paths)
{
poly_clipper clipped(extent_, geom);
unsigned cmd;
double x,y;
while ((cmd = geom.vertex(&x, &y)) != SEG_END) {}
while ((cmd = clipped.vertex(&x, &y)) != SEG_END) {}
}
}
}
@ -732,7 +666,7 @@ struct test13
unsigned long count = 0;
for (unsigned i=0;i<iter_;++i)
{
BOOST_FOREACH( std::string const& name, mapnik::freetype_engine::face_names())
BOOST_FOREACH( std::string const& name , mapnik::freetype_engine::face_names())
{
mapnik::face_ptr f = engine.create_face(name);
if (f) ++count;
@ -741,6 +675,53 @@ struct test13
}
};
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
struct test14
{
unsigned iter_;
unsigned threads_;
std::string xml_;
mapnik::box2d<double> extent_;
test14(unsigned iterations,
unsigned threads,
std::string const& xml,
mapnik::box2d<double> const& extent)
: iter_(iterations),
threads_(threads),
xml_(xml),
extent_(extent)
{}
bool validate()
{
mapnik::Map m(256,256);
mapnik::load_map(m,xml_);
m.zoom_to_box(extent_);
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
ren.apply();
//mapnik::save_to_file(im,"test.png");
return true;
}
void operator()()
{
mapnik::Map m(256,256);
mapnik::load_map(m,xml_);
m.zoom_to_box(extent_);
for (unsigned i=0;i<iter_;++i)
{
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
ren.apply();
}
}
};
int main( int argc, char** argv)
{
if (argc > 0) {
@ -751,11 +732,12 @@ int main( int argc, char** argv)
} else if (opt[0] != '-') {
int arg;
if (mapnik::util::string2int(opt,arg)) {
test_set.insert(arg);
test_set.insert(static_cast<unsigned>(arg));
}
}
}
}
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
try
{
std::cout << "starting benchmark…\n";
@ -796,17 +778,17 @@ int main( int argc, char** argv)
}
{
test3 runner(1000000,10);
test3 runner(100000,10);
benchmark(runner,"double to string conversion with std::ostringstream");
}
{
test4 runner(1000000,10);
test4 runner(100000,10);
benchmark(runner,"double to string conversion with mapnik::util_to_string");
}
{
test5 runner(1000000,10);
test5 runner(100000,10);
benchmark(runner,"double to string conversion with snprintf");
}
@ -856,18 +838,26 @@ int main( int argc, char** argv)
benchmark(runner,"expression parsing by re-using grammar");
}
{
#if BOOST_VERSION >= 105300
test9 runner(1000,10,200,50);
benchmark(runner,"rule caching using boost::move");
#else
std::clog << "not running: 'rule caching using boost::move'\n";
#endif
}
// TODO - consider bring back rule cache benchmarks after c++11 is in master
// previously test 9/10
// polygon/rect clipping
// IN : POLYGON ((155 203, 233 454, 315 340, 421 446, 463 324, 559 466, 665 253, 528 178, 394 229, 329 138, 212 134, 183 228, 200 264, 155 203),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343 287, 249 334, 229 191, 313 190))
// RECT : POLYGON ((181 106, 181 470, 631 470, 631 106, 181 106))
// OUT (expected)
// POLYGON ((181 286.6666666666667, 233 454, 315 340, 421 446, 463 324, 559 466, 631 321.3207547169811, 631 234.38686131386862, 528 178, 394 229, 329 138, 212 134, 183 228, 200 264, 181 238.24444444444444, 181 286.6666666666667),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343 287, 249 334, 229 191, 313 190))
mapnik::box2d<double> clipping_box(181,106,631,470);
{
test10 runner(1000,10,200,50);
benchmark(runner,"rule caching using heap allocation");
std::string filename_("benchmark/data/polygon.wkt");
std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
if (!in.is_open())
throw std::runtime_error("could not open: '" + filename_ + "'");
std::string wkt_in( (std::istreambuf_iterator<char>(in) ),
(std::istreambuf_iterator<char>()) );
test11a runner(10000,10,wkt_in,clipping_box);
benchmark(runner,"clipping polygon with conv_clip_polygon");
}
{
@ -877,32 +867,61 @@ int main( int argc, char** argv)
throw std::runtime_error("could not open: '" + filename_ + "'");
std::string wkt_in( (std::istreambuf_iterator<char>(in) ),
(std::istreambuf_iterator<char>()) );
mapnik::box2d<double> clipping_box(0,0,40,40);
test11 runner(100000,10,wkt_in,clipping_box);
test11 runner(10000,10,wkt_in,clipping_box);
benchmark(runner,"clipping polygon with agg_conv_clipper");
}
{
{
std::string filename_("benchmark/data/polygon.wkt");
std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
if (!in.is_open())
throw std::runtime_error("could not open: '" + filename_ + "'");
std::string wkt_in( (std::istreambuf_iterator<char>(in) ),
(std::istreambuf_iterator<char>()) );
mapnik::box2d<double> clipping_box(0,0,40,40);
test12 runner(100000,10,wkt_in,clipping_box);
test12 runner(10000,10,wkt_in,clipping_box);
benchmark(runner,"clipping polygon with mapnik::polygon_clipper");
}
{
mapnik::freetype_engine::register_fonts("./fonts", true);
unsigned face_count = mapnik::freetype_engine::face_names().size();
bool success = mapnik::freetype_engine::register_fonts("./fonts", true);
if (!success) {
std::clog << "warning, did not register any new fonts!\n";
}
std::size_t face_count = mapnik::freetype_engine::face_names().size();
test13 runner(1000,10);
benchmark(runner, (boost::format("font_engihe: created %ld faces in ") % (face_count * 1000 * 10)).str());
benchmark(runner, (boost::format("font_engine: created %ld faces in ") % (face_count * 1000 * 10)).str());
}
{
test14 runner(500,10,
"benchmark/data/polygon_rendering_clip.xml",
mapnik::box2d<double>(-20037508.3428,-8317435.0606,20037508.3428,18399242.7298));
benchmark(runner, "rendering polygon with clipping at full extent");
}
{
test14 runner(500,10,
"benchmark/data/polygon_rendering_no_clip.xml",
mapnik::box2d<double>(-20037508.3428,-8317435.0606,20037508.3428,18399242.7298));
benchmark(runner, "rendering polygon without clipping at full extent");
}
{
// note: bbox below is for 16/10491/22911.png
test14 runner(500,10,
"benchmark/data/polygon_rendering_clip.xml",
mapnik::box2d<double>(-13622912.929097254,6026906.8062295765,-13621689.93664469,6028129.79868214));
benchmark(runner, "rendering polygon with clipping at z16 extent");
}
{
test14 runner(500,10,
"benchmark/data/polygon_rendering_no_clip.xml",
mapnik::box2d<double>(-13622912.929097254,6026906.8062295765,-13621689.93664469,6028129.79868214));
benchmark(runner, "rendering polygon without clipping at z16 extent");
}
std::cout << "...benchmark done\n";
return 0;
}

View file

@ -46,20 +46,20 @@ target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.pa
py_env = env.Clone()
py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
py_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
py_env['LIBS'] = ['mapnik',env['BOOST_PYTHON_LIB']]
link_all_libs = env['LINKING'] == 'static' or env['RUNTIME_LINK'] == 'static' or (env['PLATFORM'] == 'Darwin' and not env['PYTHON_DYNAMIC_LOOKUP'])
if link_all_libs:
py_env.AppendUnique(LIBS=env['LIBMAPNIK_LIBS'])
if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
py_env.AppendUnique(LIBS='rt')
# TODO - do solaris/fedora need direct linking too?
if env['PLATFORM'] == 'Darwin':
if not env['PYTHON_DYNAMIC_LOOKUP']:
if env['PNG']:
py_env.AppendUnique(LIBS = 'png')
if env['JPEG']:
py_env.AppendUnique(LIBS = 'jpeg')
py_env.AppendUnique(LIBS = env['ICU_LIB_NAME'])
py_env.AppendUnique(LIBS = 'boost_regex%s' % env['BOOST_APPEND'])
if env['THREADING'] == 'multi':
py_env.AppendUnique(LIBS = 'boost_thread%s' % env['BOOST_APPEND'])
##### Python linking on OS X is tricky ###
# Confounding problems are:
# 1) likelyhood of multiple python installs of the same major.minor version
@ -99,7 +99,6 @@ if env['PLATFORM'] == 'Darwin':
else:
# should we fall back to -lpython here?
python_link_flag = '-F/ -framework Python'
# if we are not linking to a framework then use the *nix standard approach
else:
# TODO - do we need to pass -L/?
@ -118,9 +117,6 @@ if env['CUSTOM_LDFLAGS']:
else:
linkflags = python_link_flag
if env['LINKING'] == 'static':
py_env.AppendUnique(LIBS=env['LIBMAPNIK_LIBS'])
paths = '''
"""Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons)."""
@ -179,7 +175,7 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
if env['HAS_CAIRO']:
py_env.Append(CPPPATH = env['CAIRO_CPPPATHS'])
py_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
if env['PLATFORM'] == 'Darwin':
if link_all_libs:
py_env.Append(LIBS=env['CAIRO_ALL_LIBS'])
if env['HAS_PYCAIRO']:

View file

@ -43,6 +43,10 @@ import itertools
import os
import sys
import warnings
try:
import json
except ImportError:
import simplejson as json
def bootstrap_env():
"""
@ -255,6 +259,12 @@ class _Projection(Projection,_injector):
"""
return inverse_(obj,self)
class _Feature(Feature,_injector):
__geo_interface__ = property(lambda self: json.loads(self.to_geojson()))
class _Path(Path,_injector):
__geo_interface__ = property(lambda self: json.loads(self.to_geojson()))
class _Datasource(Datasource,_injector):
def all_features(self,fields=None):
@ -340,6 +350,53 @@ def Shapefile(**keywords):
keywords['type'] = 'shape'
return CreateDatasource(keywords)
def CSV(**keywords):
"""Create a CSV Datasource.
Required keyword arguments:
file -- path to csv
Optional keyword arguments:
inline -- inline CSV string (if provided 'file' argument will be ignored and non-needed)
base -- path prefix (default None)
encoding -- file encoding (default 'utf-8')
row_limit -- integer limit of rows to return (default: 0)
strict -- throw an error if an invalid row is encountered
escape -- The escape character to use for parsing data
quote -- The quote character to use for parsing data
separator -- The separator character to use for parsing data
headers -- A comma separated list of header names that can be set to add headers to data that lacks them
filesize_max -- The maximum filesize in MB that will be accepted
>>> from mapnik import CSV
>>> csv = CSV(file='test.csv')
>>> from mapnik import CSV
>>> csv = CSV(inline='''wkt,Name\n"POINT (120.15 48.47)","Winthrop, WA"''')
For more information see https://github.com/mapnik/mapnik/wiki/CSV-Plugin
"""
keywords['type'] = 'csv'
return CreateDatasource(keywords)
def GeoJSON(**keywords):
"""Create a GeoJSON Datasource.
Required keyword arguments:
file -- path to json
Optional keyword arguments:
encoding -- file encoding (default 'utf-8')
base -- path prefix (default None)
>>> from mapnik import GeoJSON
>>> geojson = GeoJSON(file='test.json')
"""
keywords['type'] = 'geojson'
return CreateDatasource(keywords)
def PostGIS(**keywords):
"""Create a PostGIS Datasource.

View file

@ -1,52 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2012 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <boost/python.hpp>
#include <mapnik/value.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/building_symbolizer.hpp>
using namespace mapnik;
using mapnik::building_symbolizer;
using mapnik::color;
void export_building_symbolizer()
{
using namespace boost::python;
class_<building_symbolizer>("BuildingSymbolizer",
init<>("Default BuildingSymbolizer"))
.add_property("fill",make_function
(&building_symbolizer::get_fill,
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_fill)
.add_property("fill_opacity",
&building_symbolizer::get_opacity,
&building_symbolizer::set_opacity)
.add_property("height",
make_function(&building_symbolizer::height,
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_height,
"Set/get the building height")
;
}

View file

@ -83,6 +83,7 @@ void export_color ()
.def(self != self)
.def_pickle(color_pickle_suite())
.def("__str__",&color::to_string)
.def("packed",&color::rgba)
.def("to_hex_string",&color::to_hex_string,
"Returns the hexadecimal representation of this color.\n"
"\n"

View file

@ -22,17 +22,13 @@
// boost
#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/noncopyable.hpp>
// stl
#include <sstream>
#include <vector>
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/query.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/feature_layer_desc.hpp>
@ -61,7 +57,11 @@ boost::shared_ptr<mapnik::datasource> create_datasource(dict const& d)
PyObject* temp = PyUnicode_AsUTF8String(obj.ptr());
if (temp)
{
#if PY_VERSION_HEX >= 0x03000000
char* c_str = PyBytes_AsString(temp);
#else
char* c_str = PyString_AsString(temp);
#endif
params[key] = std::string(c_str);
Py_DecRef(temp);
}

View file

@ -22,6 +22,11 @@
#ifndef MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED
#define MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED
#include <boost/python/converter/registered.hpp> // for registered
#include <boost/python/enum.hpp> // for enum_
#include <boost/python/implicit.hpp> // for implicitly_convertible
#include <boost/python/to_python_converter.hpp>
namespace mapnik {
template <typename EnumWrapper>

View file

@ -32,12 +32,19 @@
// mapnik
#include <mapnik/value_types.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/json/feature_parser.hpp>
#include <mapnik/json/geojson_generator.hpp>
#include <mapnik/json/generic_json.hpp>
// stl
#include <stdexcept>
namespace {
@ -47,12 +54,13 @@ using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;
mapnik::geometry_type const& (mapnik::feature_impl::*get_geometry_by_const_ref)(unsigned) const = &mapnik::feature_impl::get_geometry;
mapnik::geometry_type const& (mapnik::feature_impl::*get_geometry_by_const_ref)(std::size_t) const = &mapnik::feature_impl::get_geometry;
boost::ptr_vector<mapnik::geometry_type> const& (mapnik::feature_impl::*get_paths_by_const_ref)() const = &mapnik::feature_impl::paths;
void feature_add_geometries_from_wkb(mapnik::feature_impl &feature, std::string wkb)
{
geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
bool result = geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
if (!result) throw std::runtime_error("Failed to parse WKB");
}
void feature_add_geometries_from_wkt(mapnik::feature_impl &feature, std::string wkt)
@ -61,6 +69,19 @@ void feature_add_geometries_from_wkt(mapnik::feature_impl &feature, std::string
if (!result) throw std::runtime_error("Failed to parse WKT");
}
mapnik::feature_ptr from_geojson_impl(std::string const& json, mapnik::context_ptr const& ctx)
{
mapnik::transcoder tr("utf8");
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
mapnik::json::generic_json<std::string::const_iterator> json_base;
mapnik::json::feature_parser<std::string::const_iterator> parser(json_base, tr);
if (!parser.parse(json.begin(), json.end(), *feature))
{
throw std::runtime_error("Failed to parse geojson feature");
}
return feature;
}
std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
std::string json;
@ -103,14 +124,14 @@ boost::python::dict attributes(mapnik::feature_impl const& f)
} // end anonymous namespace
struct UnicodeString_from_python_str
struct unicode_string_from_python_str
{
UnicodeString_from_python_str()
unicode_string_from_python_str()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<UnicodeString>());
boost::python::type_id<mapnik::value_unicode_string>());
}
static void* convertible(PyObject* obj_ptr)
@ -150,9 +171,9 @@ struct UnicodeString_from_python_str
}
if (value == 0) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage<UnicodeString>*)
(boost::python::converter::rvalue_from_python_storage<mapnik::value_unicode_string>*)
data)->storage.bytes;
new (storage) UnicodeString(value);
new (storage) mapnik::value_unicode_string(value);
data->convertible = storage;
}
};
@ -201,7 +222,7 @@ void export_feature()
implicitly_convertible<mapnik::value_bool,mapnik::value>();
// http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
UnicodeString_from_python_str();
unicode_string_from_python_str();
value_null_from_python();
class_<context_type,context_ptr,boost::noncopyable>
@ -229,5 +250,7 @@ void export_feature()
.def("__len__", &mapnik::feature_impl::size)
.def("context",&mapnik::feature_impl::context)
.def("to_geojson",&feature_to_geojson)
.def("from_geojson",from_geojson_impl)
.staticmethod("from_geojson")
;
}

View file

@ -43,6 +43,9 @@
#include <mapnik/util/geometry_to_svg.hpp>
#endif
// stl
#include <stdexcept>
namespace {
using mapnik::from_wkt;

View file

@ -20,6 +20,8 @@
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
@ -80,3 +82,5 @@ void export_grid()
;
}
#endif

View file

@ -20,6 +20,8 @@
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
@ -49,3 +51,5 @@ void export_grid_view()
)
;
}
#endif

View file

@ -37,6 +37,7 @@
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <mapnik/cairo_context.hpp>
#include <pycairo.h>
#include <cairo.h>
#endif
using mapnik::image_32;
@ -207,7 +208,7 @@ void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, fl
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
boost::shared_ptr<image_32> from_cairo(PycairoSurface* py_surface)
{
mapnik::cairo_surface_ptr surface(py_surface->surface, mapnik::cairo_surface_closer());
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(surface);
return image_ptr;
}
@ -272,6 +273,7 @@ void export_image()
arg("mode")=mapnik::src_over,
arg("opacity")=1.0f
))
.def("premultiplied",&image_32::premultiplied)
.def("premultiply",&image_32::premultiply)
.def("demultiply",&image_32::demultiply)
.def("set_pixel",&set_pixel)

View file

@ -22,7 +22,6 @@
// boost
#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
// mapnik

View file

@ -1,78 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <boost/python.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/image_util.hpp>
#include "mapnik_svg.hpp"
using mapnik::line_pattern_symbolizer;
using mapnik::path_processor_type;
using mapnik::path_expression_ptr;
using mapnik::guess_type;
using mapnik::parse_path;
namespace {
using namespace boost::python;
std::string get_filename(line_pattern_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(line_pattern_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
void export_line_pattern_symbolizer()
{
using namespace boost::python;
class_<line_pattern_symbolizer>("LinePatternSymbolizer",
init<path_expression_ptr>
("<image file expression>"))
.add_property("transform",
mapnik::get_svg_transform<line_pattern_symbolizer>,
mapnik::set_svg_transform<line_pattern_symbolizer>)
.add_property("filename",
&get_filename,
&set_filename)
.add_property("comp_op",
&line_pattern_symbolizer::comp_op,
&line_pattern_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&line_pattern_symbolizer::clip,
&line_pattern_symbolizer::set_clip,
"Set/get the line pattern geometry's clipping status")
.add_property("smooth",
&line_pattern_symbolizer::smooth,
&line_pattern_symbolizer::set_smooth,
"smooth value (0..1.0)")
;
}

View file

@ -1,80 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <boost/python.hpp>
#include "mapnik_enumeration.hpp"
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/symbolizer_hash.hpp>
using namespace mapnik;
using mapnik::line_symbolizer;
using mapnik::stroke;
using mapnik::color;
std::size_t line_symbolizer_hash(line_symbolizer const& sym)
{
return symbolizer_hash::value(sym);
}
void export_line_symbolizer()
{
using namespace boost::python;
enumeration_<line_rasterizer_e>("line_rasterizer")
.value("FULL",RASTERIZER_FULL)
.value("FAST",RASTERIZER_FAST)
;
class_<line_symbolizer>("LineSymbolizer",
init<>("Default LineSymbolizer - 1px solid black"))
.def(init<stroke const&>("TODO"))
.def(init<color const& ,float>())
.add_property("rasterizer",
&line_symbolizer::get_rasterizer,
&line_symbolizer::set_rasterizer,
"Set/get the rasterization method of the line of the point")
.add_property("stroke",make_function
(&line_symbolizer::get_stroke,
return_value_policy<reference_existing_object>()),
&line_symbolizer::set_stroke)
.add_property("simplify_tolerance",
&line_symbolizer::simplify_tolerance,
&line_symbolizer::set_simplify_tolerance,
"simplification tolerance measure")
.add_property("offset",
&line_symbolizer::offset,
&line_symbolizer::set_offset,
"offset value")
.add_property("comp_op",
&line_symbolizer::comp_op,
&line_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&line_symbolizer::clip,
&line_symbolizer::set_clip,
"Set/get the line geometry's clipping status")
.add_property("smooth",
&line_symbolizer::smooth,
&line_symbolizer::set_smooth,
"smooth value (0..1.0)")
.def("__hash__", line_symbolizer_hash)
;
}

View file

@ -22,7 +22,6 @@
// boost
#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
@ -34,7 +33,6 @@
#include <mapnik/projection.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/feature_type_style.hpp>
//#include <mapnik/util/deepcopy.hpp>
#include "mapnik_enumeration.hpp"
using mapnik::color;
@ -91,17 +89,6 @@ mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x
return m.query_map_point(idx, x, y);
}
// deepcopy
/*
mapnik::Map map_deepcopy(mapnik::Map & m, boost::python::dict memo)
{
// FIXME: ignore memo for now
mapnik::Map result;
mapnik::util::deepcopy(m, result);
return result;
}
*/
void set_maximum_extent(mapnik::Map & m, boost::optional<mapnik::box2d<double> > const& box)
{
if (box)
@ -382,7 +369,6 @@ void export_map()
">>> m.zoom_to_box(extent)\n"
)
//.def("__deepcopy__",&map_deepcopy)
.add_property("parameters",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("aspect_fix_mode",
@ -423,6 +409,22 @@ void export_map()
">>> m.background_image = '/path/to/image.png'\n"
)
.add_property("background_image_comp_op",&Map::background_image_comp_op,
&Map::set_background_image_comp_op,
"The background image compositing operation.\n"
"\n"
"Usage:\n"
">>> m.background_image_comp_op = mapnik.CompositeOp.src_over\n"
)
.add_property("background_image_opacity",&Map::background_image_opacity,
&Map::set_background_image_opacity,
"The background image opacity.\n"
"\n"
"Usage:\n"
">>> m.background_image_opacity = 1.0\n"
)
.add_property("base",
make_function(&Map::base_path,return_value_policy<copy_const_reference>()),
&Map::set_base_path,

View file

@ -1,162 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 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 <boost/python.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/parse_path.hpp>
#include "mapnik_svg.hpp"
#include "mapnik_enumeration.hpp"
#include "python_optional.hpp"
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_
using mapnik::markers_symbolizer;
using mapnik::symbolizer_with_image;
using mapnik::path_processor_type;
using mapnik::parse_path;
namespace {
using namespace boost::python;
std::string get_filename(mapnik::markers_symbolizer const& symbolizer)
{
return path_processor_type::to_string(*symbolizer.get_filename());
}
void set_filename(mapnik::markers_symbolizer & symbolizer, std::string const& file_expr)
{
symbolizer.set_filename(parse_path(file_expr));
}
void set_marker_type(mapnik::markers_symbolizer & symbolizer, std::string const& marker_type)
{
std::string filename;
if (marker_type == "ellipse")
{
filename = mapnik::marker_cache::instance().known_svg_prefix_ + "ellipse";
}
else if (marker_type == "arrow")
{
filename = mapnik::marker_cache::instance().known_svg_prefix_ + "arrow";
}
else
{
throw mapnik::value_error("Unknown marker-type: '" + marker_type + "'");
}
symbolizer.set_filename(parse_path(filename));
}
}
void export_markers_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::marker_placement_e>("marker_placement")
.value("POINT_PLACEMENT",mapnik::MARKER_POINT_PLACEMENT)
.value("INTERIOR_PLACEMENT",mapnik::MARKER_INTERIOR_PLACEMENT)
.value("LINE_PLACEMENT",mapnik::MARKER_LINE_PLACEMENT)
;
mapnik::enumeration_<mapnik::marker_multi_policy_e>("marker_multi_policy")
.value("EACH",mapnik::MARKER_EACH_MULTI)
.value("WHOLE",mapnik::MARKER_WHOLE_MULTI)
.value("LARGEST",mapnik::MARKER_LARGEST_MULTI)
;
class_<markers_symbolizer>("MarkersSymbolizer",
init<>("Default Markers Symbolizer - circle"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
.add_property("filename",
&get_filename,
&set_filename)
.add_property("marker_type",
&get_filename,
&set_marker_type)
.add_property("allow_overlap",
&markers_symbolizer::get_allow_overlap,
&markers_symbolizer::set_allow_overlap)
.add_property("spacing",
&markers_symbolizer::get_spacing,
&markers_symbolizer::set_spacing)
.add_property("max_error",
&markers_symbolizer::get_max_error,
&markers_symbolizer::set_max_error)
.add_property("opacity",
&markers_symbolizer::get_opacity,
&markers_symbolizer::set_opacity,
"Set/get the overall opacity")
.add_property("fill_opacity",
&markers_symbolizer::get_fill_opacity,
&markers_symbolizer::set_fill_opacity,
"Set/get the fill opacity")
.add_property("ignore_placement",
&markers_symbolizer::get_ignore_placement,
&markers_symbolizer::set_ignore_placement)
.add_property("transform",
&mapnik::get_svg_transform<markers_symbolizer>,
&mapnik::set_svg_transform<markers_symbolizer>)
.add_property("width",
make_function(&markers_symbolizer::get_width,
return_value_policy<copy_const_reference>()),
&markers_symbolizer::set_width,
"Set/get the marker width")
.add_property("height",
make_function(&markers_symbolizer::get_height,
return_value_policy<copy_const_reference>()),
&markers_symbolizer::set_height,
"Set/get the marker height")
.add_property("fill",
&markers_symbolizer::get_fill,
&markers_symbolizer::set_fill,
"Set/get the marker fill color")
.add_property("stroke",
&markers_symbolizer::get_stroke,
&markers_symbolizer::set_stroke,
"Set/get the marker stroke (outline)")
.add_property("placement",
&markers_symbolizer::get_marker_placement,
&markers_symbolizer::set_marker_placement,
"Set/get the marker placement")
.add_property("multi_policy",
&markers_symbolizer::get_marker_multi_policy,
&markers_symbolizer::set_marker_multi_policy,
"Set/get the marker multi geometry rendering policy")
.add_property("comp_op",
&markers_symbolizer::comp_op,
&markers_symbolizer::set_comp_op,
"Set/get the marker comp-op")
.add_property("clip",
&markers_symbolizer::clip,
&markers_symbolizer::set_clip,
"Set/get the marker geometry's clipping status")
.add_property("smooth",
&markers_symbolizer::smooth,
&markers_symbolizer::set_smooth,
"Set/get the marker geometry's smooth value")
;
}

View file

@ -28,6 +28,9 @@
//mapnik
#include <mapnik/palette.hpp>
// stl
#include <stdexcept>
static boost::shared_ptr<mapnik::rgba_palette> make_palette( std::string const& palette, std::string const& format )
{
mapnik::rgba_palette::palette_type type = mapnik::rgba_palette::PALETTE_RGBA;

View file

@ -28,6 +28,7 @@
#include <mapnik/debug.hpp>
#include <mapnik/params.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>
// stl
#include <iterator>
@ -82,7 +83,7 @@ struct parameters_pickle_suite : boost::python::pickle_suite
extract<std::string> ex0(obj);
extract<mapnik::value_integer> ex1(obj);
extract<double> ex2(obj);
extract<UnicodeString> ex3(obj);
extract<mapnik::value_unicode_string> ex3(obj);
// TODO - this is never hit - we need proper python string -> std::string to get invoked here
if (ex0.check())
@ -175,7 +176,7 @@ mapnik::value_holder get_param(mapnik::parameter const& p, int index)
}
}
boost::shared_ptr<mapnik::parameter> create_parameter(UnicodeString const& key, mapnik::value_holder const& value)
boost::shared_ptr<mapnik::parameter> create_parameter(mapnik::value_unicode_string const& key, mapnik::value_holder const& value)
{
std::string key_utf8;
mapnik::to_utf8(key, key_utf8);
@ -184,7 +185,7 @@ boost::shared_ptr<mapnik::parameter> create_parameter(UnicodeString const& key,
// needed for Python_Unicode to std::string (utf8) conversion
boost::shared_ptr<mapnik::parameter> create_parameter_from_string(UnicodeString const& key, UnicodeString const& ustr)
boost::shared_ptr<mapnik::parameter> create_parameter_from_string(mapnik::value_unicode_string const& key, mapnik::value_unicode_string const& ustr)
{
std::string key_utf8;
std::string ustr_utf8;

View file

@ -1,89 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <boost/python.hpp>
#include "mapnik_enumeration.hpp"
#include <mapnik/graphics.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/parse_path.hpp>
#include "mapnik_svg.hpp"
using namespace mapnik;
using mapnik::point_symbolizer;
using mapnik::symbolizer_with_image;
using mapnik::path_processor_type;
using mapnik::parse_path;
namespace {
using namespace boost::python;
std::string get_filename(point_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(point_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
void export_point_symbolizer()
{
using namespace boost::python;
enumeration_<point_placement_e>("point_placement")
.value("CENTROID",CENTROID_POINT_PLACEMENT)
.value("INTERIOR",INTERIOR_POINT_PLACEMENT)
;
class_<point_symbolizer>("PointSymbolizer",
init<>("Default Point Symbolizer - 4x4 black square"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
.add_property("filename",
&get_filename,
&set_filename)
.add_property("allow_overlap",
&point_symbolizer::get_allow_overlap,
&point_symbolizer::set_allow_overlap)
.add_property("opacity",
&point_symbolizer::get_opacity,
&point_symbolizer::set_opacity)
.add_property("ignore_placement",
&point_symbolizer::get_ignore_placement,
&point_symbolizer::set_ignore_placement)
.add_property("placement",
&point_symbolizer::get_point_placement,
&point_symbolizer::set_point_placement,
"Set/get the placement of the point")
.add_property("transform",
mapnik::get_svg_transform<point_symbolizer>,
mapnik::set_svg_transform<point_symbolizer>)
.add_property("comp_op",
&point_symbolizer::comp_op,
&point_symbolizer::set_comp_op,
"Set/get the comp-op")
;
}

View file

@ -1,96 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <boost/python.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include "mapnik_enumeration.hpp"
#include <mapnik/parse_path.hpp>
#include "mapnik_svg.hpp"
using namespace mapnik;
using mapnik::polygon_pattern_symbolizer;
using mapnik::path_expression_ptr;
using mapnik::path_processor_type;
using mapnik::parse_path;
using mapnik::guess_type;
namespace {
using namespace boost::python;
std::string get_filename(polygon_pattern_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(polygon_pattern_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
void export_polygon_pattern_symbolizer()
{
using namespace boost::python;
enumeration_<pattern_alignment_e>("pattern_alignment")
.value("LOCAL",LOCAL_ALIGNMENT)
.value("GLOBAL",GLOBAL_ALIGNMENT)
;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<path_expression_ptr>("<path_expression_ptr>"))
.add_property("alignment",
&polygon_pattern_symbolizer::get_alignment,
&polygon_pattern_symbolizer::set_alignment,
"Set/get the alignment of the pattern")
.add_property("transform",
mapnik::get_svg_transform<polygon_pattern_symbolizer>,
mapnik::set_svg_transform<polygon_pattern_symbolizer>)
.add_property("filename",
&get_filename,
&set_filename)
.add_property("opacity",
&polygon_pattern_symbolizer::get_opacity,
&polygon_pattern_symbolizer::set_opacity)
.add_property("gamma",
&polygon_pattern_symbolizer::get_gamma,
&polygon_pattern_symbolizer::set_gamma)
.add_property("gamma_method",
&polygon_pattern_symbolizer::get_gamma_method,
&polygon_pattern_symbolizer::set_gamma_method,
"Set/get the gamma correction method of the polygon")
.add_property("comp_op",
&polygon_pattern_symbolizer::comp_op,
&polygon_pattern_symbolizer::set_comp_op,
"Set/get the pattern comp-op")
.add_property("clip",
&polygon_pattern_symbolizer::clip,
&polygon_pattern_symbolizer::set_clip,
"Set/get the pattern geometry's clipping status")
.add_property("smooth",
&polygon_pattern_symbolizer::smooth,
&polygon_pattern_symbolizer::set_smooth,
"Set/get the pattern geometry's smooth value")
;
}

View file

@ -1,76 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <boost/python.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/symbolizer_hash.hpp>
using namespace mapnik;
using mapnik::polygon_symbolizer;
using mapnik::color;
std::size_t polygon_symbolizer_hash(polygon_symbolizer const& sym)
{
return symbolizer_hash::value(sym);
}
void export_polygon_symbolizer()
{
using namespace boost::python;
class_<polygon_symbolizer>("PolygonSymbolizer",
init<>("Default PolygonSymbolizer - solid fill grey"))
.def(init<color const&>("TODO"))
.add_property("fill",make_function
(&polygon_symbolizer::get_fill,
return_value_policy<copy_const_reference>()),
&polygon_symbolizer::set_fill)
.add_property("fill_opacity",
&polygon_symbolizer::get_opacity,
&polygon_symbolizer::set_opacity)
.add_property("gamma",
&polygon_symbolizer::get_gamma,
&polygon_symbolizer::set_gamma)
.add_property("gamma_method",
&polygon_symbolizer::get_gamma_method,
&polygon_symbolizer::set_gamma_method,
"gamma correction method")
.add_property("comp_op",
&polygon_symbolizer::comp_op,
&polygon_symbolizer::set_comp_op,
"Set/get the polygon comp-op")
.add_property("clip",
&polygon_symbolizer::clip,
&polygon_symbolizer::set_clip,
"Set/get the polygon geometry's clipping status")
.add_property("smooth",
&polygon_symbolizer::smooth,
&polygon_symbolizer::set_smooth,
"Set/get the polygon geometry's smooth value")
.add_property("simplify_tolerance",
&polygon_symbolizer::simplify_tolerance,
&polygon_symbolizer::set_simplify_tolerance,
"simplfication tolerance measure")
.def("__hash__", polygon_symbolizer_hash)
;
}

View file

@ -27,6 +27,10 @@
// boost
#include <boost/python.hpp>
// stl
#include <stdexcept>
using mapnik::proj_transform;
using mapnik::projection;

View file

@ -20,12 +20,22 @@
*
*****************************************************************************/
#include <boost/python.hpp>
#include <boost/get_pointer.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/args.hpp> // for keywords, arg, etc
#include <boost/python/converter/from_python.hpp>
#include <boost/python/def.hpp> // for def
#include <boost/python/detail/defaults_gen.hpp>
#include <boost/python/detail/none.hpp> // for none
#include <boost/python/dict.hpp> // for dict
#include <boost/python/exception_translator.hpp>
#include <boost/python/list.hpp> // for list
#include <boost/python/module.hpp> // for BOOST_PYTHON_MODULE
#include <boost/python/object_core.hpp> // for get_managed_object
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/to_python_converter.hpp>
// stl
#include <stdexcept>
void register_cairo();
void export_color();
void export_coord();
void export_layer();
@ -38,8 +48,10 @@ void export_image();
void export_image_view();
void export_gamma_method();
void export_scaling_method();
#if defined(GRID_RENDERER)
void export_grid();
void export_grid_view();
#endif
void export_map();
void export_python();
void export_expression();
@ -70,42 +82,87 @@ void export_view_transform();
void export_raster_colorizer();
void export_label_collision_detector();
void export_logger();
void export_wkt_reader();
#include <mapnik/version.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/agg_renderer.hpp>
#ifdef HAVE_CAIRO
#include <mapnik/cairo_renderer.hpp>
#endif
#include <mapnik/graphics.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/scale_denominator.hpp>
#if defined(GRID_RENDERER)
#include "python_grid_utils.hpp"
#endif
#include "mapnik_value_converter.hpp"
#include "mapnik_threads.hpp"
#include "python_optional.hpp"
#include <mapnik/marker_cache.hpp>
#if defined(SHAPE_MEMORY_MAPPED_FILE)
#include <mapnik/mapped_memory_cache.hpp>
#endif
namespace mapnik {
class font_set;
class stroke;
class layer;
class color;
class label_collision_detector4;
}
void clear_cache()
{
mapnik::marker_cache::instance().clear();
#if defined(SHAPE_MEMORY_MAPPED_FILE)
mapnik::mapped_memory_cache::instance().clear();
#endif
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <mapnik/cairo_renderer.hpp>
#include <boost/python/type_id.hpp>
#include <boost/python/converter/registry.hpp>
#include <pycairo.h>
#include <cairo.h>
static Pycairo_CAPI_t *Pycairo_CAPI;
static void *extract_surface(PyObject* op)
{
if (PyObject_TypeCheck(op, const_cast<PyTypeObject*>(Pycairo_CAPI->Surface_Type)))
{
return op;
}
else
{
return 0;
}
}
static void *extract_context(PyObject* op)
{
if (PyObject_TypeCheck(op, const_cast<PyTypeObject*>(Pycairo_CAPI->Context_Type)))
{
return op;
}
else
{
return 0;
}
}
void register_cairo()
{
#if PY_MAJOR_VERSION >= 3
Pycairo_CAPI = (Pycairo_CAPI_t*) PyCapsule_Import(const_cast<char *>("cairo.CAPI"), 0);
#else
Pycairo_CAPI = (Pycairo_CAPI_t*) PyCObject_Import(const_cast<char *>("cairo"), const_cast<char *>("CAPI"));
#endif
if (Pycairo_CAPI == NULL) return;
boost::python::converter::registry::insert(&extract_surface, boost::python::type_id<PycairoSurface>());
boost::python::converter::registry::insert(&extract_context, boost::python::type_id<PycairoContext>());
}
#endif
using mapnik::python_thread;
@ -115,7 +172,7 @@ bool python_thread::thread_support = true;
#endif
boost::thread_specific_ptr<PyThreadState> python_thread::state;
void render(const mapnik::Map& map,
void render(mapnik::Map const& map,
mapnik::image_32& image,
double scale_factor = 1.0,
unsigned offset_x = 0u,
@ -128,7 +185,7 @@ void render(const mapnik::Map& map,
}
void render_with_detector(
const mapnik::Map &map,
mapnik::Map const& map,
mapnik::image_32 &image,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
@ -136,11 +193,11 @@ void render_with_detector(
unsigned offset_y = 0u)
{
python_unblock_auto_block b;
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector);
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector,scale_factor,offset_x,offset_y);
ren.apply();
}
void render_layer2(const mapnik::Map& map,
void render_layer2(mapnik::Map const& map,
mapnik::image_32& image,
unsigned layer_idx)
{
@ -162,7 +219,7 @@ void render_layer2(const mapnik::Map& map,
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
void render3(const mapnik::Map& map,
void render3(mapnik::Map const& map,
PycairoSurface* py_surface,
double scale_factor = 1.0,
unsigned offset_x = 0,
@ -174,7 +231,7 @@ void render3(const mapnik::Map& map,
ren.apply();
}
void render4(const mapnik::Map& map, PycairoSurface* py_surface)
void render4(mapnik::Map const& map, PycairoSurface* py_surface)
{
python_unblock_auto_block b;
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
@ -182,39 +239,39 @@ void render4(const mapnik::Map& map, PycairoSurface* py_surface)
ren.apply();
}
void render5(const mapnik::Map& map,
void render5(mapnik::Map const& map,
PycairoContext* py_context,
double scale_factor = 1.0,
unsigned offset_x = 0,
unsigned offset_y = 0)
{
python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_ptr context(cairo_reference(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* py_context)
void render6(mapnik::Map const& map, PycairoContext* py_context)
{
python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_ptr context(cairo_reference(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,
mapnik::Map const& map,
PycairoContext* py_context,
boost::shared_ptr<mapnik::label_collision_detector4> detector)
{
python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_ptr context(cairo_reference(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,
mapnik::Map const& map,
PycairoContext* py_context,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
@ -222,13 +279,13 @@ void render_with_detector3(
unsigned offset_y = 0u)
{
python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_ptr context(cairo_reference(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,
mapnik::Map const& map,
PycairoSurface* py_surface,
boost::shared_ptr<mapnik::label_collision_detector4> detector)
{
@ -239,7 +296,7 @@ void render_with_detector4(
}
void render_with_detector5(
const mapnik::Map& map,
mapnik::Map const& map,
PycairoSurface* py_surface,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
@ -255,7 +312,7 @@ void render_with_detector5(
#endif
void render_tile_to_file(const mapnik::Map& map,
void render_tile_to_file(mapnik::Map const& map,
unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height,
std::string const& file,
@ -266,7 +323,7 @@ void render_tile_to_file(const mapnik::Map& map,
mapnik::save_to_file(image.data(),file,format);
}
void render_to_file1(const mapnik::Map& map,
void render_to_file1(mapnik::Map const& map,
std::string const& filename,
std::string const& format)
{
@ -286,7 +343,7 @@ void render_to_file1(const mapnik::Map& map,
}
}
void render_to_file2(const mapnik::Map& map,std::string const& filename)
void render_to_file2(mapnik::Map const& map,std::string const& filename)
{
std::string format = mapnik::guess_type(filename);
if (format == "pdf" || format == "svg" || format =="ps")
@ -305,7 +362,7 @@ void render_to_file2(const mapnik::Map& map,std::string const& filename)
}
}
void render_to_file3(const mapnik::Map& map,
void render_to_file3(mapnik::Map const& map,
std::string const& filename,
std::string const& format,
double scale_factor = 1.0
@ -327,7 +384,7 @@ void render_to_file3(const mapnik::Map& map,
}
}
double scale_denominator(mapnik::Map const &map, bool geographic)
double scale_denominator(mapnik::Map const& map, bool geographic)
{
return mapnik::scale_denominator(map.scale(), geographic);
}
@ -363,7 +420,33 @@ std::string mapnik_version_string()
return MAPNIK_VERSION_STRING;
}
// indicator for jpeg read/write support within libmapnik
bool has_proj4()
{
#if defined(MAPNIK_USE_PROJ4)
return true;
#else
return false;
#endif
}
bool has_svg_renderer()
{
#if defined(SVG_RENDERER)
return true;
#else
return false;
#endif
}
bool has_grid_renderer()
{
#if defined(GRID_RENDERER)
return true;
#else
return false;
#endif
}
bool has_jpeg()
{
#if defined(HAVE_JPEG)
@ -373,6 +456,33 @@ bool has_jpeg()
#endif
}
bool has_png()
{
#if defined(HAVE_PNG)
return true;
#else
return false;
#endif
}
bool has_tiff()
{
#if defined(HAVE_TIFF)
return true;
#else
return false;
#endif
}
bool has_webp()
{
#if defined(HAVE_WEBP)
return true;
#else
return false;
#endif
}
// indicator for cairo rendering support inside libmapnik
bool has_cairo()
{
@ -408,7 +518,7 @@ bool has_pycairo()
}
BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_overloads, load_map, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_overloads, load_map, 2, 4)
BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_string_overloads, load_map_string, 2, 4)
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_overloads, save_map, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_to_string_overloads, save_map_to_string, 1, 2)
@ -424,13 +534,14 @@ BOOST_PYTHON_MODULE(_mapnik)
using mapnik::load_map_string;
using mapnik::save_map;
using mapnik::save_map_to_string;
using mapnik::render_grid;
register_exception_translator<std::exception>(&standard_error_translator);
register_exception_translator<std::out_of_range>(&out_of_range_error_translator);
register_exception_translator<mapnik::value_error>(&value_error_translator);
register_exception_translator<std::runtime_error>(&runtime_error_translator);
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
register_cairo();
#endif
export_query();
export_geometry();
export_feature();
@ -445,8 +556,10 @@ BOOST_PYTHON_MODULE(_mapnik)
export_image_view();
export_gamma_method();
export_scaling_method();
#if defined(GRID_RENDERER)
export_grid();
export_grid_view();
#endif
export_expression();
export_rule();
export_style();
@ -474,6 +587,7 @@ BOOST_PYTHON_MODULE(_mapnik)
export_raster_colorizer();
export_label_collision_detector();
export_logger();
export_wkt_reader();
def("clear_cache", &clear_cache,
"\n"
@ -484,7 +598,8 @@ BOOST_PYTHON_MODULE(_mapnik)
">>> clear_cache()\n"
);
def("render_grid",&render_grid,
#if defined(GRID_RENDERER)
def("render_grid",&mapnik::render_grid,
( arg("map"),
arg("layer"),
args("key")="__id__",
@ -492,6 +607,7 @@ BOOST_PYTHON_MODULE(_mapnik)
arg("fields")=boost::python::list()
)
);
#endif
def("render_to_file",&render_to_file1,
"\n"
@ -576,9 +692,11 @@ BOOST_PYTHON_MODULE(_mapnik)
(arg("map"),arg("image"),args("layer"))
);
#if defined(GRID_RENDERER)
def("render_layer", &mapnik::render_layer_for_grid,
(arg("map"),arg("grid"),args("layer"),arg("fields")=boost::python::list())
);
#endif
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
def("render",&render3,
@ -736,7 +854,13 @@ BOOST_PYTHON_MODULE(_mapnik)
def("save_map_to_string", &save_map_to_string, save_map_to_string_overloads());
def("mapnik_version", &mapnik_version,"Get the Mapnik version number");
def("mapnik_version_string", &mapnik_version_string,"Get the Mapnik version string");
def("has_proj4", &has_proj4, "Get proj4 status");
def("has_jpeg", &has_jpeg, "Get jpeg read/write support status");
def("has_png", &has_png, "Get png read/write support status");
def("has_tiff", &has_tiff, "Get tiff read/write support status");
def("has_webp", &has_webp, "Get webp read/write support status");
def("has_svg_renderer", &has_svg_renderer, "Get svg_renderer status");
def("has_grid_renderer", &has_grid_renderer, "Get grid_renderer status");
def("has_cairo", &has_cairo, "Get cairo library status");
def("has_pycairo", &has_pycairo, "Get pycairo module status");

View file

@ -60,6 +60,15 @@ void add_stop5(raster_colorizer_ptr &rc, float v, colorizer_mode_enum m, color c
colorizer_stop stop(v, m, c);
rc->add_stop(stop);
}
mapnik::color get_color(raster_colorizer_ptr &rc, float value) {
unsigned rgba = rc->get_color(value);
unsigned r = (rgba & 0xff);
unsigned g = (rgba >> 8 ) & 0xff;
unsigned b = (rgba >> 16) & 0xff;
unsigned a = (rgba >> 24) & 0xff;
return mapnik::color(r,g,b,a);
}
colorizer_stops const& get_stops(raster_colorizer_ptr & rc)
{
return rc->get_stops();
@ -142,7 +151,7 @@ void export_raster_colorizer()
">>> colorizer = mapnik.RasterColorizer(mapnik.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.COLORIZER_DISCRETE, mapnik.Color(\"#112233\"))\n"
)
.def("get_color", &raster_colorizer::get_color,
.def("get_color", get_color,
"Get the color assigned to a certain value in raster data.\n"
"\n"
"Usage:\n"

View file

@ -1,136 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
// mapnik
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/image_scaling.hpp>
using mapnik::raster_symbolizer;
void export_raster_symbolizer()
{
using namespace boost::python;
class_<raster_symbolizer>("RasterSymbolizer",
init<>("Default ctor"))
.add_property("mode",
make_function(&raster_symbolizer::get_mode,return_value_policy<copy_const_reference>()),
&raster_symbolizer::set_mode,
"Get/Set merging mode. (deprecated, use comp_op instead)\n"
)
.add_property("comp_op",
&raster_symbolizer::comp_op,
&raster_symbolizer::set_comp_op,
"Set/get the raster comp-op"
)
.add_property("scaling",
&raster_symbolizer::get_scaling_method,
&raster_symbolizer::set_scaling_method,
"Get/Set scaling algorithm.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.scaling = 'mapnik.scaling_method.GAUSSIAN'\n"
)
.add_property("opacity",
&raster_symbolizer::get_opacity,
&raster_symbolizer::set_opacity,
"Get/Set opacity.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.opacity = .5\n"
)
.add_property("colorizer",
&raster_symbolizer::get_colorizer,
&raster_symbolizer::set_colorizer,
"Get/Set the RasterColorizer used to color data rasters.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer, RasterColorizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.colorizer = RasterColorizer()\n"
">>> for value, color in [\n"
"... (0, \"#000000\"),\n"
"... (10, \"#ff0000\"),\n"
"... (40, \"#00ff00\"),\n"
"... ]:\n"
"... r.colorizer.append_band(value, color)\n"
)
.add_property("filter_factor",
&raster_symbolizer::get_filter_factor,
&raster_symbolizer::set_filter_factor,
"Get/Set the filter factor used by the datasource.\n"
"\n"
"This is used by the Raster or Gdal datasources to pre-downscale\n"
"images using overviews.\n"
"Higher numbers can sometimes cause much better scaled image\n"
"output, at the cost of speed.\n"
"\n"
"Examples:\n"
" -1.0 : (Default) A suitable value will be determined from the\n"
" chosen scaling method during rendering.\n"
" 1.0 : The datasource will take care of all the scaling\n"
" (using nearest neighbor interpolation)\n"
" 2.0 : The datasource will scale the datasource to\n"
" 2.0x the desired size, and mapnik will scale the rest\n"
" of the way using the interpolation defined in self.scaling.\n"
)
.add_property("mesh_size",
&raster_symbolizer::get_mesh_size,
&raster_symbolizer::set_mesh_size,
"Get/Set warping mesh size.\n"
"Larger values result in faster warping times but might "
"result in distorted maps.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.mesh_size = 32\n"
)
.add_property("premultiplied",
&raster_symbolizer::premultiplied,
&raster_symbolizer::set_premultiplied,
"Get/Set premultiplied status of the source image.\n"
"Can be used to override what the source data reports (when in error)\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.premultiplied = False\n"
)
;
}

View file

@ -23,7 +23,6 @@
// boost
#include <boost/python.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
// mapnik

View file

@ -23,7 +23,6 @@
#include <boost/python.hpp>
#include <mapnik/image_scaling.hpp>
#include "mapnik_enumeration.hpp"
void export_scaling_method()
{

View file

@ -1,218 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
* Copyright (C) 2006 10East Corp.
*
* 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
*
*****************************************************************************/
/* The functions in this file produce deprecation warnings.
* But as shield symbolizer doesn't fully support more than one
* placement from python yet these functions are actually the
* correct ones.
*/
#define NO_DEPRECATION_WARNINGS
// boost
#include <boost/python.hpp>
// mapnik
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/path_expression.hpp>
#include "mapnik_svg.hpp"
using mapnik::color;
using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::symbolizer_with_image;
using mapnik::path_processor_type;
using mapnik::path_expression_ptr;
using mapnik::guess_type;
using mapnik::expression_ptr;
using mapnik::parse_path;
using mapnik::position;
namespace {
using namespace boost::python;
tuple get_shield_displacement(const shield_symbolizer& s)
{
position const& pos = s.get_shield_displacement();
return boost::python::make_tuple(pos.first, pos.second);
}
void set_shield_displacement(shield_symbolizer & s, boost::python::tuple arg)
{
s.get_placement_options()->defaults.displacement.first = extract<double>(arg[0]);
s.get_placement_options()->defaults.displacement.second = extract<double>(arg[1]);
}
tuple get_text_displacement(const shield_symbolizer& t)
{
position const& pos = t.get_placement_options()->defaults.displacement;
return boost::python::make_tuple(pos.first, pos.second);
}
void set_text_displacement(shield_symbolizer & t, boost::python::tuple arg)
{
t.set_displacement(extract<double>(arg[0]),extract<double>(arg[1]));
}
std::string get_filename(shield_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(shield_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
void export_shield_symbolizer()
{
using namespace boost::python;
class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer",
init<expression_ptr,
std::string const&,
unsigned, mapnik::color const&,
path_expression_ptr>()
)
.add_property("allow_overlap",
&shield_symbolizer::get_allow_overlap,
&shield_symbolizer::set_allow_overlap,
"Set/get the allow_overlap property of the label")
.add_property("avoid_edges",
&shield_symbolizer::get_avoid_edges,
&shield_symbolizer::set_avoid_edges,
"Set/get the avoid_edge property of the label")
.add_property("character_spacing",
&shield_symbolizer::get_character_spacing,
&shield_symbolizer::set_character_spacing,
"Set/get the character_spacing property of the label")
.add_property("displacement",
&get_text_displacement,
&set_text_displacement)
.add_property("face_name",
make_function(&shield_symbolizer::get_face_name,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_face_name,
"Set/get the face_name property of the label")
.add_property("fill",
make_function(&shield_symbolizer::get_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fill)
.add_property("fontset",
make_function(&shield_symbolizer::get_fontset,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fontset)
.add_property("force_odd_labels",
&shield_symbolizer::get_force_odd_labels,
&shield_symbolizer::set_force_odd_labels)
.add_property("halo_fill",
make_function(&shield_symbolizer::get_halo_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_halo_fill)
.add_property("halo_radius",
&shield_symbolizer::get_halo_radius,
&shield_symbolizer::set_halo_radius)
.add_property("horizontal_alignment",
&shield_symbolizer::get_horizontal_alignment,
&shield_symbolizer::set_horizontal_alignment,
"Set/get the horizontal alignment of the label")
.add_property("justify_alignment",
&shield_symbolizer::get_justify_alignment,
&shield_symbolizer::set_justify_alignment,
"Set/get the text justification")
.add_property("label_placement",
&shield_symbolizer::get_label_placement,
&shield_symbolizer::set_label_placement,
"Set/get the placement of the label")
.add_property("label_position_tolerance",
&shield_symbolizer::get_label_position_tolerance,
&shield_symbolizer::set_label_position_tolerance)
.add_property("label_spacing",
&shield_symbolizer::get_label_spacing,
&shield_symbolizer::set_label_spacing)
.add_property("line_spacing",
&shield_symbolizer::get_line_spacing,
&shield_symbolizer::set_line_spacing)
.add_property("max_char_angle_delta",
&shield_symbolizer::get_max_char_angle_delta,
&shield_symbolizer::set_max_char_angle_delta)
.add_property("minimum_distance",
&shield_symbolizer::get_minimum_distance,
&shield_symbolizer::set_minimum_distance)
.add_property("minimum_padding",
&shield_symbolizer::get_minimum_padding,
&shield_symbolizer::set_minimum_padding)
.add_property("name",&shield_symbolizer::get_name,
&shield_symbolizer::set_name)
.add_property("opacity",
&shield_symbolizer::get_opacity,
&shield_symbolizer::set_opacity,
"Set/get the shield opacity")
.add_property("shield_displacement",
get_shield_displacement,
set_shield_displacement)
.add_property("text_opacity",
&shield_symbolizer::get_text_opacity,
&shield_symbolizer::set_text_opacity,
"Set/get the text opacity")
.add_property("text_transform",
&shield_symbolizer::get_text_transform,
&shield_symbolizer::set_text_transform,
"Set/get the text conversion method")
.add_property("text_ratio",
&shield_symbolizer::get_text_ratio,
&shield_symbolizer::set_text_ratio)
.add_property("text_size",
&shield_symbolizer::get_text_size,
&shield_symbolizer::set_text_size)
.add_property("vertical_alignment",
&shield_symbolizer::get_vertical_alignment,
&shield_symbolizer::set_vertical_alignment,
"Set/get the vertical alignment of the label")
.add_property("wrap_width",
&shield_symbolizer::get_wrap_width,
&shield_symbolizer::set_wrap_width)
.add_property("wrap_character",
&shield_symbolizer::get_wrap_char_string,
&shield_symbolizer::set_wrap_char_from_string)
.add_property("wrap_before",
&shield_symbolizer::get_wrap_before,
&shield_symbolizer::set_wrap_before)
.add_property("unlock_image",
&shield_symbolizer::get_unlock_image,
&shield_symbolizer::set_unlock_image)
.add_property("filename",
&get_filename,
&set_filename)
.add_property("transform",
mapnik::get_svg_transform<shield_symbolizer>,
mapnik::set_svg_transform<shield_symbolizer>)
.add_property("comp_op",
&shield_symbolizer::comp_op,
&shield_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&shield_symbolizer::clip,
&shield_symbolizer::set_clip,
"Set/get the shield geometry's clipping status")
;
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
* 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
@ -20,6 +20,14 @@
*
*****************************************************************************/
/* The functions in this file produce deprecation warnings.
* But as shield symbolizer doesn't fully support more than one
* placement from python yet these functions are actually the
* correct ones.
*/
#define NO_DEPRECATION_WARNINGS
// boost
#include <boost/python.hpp>
#include <boost/variant.hpp>
@ -28,9 +36,18 @@
//symbolizer typdef here rather than mapnik/symbolizer.hpp
#include <mapnik/rule.hpp>
#include <mapnik/symbolizer_hash.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/path_expression.hpp>
#include "mapnik_enumeration.hpp"
#include "mapnik_svg.hpp"
#include <mapnik/graphics.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_
using mapnik::symbolizer;
using mapnik::rule;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
@ -42,6 +59,59 @@ using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::markers_symbolizer;
using mapnik::color;
using mapnik::path_processor_type;
using mapnik::path_expression_ptr;
using mapnik::guess_type;
using mapnik::expression_ptr;
using mapnik::parse_path;
using mapnik::position;
namespace {
using namespace boost::python;
tuple get_shield_displacement(const shield_symbolizer& s)
{
position const& pos = s.get_shield_displacement();
return boost::python::make_tuple(pos.first, pos.second);
}
void set_shield_displacement(shield_symbolizer & s, boost::python::tuple arg)
{
s.get_placement_options()->defaults.displacement.first = extract<double>(arg[0]);
s.get_placement_options()->defaults.displacement.second = extract<double>(arg[1]);
}
tuple get_text_displacement(const shield_symbolizer& t)
{
position const& pos = t.get_placement_options()->defaults.displacement;
return boost::python::make_tuple(pos.first, pos.second);
}
void set_text_displacement(shield_symbolizer & t, boost::python::tuple arg)
{
t.set_displacement(extract<double>(arg[0]),extract<double>(arg[1]));
}
void set_marker_type(mapnik::markers_symbolizer & symbolizer, std::string const& marker_type)
{
std::string filename;
if (marker_type == "ellipse")
{
filename = mapnik::marker_cache::instance().known_svg_prefix_ + "ellipse";
}
else if (marker_type == "arrow")
{
filename = mapnik::marker_cache::instance().known_svg_prefix_ + "arrow";
}
else
{
throw mapnik::value_error("Unknown marker-type: '" + marker_type + "'");
}
symbolizer.set_filename(parse_path(filename));
}
struct get_symbolizer_type : public boost::static_visitor<std::string>
{
@ -184,6 +254,20 @@ std::size_t hash_impl(symbolizer const& sym)
return boost::apply_visitor(symbolizer_hash_visitor(), sym);
}
template <typename T>
std::string get_file_impl(T const& sym)
{
return path_processor_type::to_string(*sym.get_filename());
}
template <typename T>
void set_file_impl(T & sym, std::string const& file_expr)
{
sym.set_filename(parse_path(file_expr));
}
}
void export_symbolizer()
{
using namespace boost::python;
@ -225,3 +309,569 @@ void export_symbolizer()
return_value_policy<copy_const_reference>())
;
}
void export_shield_symbolizer()
{
using namespace boost::python;
class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer",
init<expression_ptr,
std::string const&,
unsigned, mapnik::color const&,
path_expression_ptr>()
)
.add_property("allow_overlap",
&shield_symbolizer::get_allow_overlap,
&shield_symbolizer::set_allow_overlap,
"Set/get the allow_overlap property of the label")
.add_property("avoid_edges",
&shield_symbolizer::get_avoid_edges,
&shield_symbolizer::set_avoid_edges,
"Set/get the avoid_edge property of the label")
.add_property("character_spacing",
&shield_symbolizer::get_character_spacing,
&shield_symbolizer::set_character_spacing,
"Set/get the character_spacing property of the label")
.add_property("displacement",
&get_text_displacement,
&set_text_displacement)
.add_property("face_name",
make_function(&shield_symbolizer::get_face_name,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_face_name,
"Set/get the face_name property of the label")
.add_property("fill",
make_function(&shield_symbolizer::get_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fill)
.add_property("fontset",
make_function(&shield_symbolizer::get_fontset,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fontset)
.add_property("force_odd_labels",
&shield_symbolizer::get_force_odd_labels,
&shield_symbolizer::set_force_odd_labels)
.add_property("halo_fill",
make_function(&shield_symbolizer::get_halo_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_halo_fill)
.add_property("halo_radius",
&shield_symbolizer::get_halo_radius,
&shield_symbolizer::set_halo_radius)
.add_property("horizontal_alignment",
&shield_symbolizer::get_horizontal_alignment,
&shield_symbolizer::set_horizontal_alignment,
"Set/get the horizontal alignment of the label")
.add_property("justify_alignment",
&shield_symbolizer::get_justify_alignment,
&shield_symbolizer::set_justify_alignment,
"Set/get the text justification")
.add_property("label_placement",
&shield_symbolizer::get_label_placement,
&shield_symbolizer::set_label_placement,
"Set/get the placement of the label")
.add_property("label_position_tolerance",
&shield_symbolizer::get_label_position_tolerance,
&shield_symbolizer::set_label_position_tolerance)
.add_property("label_spacing",
&shield_symbolizer::get_label_spacing,
&shield_symbolizer::set_label_spacing)
.add_property("line_spacing",
&shield_symbolizer::get_line_spacing,
&shield_symbolizer::set_line_spacing)
.add_property("max_char_angle_delta",
&shield_symbolizer::get_max_char_angle_delta,
&shield_symbolizer::set_max_char_angle_delta)
.add_property("minimum_distance",
&shield_symbolizer::get_minimum_distance,
&shield_symbolizer::set_minimum_distance)
.add_property("minimum_padding",
&shield_symbolizer::get_minimum_padding,
&shield_symbolizer::set_minimum_padding)
.add_property("name",&shield_symbolizer::get_name,
&shield_symbolizer::set_name)
.add_property("opacity",
&shield_symbolizer::get_opacity,
&shield_symbolizer::set_opacity,
"Set/get the shield opacity")
.add_property("shield_displacement",
get_shield_displacement,
set_shield_displacement)
.add_property("text_opacity",
&shield_symbolizer::get_text_opacity,
&shield_symbolizer::set_text_opacity,
"Set/get the text opacity")
.add_property("text_transform",
&shield_symbolizer::get_text_transform,
&shield_symbolizer::set_text_transform,
"Set/get the text conversion method")
.add_property("text_ratio",
&shield_symbolizer::get_text_ratio,
&shield_symbolizer::set_text_ratio)
.add_property("text_size",
&shield_symbolizer::get_text_size,
&shield_symbolizer::set_text_size)
.add_property("vertical_alignment",
&shield_symbolizer::get_vertical_alignment,
&shield_symbolizer::set_vertical_alignment,
"Set/get the vertical alignment of the label")
.add_property("wrap_width",
&shield_symbolizer::get_wrap_width,
&shield_symbolizer::set_wrap_width)
.add_property("wrap_character",
&shield_symbolizer::get_wrap_char_string,
&shield_symbolizer::set_wrap_char_from_string)
.add_property("wrap_before",
&shield_symbolizer::get_wrap_before,
&shield_symbolizer::set_wrap_before)
.add_property("unlock_image",
&shield_symbolizer::get_unlock_image,
&shield_symbolizer::set_unlock_image)
.add_property("filename",
get_file_impl<shield_symbolizer>,
set_file_impl<shield_symbolizer>)
.add_property("transform",
mapnik::get_svg_transform<shield_symbolizer>,
mapnik::set_svg_transform<shield_symbolizer>)
.add_property("comp_op",
&shield_symbolizer::comp_op,
&shield_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&shield_symbolizer::clip,
&shield_symbolizer::set_clip,
"Set/get the shield geometry's clipping status")
;
}
void export_polygon_symbolizer()
{
using namespace boost::python;
class_<polygon_symbolizer>("PolygonSymbolizer",
init<>("Default PolygonSymbolizer - solid fill grey"))
.def(init<color const&>("TODO"))
.add_property("fill",make_function
(&polygon_symbolizer::get_fill,
return_value_policy<copy_const_reference>()),
&polygon_symbolizer::set_fill)
.add_property("fill_opacity",
&polygon_symbolizer::get_opacity,
&polygon_symbolizer::set_opacity)
.add_property("gamma",
&polygon_symbolizer::get_gamma,
&polygon_symbolizer::set_gamma)
.add_property("gamma_method",
&polygon_symbolizer::get_gamma_method,
&polygon_symbolizer::set_gamma_method,
"gamma correction method")
.add_property("comp_op",
&polygon_symbolizer::comp_op,
&polygon_symbolizer::set_comp_op,
"Set/get the polygon comp-op")
.add_property("clip",
&polygon_symbolizer::clip,
&polygon_symbolizer::set_clip,
"Set/get the polygon geometry's clipping status")
.add_property("smooth",
&polygon_symbolizer::smooth,
&polygon_symbolizer::set_smooth,
"Set/get the polygon geometry's smooth value")
.add_property("simplify_tolerance",
&polygon_symbolizer::simplify_tolerance,
&polygon_symbolizer::set_simplify_tolerance,
"simplfication tolerance measure")
.def("__hash__", hash_impl)
;
}
void export_polygon_pattern_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::pattern_alignment_e>("pattern_alignment")
.value("LOCAL",mapnik::LOCAL_ALIGNMENT)
.value("GLOBAL",mapnik::GLOBAL_ALIGNMENT)
;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<path_expression_ptr>("<path_expression_ptr>"))
.add_property("alignment",
&polygon_pattern_symbolizer::get_alignment,
&polygon_pattern_symbolizer::set_alignment,
"Set/get the alignment of the pattern")
.add_property("transform",
mapnik::get_svg_transform<polygon_pattern_symbolizer>,
mapnik::set_svg_transform<polygon_pattern_symbolizer>)
.add_property("filename",
&get_file_impl<polygon_pattern_symbolizer>,
&set_file_impl<polygon_pattern_symbolizer>)
.add_property("opacity",
&polygon_pattern_symbolizer::get_opacity,
&polygon_pattern_symbolizer::set_opacity)
.add_property("gamma",
&polygon_pattern_symbolizer::get_gamma,
&polygon_pattern_symbolizer::set_gamma)
.add_property("gamma_method",
&polygon_pattern_symbolizer::get_gamma_method,
&polygon_pattern_symbolizer::set_gamma_method,
"Set/get the gamma correction method of the polygon")
.add_property("comp_op",
&polygon_pattern_symbolizer::comp_op,
&polygon_pattern_symbolizer::set_comp_op,
"Set/get the pattern comp-op")
.add_property("clip",
&polygon_pattern_symbolizer::clip,
&polygon_pattern_symbolizer::set_clip,
"Set/get the pattern geometry's clipping status")
.add_property("smooth",
&polygon_pattern_symbolizer::smooth,
&polygon_pattern_symbolizer::set_smooth,
"Set/get the pattern geometry's smooth value")
;
}
void export_raster_symbolizer()
{
using namespace boost::python;
class_<raster_symbolizer>("RasterSymbolizer",
init<>("Default ctor"))
.add_property("mode",
make_function(&raster_symbolizer::get_mode,return_value_policy<copy_const_reference>()),
&raster_symbolizer::set_mode,
"Get/Set merging mode. (deprecated, use comp_op instead)\n"
)
.add_property("comp_op",
&raster_symbolizer::comp_op,
&raster_symbolizer::set_comp_op,
"Set/get the raster comp-op"
)
.add_property("scaling",
&raster_symbolizer::get_scaling_method,
&raster_symbolizer::set_scaling_method,
"Get/Set scaling algorithm.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.scaling = 'mapnik.scaling_method.GAUSSIAN'\n"
)
.add_property("opacity",
&raster_symbolizer::get_opacity,
&raster_symbolizer::set_opacity,
"Get/Set opacity.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.opacity = .5\n"
)
.add_property("colorizer",
&raster_symbolizer::get_colorizer,
&raster_symbolizer::set_colorizer,
"Get/Set the RasterColorizer used to color data rasters.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer, RasterColorizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.colorizer = RasterColorizer()\n"
">>> for value, color in [\n"
"... (0, \"#000000\"),\n"
"... (10, \"#ff0000\"),\n"
"... (40, \"#00ff00\"),\n"
"... ]:\n"
"... r.colorizer.append_band(value, color)\n"
)
.add_property("filter_factor",
&raster_symbolizer::get_filter_factor,
&raster_symbolizer::set_filter_factor,
"Get/Set the filter factor used by the datasource.\n"
"\n"
"This is used by the Raster or Gdal datasources to pre-downscale\n"
"images using overviews.\n"
"Higher numbers can sometimes cause much better scaled image\n"
"output, at the cost of speed.\n"
"\n"
"Examples:\n"
" -1.0 : (Default) A suitable value will be determined from the\n"
" chosen scaling method during rendering.\n"
" 1.0 : The datasource will take care of all the scaling\n"
" (using nearest neighbor interpolation)\n"
" 2.0 : The datasource will scale the datasource to\n"
" 2.0x the desired size, and mapnik will scale the rest\n"
" of the way using the interpolation defined in self.scaling.\n"
)
.add_property("mesh_size",
&raster_symbolizer::get_mesh_size,
&raster_symbolizer::set_mesh_size,
"Get/Set warping mesh size.\n"
"Larger values result in faster warping times but might "
"result in distorted maps.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.mesh_size = 32\n"
)
.add_property("premultiplied",
&raster_symbolizer::premultiplied,
&raster_symbolizer::set_premultiplied,
"Get/Set premultiplied status of the source image.\n"
"Can be used to override what the source data reports (when in error)\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.premultiplied = False\n"
)
;
}
void export_point_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::point_placement_e>("point_placement")
.value("CENTROID",mapnik::CENTROID_POINT_PLACEMENT)
.value("INTERIOR",mapnik::INTERIOR_POINT_PLACEMENT)
;
class_<point_symbolizer>("PointSymbolizer",
init<>("Default Point Symbolizer - 4x4 black square"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
.add_property("filename",
&get_file_impl<point_symbolizer>,
&set_file_impl<point_symbolizer>)
.add_property("allow_overlap",
&point_symbolizer::get_allow_overlap,
&point_symbolizer::set_allow_overlap)
.add_property("opacity",
&point_symbolizer::get_opacity,
&point_symbolizer::set_opacity)
.add_property("ignore_placement",
&point_symbolizer::get_ignore_placement,
&point_symbolizer::set_ignore_placement)
.add_property("placement",
&point_symbolizer::get_point_placement,
&point_symbolizer::set_point_placement,
"Set/get the placement of the point")
.add_property("transform",
mapnik::get_svg_transform<point_symbolizer>,
mapnik::set_svg_transform<point_symbolizer>)
.add_property("comp_op",
&point_symbolizer::comp_op,
&point_symbolizer::set_comp_op,
"Set/get the comp-op")
;
}
void export_markers_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::marker_placement_e>("marker_placement")
.value("POINT_PLACEMENT",mapnik::MARKER_POINT_PLACEMENT)
.value("INTERIOR_PLACEMENT",mapnik::MARKER_INTERIOR_PLACEMENT)
.value("LINE_PLACEMENT",mapnik::MARKER_LINE_PLACEMENT)
;
mapnik::enumeration_<mapnik::marker_multi_policy_e>("marker_multi_policy")
.value("EACH",mapnik::MARKER_EACH_MULTI)
.value("WHOLE",mapnik::MARKER_WHOLE_MULTI)
.value("LARGEST",mapnik::MARKER_LARGEST_MULTI)
;
class_<markers_symbolizer>("MarkersSymbolizer",
init<>("Default Markers Symbolizer - circle"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
.add_property("filename",
&get_file_impl<markers_symbolizer>,
&set_file_impl<markers_symbolizer>)
.add_property("marker_type",
&get_file_impl<markers_symbolizer>,
&set_marker_type)
.add_property("allow_overlap",
&markers_symbolizer::get_allow_overlap,
&markers_symbolizer::set_allow_overlap)
.add_property("spacing",
&markers_symbolizer::get_spacing,
&markers_symbolizer::set_spacing)
.add_property("max_error",
&markers_symbolizer::get_max_error,
&markers_symbolizer::set_max_error)
.add_property("opacity",
&markers_symbolizer::get_opacity,
&markers_symbolizer::set_opacity,
"Set/get the overall opacity")
.add_property("fill_opacity",
&markers_symbolizer::get_fill_opacity,
&markers_symbolizer::set_fill_opacity,
"Set/get the fill opacity")
.add_property("ignore_placement",
&markers_symbolizer::get_ignore_placement,
&markers_symbolizer::set_ignore_placement)
.add_property("transform",
&mapnik::get_svg_transform<markers_symbolizer>,
&mapnik::set_svg_transform<markers_symbolizer>)
.add_property("width",
make_function(&markers_symbolizer::get_width,
return_value_policy<copy_const_reference>()),
&markers_symbolizer::set_width,
"Set/get the marker width")
.add_property("height",
make_function(&markers_symbolizer::get_height,
return_value_policy<copy_const_reference>()),
&markers_symbolizer::set_height,
"Set/get the marker height")
.add_property("fill",
&markers_symbolizer::get_fill,
&markers_symbolizer::set_fill,
"Set/get the marker fill color")
.add_property("stroke",
&markers_symbolizer::get_stroke,
&markers_symbolizer::set_stroke,
"Set/get the marker stroke (outline)")
.add_property("placement",
&markers_symbolizer::get_marker_placement,
&markers_symbolizer::set_marker_placement,
"Set/get the marker placement")
.add_property("multi_policy",
&markers_symbolizer::get_marker_multi_policy,
&markers_symbolizer::set_marker_multi_policy,
"Set/get the marker multi geometry rendering policy")
.add_property("comp_op",
&markers_symbolizer::comp_op,
&markers_symbolizer::set_comp_op,
"Set/get the marker comp-op")
.add_property("clip",
&markers_symbolizer::clip,
&markers_symbolizer::set_clip,
"Set/get the marker geometry's clipping status")
.add_property("smooth",
&markers_symbolizer::smooth,
&markers_symbolizer::set_smooth,
"Set/get the marker geometry's smooth value")
;
}
void export_line_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::line_rasterizer_e>("line_rasterizer")
.value("FULL",mapnik::RASTERIZER_FULL)
.value("FAST",mapnik::RASTERIZER_FAST)
;
class_<line_symbolizer>("LineSymbolizer",
init<>("Default LineSymbolizer - 1px solid black"))
.def(init<mapnik::stroke const&>("TODO"))
.def(init<mapnik::color const& ,float>())
.add_property("rasterizer",
&line_symbolizer::get_rasterizer,
&line_symbolizer::set_rasterizer,
"Set/get the rasterization method of the line of the point")
.add_property("stroke",make_function
(&line_symbolizer::get_stroke,
return_value_policy<reference_existing_object>()),
&line_symbolizer::set_stroke)
.add_property("simplify_tolerance",
&line_symbolizer::simplify_tolerance,
&line_symbolizer::set_simplify_tolerance,
"simplification tolerance measure")
.add_property("offset",
&line_symbolizer::offset,
&line_symbolizer::set_offset,
"offset value")
.add_property("comp_op",
&line_symbolizer::comp_op,
&line_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&line_symbolizer::clip,
&line_symbolizer::set_clip,
"Set/get the line geometry's clipping status")
.add_property("smooth",
&line_symbolizer::smooth,
&line_symbolizer::set_smooth,
"smooth value (0..1.0)")
.def("__hash__", hash_impl)
;
}
void export_line_pattern_symbolizer()
{
using namespace boost::python;
class_<line_pattern_symbolizer>("LinePatternSymbolizer",
init<path_expression_ptr>
("<image file expression>"))
.add_property("transform",
mapnik::get_svg_transform<line_pattern_symbolizer>,
mapnik::set_svg_transform<line_pattern_symbolizer>)
.add_property("filename",
&get_file_impl<line_pattern_symbolizer>,
&set_file_impl<line_pattern_symbolizer>)
.add_property("offset",
&line_pattern_symbolizer::offset,
&line_pattern_symbolizer::set_offset,
"Set/get the offset")
.add_property("comp_op",
&line_pattern_symbolizer::comp_op,
&line_pattern_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&line_pattern_symbolizer::clip,
&line_pattern_symbolizer::set_clip,
"Set/get the line pattern geometry's clipping status")
.add_property("smooth",
&line_pattern_symbolizer::smooth,
&line_pattern_symbolizer::set_smooth,
"smooth value (0..1.0)")
;
}
void export_debug_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::debug_symbolizer_mode_e>("debug_symbolizer_mode")
.value("COLLISION",mapnik::DEBUG_SYM_MODE_COLLISION)
.value("VERTEX",mapnik::DEBUG_SYM_MODE_VERTEX)
;
class_<mapnik::debug_symbolizer>("DebugSymbolizer",
init<>("Default debug Symbolizer"))
.add_property("mode",
&mapnik::debug_symbolizer::get_mode,
&mapnik::debug_symbolizer::set_mode)
;
}
void export_building_symbolizer()
{
using namespace boost::python;
class_<building_symbolizer>("BuildingSymbolizer",
init<>("Default BuildingSymbolizer"))
.add_property("fill",make_function
(&building_symbolizer::get_fill,
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_fill)
.add_property("fill_opacity",
&building_symbolizer::get_opacity,
&building_symbolizer::set_opacity)
.add_property("height",
make_function(&building_symbolizer::height,
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_height,
"Set/get the building height")
;
}

View file

@ -24,19 +24,15 @@
#include <boost/noncopyable.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/text_placements/simple.hpp>
#include <mapnik/text_placements/list.hpp>
#include <mapnik/formatting/text.hpp>
#include <mapnik/formatting/list.hpp>
#include <mapnik/formatting/format.hpp>
#include <mapnik/formatting/expression_format.hpp>
#include <mapnik/processed_text.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/text_symbolizer.hpp>
#include "mapnik_enumeration.hpp"
#include "mapnik_threads.hpp"
#include "python_optional.hpp"
using namespace mapnik;
@ -53,8 +49,48 @@ using namespace mapnik;
*/
namespace {
using namespace boost::python;
// This class works around a feature in boost python.
// See http://osdir.com/ml/python.c++/2003-11/msg00158.html
template <typename T,
typename X1 = boost::python::detail::not_specified,
typename X2 = boost::python::detail::not_specified,
typename X3 = boost::python::detail::not_specified>
class class_with_converter : public boost::python::class_<T, X1, X2, X3>
{
public:
typedef class_with_converter<T,X1,X2,X3> self;
// Construct with the class name, with or without docstring, and default __init__() function
class_with_converter(char const* name, char const* doc = 0) : boost::python::class_<T, X1, X2, X3>(name, doc) { }
// Construct with class name, no docstring, and an uncallable __init__ function
class_with_converter(char const* name, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, y) { }
// Construct with class name, docstring, and an uncallable __init__ function
class_with_converter(char const* name, char const* doc, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, doc, y) { }
// Construct with class name and init<> function
template <class DerivedT> class_with_converter(char const* name, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, i) { }
// Construct with class name, docstring and init<> function
template <class DerivedT>
inline class_with_converter(char const* name, char const* doc, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, doc, i) { }
template <class D>
self& def_readwrite_convert(char const* name, D const& d, char const* /*doc*/=0)
{
this->add_property(name,
boost::python::make_getter(d, boost::python::return_value_policy<boost::python::return_by_value>()),
boost::python::make_setter(d, boost::python::default_call_policies()));
return *this;
}
};
boost::python::tuple get_displacement(text_symbolizer_properties const& t)
{
return boost::python::make_tuple(t.displacement.first, t.displacement.second);
@ -194,13 +230,16 @@ struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node>
ListNodeWrap(object l) : formatting::list_node(), wrapper<formatting::list_node>()
{
stl_input_iterator<formatting::node_ptr> begin(l), end;
children_.insert(children_.end(), begin, end);
while (begin != end)
{
children_.push_back(*begin);
++begin;
}
}
/* TODO: Add constructor taking variable number of arguments.
http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_function */
virtual void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
if(override o = this->get_override("apply"))

View file

@ -22,9 +22,9 @@
#ifndef MAPNIK_THREADS_HPP
#define MAPNIK_THREADS_HPP
#include <boost/thread.hpp>
#include <boost/python.hpp>
#include <boost/thread/tss.hpp> // for thread_specific_ptr
#include <Python.h>
namespace mapnik {
class python_thread
{

View file

@ -35,11 +35,7 @@ namespace boost { namespace python {
{
PyObject * operator() (mapnik::value_integer val) const
{
#if PY_VERSION_HEX >= 0x03000000
return ::PyLong_FromLong(val);
#else
return ::PyInt_FromLong(val);
#endif
return ::PyLong_FromLongLong(val);
}
PyObject * operator() (double val) const

View file

@ -0,0 +1,55 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 Artem Pavlenko, Jean-Francois Doyon
*
* 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
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/make_shared.hpp>
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
namespace impl {
typedef boost::ptr_vector<mapnik::geometry_type> path_type;
boost::shared_ptr<path_type> from_wkt(mapnik::wkt_parser & p, std::string const& wkt)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
if (!p.parse(wkt, *paths))
throw std::runtime_error("Failed to parse WKT");
return paths;
}
}
void export_wkt_reader()
{
using mapnik::wkt_parser;
using namespace boost::python;
class_<wkt_parser, boost::noncopyable>("WKTReader",init<>())
.def("read",&impl::from_wkt)
;
}

View file

@ -1,76 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2008 Tom Hughes
*
* 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
*
*****************************************************************************/
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <boost/python/type_id.hpp>
#include <boost/python/converter/registry.hpp>
#include <pycairo.h>
static Pycairo_CAPI_t *Pycairo_CAPI;
static void *extract_surface(PyObject* op)
{
if (PyObject_TypeCheck(op, const_cast<PyTypeObject*>(Pycairo_CAPI->Surface_Type)))
{
return op;
}
else
{
return 0;
}
}
static void *extract_context(PyObject* op)
{
if (PyObject_TypeCheck(op, const_cast<PyTypeObject*>(Pycairo_CAPI->Context_Type)))
{
return op;
}
else
{
return 0;
}
}
void register_cairo()
{
#if PY_MAJOR_VERSION >= 3
Pycairo_CAPI = (Pycairo_CAPI_t*) PyCapsule_Import(const_cast<char *>("cairo.CAPI"), 0);
#else
Pycairo_CAPI = (Pycairo_CAPI_t*) PyCObject_Import(const_cast<char *>("cairo"), const_cast<char *>("CAPI"));
#endif
if (Pycairo_CAPI == NULL) return;
boost::python::converter::registry::insert(&extract_surface, boost::python::type_id<PycairoSurface>());
boost::python::converter::registry::insert(&extract_context, boost::python::type_id<PycairoContext>());
}
#else
void register_cairo()
{
}
#endif

View file

@ -20,6 +20,8 @@
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/scoped_array.hpp>
@ -36,9 +38,11 @@
#include <mapnik/value_error.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include "mapnik_value_converter.hpp"
#include "python_grid_utils.hpp"
// stl
#include <stdexcept>
namespace mapnik {
@ -469,3 +473,5 @@ boost::python::dict render_grid(mapnik::Map const& map,
}
}
#endif

View file

@ -196,43 +196,3 @@ struct python_optional<bool> : public mapnik::noncopyable
optional_to_python, optional_from_python>();
}
};
// This class works around a feature in boost python.
// See http://osdir.com/ml/python.c++/2003-11/msg00158.html
template <typename T,
typename X1 = boost::python::detail::not_specified,
typename X2 = boost::python::detail::not_specified,
typename X3 = boost::python::detail::not_specified>
class class_with_converter : public boost::python::class_<T, X1, X2, X3>
{
public:
typedef class_with_converter<T,X1,X2,X3> self;
// Construct with the class name, with or without docstring, and default __init__() function
class_with_converter(char const* name, char const* doc = 0) : boost::python::class_<T, X1, X2, X3>(name, doc) { }
// Construct with class name, no docstring, and an uncallable __init__ function
class_with_converter(char const* name, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, y) { }
// Construct with class name, docstring, and an uncallable __init__ function
class_with_converter(char const* name, char const* doc, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, doc, y) { }
// Construct with class name and init<> function
template <class DerivedT> class_with_converter(char const* name, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, i) { }
// Construct with class name, docstring and init<> function
template <class DerivedT>
inline class_with_converter(char const* name, char const* doc, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, doc, i) { }
template <class D>
self& def_readwrite_convert(char const* name, D const& d, char const* doc=0)
{
this->add_property(name,
boost::python::make_getter(d, boost::python::return_value_policy<boost::python::return_by_value>()),
boost::python::make_setter(d, boost::python::default_call_policies()));
return *this;
}
};

View file

@ -34,14 +34,14 @@ demo_env = env.Clone()
demo_env['CXXFLAGS'] = copy(env['LIBMAPNIK_CXXFLAGS'])
demo_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
if env['HAS_CAIRO']:
demo_env.PrependUnique(CPPPATH=env['CAIRO_CPPPATHS'])
demo_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
libraries = copy(env['LIBMAPNIK_LIBS'])
libraries.append('mapnik')
libraries = ['mapnik']
libraries.extend(copy(env['LIBMAPNIK_LIBS']))
rundemo = demo_env.Program('rundemo', source, LIBS=libraries, LINKFLAGS=env["CUSTOM_LDFLAGS"])
Depends(rundemo, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))

View file

@ -263,18 +263,27 @@ int main ( int argc , char** argv)
image_32 buf(m.width(),m.height());
agg_renderer<image_32> ren(m,buf);
ren.apply();
std::string msg("These maps have been rendered using AGG in the current directory:\n");
#ifdef HAVE_JPEG
save_to_file(buf,"demo.jpg","jpeg");
msg += "- demo.jpg\n";
#endif
#ifdef HAVE_PNG
save_to_file(buf,"demo.png","png");
save_to_file(buf,"demo256.png","png8");
msg += "- demo.png\n";
msg += "- demo256.png\n";
#endif
#ifdef HAVE_TIFF
save_to_file(buf,"demo.tif","tiff");
std::cout << "Three maps have been rendered using AGG in the current directory:\n"
"- demo.jpg\n"
"- demo.png\n"
"- demo256.png\n"
"- demo.tif\n"
"Have a look!\n";
msg += "- demo.tif\n";
#endif
#ifdef HAVE_WEBP
save_to_file(buf,"demo.webp","webp");
msg += "- demo.webp\n";
#endif
msg += "Have a look!\n";
std::cout << msg;
#if defined(HAVE_CAIRO)
// save to pdf/svg files
@ -292,7 +301,7 @@ int main ( int argc , char** argv)
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,m.width(),m.height()),
cairo_surface_closer());
double scale_factor = 1.0;
cairo_ptr image_context = (create_context(image_surface));
cairo_ptr image_context(create_context(image_surface));
mapnik::cairo_renderer<cairo_ptr> png_render(m,image_context,scale_factor);
png_render.apply();
// we can now write to png with cairo functionality

View file

@ -330,27 +330,41 @@ mapnik.render(m, im)
# Save image to files
images_ = []
im.save('demo.png', 'png') # true-colour RGBA
images_.append('demo.png')
if mapnik.has_png():
im.save('demo.png', 'png') # true-colour RGBA
images_.append('demo.png')
# old behavior, now can do 'png8:c=256'
im.save('demo256.png', 'png256') # save to palette based (max 256 colours) png
images_.append('demo256.png')
# old behavior, now can do 'png8:c=256'
im.save('demo256.png', 'png256') # save to palette based (max 256 colours) png
images_.append('demo256.png')
im.save('demo64_binary_transparency.png', 'png8:c=64:t=1')
images_.append('demo64_binary_transparency.png')
im.save('demo64_binary_transparency.png', 'png8:c=64:t=1')
images_.append('demo64_binary_transparency.png')
im.save('demo128_colors_hextree_no_alpha.png', 'png8:c=100:m=h:t=0')
images_.append('demo128_colors_hextree_no_alpha.png')
im.save('demo128_colors_hextree_no_alpha.png', 'png8:c=100:m=h:t=0')
images_.append('demo128_colors_hextree_no_alpha.png')
im.save('demo_high.jpg', 'jpeg100')
images_.append('demo_high.jpg')
if mapnik.has_jpeg():
im.save('demo_high.jpg', 'jpeg100')
images_.append('demo_high.jpg')
im.save('demo_low.jpg', 'jpeg50')
images_.append('demo_low.jpg')
im.save('demo_low.jpg', 'jpeg50')
images_.append('demo_low.jpg')
if mapnik.has_tiff():
im.save('demo.tif', 'tiff')
images_.append('demo.tif')
if mapnik.has_webp():
im.save('demo.webp', 'webp') # default quality is 90
images_.append('demo.webp')
im.save('demo_highest.webp', 'webp:quality=100')
images_.append('demo_med.webp')
im.save('demo_low.webp', 'webp:quality=50')
images_.append('demo_low.webp')
im.save('demo.tif', 'tiff')
images_.append('demo.tif')
# Render cairo examples
if HAS_PYCAIRO_MODULE and mapnik.has_pycairo():

View file

@ -1,82 +0,0 @@
# $Id: rundemo.py 577 2008-01-03 11:39:10Z artem $
#
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Import everything. In this case this is safe, in more complex systems, you
# will want to be more selective.
try:
from mapnik import *
except:
print '\n\nThe mapnik library and python bindings must have been compiled and \
installed successfully before running this script.\n\n'
raise
m = Map(690,690,"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
m.background = Color(255,100,100,255)
road_style = Style()
#Road
road_rule = Rule()
road_stroke = Stroke(Color('white'), 1)
road_stroke.opacity = 0.7
#road_rule.filter = Filter("[CLASS] = 'BENDUNDER' or [CLASS] = 'BENDOVER'")
road_rule.symbols.append(LineSymbolizer(road_stroke))
road_style.rules.append(road_rule);
#Road text
text_symbolizer = TextSymbolizer(Expression('[NAME]'), 'DejaVu Sans Book', 20, Color('black'))
text_symbolizer.label_placement=label_placement.LINE_PLACEMENT
text_symbolizer.minimum_distance = 0
#text_symbolizer.max_char_angle_delta = 40
#text_symbolizer.force_odd_labels = 1
text_symbolizer.label_spacing = 20
text_symbolizer.label_position_tolerance = 50
text_symbolizer.minimum_distance = 5
text_symbolizer.avoid_edges = 0
text_symbolizer.halo_fill = Color('yellow')
text_symbolizer.halo_radius = 1
road_rule = Rule()
#road_rule.filter = Filter("[CLASS] = 'BENDUNDER' or [CLASS] = 'BENDOVER'")
road_rule.symbols.append(text_symbolizer)
road_style.rules.append(road_rule)
road_layer = Layer('road')
road_layer.datasource = Shapefile(file='../data/test/charplacement')
m.append_style('road', road_style)
road_layer.styles.append('road')
m.layers.append(road_layer)
# Draw map
# Set the initial extent of the map.
m.zoom_to_box(Box2d(0,0,14,-14))
# Render
im = Image(m.width,m.height)
render(m, im)
# Save image to file
im.save('output.png') # true-colour RGBA
print "Done\n"

View file

@ -1,83 +0,0 @@
# $Id: rundemo.py 577 2008-01-03 11:39:10Z artem $
#
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Import everything. In this case this is safe, in more complex systems, you
# will want to be more selective.
try:
from mapnik import *
except:
print '\n\nThe mapnik library and python bindings must have been compiled and \
installed successfully before running this script.\n\n'
raise
m = Map(690,690,"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
m.background = Color(255,100,100,255)
road_style = Style()
#Road
road_rule = Rule()
road_stroke = Stroke(Color('white'), 1)
road_stroke.line_cap = line_cap.ROUND_CAP
road_stroke.line_join = line_join.ROUND_JOIN
#road_rule.filter = Filter("[CLASS] = 'CROSS'")
road_rule.symbols.append(LineSymbolizer(road_stroke))
road_style.rules.append(road_rule);
#Road text
text_symbolizer = TextSymbolizer(Expression('[NAME]'), 'DejaVu Sans Book', 10, Color('black'))
text_symbolizer.label_placement=label_placement.LINE_PLACEMENT
text_symbolizer.minimum_distance = 0
#text_symbolizer.max_char_angle_delta = 40
#text_symbolizer.force_odd_labels = 1
#FIXME: Displacement cannot be set from python so we can't set it here, lol!
text_symbolizer.label_spacing = 60
text_symbolizer.label_position_tolerance = 5
text_symbolizer.avoid_edges = 0
text_symbolizer.halo_fill = Color('yellow')
text_symbolizer.halo_radius = 1
road_rule = Rule()
#road_rule.filter = Filter("[CLASS] = 'CROSS'")
road_rule.symbols.append(text_symbolizer)
road_style.rules.append(road_rule)
road_layer = Layer('road')
road_layer.datasource = Shapefile(file='../data/test/displacement')
m.append_style('road', road_style)
road_layer.styles.append('road')
m.layers.append(road_layer)
# Draw map
# Set the initial extent of the map.
m.zoom_to_box(Box2d(0,0,14,-14))
# Render
im = Image(m.width,m.height)
render(m, im)
# Save image to file
im.save('output.png') # true-colour RGBA
print "Done\n"

View file

@ -1,84 +0,0 @@
# $Id: rundemo.py 577 2008-01-03 11:39:10Z artem $
#
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Import everything. In this case this is safe, in more complex systems, you
# will want to be more selective.
try:
from mapnik import *
except:
print '\n\nThe mapnik library and python bindings must have been compiled and \
installed successfully before running this script.\n\n'
raise
m = Map(690,690,"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
m.background = Color(255,100,100,255)
road_style = Style()
#Road
road_rule = Rule()
road_stroke = Stroke(Color('white'), 12)
road_stroke.opacity = 0.7
#road_stroke.line_cap = line_cap.ROUND_CAP
#road_stroke.line_join = line_join.ROUND_JOIN
#road_rule.filter = Filter("[CLASS] = 'CROSS'")
road_rule.symbols.append(LineSymbolizer(road_stroke))
road_style.rules.append(road_rule);
#Road text
text_symbolizer = TextSymbolizer(Expression('[NAME]'), 'DejaVu Sans Book', 10, Color('black'))
text_symbolizer.label_placement=label_placement.LINE_PLACEMENT
text_symbolizer.minimum_distance = 0
#text_symbolizer.max_char_angle_delta = 40
#text_symbolizer.force_odd_labels = 1
text_symbolizer.label_spacing = 60
text_symbolizer.label_position_tolerance = 50
text_symbolizer.minimum_distance = 5
text_symbolizer.avoid_edges = 0
text_symbolizer.halo_fill = Color('yellow')
text_symbolizer.halo_radius = 1
road_rule = Rule()
#road_rule.filter = Filter("[CLASS] = 'CROSS'")
road_rule.symbols.append(text_symbolizer)
road_style.rules.append(road_rule)
road_layer = Layer('road')
road_layer.datasource = Shapefile(file='../data/test/overlap')
m.append_style('road', road_style)
road_layer.styles.append('road')
m.layers.append(road_layer)
# Draw map
# Set the initial extent of the map.
m.zoom_to_box(Box2d(0,0,14,-14))
# Render
im = Image(m.width,m.height)
render(m, im)
# Save image to file
im.save('output.png') # true-colour RGBA
print "Done\n"

View file

@ -1,82 +0,0 @@
# $Id: rundemo.py 577 2008-01-03 11:39:10Z artem $
#
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Import everything. In this case this is safe, in more complex systems, you
# will want to be more selective.
try:
from mapnik import *
except:
print '\n\nThe mapnik library and python bindings must have been compiled and \
installed successfully before running this script.\n\n'
raise
m = Map(690,690,"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
m.background = Color(255,100,100,255)
road_style = Style()
#Road
road_rule = Rule()
road_stroke = Stroke(Color('white'), 12)
road_stroke.line_cap = line_cap.ROUND_CAP
road_stroke.line_join = line_join.ROUND_JOIN
#road_rule.filter = Filter("[CLASS] = 'STRAIGHT'")
road_rule.symbols.append(LineSymbolizer(road_stroke))
road_style.rules.append(road_rule);
#Road text
text_symbolizer = TextSymbolizer(Expression('[NAME]'), 'DejaVu Sans Book', 10, Color('black'))
text_symbolizer.label_placement=label_placement.LINE_PLACEMENT
text_symbolizer.minimum_distance = 0
#text_symbolizer.max_char_angle_delta = 40
#text_symbolizer.force_odd_labels = 1
text_symbolizer.label_spacing = 80
text_symbolizer.label_position_tolerance = 5
text_symbolizer.avoid_edges = 0
text_symbolizer.halo_fill = Color('yellow')
text_symbolizer.halo_radius = 1
road_rule = Rule()
#road_rule.filter = Filter("[CLASS] = 'STRAIGHT'")
road_rule.symbols.append(text_symbolizer)
road_style.rules.append(road_rule)
road_layer = Layer('road')
road_layer.datasource = Shapefile(file='../data/test/textspacing')
m.append_style('road', road_style)
road_layer.styles.append('road')
m.layers.append(road_layer)
# Draw map
# Set the initial extent of the map.
m.zoom_to_box(Box2d(0,0,14,-14))
# Render
im = Image(m.width,m.height)
render(m, im)
# Save image to file
im.save('output.png') # true-colour RGBA
print "Done\n"

View file

@ -1,7 +1,7 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2010 Artem Pavlenko, Jean-Francois Doyon
# Copyright (C) 2013 Artem Pavlenko
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public

View file

@ -19,15 +19,15 @@
// qt
#include <QtWidgets/QApplication>
#include <QApplication>
#include <QStringList>
#include <QSettings>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include "mainwindow.hpp"
// boost
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/operations.hpp>
int main( int argc, char **argv )

View file

@ -21,7 +21,8 @@
#include <QtGui>
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/timer/timer.hpp>
#include <boost/chrono/process_cpu_clocks.hpp>
#include <boost/chrono.hpp>
#include <boost/bind.hpp>
#include <mapnik/agg_renderer.hpp>
@ -504,8 +505,10 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
try
{
{
boost::timer::auto_cpu_timer t;
boost::chrono::process_cpu_clock::time_point start = boost::chrono::process_cpu_clock::now();
ren.apply();
boost::chrono::process_cpu_clock::duration elapsed = boost::chrono::process_cpu_clock::now() - start;
std::clog << "rendering took: " << boost::chrono::duration_cast<boost::chrono::milliseconds>(elapsed) << "\n";
}
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());

View file

@ -263,7 +263,6 @@ public:
QString name() const
{
mapnik::expression_ptr filter = rule_.get_filter();
return QString(mapnik::to_expression_string(*filter).c_str());
}

View file

@ -3,12 +3,12 @@
######################################################################
TEMPLATE = app
QT += core gui widgets
QMAKE_CXX = clang++
QMAKE_CXX = $$system(mapnik-config --cxx)
QMAKE_LINK = $$system(mapnik-config --cxx)
QMAKE_CXXFLAGS += $$system(mapnik-config --cxxflags)
QMAKE_CXXFLAGS += $$system(mapnik-config --includes --dep-includes)
QMAKE_CXXFLAGS += $$system(mapnik-config --includes --dep-includes --defines)
QMAKE_LFLAGS += $$system(mapnik-config --libs)
QMAKE_LFLAGS += $$system(mapnik-config --ldflags --dep-libs)
QMAKE_LFLAGS += -lboost_timer
# Input
CONFIG += qt debug_and_release

33
deps/agg/build.py vendored
View file

@ -1,19 +1,21 @@
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
# This file is part of Mapnik (c++ mapping toolkit)
#
# This program 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 General Public License for more details.
# Copyright (C) 2013 Artem Pavlenko
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Mapnik 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
#
#
@ -24,9 +26,6 @@ Import('env')
agg_env = env.Clone()
if env['SUNCC']:
cxxflags = env['CUSTOM_CXXFLAGS'] + ' -O -KPIC -DNDEBUG'
else:
cxxflags = env['CUSTOM_CXXFLAGS'] + ' -O%s -fPIC -DNDEBUG' % env['OPTIMIZATION']
cxxflags = env['CUSTOM_CXXFLAGS'] + ' -O%s -fPIC -DNDEBUG' % env['OPTIMIZATION']
agg_env.StaticLibrary('agg', glob('./src/' + '*.cpp'), LIBS=[], CXXFLAGS=cxxflags, LINKFLAGS=env['CUSTOM_LDFLAGS'])

View file

@ -516,10 +516,11 @@ namespace agg
if(m_num_blocks)
{
T** blk = m_blocks + m_num_blocks - 1;
while(m_num_blocks--)
while(m_num_blocks > 0)
{
pod_allocator<T>::deallocate(*blk, block_size);
--blk;
--m_num_blocks;
}
}
pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);

View file

@ -1,295 +1,295 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 1.1 *
* Date : 4 April 2011 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2011 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
* *
*******************************************************************************/
#ifndef AGG_CONV_CLIPPER_INCLUDED
#define AGG_CONV_CLIPPER_INCLUDED
#include <cmath>
#include "agg_basics.h"
#include "agg_array.h"
#include "clipper.hpp"
namespace agg
{
enum clipper_op_e { clipper_or,
clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a };
enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative};
template<class VSA, class VSB> class conv_clipper
{
enum status { status_move_to, status_line_to, status_stop };
typedef VSA source_a_type;
typedef VSB source_b_type;
typedef conv_clipper<source_a_type, source_b_type> self_type;
private:
source_a_type* m_src_a;
source_b_type* m_src_b;
status m_status;
int m_vertex;
int m_contour;
int m_scaling_factor;
clipper_op_e m_operation;
pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator;
ClipperLib::Polygons m_poly_a;
ClipperLib::Polygons m_poly_b;
ClipperLib::Polygons m_result;
ClipperLib::Clipper m_clipper;
clipper_PolyFillType m_subjFillType;
clipper_PolyFillType m_clipFillType;
int Round(double val)
{
if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5);
}
public:
conv_clipper(source_a_type &a, source_b_type &b,
clipper_op_e op = clipper_or,
clipper_PolyFillType subjFillType = clipper_even_odd,
clipper_PolyFillType clipFillType = clipper_even_odd,
int scaling_factor = 2) :
m_src_a(&a),
m_src_b(&b),
m_status(status_move_to),
m_vertex(-1),
m_contour(-1),
m_operation(op),
m_subjFillType(subjFillType),
m_clipFillType(clipFillType)
{
m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
}
~conv_clipper()
{
}
void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd)
{ m_src_a = &source; m_subjFillType = subjFillType; }
void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd)
{ m_src_b = &source; m_clipFillType = clipFillType; }
void operation(clipper_op_e v) { m_operation = v; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
bool next_contour();
bool next_vertex(double* x, double* y);
void start_extracting();
void add_vertex_(double &x, double &y);
void end_contour(ClipperLib::Polygons &p);
template<class VS> void add(VS &src, ClipperLib::Polygons &p){
unsigned cmd;
double x; double y; double start_x; double start_y;
bool starting_first_line;
start_x = 0.0;
start_y = 0.0;
starting_first_line = true;
p.resize(0);
cmd = src->vertex( &x , &y );
while(!is_stop(cmd))
{
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
if(!starting_first_line ) end_contour(p);
start_x = x;
start_y = y;
}
add_vertex_( x, y );
starting_first_line = false;
}
else if(is_end_poly(cmd))
{
if(!starting_first_line && is_closed(cmd))
add_vertex_( start_x, start_y );
}
cmd = src->vertex( &x, &y );
}
end_contour(p);
}
};
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::start_extracting()
{
m_status = status_move_to;
m_contour = -1;
m_vertex = -1;
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::rewind(unsigned path_id)
{
m_src_a->rewind( path_id );
m_src_b->rewind( path_id );
add( m_src_a , m_poly_a );
add( m_src_b , m_poly_b );
m_result.resize(0);
ClipperLib::PolyFillType pftSubj, pftClip;
switch (m_subjFillType)
{
case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break;
case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break;
case clipper_positive: pftSubj = ClipperLib::pftPositive; break;
default: pftSubj = ClipperLib::pftNegative;
}
switch (m_clipFillType)
{
case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break;
case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break;
case clipper_positive: pftClip = ClipperLib::pftPositive; break;
default: pftClip = ClipperLib::pftNegative;
}
m_clipper.Clear();
switch( m_operation ) {
case clipper_or:
{
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip);
break;
}
case clipper_and:
{
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip );
break;
}
case clipper_xor:
{
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip );
break;
}
case clipper_a_minus_b:
{
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip );
break;
}
case clipper_b_minus_a:
{
m_clipper.AddPolygons( m_poly_b , ClipperLib::ptSubject );
m_clipper.AddPolygons( m_poly_a , ClipperLib::ptClip );
m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip );
break;
}
}
start_extracting();
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::end_contour( ClipperLib::Polygons &p)
{
unsigned i, len;
if( m_vertex_accumulator.size() < 3 ) return;
len = p.size();
p.resize(len+1);
p[len].resize(m_vertex_accumulator.size());
for( i = 0 ; i < m_vertex_accumulator.size() ; i++ )
p[len][i] = m_vertex_accumulator[i];
m_vertex_accumulator.remove_all();
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::add_vertex_(double &x, double &y)
{
ClipperLib::IntPoint v;
v.X = Round(x * m_scaling_factor);
v.Y = Round(y * m_scaling_factor);
m_vertex_accumulator.add( v );
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
bool conv_clipper<VSA, VSB>::next_contour()
{
m_contour++;
if(m_contour >= (int)m_result.size()) return false;
m_vertex =-1;
return true;
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
bool conv_clipper<VSA, VSB>::next_vertex(double *x, double *y)
{
m_vertex++;
if(m_vertex >= (int)m_result[m_contour].size()) return false;
*x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor;
*y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor;
return true;
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y)
{
if( m_status == status_move_to )
{
if( next_contour() )
{
if( next_vertex( x, y ) )
{
m_status =status_line_to;
return path_cmd_move_to;
}
else
{
m_status = status_stop;
return path_cmd_end_poly | path_flags_close;
}
}
else
return path_cmd_stop;
}
else
{
if( next_vertex( x, y ) )
{
return path_cmd_line_to;
}
else
{
m_status = status_move_to;
return path_cmd_end_poly | path_flags_close;
}
}
}
//------------------------------------------------------------------------------
} //namespace agg
#endif //AGG_CONV_CLIPPER_INCLUDED
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 1.1 *
* Date : 4 April 2011 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2011 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
* *
*******************************************************************************/
#ifndef AGG_CONV_CLIPPER_INCLUDED
#define AGG_CONV_CLIPPER_INCLUDED
#include <cmath>
#include "agg_basics.h"
#include "agg_array.h"
#include "clipper.hpp"
namespace agg
{
enum clipper_op_e { clipper_or,
clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a };
enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative};
template<class VSA, class VSB> class conv_clipper
{
enum status { status_move_to, status_line_to, status_stop };
typedef VSA source_a_type;
typedef VSB source_b_type;
typedef conv_clipper<source_a_type, source_b_type> self_type;
private:
source_a_type* m_src_a;
source_b_type* m_src_b;
status m_status;
int m_vertex;
int m_contour;
int m_scaling_factor;
clipper_op_e m_operation;
pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator;
ClipperLib::Paths m_poly_a;
ClipperLib::Paths m_poly_b;
ClipperLib::Paths m_result;
ClipperLib::Clipper m_clipper;
clipper_PolyFillType m_subjFillType;
clipper_PolyFillType m_clipFillType;
int Round(double val)
{
if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5);
}
public:
conv_clipper(source_a_type &a, source_b_type &b,
clipper_op_e op = clipper_or,
clipper_PolyFillType subjFillType = clipper_even_odd,
clipper_PolyFillType clipFillType = clipper_even_odd,
int scaling_factor = 2) :
m_src_a(&a),
m_src_b(&b),
m_status(status_move_to),
m_vertex(-1),
m_contour(-1),
m_operation(op),
m_subjFillType(subjFillType),
m_clipFillType(clipFillType)
{
m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
}
~conv_clipper()
{
}
void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd)
{ m_src_a = &source; m_subjFillType = subjFillType; }
void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd)
{ m_src_b = &source; m_clipFillType = clipFillType; }
void operation(clipper_op_e v) { m_operation = v; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
bool next_contour();
bool next_vertex(double* x, double* y);
void start_extracting();
void add_vertex_(double &x, double &y);
void end_contour(ClipperLib::Paths &p);
template<class VS> void add(VS &src, ClipperLib::Paths &p){
unsigned cmd;
double x; double y; double start_x; double start_y;
bool starting_first_line;
start_x = 0.0;
start_y = 0.0;
starting_first_line = true;
p.resize(0);
cmd = src->vertex( &x , &y );
while(!is_stop(cmd))
{
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
if(!starting_first_line ) end_contour(p);
start_x = x;
start_y = y;
}
add_vertex_( x, y );
starting_first_line = false;
}
else if(is_end_poly(cmd))
{
if(!starting_first_line && is_closed(cmd))
add_vertex_( start_x, start_y );
}
cmd = src->vertex( &x, &y );
}
end_contour(p);
}
};
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::start_extracting()
{
m_status = status_move_to;
m_contour = -1;
m_vertex = -1;
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::rewind(unsigned path_id)
{
m_src_a->rewind( path_id );
m_src_b->rewind( path_id );
add( m_src_a , m_poly_a );
add( m_src_b , m_poly_b );
m_result.resize(0);
ClipperLib::PolyFillType pftSubj, pftClip;
switch (m_subjFillType)
{
case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break;
case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break;
case clipper_positive: pftSubj = ClipperLib::pftPositive; break;
default: pftSubj = ClipperLib::pftNegative;
}
switch (m_clipFillType)
{
case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break;
case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break;
case clipper_positive: pftClip = ClipperLib::pftPositive; break;
default: pftClip = ClipperLib::pftNegative;
}
m_clipper.Clear();
switch( m_operation ) {
case clipper_or:
{
m_clipper.AddPaths( m_poly_a , ClipperLib::ptSubject, true );
m_clipper.AddPaths( m_poly_b , ClipperLib::ptClip, true );
m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip);
break;
}
case clipper_and:
{
m_clipper.AddPaths( m_poly_a , ClipperLib::ptSubject, true );
m_clipper.AddPaths( m_poly_b , ClipperLib::ptClip, true );
m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip );
break;
}
case clipper_xor:
{
m_clipper.AddPaths( m_poly_a , ClipperLib::ptSubject, true );
m_clipper.AddPaths( m_poly_b , ClipperLib::ptClip, true );
m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip );
break;
}
case clipper_a_minus_b:
{
m_clipper.AddPaths( m_poly_a , ClipperLib::ptSubject, true );
m_clipper.AddPaths( m_poly_b , ClipperLib::ptClip, true );
m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip );
break;
}
case clipper_b_minus_a:
{
m_clipper.AddPaths( m_poly_b , ClipperLib::ptSubject, true );
m_clipper.AddPaths( m_poly_a , ClipperLib::ptClip, true );
m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip );
break;
}
}
start_extracting();
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::end_contour( ClipperLib::Paths &p)
{
unsigned i, len;
if( m_vertex_accumulator.size() < 3 ) return;
len = p.size();
p.resize(len+1);
p[len].resize(m_vertex_accumulator.size());
for( i = 0 ; i < m_vertex_accumulator.size() ; i++ )
p[len][i] = m_vertex_accumulator[i];
m_vertex_accumulator.remove_all();
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_clipper<VSA, VSB>::add_vertex_(double &x, double &y)
{
ClipperLib::IntPoint v;
v.X = Round(x * m_scaling_factor);
v.Y = Round(y * m_scaling_factor);
m_vertex_accumulator.add( v );
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
bool conv_clipper<VSA, VSB>::next_contour()
{
m_contour++;
if(m_contour >= (int)m_result.size()) return false;
m_vertex =-1;
return true;
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
bool conv_clipper<VSA, VSB>::next_vertex(double *x, double *y)
{
m_vertex++;
if(m_vertex >= (int)m_result[m_contour].size()) return false;
*x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor;
*y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor;
return true;
}
//------------------------------------------------------------------------------
template<class VSA, class VSB>
unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y)
{
if( m_status == status_move_to )
{
if( next_contour() )
{
if( next_vertex( x, y ) )
{
m_status =status_line_to;
return path_cmd_move_to;
}
else
{
m_status = status_stop;
return path_cmd_end_poly | path_flags_close;
}
}
else
return path_cmd_stop;
}
else
{
if( next_vertex( x, y ) )
{
return path_cmd_line_to;
}
else
{
m_status = status_move_to;
return path_cmd_end_poly | path_flags_close;
}
}
}
//------------------------------------------------------------------------------
} //namespace agg
#endif //AGG_CONV_CLIPPER_INCLUDED

View file

@ -137,7 +137,7 @@ namespace agg
//--------------------------------------------------------------------
void remove_all();
void add_color(double offset, const color_type& color);
void build_lut();
bool build_lut();
// Size-index Interface. This class can be used directly as the
// ColorF in span_gradient. All it needs is two access methods
@ -202,7 +202,7 @@ namespace agg
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T,S>::build_lut()
bool gradient_lut<T,S>::build_lut()
{
quick_sort(m_color_profile, offset_less);
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
@ -234,7 +234,9 @@ namespace agg
{
m_color_lut[end] = c;
}
return true;
}
return false;
}
}

View file

@ -134,7 +134,7 @@ namespace agg
static AGG_INLINE void blend_pix(value_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned cover=0)
unsigned /*cover*/=0)
{
calc_type r = p[Order::R];
calc_type g = p[Order::G];
@ -363,7 +363,7 @@ namespace agg
p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift));
p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift));
p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
p[Order::A] = (value_type)(p[Order::A] + ((sa * d1a + base_mask) >> base_shift));
}
};
@ -686,9 +686,9 @@ namespace agg
}
if(sa)
{
calc_type dr = p[Order::R] - sr;
calc_type dg = p[Order::G] - sg;
calc_type db = p[Order::B] - sb;
calc_type dr = (sr > p[Order::R]) ? 0 : p[Order::R] - sr;
calc_type dg = (sg > p[Order::G]) ? 0 : p[Order::G] - sg;
calc_type db = (sb > p[Order::B]) ? 0 : p[Order::B] - sb;
p[Order::R] = (dr > base_mask) ? 0 : dr;
p[Order::G] = (dg > base_mask) ? 0 : dg;
p[Order::B] = (db > base_mask) ? 0 : db;
@ -1444,68 +1444,8 @@ namespace agg
}
};
// colorize alpha values
// TODO - consider moving to image-filters:
// https://github.com/mapnik/mapnik/issues/1371
/*
template <typename ColorT, typename Order>
struct comp_op_rgba_colorize_alpha
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
enum base_scale_e
{
base_shift = color_type::base_shift,
base_mask = color_type::base_mask
};
static AGG_INLINE void blend_pix(value_type* p,
// source rgb
unsigned sr, unsigned sg, unsigned sb,
// source alpha and opacity
unsigned sa, unsigned cover)
{
if(cover < 255)
{
sr = (sr * cover + 255) >> 8;
sg = (sg * cover + 255) >> 8;
sb = (sb * cover + 255) >> 8;
sa = (sa * cover + 255) >> 8;
}
if (sa > 0)
{
p[Order::R] = (value_type)(((0 + base_mask) >> base_shift));
p[Order::G] = (value_type)(((0 + base_mask) >> base_shift));
p[Order::B] = (value_type)(((0 + base_mask) >> base_shift));
p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
// http://en.wikipedia.org/wiki/File:HSV-RGB-comparison.svg
if (p[Order::A] < 64) {
p[Order::G] = ((p[Order::A] - 64) * 4);
p[Order::B] = 255;
}
if (p[Order::A] >= 64 && p[Order::A] < 128) {
p[Order::G] = 255;
p[Order::B] = 255 - ((p[Order::A] - 64) * 4);
}
if (p[Order::A] >= 128 && p[Order::A] < 192) {
p[Order::R] = ((p[Order::A] - 128) * 4);
p[Order::G] = 255;
}
if (p[Order::A] >= 192) {
p[Order::R] = 255;
p[Order::G] = 255 - ((p[Order::A] - 192) * 4);
}
}
}
};
*/
// grain extract (GIMP)
// E = I - M + 128
template <typename ColorT, typename Order>
struct comp_op_rgba_grain_extract
{

View file

@ -131,10 +131,11 @@ namespace agg
if(m_num_blocks)
{
cell_type** ptr = m_cells + m_num_blocks - 1;
while(m_num_blocks--)
while(m_num_blocks > 0)
{
pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
ptr--;
--m_num_blocks;
}
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
}
@ -663,23 +664,26 @@ namespace agg
cell_type* cell_ptr;
unsigned nb = m_num_cells >> cell_block_shift;
unsigned i;
while(nb--)
while(nb > 0)
{
cell_ptr = *block_ptr++;
i = cell_block_size;
while(i--)
while(i > 0)
{
m_sorted_y[cell_ptr->y - m_min_y].start++;
++cell_ptr;
--i;
}
--nb;
}
cell_ptr = *block_ptr++;
i = m_num_cells & cell_block_mask;
while(i--)
while(i > 0)
{
m_sorted_y[cell_ptr->y - m_min_y].start++;
++cell_ptr;
--i;
}
// Convert the Y-histogram into the array of starting indexes
@ -694,27 +698,30 @@ namespace agg
// Fill the cell pointer array sorted by Y
block_ptr = m_cells;
nb = m_num_cells >> cell_block_shift;
while(nb--)
while(nb > 0)
{
cell_ptr = *block_ptr++;
i = cell_block_size;
while(i--)
while(i > 0)
{
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
++curr_y.num;
++cell_ptr;
--i;
}
--nb;
}
cell_ptr = *block_ptr++;
i = m_num_cells & cell_block_mask;
while(i--)
while(i > 0)
{
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
++curr_y.num;
++cell_ptr;
--i;
}
// Finally arrange the X-arrays

View file

@ -186,10 +186,11 @@ namespace agg
T** rows = &m_rows[0];
while(height--)
while(height > 0)
{
*rows++ = row_ptr;
row_ptr += stride;
--height;
}
}

View file

@ -895,9 +895,9 @@ namespace agg
if(fg[3] < 0) fg[3] = 0;
if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R];
if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G];
if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B];
if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
span->r = (value_type)fg[order_type::R];
span->g = (value_type)fg[order_type::G];

View file

@ -18,6 +18,9 @@
#include "agg_basics.h"
// https://github.com/mapnik/mapnik/issues/1860
#include <mapnik/config.hpp>
namespace agg
{
@ -25,7 +28,7 @@ namespace agg
//
// See Implementation agg_vpgen_clip_polyline.cpp
//
class vpgen_clip_polyline
class MAPNIK_DECL vpgen_clip_polyline
{
public:
vpgen_clip_polyline() :

View file

@ -24,9 +24,6 @@ Import('env')
clipper_env = env.Clone()
if env['SUNCC']:
cxxflags = env['CUSTOM_CXXFLAGS'] + ' -O -KPIC -DNDEBUG'
else:
cxxflags = env['CUSTOM_CXXFLAGS'] + ' -O%s -fPIC -DNDEBUG' % env['OPTIMIZATION']
cxxflags = env['CUSTOM_CXXFLAGS'] + ' -O%s -fPIC -DNDEBUG' % env['OPTIMIZATION']
clipper_env.StaticLibrary('clipper', ['./src/clipper.cpp',], LIBS=[], CXXFLAGS=cxxflags, LINKFLAGS=env['CUSTOM_LDFLAGS'])

View file

@ -1,8 +1,8 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 5.1.5 *
* Date : 4 May 2013 *
* Version : 6.0.0 *
* Date : 30 October 2013 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 *
* *
@ -35,12 +35,30 @@
#define clipper_hpp
#include <mapnik/config.hpp>
#define CLIPPER_VERSION "6.0.0"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
//#define use_int32
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines
//When enabled, code developed with earlier versions of Clipper
//(ie prior to ver 6) should compile without changes.
//In a future update, this compatability code will be removed.
#define use_deprecated
#include <vector>
#include <set>
#include <stdexcept>
#include <cstring>
#include <cstdlib>
#include <ostream>
#include <functional>
namespace ClipperLib {
@ -52,23 +70,63 @@ enum PolyType { ptSubject, ptClip };
//see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
typedef signed long long long64;
typedef unsigned long long ulong64;
#ifdef use_int32
typedef int cInt;
typedef unsigned int cUInt;
#else
typedef signed long long cInt;
typedef unsigned long long cUInt;
#endif
struct IntPoint {
public:
long64 X;
long64 Y;
IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {};
friend std::ostream& operator <<(std::ostream &s, IntPoint &p);
cInt X;
cInt Y;
#ifdef use_xyz
cInt Z;
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
#else
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
#endif
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
{
return a.X != b.X || a.Y != b.Y;
}
};
//------------------------------------------------------------------------------
typedef std::vector< IntPoint > Polygon;
typedef std::vector< Polygon > Polygons;
typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
std::ostream& operator <<(std::ostream &s, Polygon &p);
std::ostream& operator <<(std::ostream &s, Polygons &p);
std::ostream& operator <<(std::ostream &s, const IntPoint &p);
std::ostream& operator <<(std::ostream &s, const Path &p);
std::ostream& operator <<(std::ostream &s, const Paths &p);
#ifdef use_deprecated
typedef signed long long long64; //backward compatibility only
typedef Path Polygon;
typedef Paths Polygons;
#endif
struct DoublePoint
{
double X;
double Y;
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
};
//------------------------------------------------------------------------------
#ifdef use_xyz
typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt);
#endif
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;
@ -77,13 +135,15 @@ class PolyNode
{
public:
PolyNode();
Polygon Contour;
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
bool m_IsOpen;
PolyNode* GetNextSiblingUp() const;
unsigned Index; //node index in Parent.Childs
void AddChild(PolyNode& child);
@ -101,113 +161,63 @@ private:
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
};
enum JoinType { jtSquare, jtRound, jtMiter };
bool Orientation(const Polygon &poly);
MAPNIK_DECL double Area(const Polygon &poly);
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosed, etButt, etSquare, etRound};
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
bool Orientation(const Path &poly);
double Area(const Path &poly);
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
#ifdef use_deprecated
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
void PolyTreeToPolygons(const PolyTree& polytree, Paths& paths);
void ReversePolygon(Path& p);
void ReversePolygons(Paths& p);
#endif
void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance = 1.415);
void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance = 1.415);
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype, EndType endtype, double limit = 0);
void PolyTreeToPolygons(PolyTree& polytree, Polygons& polygons);
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
void ReversePolygon(Polygon& p);
void ReversePolygons(Polygons& p);
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
void CleanPolygon(Path& poly, double distance = 1.415);
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
void CleanPolygons(Paths& polys, double distance = 1.415);
//used internally ...
void MinkowkiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void MinkowkiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
void ReversePath(Path& p);
void ReversePaths(Paths& p);
struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
//enums that are used internally ...
enum EdgeSide { esLeft = 1, esRight = 2};
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
struct TEdge {
long64 xbot;
long64 ybot;
long64 xcurr;
long64 ycurr;
long64 xtop;
long64 ytop;
double dx;
long64 deltaX;
long64 deltaY;
PolyType polyType;
EdgeSide side;
int windDelta; //1 or -1 depending on winding direction
int windCnt;
int windCnt2; //winding count of the opposite polytype
int outIdx;
TEdge *next;
TEdge *prev;
TEdge *nextInLML;
TEdge *nextInAEL;
TEdge *prevInAEL;
TEdge *nextInSEL;
TEdge *prevInSEL;
};
struct IntersectNode {
TEdge *edge1;
TEdge *edge2;
IntPoint pt;
IntersectNode *next;
};
struct LocalMinima {
long64 Y;
TEdge *leftBound;
TEdge *rightBound;
LocalMinima *next;
};
struct Scanbeam {
long64 Y;
Scanbeam *next;
};
struct OutPt; //forward declaration
struct OutRec {
int idx;
bool isHole;
OutRec *FirstLeft; //see comments in clipper.pas
PolyNode *polyNode;
OutPt *pts;
OutPt *bottomPt;
};
struct OutPt {
int idx;
IntPoint pt;
OutPt *next;
OutPt *prev;
};
struct JoinRec {
IntPoint pt1a;
IntPoint pt1b;
int poly1Idx;
IntPoint pt2a;
IntPoint pt2b;
int poly2Idx;
};
struct HorzJoinRec {
TEdge *edge;
int savedIdx;
};
struct IntRect { long64 left; long64 top; long64 right; long64 bottom; };
//forward declarations (for stuff used internally) ...
struct TEdge;
struct IntersectNode;
struct LocalMinima;
struct Scanbeam;
struct OutPt;
struct OutRec;
struct Join;
typedef std::vector < OutRec* > PolyOutList;
typedef std::vector < TEdge* > EdgeList;
typedef std::vector < JoinRec* > JoinList;
typedef std::vector < HorzJoinRec* > HorzJoinList;
typedef std::vector < Join* > JoinList;
//------------------------------------------------------------------------------
//ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of
@ -217,29 +227,43 @@ class MAPNIK_DECL ClipperBase
public:
ClipperBase();
virtual ~ClipperBase();
bool AddPolygon(const Polygon &pg, PolyType polyType);
bool AddPolygons( const Polygons &ppg, PolyType polyType);
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
#ifdef use_deprecated
bool AddPolygon(const Path &pg, PolyType PolyTyp);
bool AddPolygons(const Paths &ppg, PolyType PolyTyp);
#endif
virtual void Clear();
IntRect GetBounds();
bool PreserveCollinear() {return m_PreserveCollinear;};
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
protected:
void DisposeLocalMinimaList();
TEdge* AddBoundsToLML(TEdge *e);
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
void PopLocalMinima();
virtual void Reset();
void InsertLocalMinima(LocalMinima *newLm);
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
TEdge* DescendToMin(TEdge *&E);
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
LocalMinima *m_CurrentLM;
LocalMinima *m_MinimaList;
bool m_UseFullRange;
EdgeList m_edges;
bool m_PreserveCollinear;
bool m_HasOpenPaths;
};
//------------------------------------------------------------------------------
class MAPNIK_DECL Clipper : public virtual ClipperBase
{
public:
Clipper();
Clipper(int initOptions = 0);
~Clipper();
bool Execute(ClipType clipType,
Polygons &solution,
Paths &solution,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
bool Execute(ClipType clipType,
@ -249,17 +273,21 @@ public:
void Clear();
bool ReverseSolution() {return m_ReverseOutput;};
void ReverseSolution(bool value) {m_ReverseOutput = value;};
bool ForceSimple() {return m_ForceSimple;};
void ForceSimple(bool value) {m_ForceSimple = value;};
bool StrictlySimple() {return m_StrictSimple;};
void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
void ZFillFunction(TZFillCallback zFillFunc);
#endif
protected:
void Reset();
virtual bool ExecuteInternal();
private:
PolyOutList m_PolyOuts;
JoinList m_Joins;
HorzJoinList m_HorizJoins;
JoinList m_GhostJoins;
ClipType m_ClipType;
Scanbeam *m_Scanbeam;
std::set< cInt, std::greater<cInt> > m_Scanbeam;
TEdge *m_ActiveEdges;
TEdge *m_SortedEdges;
IntersectNode *m_IntersectNodes;
@ -268,15 +296,17 @@ private:
PolyFillType m_SubjFillType;
bool m_ReverseOutput;
bool m_UsingPolyTree;
bool m_ForceSimple;
void DisposeScanbeamList();
bool m_StrictSimple;
#ifdef use_xyz
TZFillCallback m_ZFill; //custom callback
#endif
void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const;
bool IsEvenOddAltFillType(const TEdge& edge) const;
void InsertScanbeam(const long64 Y);
long64 PopScanbeam();
void InsertLocalMinimaIntoAEL(const long64 botY);
void InsertEdgeIntoAEL(TEdge *edge);
void InsertScanbeam(const cInt Y);
cInt PopScanbeam();
void InsertLocalMinimaIntoAEL(const cInt botY);
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
void AddEdgeToSEL(TEdge *edge);
void CopyAELToSEL();
void DeleteFromSEL(TEdge *e);
@ -284,27 +314,28 @@ private:
void UpdateEdgeIntoAEL(TEdge *&e);
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
bool IsContributing(const TEdge& edge) const;
bool IsTopHorz(const long64 XPos);
bool IsTopHorz(const cInt XPos);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
void DoMaxima(TEdge *e, long64 topY);
void ProcessHorizontals();
void ProcessHorizontal(TEdge *horzEdge);
void DoMaxima(TEdge *e);
void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam);
void ProcessHorizontals(bool IsTopOfScanbeam);
void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutRec* GetOutRec(int idx);
void AppendPolygon(TEdge *e1, TEdge *e2);
void IntersectEdges(TEdge *e1, TEdge *e2,
const IntPoint &pt, const IntersectProtects protects);
const IntPoint &pt, bool protect = false);
OutRec* CreateOutRec();
void AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeAllPolyPts();
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const long64 botY, const long64 topY);
void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
void BuildIntersectList(const long64 botY, const long64 topY);
bool ProcessIntersections(const cInt botY, const cInt topY);
void InsertIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
void BuildIntersectList(const cInt botY, const cInt topY);
void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const long64 topY);
void BuildResult(Polygons& polys);
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Paths& polys);
void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *outrec);
void DisposeIntersectNodes();
@ -312,19 +343,19 @@ private:
void FixupOutPolygon(OutRec &outrec);
bool IsHole(TEdge *e);
void FixHoleLinkage(OutRec &outrec);
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
void ClearJoins();
void AddHorzJoin(TEdge *e, int idx);
void ClearHorzJoins();
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
void ClearGhostJoins();
void AddGhostJoin(OutPt *op, const IntPoint offPt);
bool JoinPoints(const Join *j, OutPt *&p1, OutPt *&p2);
void JoinCommonEdges();
void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
#ifdef use_xyz
void SetZ(IntPoint& pt, TEdge& e);
#endif
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class clipperException : public std::exception

File diff suppressed because it is too large Load diff

View file

@ -48,12 +48,11 @@ Mapnik is licensed LGPL, which means that you are a free to use the code in any
## Copyright
Mapnik is an open source project and will always be, proudly, an open source project. Your contributions to Mapnik should be motivated by (amount other things) your desire to contribute to a community effort and by the knowledge that your open code will stay that way.
Mapnik is an open source project and will always be. Your contributions to Mapnik should be motivated by your desire to contribute to a community effort and by the knowledge that your open code will stay that way.
Artem, as the founder and leader of the Mapnik project, is the primary copyright holder and therefore also the primary contact for any current or future license questions around Mapnik. It is important that the copyright holder is respected, trusted, and known to the community so maintaining copyright with Artem is key to maintaining the project as open source.
Therefore, convention is that all new files created by any core developers or patch
authors should have a copyright declaration like:
Therefore all files created by any core developers or patch authors should have a copyright declaration like:
/*****************************************************************************
*

View file

@ -1,20 +1,22 @@
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2013 Artem Pavlenko
#
# Mapnik 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
#
#
import os

View file

@ -1,3 +1,24 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2013 Artem Pavlenko
#
# Mapnik 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
#
#
import os
from glob import glob
@ -9,6 +30,9 @@ subdirs = ['','svg','wkt','grid','json','util','text_placements','formatting']
if env['SVG_RENDERER']:
subdirs.append('svg/output')
if env['GRID_RENDERER']:
subdirs.append('grid')
if 'install' in COMMAND_LINE_TARGETS:
for subdir in subdirs:
pathdir = os.path.join(base,subdir,'*.hpp')

View file

@ -25,17 +25,12 @@
// mapnik
#include <mapnik/gamma_method.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/stroke.hpp> // for line_cap_e, line_join_e, etc
// agg
#include "agg_basics.h"
#include "agg_gamma_functions.h"
#include "agg_math_stroke.h"
#include "agg_pixfmt_rgba.h"
#include "agg_scanline_u.h"
#include "agg_scanline_p.h"
#include "agg_renderer_outline_aa.h"
#include "agg_renderer_scanline.h"
#include "agg_gamma_functions.h" // for gamma_power, gamma_linear, etc
#include "agg_math_stroke.h" // for line_join_e::miter_join, etc
#include "agg_rasterizer_outline_aa.h"
namespace mapnik {

View file

@ -31,7 +31,7 @@
namespace mapnik {
struct rasterizer : agg::rasterizer_scanline_aa<>, mapnik::noncopyable {};
struct rasterizer : agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_int_sat>, mapnik::noncopyable {};
}

View file

@ -132,6 +132,26 @@ public:
return DEFAULT;
}
inline double scale_factor() const
{
return scale_factor_;
}
inline box2d<double> clipping_extent() const
{
if (t_.offset() > 0)
{
box2d<double> box = query_extent_;
double scale = static_cast<double>(query_extent_.width())/static_cast<double>(width_);
// 3 is used here because at least 3 was needed for the 'style-level-compositing-tiled-0,1' visual test to pass
// TODO - add more tests to hone in on a more robust #
scale *= t_.offset()*3;
box.pad(scale);
return box;
}
return query_extent_;
}
protected:
template <typename R>
void debug_draw_box(R& buf, box2d<double> const& extent,
@ -144,14 +164,14 @@ private:
buffer_type & pixmap_;
boost::shared_ptr<buffer_type> internal_buffer_;
boost::shared_ptr<buffer_type> internal_buffer2_;
mutable buffer_type * current_buffer_;
mutable buffer_type * current_layer_buffer_;
mutable buffer_type * current_buffer_;
CoordTransform t_;
mutable bool style_level_compositing_;
mutable bool layer_level_opacity_;
unsigned width_;
unsigned height_;
double scale_factor_;
CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
boost::shared_ptr<label_collision_detector4> detector_;

View file

@ -47,7 +47,6 @@
#include <mapnik/text_placements/base.hpp> // for text_placements
// boost
#include <boost/concept_check.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
@ -62,12 +61,11 @@ struct expression_attributes : boost::static_visitor<void>
explicit expression_attributes(Container& names)
: names_(names) {}
void operator() (value_type const& x) const
void operator() (value_type const& /*x*/) const
{
boost::ignore_unused_variable_warning(x);
}
void operator() (geometry_type_attribute const& type) const
void operator() (geometry_type_attribute const& /*type*/) const
{
// do nothing
}
@ -107,8 +105,11 @@ private:
struct symbolizer_attributes : public boost::static_visitor<>
{
symbolizer_attributes(std::set<std::string>& names)
: names_(names), f_attr(names) {}
symbolizer_attributes(std::set<std::string>& names,
double & filter_factor)
: names_(names),
filter_factor_(filter_factor),
f_attr(names) {}
template <typename T>
void operator () (T const&) const {}
@ -199,6 +200,11 @@ struct symbolizer_attributes : public boost::static_visitor<>
{
boost::apply_visitor(f_attr,*width_expr);
}
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform());
}
@ -212,10 +218,15 @@ struct symbolizer_attributes : public boost::static_visitor<>
}
collect_transform(sym.get_transform());
}
// TODO - support remaining syms
void operator () (raster_symbolizer const& sym)
{
filter_factor_ = sym.calculate_filter_factor();
}
private:
std::set<std::string>& names_;
double & filter_factor_;
expression_attributes<std::set<std::string> > f_attr;
void collect_transform(transform_list_ptr const& trans_expr)
{
@ -231,18 +242,20 @@ class attribute_collector : public mapnik::noncopyable
{
private:
std::set<std::string>& names_;
double filter_factor_;
expression_attributes<std::set<std::string> > f_attr;
public:
attribute_collector(std::set<std::string>& names)
: names_(names), f_attr(names) {}
: names_(names),
filter_factor_(1.0),
f_attr(names) {}
template <typename RuleType>
void operator() (RuleType const& r)
{
typename RuleType::symbolizers const& symbols = r.get_symbolizers();
typename RuleType::symbolizers::const_iterator symIter=symbols.begin();
symbolizer_attributes s_attr(names_);
symbolizer_attributes s_attr(names_,filter_factor_);
while (symIter != symbols.end())
{
boost::apply_visitor(s_attr,*symIter++);
@ -251,22 +264,11 @@ public:
expression_ptr const& expr = r.get_filter();
boost::apply_visitor(f_attr,*expr);
}
};
struct directive_collector : public boost::static_visitor<>
{
directive_collector(double & filter_factor)
: filter_factor_(filter_factor) {}
template <typename T>
void operator () (T const&) const {}
void operator () (raster_symbolizer const& sym)
double get_filter_factor() const
{
filter_factor_ = sym.calculate_filter_factor();
return filter_factor_;
}
private:
double & filter_factor_;
};
} // namespace mapnik

View file

@ -57,12 +57,14 @@ private:
T miny_;
T maxx_;
T maxy_;
void swap(box2d_type & rhs);
public:
box2d();
box2d(T minx,T miny,T maxx,T maxy);
box2d(const coord<T,2>& c0,const coord<T,2>& c1);
box2d(const box2d_type& rhs);
box2d(const box2d_type& rhs, const agg::trans_affine& tr);
box2d(coord<T,2> const& c0, coord<T,2> const& c1);
box2d(box2d_type const& rhs);
box2d(box2d_type const& rhs, agg::trans_affine const& tr);
box2d_type& operator=(box2d_type other);
T minx() const;
T miny() const;
T maxx() const;
@ -77,22 +79,22 @@ public:
void height(T h);
coord<T,2> center() const;
void expand_to_include(T x,T y);
void expand_to_include(const coord<T,2>& c);
void expand_to_include(const box2d_type& other);
bool contains(const coord<T,2> &c) const;
void expand_to_include(coord<T,2> const& c);
void expand_to_include(box2d_type const& other);
bool contains(coord<T,2> const& c) const;
bool contains(T x,T y) const;
bool contains(const box2d_type &other) const;
bool intersects(const coord<T,2> &c) const;
bool contains(box2d_type const& other) const;
bool intersects(coord<T,2> const& c) const;
bool intersects(T x,T y) const;
bool intersects(const box2d_type &other) const;
box2d_type intersect(const box2d_type& other) const;
bool operator==(const box2d_type &other) const;
bool intersects(box2d_type const& other) const;
box2d_type intersect(box2d_type const& other) const;
bool operator==(box2d_type const& other) const;
void re_center(T cx,T cy);
void re_center(const coord<T,2>& c);
void re_center(coord<T,2> const& c);
void init(T x0,T y0,T x1,T y1);
void clip(const box2d_type &other);
void clip(box2d_type const& other);
void pad(T padding);
bool from_string(std::string const& s);
bool from_string(std::string const& str);
bool valid() const;
// define some operators

View file

@ -59,7 +59,7 @@ 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");
throw std::runtime_error(std::string("cairo: ") + cairo_status_to_string(status));
}
//We inline this because it is called so often.
@ -70,7 +70,7 @@ inline void check_status_and_throw_exception(ErrorStatus status)
}
template<class T>
void check_object_status_and_throw_exception(const T& object)
void check_object_status_and_throw_exception(T const& object)
{
check_status_and_throw_exception(object.get_status());
}

View file

@ -43,10 +43,6 @@
// boost
#include <boost/scoped_ptr.hpp>
// FIXME
// forward declare so that
// apps using mapnik do not
// need agg headers
namespace agg {
struct trans_affine;
}
@ -129,6 +125,11 @@ public:
return DEFAULT;
}
inline double scale_factor() const
{
return scale_factor_;
}
void render_marker(pixel_position const& pos,
marker const& marker,
agg::trans_affine const& mtx,

View file

@ -134,9 +134,9 @@ public:
inline unsigned rgba() const
{
#ifdef MAPNIK_BIG_ENDIAN
return (alpha_) | (blue_ << 8) | (green_ << 16) | (red_ << 24) ;
return static_cast<unsigned>((alpha_) | (blue_ << 8) | (green_ << 16) | (red_ << 24)) ;
#else
return (alpha_ << 24) | (blue_ << 16) | (green_ << 8) | (red_) ;
return static_cast<unsigned>((alpha_ << 24) | (blue_ << 16) | (green_ << 8) | (red_)) ;
#endif
}
};

View file

@ -25,6 +25,7 @@
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/util/hsl.hpp>
// spirit2
#include <boost/spirit/include/qi.hpp>
@ -39,24 +40,6 @@
// stl
#include <string>
namespace mapnik {
// http://www.w3.org/TR/css3-color/#hsl-color
inline double hue_to_rgb( double m1, double m2, double h)
{
if (h < 0.0) h = h + 1.0;
else if (h > 1) h = h - 1.0;
if (h * 6 < 1.0)
return m1 + (m2 - m1) * h * 6.0;
if (h * 2 < 1.0)
return m2;
if (h * 3 < 2.0)
return m1 + (m2 - m1)* (2.0/3.0 - h) * 6.0;
return m1;
}
} // namespace mapnik
// boost
#include <boost/version.hpp>
@ -125,7 +108,11 @@ struct alpha_conv_impl
struct hsl_conv_impl
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template<typename T>
#else
template<typename T0,typename T1, typename T2, typename T3>
#endif
struct result
{
typedef void type;

View file

@ -123,17 +123,19 @@ private:
box2d<double> extent_;
double offset_x_;
double offset_y_;
int offset_;
double sx_;
double sy_;
public:
CoordTransform(int width, int height, const box2d<double>& extent,
double offset_x = 0, double offset_y = 0)
double offset_x = 0.0, double offset_y = 0.0)
: width_(width),
height_(height),
extent_(extent),
offset_x_(offset_x),
offset_y_(offset_y),
offset_(0),
sx_(1.0),
sy_(1.0)
{
@ -143,6 +145,26 @@ public:
sy_ = static_cast<double>(height_) / extent_.height();
}
inline int offset() const
{
return offset_;
}
inline void set_offset(int offset)
{
offset_ = offset;
}
inline double offset_x() const
{
return offset_x_;
}
inline double offset_y() const
{
return offset_y_;
}
inline int width() const
{
return width_;
@ -165,14 +187,14 @@ public:
inline void forward(double *x, double *y) const
{
*x = (*x - extent_.minx()) * sx_ - offset_x_;
*y = (extent_.maxy() - *y) * sy_ - offset_y_;
*x = (*x - extent_.minx()) * sx_ - (offset_x_ - offset_);
*y = (extent_.maxy() - *y) * sy_ - (offset_y_ - offset_);
}
inline void backward(double *x, double *y) const
{
*x = extent_.minx() + (*x + offset_x_) / sx_;
*y = extent_.maxy() - (*y + offset_y_) / sy_;
*x = extent_.minx() + (*x + (offset_x_ - offset_)) / sx_;
*y = extent_.maxy() - (*y + (offset_y_ - offset_)) / sy_;
}
inline coord2d& forward(coord2d& c) const

View file

@ -30,6 +30,7 @@
#include <mapnik/query.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/noncopyable.hpp>
#include <mapnik/feature_style_processor_context.hpp>
// boost
#include <boost/shared_ptr.hpp>
@ -109,6 +110,13 @@ public:
* @return The type of the datasource (Vector or Raster)
*/
virtual datasource_t type() const = 0;
virtual processor_context_ptr get_context(feature_style_context_map&) const { return processor_context_ptr(); }
virtual featureset_ptr features_with_context(query const& q,processor_context_ptr /*ctx*/) const
{
// default implementation without context use features method
return features(q);
}
virtual featureset_ptr features(query const& q) const = 0;
virtual featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const = 0;
virtual box2d<double> envelope() const = 0;

View file

@ -164,7 +164,7 @@ namespace mapnik {
public:
typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
void operator()(const logger::severity_type& severity, const stream_buffer &s)
void operator()(const logger::severity_type& /*severity*/, const stream_buffer &s)
{
#ifdef MAPNIK_THREADSAFE
static boost::mutex mutex;
@ -193,15 +193,19 @@ namespace mapnik {
base_log() {}
#ifdef MAPNIK_LOG
base_log(const char* object_name)
{
#ifdef MAPNIK_LOG
if (object_name != NULL)
{
object_name_ = object_name;
}
#endif
}
#else
base_log(const char* /*object_name*/)
{
}
#endif
~base_log()
{
@ -214,13 +218,20 @@ namespace mapnik {
}
template<class T>
#ifdef MAPNIK_LOG
base_log &operator<<(const T &x)
{
#ifdef MAPNIK_LOG
streambuf_ << x;
#endif
return *this;
}
#else
base_log &operator<<(const T& /*x*/)
{
return *this;
}
#endif
private:
#ifdef MAPNIK_LOG

View file

@ -47,9 +47,29 @@ struct evaluate : boost::static_visitor<T1>
explicit evaluate(feature_type const& f)
: feature_(f) {}
value_type operator() (value_type x) const
value_integer operator() (value_integer val) const
{
return x;
return val;
}
value_double operator() (value_double val) const
{
return val;
}
value_bool operator() (value_bool val) const
{
return val;
}
value_null operator() (value_null val) const
{
return val;
}
value_unicode_string const& operator() (value_unicode_string const& str) const
{
return str;
}
value_type operator() (attribute const& attr) const

View file

@ -49,13 +49,13 @@ struct unicode_impl
template <typename T>
struct result
{
typedef UnicodeString type;
typedef mapnik::value_unicode_string type;
};
explicit unicode_impl(mapnik::transcoder const& tr)
: tr_(tr) {}
UnicodeString operator()(std::string const& str) const
mapnik::value_unicode_string operator()(std::string const& str) const
{
return tr_.transcode(str.c_str());
}
@ -65,7 +65,11 @@ struct unicode_impl
struct regex_match_impl
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef expr_node type;
@ -82,7 +86,12 @@ struct regex_match_impl
struct regex_replace_impl
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result
{
typedef expr_node type;
@ -116,8 +125,13 @@ struct integer_parser
typedef qi::int_parser<T,10,1,-1> type;
};
#ifdef __GNUC__
template <typename Iterator>
struct MAPNIK_DECL expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
#else
template <typename Iterator>
struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
#endif
{
typedef qi::rule<Iterator, expr_node(), space_type> rule_type;

View file

@ -145,7 +145,7 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
multiplicative_expr = unary_expr [_val = _1]
>> *( '*' >> unary_expr [_val *= _1]
| '/' >> unary_expr [_val /= _1]
| '%' >> unary_expr [_val %= _1]
| '%' >> unary_expr [_val %= construct<mapnik::expr_node>(_1)] //needed by clang++ with -std=c++11
| regex_match_expr[_val = regex_match_(_val, _1)]
| regex_replace_expr(_val) [_val = _1]
)

View file

@ -24,6 +24,7 @@
#define MAPNIK_EXPRESSION_NODE_HPP
// mapnik
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/expression_node_types.hpp>
@ -87,7 +88,7 @@ struct binary_node
struct regex_match_node
{
regex_match_node (expr_node const& a, UnicodeString const& ustr);
regex_match_node (expr_node const& a, mapnik::value_unicode_string const& ustr);
expr_node expr;
boost::u32regex pattern;
};
@ -95,10 +96,10 @@ struct regex_match_node
struct regex_replace_node
{
regex_replace_node (expr_node const& a, UnicodeString const& ustr, UnicodeString const& f);
regex_replace_node (expr_node const& a, mapnik::value_unicode_string const& ustr, mapnik::value_unicode_string const& f);
expr_node expr;
boost::u32regex pattern;
UnicodeString format;
mapnik::value_unicode_string format;
};
#else
@ -138,27 +139,27 @@ inline expr_node& operator- (expr_node& expr)
return expr = unary_node<tags::negate>(expr);
}
inline expr_node & operator += ( expr_node &left ,const expr_node &right)
inline expr_node & operator += ( expr_node &left, expr_node const& right)
{
return left = binary_node<tags::plus>(left,right);
}
inline expr_node & operator -= ( expr_node &left ,const expr_node &right)
inline expr_node & operator -= ( expr_node &left, expr_node const& right)
{
return left = binary_node<tags::minus>(left,right);
}
inline expr_node & operator *= ( expr_node &left ,const expr_node &right)
inline expr_node & operator *= ( expr_node &left , expr_node const& right)
{
return left = binary_node<tags::mult>(left,right);
}
inline expr_node & operator /= ( expr_node &left ,const expr_node &right)
inline expr_node & operator /= ( expr_node &left , expr_node const& right)
{
return left = binary_node<tags::div>(left,right);
}
inline expr_node & operator %= ( expr_node &left ,const expr_node &right)
inline expr_node & operator %= ( expr_node &left , expr_node const& right)
{
return left = binary_node<tags::mod>(left,right);
}

View file

@ -24,24 +24,17 @@
#define MAPNIK_EXPRESSION_NODE_TYPES_HPP
// mapnik
//#include <mapnik/value.hpp>
//#include <mapnik/attribute.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>
#include <mapnik/attribute.hpp>
// boost
#include <boost/variant/variant_fwd.hpp>
namespace boost { template <typename T> class recursive_wrapper; }
#include <boost/mpl/vector/vector30.hpp>
#include <boost/variant.hpp>
namespace mapnik
{
struct attribute;
struct geometry_type_attribute;
namespace value_adl_barrier {
class value;
}
using value_adl_barrier::value;
namespace tags {
struct negate
{
@ -174,8 +167,12 @@ struct regex_replace_node;
typedef mapnik::value value_type;
typedef boost::variant <
value_type,
typedef boost::mpl::vector24<
value_null,
value_bool,
value_integer,
value_double,
value_unicode_string,
attribute,
geometry_type_attribute,
boost::recursive_wrapper<unary_node<tags::negate> >,
@ -195,7 +192,9 @@ boost::recursive_wrapper<binary_node<tags::logical_and> >,
boost::recursive_wrapper<binary_node<tags::logical_or> >,
boost::recursive_wrapper<regex_match_node>,
boost::recursive_wrapper<regex_replace_node>
> expr_node;
>::type expr_types;
typedef boost::make_recursive_variant_over<expr_types>::type expr_node;
}

View file

@ -67,21 +67,21 @@ public:
context()
: mapping_() {}
size_type push(key_type const& name)
inline size_type push(key_type const& name)
{
size_type index = mapping_.size();
mapping_.insert(std::make_pair(name, index));
return index;
}
void add(key_type const& name, size_type index)
inline void add(key_type const& name, size_type index)
{
mapping_.insert(std::make_pair(name, index));
}
size_type size() const { return mapping_.size(); }
const_iterator begin() const { return mapping_.begin();}
const_iterator end() const { return mapping_.end();}
inline size_type size() const { return mapping_.size(); }
inline const_iterator begin() const { return mapping_.begin();}
inline const_iterator end() const { return mapping_.end();}
private:
map_type mapping_;
@ -114,18 +114,18 @@ public:
inline void set_id(mapnik::value_integer id) { id_ = id;}
template <typename T>
void put(context_type::key_type const& key, T const& val)
inline void put(context_type::key_type const& key, T const& val)
{
put(key,value(val));
}
template <typename T>
void put_new(context_type::key_type const& key, T const& val)
inline void put_new(context_type::key_type const& key, T const& val)
{
put_new(key,value(val));
}
void put(context_type::key_type const& key, value const& val)
inline void put(context_type::key_type const& key, value const& val)
{
context_type::map_type::const_iterator itr = ctx_->mapping_.find(key);
if (itr != ctx_->mapping_.end()
@ -139,7 +139,7 @@ public:
}
}
void put_new(context_type::key_type const& key, value const& val)
inline void put_new(context_type::key_type const& key, value const& val)
{
context_type::map_type::const_iterator itr = ctx_->mapping_.find(key);
if (itr != ctx_->mapping_.end()
@ -155,12 +155,12 @@ public:
}
}
bool has_key(context_type::key_type const& key) const
inline bool has_key(context_type::key_type const& key) const
{
return (ctx_->mapping_.find(key) != ctx_->mapping_.end());
}
value_type const& get(context_type::key_type const& key) const
inline value_type const& get(context_type::key_type const& key) const
{
context_type::map_type::const_iterator itr = ctx_->mapping_.find(key);
if (itr != ctx_->mapping_.end())
@ -169,74 +169,76 @@ public:
return default_value;
}
value_type const& get(std::size_t index) const
inline value_type const& get(std::size_t index) const
{
if (index < data_.size())
return data_[index];
return default_value;
}
std::size_t size() const
inline std::size_t size() const
{
return data_.size();
}
cont_type const& get_data() const
inline cont_type const& get_data() const
{
return data_;
}
void set_data(cont_type const& data)
inline void set_data(cont_type const& data)
{
data_ = data;
}
context_ptr context()
inline context_ptr context()
{
return ctx_;
}
boost::ptr_vector<geometry_type> const& paths() const
inline boost::ptr_vector<geometry_type> const& paths() const
{
return geom_cont_;
}
boost::ptr_vector<geometry_type> & paths()
inline boost::ptr_vector<geometry_type> & paths()
{
return geom_cont_;
}
void add_geometry(geometry_type * geom)
inline void add_geometry(geometry_type * geom)
{
geom_cont_.push_back(geom);
}
unsigned num_geometries() const
inline std::size_t num_geometries() const
{
return geom_cont_.size();
}
geometry_type const& get_geometry(unsigned index) const
inline geometry_type const& get_geometry(std::size_t index) const
{
return geom_cont_[index];
}
geometry_type& get_geometry(unsigned index)
inline geometry_type& get_geometry(std::size_t index)
{
return geom_cont_[index];
}
box2d<double> envelope() const
inline box2d<double> envelope() const
{
// TODO - cache this
box2d<double> result;
bool first = true;
for (unsigned i=0;i<num_geometries();++i)
{
geometry_type const& geom = get_geometry(i);
if (i==0)
if (first)
{
box2d<double> box = geom.envelope();
result.init(box.minx(),box.miny(),box.maxx(),box.maxy());
first = false;
}
else
{
@ -246,22 +248,22 @@ public:
return result;
}
raster_ptr const& get_raster() const
inline raster_ptr const& get_raster() const
{
return raster_;
}
void set_raster(raster_ptr const& raster)
inline void set_raster(raster_ptr const& raster)
{
raster_ = raster;
}
feature_kv_iterator begin() const
inline feature_kv_iterator begin() const
{
return feature_kv_iterator(*this,true);
}
feature_kv_iterator end() const
inline feature_kv_iterator end() const
{
return feature_kv_iterator(*this);
}

View file

@ -27,6 +27,7 @@
#include <mapnik/datasource.hpp> // for featureset_ptr
#include <mapnik/config.hpp>
// stl
#include <set>
#include <string>
@ -41,6 +42,7 @@ class projection;
class proj_transform;
class feature_type_style;
class rule_cache;
struct layer_rendering_material;
enum eAttributeCollectionPolicy
{
@ -67,6 +69,7 @@ public:
void apply(mapnik::layer const& lyr,
std::set<std::string>& names,
double scale_denom_override=0.0);
/*!
* \brief render a layer given a projection and scale.
*/
@ -85,16 +88,32 @@ private:
/*!
* \brief renders a featureset with the given styles.
*/
void render_style(layer const& lay,
Processor & p,
void render_style(Processor & p,
feature_type_style const* style,
rule_cache const& rules,
std::string const& style_name,
featureset_ptr features,
proj_transform const& prj_trans);
/*!
* \brief prepare features for rendering asynchronously.
*/
void prepare_layer(layer_rendering_material & mat,
feature_style_context_map & ctx_map,
Processor & p,
double scale,
double scale_denom,
unsigned width,
unsigned height,
box2d<double> const& extent,
int buffer_size,
std::set<std::string>& names);
/*!
* \brief render features list queued when they are available.
*/
void render_material(layer_rendering_material & mat, Processor & p );
Map const& m_;
double scale_factor_;
};
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
* 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
@ -20,16 +20,28 @@
*
*****************************************************************************/
#ifndef MAPNIK_DEEPCOPY_HPP
#define MAPNIK_DEEPCOPY_HPP
#ifndef FEATURE_STYLE_PROCESSOR_CONTEXT_HPP
#define FEATURE_STYLE_PROCESSOR_CONTEXT_HPP
#include <mapnik/map.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
namespace mapnik { namespace util {
// stl
#include <map>
#include <string>
// poor man deepcopy implementation
void deepcopy(Map const& map_in, Map & map_out);
namespace mapnik {
}}
#endif // MAPNIK_DEEPSOPY_HPP
class IProcessorContext {
public:
virtual ~IProcessorContext() {}
};
typedef boost::shared_ptr<IProcessorContext> processor_context_ptr;
typedef std::map<std::string, processor_context_ptr > feature_style_context_map;
}
#endif /* FEATURE_STYLE_PROCESSOR_CONTEXT_HPP */

View file

@ -33,7 +33,6 @@
#include <mapnik/query.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/memory_datasource.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/layer.hpp>
@ -41,26 +40,19 @@
#include <mapnik/rule_cache.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/util/featureset_buffer.hpp>
// boost
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/foreach.hpp>
#include <boost/concept_check.hpp>
// stl
#include <vector>
#if defined(RENDERING_STATS)
#include <mapnik/timer.hpp>
#include <iomanip>
#include <sstream>
#endif
#include <stdexcept>
namespace mapnik
{
@ -81,11 +73,8 @@ template <> // No-op specialization
struct process_impl<false>
{
template <typename T0, typename T1, typename T2, typename T3>
static void process(T0 & ren, T1 const& sym, T2 & f, T3 const& tr)
static void process(T0 & /*ren*/, T1 const& /*sym*/, T2 & /*f*/, T3 const& /*tr*/)
{
boost::ignore_unused_variable_warning(ren);
boost::ignore_unused_variable_warning(f);
boost::ignore_unused_variable_warning(tr);
#ifdef MAPNIK_DEBUG
std::clog << "NO-OP ...\n";
#endif
@ -137,13 +126,31 @@ struct has_process
);
};
// Store material for layer rendering in a two step process
struct layer_rendering_material {
layer const& lay_;
projection const& proj0_;
projection proj1_;
box2d<double> layer_ext2_;
std::vector<feature_type_style const*> active_styles_;
std::vector<featureset_ptr> featureset_ptr_list_;
boost::ptr_vector<rule_cache> rule_caches_;
layer_rendering_material(layer const& lay, projection const& dest) :
lay_(lay),
proj0_(dest),
proj1_(lay.srs(),true) {}
};
typedef boost::shared_ptr<layer_rendering_material> layer_rendering_material_ptr;
template <typename Processor>
feature_style_processor<Processor>::feature_style_processor(Map const& m, double scale_factor)
: m_(m),
scale_factor_(scale_factor)
: m_(m)
{
// https://github.com/mapnik/mapnik/issues/1100
if (scale_factor_ <= 0)
if (scale_factor <= 0)
{
throw std::runtime_error("scale_factor must be greater than 0.0");
}
@ -152,52 +159,61 @@ feature_style_processor<Processor>::feature_style_processor(Map const& m, double
template <typename Processor>
void feature_style_processor<Processor>::apply(double scale_denom)
{
#if defined(RENDERING_STATS)
std::clog << "\n//-- starting rendering timer...\n";
mapnik::progress_timer t(std::clog, "total map rendering");
#endif
Processor & p = static_cast<Processor&>(*this);
p.start_map_processing(m_);
try
projection proj(m_.srs(),true);
if (scale_denom <= 0.0)
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
scale_denom *= p.scale_factor();
// Asynchronous query supports:
// This is a two steps process,
// first we setup all queries at layer level
// in a second time, we fetch the results and
// do the actual rendering
std::vector<layer_rendering_material_ptr> mat_list;
// Define processing context map used by datasources
// implementing asynchronous queries
feature_style_context_map ctx_map;
BOOST_FOREACH ( layer const& lyr, m_.layers() )
{
projection proj(m_.srs(),true);
if (scale_denom <= 0.0)
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
scale_denom *= scale_factor_;
BOOST_FOREACH ( layer const& lyr, m_.layers() )
if (lyr.visible(scale_denom))
{
if (lyr.visible(scale_denom))
{
std::set<std::string> names;
apply_to_layer(lyr,
p,
proj,
m_.scale(),
scale_denom,
m_.width(),
m_.height(),
m_.get_current_extent(),
m_.buffer_size(),
names);
std::set<std::string> names;
layer_rendering_material_ptr mat = boost::make_shared<layer_rendering_material>(lyr, proj);
prepare_layer(*mat,
ctx_map,
p,
m_.scale(),
scale_denom,
m_.width(),
m_.height(),
m_.get_current_extent(),
m_.buffer_size(),
names);
// Store active material
if (!mat->active_styles_.empty())
{
mat_list.push_back(mat);
}
}
}
catch (proj_init_error const& ex)
BOOST_FOREACH ( layer_rendering_material_ptr mat, mat_list )
{
MAPNIK_LOG_ERROR(feature_style_processor) << "feature_style_processor: proj_init_error=" << ex.what();
if (!mat->active_styles_.empty())
{
render_material(*mat,p);
}
}
p.end_map_processing(m_);
#if defined(RENDERING_STATS)
t.stop();
std::clog << "//-- rendering timer stopped...\n\n";
#endif
}
template <typename Processor>
@ -207,36 +223,33 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
{
Processor & p = static_cast<Processor&>(*this);
p.start_map_processing(m_);
try
{
projection proj(m_.srs(),true);
if (scale_denom <= 0.0)
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
scale_denom *= scale_factor_;
projection proj(m_.srs(),true);
if (scale_denom <= 0.0)
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
scale_denom *= p.scale_factor();
if (lyr.visible(scale_denom))
{
apply_to_layer(lyr,
p,
proj,
m_.scale(),
scale_denom,
m_.width(),
m_.height(),
m_.get_current_extent(),
m_.buffer_size(),
names);
}
}
catch (proj_init_error const& ex)
if (lyr.visible(scale_denom))
{
MAPNIK_LOG_ERROR(feature_style_processor) << "feature_style_processor: proj_init_error=" << ex.what();
apply_to_layer(lyr,
p,
proj,
m_.scale(),
scale_denom,
m_.width(),
m_.height(),
m_.get_current_extent(),
m_.buffer_size(),
names);
}
p.end_map_processing(m_);
}
/*!
* \brief render a layer given a projection and scale.
*/
template <typename Processor>
void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Processor & p,
void feature_style_processor<Processor>::apply_to_layer(layer const& lay,
Processor & p,
projection const& proj0,
double scale,
double scale_denom,
@ -246,40 +259,60 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
int buffer_size,
std::set<std::string>& names)
{
feature_style_context_map ctx_map;
layer_rendering_material mat(lay, proj0);
prepare_layer(mat,
ctx_map,
p,
scale,
scale_denom,
width,
height,
extent,
buffer_size,
names);
if (!mat.active_styles_.empty())
{
render_material(mat,p);
}
}
template <typename Processor>
void feature_style_processor<Processor>::prepare_layer(layer_rendering_material & mat,
feature_style_context_map & ctx_map,
Processor & p,
double scale,
double scale_denom,
unsigned width,
unsigned height,
box2d<double> const& extent,
int buffer_size,
std::set<std::string>& names)
{
layer const& lay = mat.lay_;
std::vector<std::string> const& style_names = lay.styles();
unsigned int num_styles = style_names.size();
if (! num_styles)
{
MAPNIK_LOG_DEBUG(feature_style_processor) << "feature_style_processor: No style for layer=" << lay.name();
MAPNIK_LOG_DEBUG(feature_style_processor)
<< "feature_style_processor: No style for layer=" << lay.name();
return;
}
mapnik::datasource_ptr ds = lay.datasource();
if (! ds)
{
MAPNIK_LOG_DEBUG(feature_style_processor) << "feature_style_processor: No datasource for layer=" << lay.name();
MAPNIK_LOG_DEBUG(feature_style_processor)
<< "feature_style_processor: No datasource for layer=" << lay.name();
return;
}
#if defined(RENDERING_STATS)
progress_timer layer_timer(std::clog, "rendering total for layer: '" + lay.name() + "'");
#endif
projection proj1(lay.srs(),true);
proj_transform prj_trans(proj0,proj1);
#if defined(RENDERING_STATS)
if (! prj_trans.equal())
{
std::clog << "notice: reprojecting layer: '" << lay.name() << "' from/to:\n\t'"
<< lay.srs() << "'\n\t'"
<< m_.srs() << "'\n";
}
#endif
processor_context_ptr current_ctx = ds->get_context(ctx_map);
proj_transform prj_trans(mat.proj0_,mat.proj1_);
box2d<double> query_ext = extent; // unbuffered
box2d<double> buffered_query_ext(query_ext); // buffered
@ -299,7 +332,8 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
// clip buffered extent by maximum extent, if supplied
boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent();
if (maximum_extent) {
if (maximum_extent)
{
buffered_query_ext.clip(*maximum_extent);
}
@ -337,6 +371,8 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
early_return = true;
}
std::vector<feature_type_style const*> & active_styles = mat.active_styles_;
if (early_return)
{
// check for styles needing compositing operations applied
@ -348,19 +384,16 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
{
continue;
}
if (style->comp_op() || style->image_filters().size() > 0)
{
if (style->active(scale_denom))
{
// trigger any needed compositing ops
p.start_style_processing(*style);
p.end_style_processing(*style);
// we'll have to handle compositing ops
active_styles.push_back(&(*style));
}
}
}
#if defined(RENDERING_STATS)
layer_timer.discard();
#endif
return;
}
@ -371,7 +404,9 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
query_ext.clip(*maximum_extent);
}
box2d<double> layer_ext2 = lay.envelope();
box2d<double> & layer_ext2 = mat.layer_ext2_;
layer_ext2 = lay.envelope();
if (fw_success)
{
if (prj_trans.forward(query_ext, PROJ_ENVELOPE_POINTS))
@ -390,17 +425,8 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
p.start_layer_processing(lay, layer_ext2);
double qw = query_ext.width()>0 ? query_ext.width() : 1;
double qh = query_ext.height()>0 ? query_ext.height() : 1;
query::resolution_type res(width/qw,
height/qh);
query q(layer_ext,res,scale_denom,extent);
std::vector<feature_type_style const*> active_styles;
boost::ptr_vector<rule_cache> & rule_caches = mat.rule_caches_;
attribute_collector collector(names);
double filt_factor = 1.0;
directive_collector d_collector(filt_factor);
boost::ptr_vector<rule_cache> rule_caches;
// iterate through all named styles collecting active styles and attribute names
BOOST_FOREACH(std::string const& style_name, style_names)
@ -424,11 +450,7 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
{
rc->add_rule(r);
active_rules = true;
if (ds->type() == datasource::Vector)
{
collector(r);
}
// TODO - in the future rasters should be able to be filtered.
collector(r);
}
}
if (active_rules)
@ -439,139 +461,180 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
}
// Don't even try to do more work if there are no active styles.
if (active_styles.size() > 0)
if (active_styles.empty())
{
if (p.attribute_collection_policy() == COLLECT_ALL)
{
layer_descriptor lay_desc = ds->get_descriptor();
BOOST_FOREACH(attribute_descriptor const& desc, lay_desc.get_descriptors())
{
q.add_property_name(desc.get_name());
}
}
else
{
BOOST_FOREACH(std::string const& name, names)
{
q.add_property_name(name);
}
}
// Update filter_factor for all enabled raster layers.
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
BOOST_FOREACH(rule const& r, style->get_rules())
{
if (r.active(scale_denom) &&
ds->type() == datasource::Raster &&
ds->params().get<double>("filter_factor",0.0) == 0.0)
{
BOOST_FOREACH (rule::symbolizers::value_type sym, r.get_symbolizers())
{
// if multiple raster symbolizers, last will be respected
// should we warn or throw?
boost::apply_visitor(d_collector,sym);
}
q.set_filter_factor(filt_factor);
}
}
}
// Also query the group by attribute
std::string group_by = lay.group_by();
if (group_by != "")
{
q.add_property_name(group_by);
}
bool cache_features = lay.cache_features() && active_styles.size() > 1;
// Render incrementally when the column that we group by
// changes value.
if (group_by != "")
{
featureset_ptr features = ds->features(q);
if (features) {
// Cache all features into the memory_datasource before rendering.
memory_datasource cache(ds->type(),false);
feature_ptr feature, prev;
while ((feature = features->next()))
{
if (prev && prev->get(group_by) != feature->get(group_by))
{
// We're at a value boundary, so render what we have
// up to this point.
int i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
render_style(lay, p, style, rule_caches[i], style_names[i],
cache.features(q), prj_trans);
i++;
}
cache.clear();
}
cache.push(feature);
prev = feature;
}
int i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
render_style(lay, p, style, rule_caches[i], style_names[i],
cache.features(q), prj_trans);
i++;
}
}
}
else if (cache_features)
{
memory_datasource cache(ds->type(),false);
featureset_ptr features = ds->features(q);
if (features) {
// Cache all features into the memory_datasource before rendering.
feature_ptr feature;
while ((feature = features->next()))
{
cache.push(feature);
}
}
int i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
render_style(lay, p, style, rule_caches[i], style_names[i],
cache.features(q), prj_trans);
i++;
}
}
// We only have a single style and no grouping.
else
{
int i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
render_style(lay, p, style, rule_caches[i], style_names[i],
ds->features(q), prj_trans);
i++;
}
}
return;
}
#if defined(RENDERING_STATS)
layer_timer.stop();
#endif
double qw = query_ext.width()>0 ? query_ext.width() : 1;
double qh = query_ext.height()>0 ? query_ext.height() : 1;
query::resolution_type res(width/qw,
height/qh);
p.end_layer_processing(lay);
query q(layer_ext,res,scale_denom,extent);
if (p.attribute_collection_policy() == COLLECT_ALL)
{
layer_descriptor lay_desc = ds->get_descriptor();
BOOST_FOREACH(attribute_descriptor const& desc, lay_desc.get_descriptors())
{
q.add_property_name(desc.get_name());
}
}
else
{
BOOST_FOREACH(std::string const& name, names)
{
q.add_property_name(name);
}
}
q.set_filter_factor(collector.get_filter_factor());
// Also query the group by attribute
std::string const& group_by = lay.group_by();
if (!group_by.empty())
{
q.add_property_name(group_by);
}
bool cache_features = lay.cache_features() && active_styles.size() > 1;
std::vector<featureset_ptr> & featureset_ptr_list = mat.featureset_ptr_list_;
if (!group_by.empty() || cache_features)
{
featureset_ptr_list.push_back(ds->features_with_context(q,current_ctx));
}
else
{
for(std::size_t i = 0; i < active_styles.size(); ++i)
{
featureset_ptr_list.push_back(ds->features_with_context(q,current_ctx));
}
}
}
template <typename Processor>
void feature_style_processor<Processor>::render_material(layer_rendering_material & mat,
Processor & p )
{
std::vector<feature_type_style const*> & active_styles = mat.active_styles_;
std::vector<featureset_ptr> & featureset_ptr_list = mat.featureset_ptr_list_;
if (featureset_ptr_list.empty())
{
// The datasource wasn't queried because of early return
// but we have to apply compositing operations on styles
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
p.start_style_processing(*style);
p.end_style_processing(*style);
}
return;
}
p.start_layer_processing(mat.lay_, mat.layer_ext2_);
layer const& lay = mat.lay_;
boost::ptr_vector<rule_cache> & rule_caches = mat.rule_caches_;
proj_transform prj_trans(mat.proj0_,mat.proj1_);
bool cache_features = lay.cache_features() && active_styles.size() > 1;
datasource_ptr ds = lay.datasource();
std::string group_by = lay.group_by();
// Render incrementally when the column that we group by changes value.
if (!group_by.empty())
{
featureset_ptr features = *featureset_ptr_list.begin();
if (features)
{
// Cache all features into the memory_datasource before rendering.
boost::shared_ptr<featureset_buffer> cache = boost::make_shared<featureset_buffer>();
feature_ptr feature, prev;
while ((feature = features->next()))
{
if (prev && prev->get(group_by) != feature->get(group_by))
{
// We're at a value boundary, so render what we have
// up to this point.
std::size_t i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
cache->prepare();
render_style(p, style,
rule_caches[i],
cache,
prj_trans);
++i;
}
cache->clear();
}
cache->push(feature);
prev = feature;
}
std::size_t i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
cache->prepare();
render_style(p, style, rule_caches[i], cache, prj_trans);
++i;
}
cache->clear();
}
}
else if (cache_features)
{
boost::shared_ptr<featureset_buffer> cache = boost::make_shared<featureset_buffer>();
featureset_ptr features = *featureset_ptr_list.begin();
if (features)
{
// Cache all features into the memory_datasource before rendering.
feature_ptr feature;
while ((feature = features->next()))
{
cache->push(feature);
}
}
std::size_t i = 0;
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
cache->prepare();
render_style(p, style,
rule_caches[i],
cache, prj_trans);
++i;
}
}
// We only have a single style and no grouping.
else
{
std::size_t i = 0;
std::vector<featureset_ptr>::iterator featuresets = featureset_ptr_list.begin();
BOOST_FOREACH (feature_type_style const* style, active_styles)
{
featureset_ptr features = *featuresets++;
render_style(p, style,
rule_caches[i],
features,
prj_trans);
++i;
}
}
p.end_layer_processing(mat.lay_);
}
template <typename Processor>
void feature_style_processor<Processor>::render_style(
layer const& lay,
Processor & p,
feature_type_style const* style,
rule_cache const& rc,
std::string const& style_name,
featureset_ptr features,
proj_transform const& prj_trans)
{
@ -581,49 +644,24 @@ void feature_style_processor<Processor>::render_style(
p.end_style_processing(*style);
return;
}
#if defined(RENDERING_STATS)
std::ostringstream s1;
s1 << "rendering style for layer: '" << lay.name()
<< "' and style '" << style_name << "'";
mapnik::progress_timer style_timer(std::clog, s1.str());
int feature_processed_count = 0;
int feature_count = 0;
#endif
feature_ptr feature;
bool was_painted = false;
while ((feature = features->next()))
{
#if defined(RENDERING_STATS)
feature_count++;
bool feat_processed = false;
#endif
bool do_else = true;
bool do_also = false;
BOOST_FOREACH(rule const* r, rc.get_if_rules() )
{
expression_ptr const& expr=r->get_filter();
expression_ptr const& expr = r->get_filter();
value_type result = boost::apply_visitor(evaluate<feature_impl,value_type>(*feature),*expr);
if (result.to_bool())
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
was_painted = true;
do_else=false;
do_also=true;
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
if(!p.process(symbols,*feature,prj_trans))
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
@ -641,15 +679,8 @@ void feature_style_processor<Processor>::render_style(
{
BOOST_FOREACH( rule const* r, rc.get_else_rules() )
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
was_painted = true;
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
if(!p.process(symbols,*feature,prj_trans))
{
BOOST_FOREACH (symbolizer const& sym, symbols)
@ -663,15 +694,8 @@ void feature_style_processor<Processor>::render_style(
{
BOOST_FOREACH( rule const* r, rc.get_also_rules() )
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
was_painted = true;
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
if(!p.process(symbols,*feature,prj_trans))
{
BOOST_FOREACH (symbolizer const& sym, symbols)
@ -681,32 +705,8 @@ void feature_style_processor<Processor>::render_style(
}
}
}
#if defined(RENDERING_STATS)
if (feat_processed)
feature_processed_count++;
#endif
}
#if defined(RENDERING_STATS)
style_timer.stop();
// done with style
std::ostringstream s;
if (feature_count > 0)
{
double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0;
s << "percent rendered: " << perc_processed << "% - " << feature_processed_count
<< " rendered for " << feature_count << " queried for ";
s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << style_name << "'\n";
}
else
{
s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << style_name << "'\n";
}
std::clog << s.str();
style_timer.discard();
#endif
p.painted(was_painted);
p.end_style_processing(*style);
}

View file

@ -65,7 +65,7 @@ private:
public:
feature_type_style();
feature_type_style(feature_type_style const& rhs, bool deep_copy = false);
feature_type_style(feature_type_style const& rhs);
feature_type_style& operator=(feature_type_style const& rhs);

View file

@ -35,7 +35,7 @@ class filter_featureset : public Featureset
typedef T filter_type;
public:
filter_featureset(featureset_ptr fs, filter_type const& filter)
filter_featureset(featureset_ptr const& fs, filter_type const& filter)
: fs_(fs), filter_(filter) {}
feature_ptr next()

View file

@ -52,9 +52,6 @@
#include <vector>
#include <map>
// uci
#include <unicode/unistr.h>
struct FT_LibraryRec_;
namespace mapnik
@ -106,7 +103,7 @@ public:
size_type size() const;
glyph_ptr get_glyph(unsigned c) const;
char_info character_dimensions(unsigned c);
void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);
void get_string_info(string_info & info, mapnik::value_unicode_string const& ustr, char_properties *format);
void set_pixel_sizes(unsigned size);
void set_character_sizes(double size);
private:

View file

@ -38,10 +38,10 @@ public:
font_set(std::string const& name);
font_set(font_set const& rhs);
font_set& operator=(font_set const& rhs);
unsigned size() const;
std::size_t size() const;
void set_name(std::string const& name);
std::string const& get_name() const;
void add_face_name(std::string);
void add_face_name(std::string const& face_name);
std::vector<std::string> const& get_face_names() const;
~font_set();
private:

View file

@ -26,6 +26,7 @@
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/geometry.hpp> // for eGeomType (TODO: avoid this interdependence)
// boost
#include <boost/tuple/tuple.hpp>
@ -414,11 +415,18 @@ bool hit_test(PathType & path, double x, double y, double tol)
double y1 = 0;
path.rewind(0);
unsigned command = path.vertex(&x0, &y0);
if (command == SEG_END) return false;
if (command == SEG_END)
{
return false;
}
unsigned count = 0;
mapnik::eGeomType geom_type = static_cast<mapnik::eGeomType>(path.type());
while (SEG_END != (command = path.vertex(&x1, &y1)))
{
if (command == SEG_CLOSE) continue;
if (command == SEG_CLOSE)
{
continue;
}
++count;
if (command == SEG_MOVETO)
{
@ -426,18 +434,34 @@ bool hit_test(PathType & path, double x, double y, double tol)
y0 = y1;
continue;
}
if ((((y1 <= y) && (y < y0)) ||
((y0 <= y) && (y < y1))) &&
(x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
inside=!inside;
switch(geom_type)
{
case mapnik::Polygon:
{
if ((((y1 <= y) && (y < y0)) ||
((y0 <= y) && (y < y1))) &&
(x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
inside=!inside;
break;
}
case mapnik::LineString:
{
double distance = point_to_segment_distance(x,y,x0,y0,x1,y1);
if (distance < tol)
return true;
break;
}
default:
break;
}
x0 = x1;
y0 = y1;
}
// TODO - handle multi-point?
if (count == 0) // one vertex
{
return distance(x, y, x0, y0) <= std::fabs(tol);
return distance(x, y, x0, y0) <= tol;
}
return inside;
}

Some files were not shown because too many files have changed in this diff Show more