diff --git a/CHANGELOG.md b/CHANGELOG.md
index b54510ea5..4f3e83d1e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,12 +6,104 @@ Developers: Please commit along with changes.
For a complete change history, see the git log.
-## Future
+## 2.2.0
-- Added new mapnik-config options: `git-describe`, `defines`, `includes`, `dep-includes`, and `cxxflags` (#1443)
+Released ---
+
+(Packaged from ---)
+
+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 uneeded and hard to install dependencies.
+
+- Removed 3 depedencies without loosing any functionality: `ltdl`, `cairomm` and `libsigc++` (#1804,#806,#1681)
+
+- Added 64 bit integer support in expressions, feature ids, and the grid_renderer (#1661,#1662,#1662)
+
+- Added the ability to disable needing various depedencies: `proj4`, `libpng`, `libtiff`, `libjpeg`
+
+- Added faster reprojection support between `epsg:3857` and `epsg:4326` (#1705,#1703,#1579)
+
+- Fixed concurrency problem when using cursors in postgis plugin (#1823,#1588)
+
+- Fixed postgres connection pool leaks when using `persist_connection=false` (#1764)
+
+- Fixed postgres connection key to respect highest value of `max_size` and `initial_size` for any layer in map (#1599)
+
+- Fixed potential crash in wkb parsing when postgis returns null geometry (#1843)
+
+- Fixed blurry rendering of image and SVG icons (#1316)
+
+- Improved logging system (https://github.com/mapnik/mapnik/wiki/Logging)
+
+- Added support for reading images from in memory streams (#1805)
+
+- Optimized halo rendering. When halo radius is < 1 new method will be used automatically (#1781)
- Added `text-halo-rasterizer` property. Set to `fast` for lower quality but faster
- halo rendering (#1298)
+ halo rendering (#1298) which matched new default method when radius is < 1.
+
+- Added support in `shape`, `sqlite`, `geojson`, and `csv` plugin for handling non-latin characters in the paths to file-based resources (#1177)
+
+- Fixed rendering of markers when their size is greater than the specified `spacing` value (#1487)
+
+- Fixed handling of alpha premultiplication in image scaling (#1489)
+
+- Optimized rendering when a style with no symbolizers is encountered (#1517)
+
+- Optimized string handling and type conversion by removing `boost::to_lower`, `boost::trim`, and `boost::lexical_cast` usage (#1687,#1687,#1633)
+
+- Optimized alpha preserving `hextree` method for quantization of png images (#1629)
+
+- Faster rendering of rasters by reducing memory allocation of temporary buffers (#1516)
+
+- Fixed some raster reprojection artifacts (#1501)
+
+- Fixed raster alignment when width != height and raster is being scaled (#1748,#1622)
+
+- Added support for caching rasters for re-use during rendering when styling more than once per layer (#1543)
+
+- Improved compile speeds of the code - in some cases by up to 2x and removed need for freetype dependency when building code against mapnik (#1688, #1756)
+
+- Removed internal rule cache on `mapnik::Map` c++ object (#1723)
+
+- Improved the scaled rendering of various map features when using `scale_factor` > 1 (#1280,#1100,#1273,#1792,#1291,#1344,#1279,#1624,#1767,#1766)
+
+- Added C++ api for overriding scale_denominator to enable rendering at fixed scale (#1582)
+
+- Added Layer `buffer-size` that can be used to override Map `buffer-size` to avoid
+ over-fetching of data that does not need to be buffered as much as other layers.
+ Map level `buffer-size` will be default if layers do not set the option. Renamed a
+ previously undocumented parameter by the same name that impacted clipping extent and
+ was not needed (clipping padding should likely be a symbolizer level option) (#1566)
+
+- Fixed potential file descriptor leaks in image readers when invalid images were encountered (#1783)
+
+- Fixed alpha handling in the `blur` and `invert` image filters (#1541)
+
+- Fixed error reporting in the python plugin (#1422)
+
+- Added the ability to run tests without installing with `make test-local`
+
+- Reduced library binary size by adding support for `-fvisibility-inlines-hidden` and `-fvisibility=hidden` (#1826,#1832)
+
+- Added `mapnik::map_request` class, a special object to allow passing mutable map objects to renderer (#1737)
+
+- Added the ability to use `boost::hash` on `mapnik::value` types (#1729)
+
+- Removed obsolete `geos` plugin (functionality replaced by `csv` plugin) and unmaintained `kismet` plugin (#1809,#1833)
+
+- Added new `mapnik-config` flags: `--all-flags`, `--defines`, `--git-describe`, `--includes`, `--dep-includes`, `--cxxflags`, `--cxx` (#1443)
+
+- Added support for unicode strings as arguments in python bindings (#163)
+
+- Added DebugSymbolizer which is able to render the otherwise invisible collision boxes (#1366)
+
+- Optimized rendering by reducing overhead of using `gamma` property (#1174)
+
+- Fixed rendering artifacts when using `polygon-gamma` or `line-gamma` equal to 0 (#761,#1763)
+
+- Fixed and optimized the display of excessive precision of some float data in labels (#430,#1697)
+
+- Removed the `bind` option for datasources (#1654)
- Added ability to access style list from map by (name,obj) in python (#1725)
@@ -21,19 +113,11 @@ For a complete change history, see the git log.
- Added support for `background-image` in cairo_renderer (#1724)
-- Added Layer `buffer-size` that can be used to override Map `buffer-size` to avoid
- over-fetching of data that does not need to be buffered as much as other layers.
- Map level `buffer-size` will be default if layers do not set the option. Renamed a
- previously undocumented parameter by the same name that impacted clipping extent and
- was not needed (clipping padding should likely be a symbolizer level option) (#1566)
-
- Fixed building symbolizer rendering to be fully sensitive to alpha (8b66128c892 / bc8ea1c5a7a)
-- Added 64 bit integer support in the grid_renderer (#1662)
-
- `[attr]` now returns false if attr is an empty string (#1665)
-- Added 64 bit integer support in expressions and feature ids (#1661,#1662)
+- `[attr]!=null` now returns true if attr is not null (#1642)
- Added support for DBF `Logical` type: #1614
@@ -50,9 +134,7 @@ For a complete change history, see the git log.
- Added support for setting zlib `Z_FIXED` strategy with format string: `png:z=fixed`
-- Fixed handling of transparency level option in Octree-based PNG encoding (#1556)
-
-- Faster rendering of rasters by reducing memory allocation of temporary buffers (#1516)
+- Fixed handling of transparency level option in `octree` png encoding (#1556)
- Added ability to pass a pre-created collision detector to the cairo renderer (#1444)
@@ -68,6 +150,24 @@ For a complete change history, see the git log.
now the combined layer extents will be again respected: they will be clipped to the maximum-extent if possible
and only when back-projecting fails for all layers will the maximum-extent be used as a fallback (#1473)
+- Compile time flag called `PLUGIN_LINKING` to allow input datasource plugins to be statically linked with the mapnik library (#249)
+
+- Fixed `dasharray` rendering in cairo backend (#1740)
+
+- Fixed handling of `opacity` in svg rendering (#1744)
+
+- Fixed uneven rendering of markers along lines (#1693)
+
+- Fixed handling of extra bytes in some shapefile fields (#1605)
+
+- Fixed handling (finally) of null shapes and partially corrupt shapefiles (#1630,#1621)
+
+- Added ability to re-use `mapnik::image_32` and `mapnik::grid` by exposing a `clear` method (#1571)
+
+- Added support for writing RGB (no A) png images by using the format string of `png:t=0` (#1559)
+
+- Added experimental support for geometry simplification at symbolizer level (#1385)
+
## Mapnik 2.1.0
Released Aug 23, 2012
@@ -215,7 +315,7 @@ Released April 10, 2012
- Workaround for boost interprocess compile error with recent gcc versions (#950,#1001,#1082)
-- Fix possible memory corruption when using hextree mode for png color reduction (#1087)
+- Fix possible memory corruption when using `hextree` mode for png color reduction (#1087)
- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908)
@@ -395,14 +495,14 @@ Released March 23, 2010
- PNG: fixed png256 for large images and some improvements to reduce color corruptions ([#522](https://github.com/mapnik/mapnik/issues/522))
-- PNG: Added new quantization method for indexed png format using hextree with full support for alpha
+- PNG: Added new quantization method for indexed png format using `hextree` with full support for alpha
channel. Also new method has some optimizations for color gradients common when using elevation based
- rasters. By default old method using octree is used. (r1680, r1683, [#477](https://github.com/mapnik/mapnik/issues/477))
+ rasters. By default old method using `octree` is used. (r1680, r1683, [#477](https://github.com/mapnik/mapnik/issues/477))
- PNG: Added initial support for passing options to png writter like number of colors, transparency
support, quantization method and possibly other in future using type parameter. For example
"png8:c=128:t=1:m=h" limits palette to 128 colors, uses only binary transparency (0 - none,
- 1 - binary, 2 - full), and new method of quantization using hextree (h - hextree, o - octree).
+ 1 - binary, 2 - full), and new method of quantization using `hextree` (h - `hextree`, o - `octree`).
Existing type "png256" can be also written using "png8:c=256:m=o:t=2" (r1680, r1683, [#477](https://github.com/mapnik/mapnik/issues/477))
diff --git a/SConstruct b/SConstruct
index abc2695d3..0f96b0a89 100644
--- a/SConstruct
+++ b/SConstruct
@@ -22,6 +22,7 @@ import sys
import re
import platform
from glob import glob
+from copy import copy
from subprocess import Popen, PIPE
from SCons.SConf import SetCacheMode
import pickle
@@ -35,6 +36,12 @@ except:
LIBDIR_SCHEMA_DEFAULT='lib'
severities = ['debug', 'warn', 'error', 'none']
+DEFAULT_CC = "gcc"
+DEFAULT_CXX = "g++"
+if sys.platform == 'darwin':
+ DEFAULT_CC = "clang"
+ DEFAULT_CXX = "clang++"
+
py3 = None
# local file to hold custom user configuration variables
@@ -72,6 +79,7 @@ pretty_dep_names = {
'pkg-config':'pkg-config tool | more info: http://pkg-config.freedesktop.org',
'pg_config':'pg_config program | try setting PG_CONFIG SCons option',
'xml2-config':'xml2-config program | try setting XML2_CONFIG SCons option',
+ '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',
@@ -101,7 +109,6 @@ PLUGINS = { # plugins with external dependencies
'csv': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'geojson': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
- 'kismet': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
'python': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
}
@@ -166,10 +173,14 @@ def shortest_name(libs):
name = lib
return name
+def rm_path(item,set,_env):
+ for i in _env[set]:
+ if item in i:
+ _env[set].remove(i)
def sort_paths(items,priority):
"""Sort paths such that compiling and linking will globally prefer custom or local libs
- over system libraries by fixing up the order libs are passed to gcc and the linker.
+ over system libraries by fixing up the order libs are passed to the compiler and the linker.
Ideally preference could be by-target instead of global, but our SCons implementation
is not currently utilizing different SCons build env()'s as we should.
@@ -254,15 +265,15 @@ opts = Variables()
opts.AddVariables(
# Compiler options
- ('CXX', 'The C++ compiler to use to compile mapnik (defaults to g++).', 'g++'),
- ('CC', 'The C compiler used for configure checks of C libs (defaults to gcc).', 'gcc'),
+ ('CXX', 'The C++ compiler to use to compile mapnik', DEFAULT_CXX),
+ ('CC', 'The C compiler used for configure checks of C libs.', DEFAULT_CC),
('CUSTOM_CXXFLAGS', 'Custom C++ flags, e.g. -I if you have headers in a nonstandard directory ', ''),
('CUSTOM_DEFINES', 'Custom Compiler DEFINES, e.g. -DENABLE_THIS', ''),
('CUSTOM_CFLAGS', 'Custom C flags, e.g. -I if you have headers in a nonstandard directory (only used for configure checks)', ''),
('CUSTOM_LDFLAGS', 'Custom linker flags, e.g. -L if you have libraries in a nonstandard directory ', ''),
EnumVariable('LINKING', "Set library format for libmapnik",'shared', ['shared','static']),
EnumVariable('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']),
- EnumVariable('OPTIMIZATION','Set g++ optimization level','3', ['0','1','2','3','4','s']),
+ EnumVariable('OPTIMIZATION','Set compiler optimization level','3', ['0','1','2','3','4','s']),
# Note: setting DEBUG=True will override any custom OPTIMIZATION level
BoolVariable('DEBUG', 'Compile a debug version of Mapnik', 'False'),
BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'),
@@ -303,8 +314,8 @@ opts.AddVariables(
('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),
- ('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc',
-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'),
PathVariable('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include', PathVariable.PathAccept),
PathVariable('PNG_LIBS','Search path for libpng library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
@@ -325,6 +336,7 @@ PathVariable.PathAccept),
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'),
# Variables for optional dependencies
# Note: cairo and and pycairo are optional but configured automatically through pkg-config
@@ -346,6 +358,9 @@ PathVariable.PathAccept),
BoolVariable('ENABLE_STATS', 'Enable global statistics during map processing', 'False'),
('DEFAULT_LOG_SEVERITY', 'The default severity of the logger (eg. ' + ', '.join(severities) + ')', 'error'),
+ # Plugin linking
+ EnumVariable('PLUGIN_LINKING', "Set plugin linking with libmapnik", 'shared', ['shared','static']),
+
# Other variables
BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'),
('SYSTEM_FONTS','Provide location for python bindings to register fonts (if provided then the bundled DejaVu fonts are not installed)',''),
@@ -393,6 +408,7 @@ pickle_store = [# Scons internal variables
'PLUGINS',
'ABI_VERSION',
'MAPNIK_VERSION_STRING',
+ 'MAPNIK_VERSION',
'PLATFORM',
'BOOST_ABI',
'BOOST_APPEND',
@@ -427,7 +443,7 @@ pickle_store = [# Scons internal variables
'LIBMAPNIK_DEFINES',
'LIBMAPNIK_CXXFLAGS',
'CAIRO_LIBPATHS',
- 'CAIRO_LINKFLAGS',
+ 'CAIRO_ALL_LIBS',
'CAIRO_CPPPATHS',
'SVG_RENDERER',
'SQLITE_LINKFLAGS',
@@ -722,25 +738,23 @@ def FindBoost(context, prefixes, thread_flag):
msg = str()
if BOOST_LIB_DIR:
- msg += '\n *libs found: %s' % BOOST_LIB_DIR
+ msg += '\nFound boost libs: %s' % BOOST_LIB_DIR
env['BOOST_LIBS'] = BOOST_LIB_DIR
else:
env['BOOST_LIBS'] = '/usr/' + env['LIBDIR_SCHEMA']
- msg += '\n *using default boost lib dir: %s' % env['BOOST_LIBS']
+ msg += '\nUsing default boost lib dir: %s' % env['BOOST_LIBS']
if BOOST_INCLUDE_DIR:
- msg += '\n *headers found: %s' % BOOST_INCLUDE_DIR
+ msg += '\nFound boost headers: %s' % BOOST_INCLUDE_DIR
env['BOOST_INCLUDES'] = BOOST_INCLUDE_DIR
else:
env['BOOST_INCLUDES'] = '/usr/include'
- msg += '\n *using default boost include dir: %s' % env['BOOST_INCLUDES']
+ msg += '\nUsing default boost include dir: %s' % env['BOOST_INCLUDES']
if not env['BOOST_TOOLKIT'] and not env['BOOST_ABI'] and not env['BOOST_VERSION']:
if BOOST_APPEND:
- msg += '\n *lib naming extension found: %s' % BOOST_APPEND
+ msg += '\nFound boost lib name extension: %s' % BOOST_APPEND
env['BOOST_APPEND'] = BOOST_APPEND
- else:
- msg += '\n *no lib naming extension found'
else:
# Creating BOOST_APPEND according to the Boost library naming order,
# which goes ---. See:
@@ -755,7 +769,7 @@ def FindBoost(context, prefixes, thread_flag):
# Boost libraries.
if len(append_params) > 1:
env['BOOST_APPEND'] = '-'.join(append_params)
- msg += '\n *using boost lib naming: %s' % env['BOOST_APPEND']
+ msg += '\nFound boost lib name extension: %s' % env['BOOST_APPEND']
env.AppendUnique(CPPPATH = os.path.realpath(env['BOOST_INCLUDES']))
env.AppendUnique(LIBPATH = os.path.realpath(env['BOOST_LIBS']))
@@ -792,6 +806,32 @@ int main()
context.Result(ret)
return ret
+def CheckCairoHasFreetype(context, silent=False):
+ if not silent:
+ context.Message('Checking for cairo freetype font support ... ')
+ context.env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS']))
+
+ ret = context.TryRun("""
+
+#include
+
+int main()
+{
+ #ifdef CAIRO_HAS_FT_FONT
+ return 0;
+ #else
+ return 1;
+ #endif
+}
+
+""", '.cpp')[0]
+ if silent:
+ context.did_show_result=1
+ context.Result(ret)
+ for item in env['CAIRO_CPPPATHS']:
+ rm_path(item,'CPPPATH',context.env)
+ return ret
+
def GetBoostLibVersion(context):
ret = context.TryRun("""
@@ -939,6 +979,7 @@ conf_tests = { 'prioritize_paths' : prioritize_paths,
'CheckPKGVersion' : CheckPKGVersion,
'FindBoost' : FindBoost,
'CheckBoost' : CheckBoost,
+ 'CheckCairoHasFreetype' : CheckCairoHasFreetype,
'GetBoostLibVersion' : GetBoostLibVersion,
'GetMapnikLibVersion' : GetMapnikLibVersion,
'parse_config' : parse_config,
@@ -1000,11 +1041,12 @@ if not preconfigured:
env['SKIPPED_DEPS'] = []
env['HAS_CAIRO'] = False
env['CAIRO_LIBPATHS'] = []
- env['CAIRO_LINKFLAGS'] = []
+ env['CAIRO_ALL_LIBS'] = []
env['CAIRO_CPPPATHS'] = []
env['HAS_PYCAIRO'] = False
env['HAS_LIBXML2'] = False
env['LIBMAPNIK_LIBS'] = []
+ env['LIBMAPNIK_LINKFLAGS'] = []
env['LIBMAPNIK_CPPATHS'] = []
env['LIBMAPNIK_DEFINES'] = []
env['LIBMAPNIK_CXXFLAGS'] = []
@@ -1083,7 +1125,7 @@ if not preconfigured:
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 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
@@ -1130,6 +1172,8 @@ if not preconfigured:
# https://github.com/mapnik/mapnik/issues/913
if conf.parse_config('XML2_CONFIG',checks='--cflags'):
env['HAS_LIBXML2'] = True
+ else:
+ env['MISSING_DEPS'].append('libxml2')
LIBSHEADERS = [
['z', 'zlib.h', True,'C'],
@@ -1178,7 +1222,7 @@ if not preconfigured:
# if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
if env['PRIORITIZE_LINKING']:
- conf.prioritize_paths(silent=False)
+ conf.prioritize_paths(silent=True)
if not env['HOST']:
for libname, headers, required, lang in LIBSHEADERS:
@@ -1227,7 +1271,7 @@ if not preconfigured:
# if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
if env['PRIORITIZE_LINKING']:
- conf.prioritize_paths()
+ conf.prioritize_paths(silent=True)
if not env['HOST']:
# if the user is not setting custom boost configuration
@@ -1362,9 +1406,9 @@ if not preconfigured:
#os.path.join(c_inc,'include/libpng'),
]
)
- env["CAIRO_LINKFLAGS"] = ['cairo']
+ env["CAIRO_ALL_LIBS"] = ['cairo']
if env['RUNTIME_LINK'] == 'static':
- env["CAIRO_LINKFLAGS"].extend(
+ env["CAIRO_ALL_LIBS"].extend(
['pixman-1','expat','fontconfig','iconv']
)
# todo - run actual checkLib?
@@ -1387,7 +1431,7 @@ if not preconfigured:
cairo_env.ParseConfig(cmd)
for lib in cairo_env['LIBS']:
if not lib in env['LIBS']:
- env["CAIRO_LINKFLAGS"].append(lib)
+ env["CAIRO_ALL_LIBS"].append(lib)
for lpath in cairo_env['LIBPATH']:
if not lpath in env['LIBPATH']:
env["CAIRO_LIBPATHS"].append(lpath)
@@ -1404,6 +1448,11 @@ if not preconfigured:
else:
color_print(4,'Not building with cairo support, pass CAIRO=True to enable')
+ if not env['HOST'] and env['HAS_CAIRO']:
+ if not conf.CheckCairoHasFreetype():
+ env['SKIPPED_DEPS'].append('cairo')
+ env['HAS_CAIRO'] = False
+
if 'python' in env['BINDINGS'] or 'python' in env['REQUESTED_PLUGINS']:
if not os.access(env['PYTHON'], os.X_OK):
color_print(1,"Cannot run python interpreter at '%s', make sure that you have the permissions to execute it." % env['PYTHON'])
@@ -1530,8 +1579,10 @@ if not preconfigured:
color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback)
abi = abi_fallback
- env['ABI_VERSION'] = abi.replace('-pre','').split('.')
+ abi_no_pre = abi.replace('-pre','').split('.')
+ env['ABI_VERSION'] = abi_no_pre
env['MAPNIK_VERSION_STRING'] = abi
+ env['MAPNIK_VERSION'] = str(int(abi_no_pre[0])*100000+int(abi_no_pre[1])*100+int(abi_no_pre[2]))
# Common DEFINES.
env.Append(CPPDEFINES = '-D%s' % env['PLATFORM'].upper())
@@ -1588,12 +1639,18 @@ if not preconfigured:
env.Append(CPPDEFINES = ndebug_defines)
if not env['SUNCC']:
- # Common flags for GCC.
- gcc_cxx_flags = '-ansi -Wall %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 '
+
if env['DEBUG']:
- env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline')
+ env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline')
else:
- env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION']))
+ env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fvisibility-inlines-hidden -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')
@@ -1623,7 +1680,7 @@ if not preconfigured:
# if requested, sort LIBPATH and CPPPATH one last time before saving...
if env['PRIORITIZE_LINKING']:
- conf.prioritize_paths()
+ conf.prioritize_paths(silent=True)
# finish config stage and pickle results
env = conf.Finish()
@@ -1681,15 +1738,11 @@ if not HELP_REQUESTED:
p = env['PATH_REMOVE']
if p in env['ENV']['PATH']:
env['ENV']['PATH'].replace(p,'')
- def rm_path(set):
- for i in env[set]:
- if p in i:
- env[set].remove(i)
- rm_path('LIBPATH')
- rm_path('CPPPATH')
- rm_path('CXXFLAGS')
- rm_path('CAIRO_LIBPATHS')
- rm_path('CAIRO_CPPPATHS')
+ 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(':')
@@ -1712,11 +1765,8 @@ if not HELP_REQUESTED:
Export('env')
plugin_base = env.Clone()
- # for this to work you need:
- # if __GNUC__ >= 4
- # define MAPNIK_EXP __attribute__ ((visibility ("default")))
- #plugin_base.Append(CXXFLAGS='-fvisibility=hidden')
- #plugin_base.Append(CXXFLAGS='-fvisibility-inlines-hidden')
+ if not env['DEBUG']:
+ plugin_base.Append(CXXFLAGS='-fvisibility=hidden')
Export('plugin_base')
@@ -1749,7 +1799,8 @@ if not HELP_REQUESTED:
for plugin in env['REQUESTED_PLUGINS']:
details = env['PLUGINS'][plugin]
if details['lib'] in env['LIBS']:
- SConscript('plugins/input/%s/build.py' % plugin)
+ if env['PLUGIN_LINKING'] == 'shared':
+ SConscript('plugins/input/%s/build.py' % plugin)
if plugin == 'ogr': OGR_BUILT = True
if plugin == 'gdal': GDAL_BUILT = True
if plugin == 'ogr' or plugin == 'gdal':
@@ -1758,8 +1809,9 @@ if not HELP_REQUESTED:
else:
env['LIBS'].remove(details['lib'])
elif not details['lib']:
- # build internal shape and raster plugins
- SConscript('plugins/input/%s/build.py' % plugin)
+ if env['PLUGIN_LINKING'] == 'shared':
+ # build internal datasource input plugins
+ SConscript('plugins/input/%s/build.py' % plugin)
else:
color_print(1,"Notice: dependencies not met for plugin '%s', not building..." % plugin)
# also clear out locally built target
@@ -1773,11 +1825,11 @@ if not HELP_REQUESTED:
# installed plugins that we are no longer building
if 'install' in COMMAND_LINE_TARGETS:
for plugin in PLUGINS.keys():
- if plugin not in env['REQUESTED_PLUGINS']:
- plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'%s.input' % plugin)
- if os.path.exists(plugin_path):
+ 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)
- os.unlink(plugin_path)
+ os.unlink(plugin_path)
# Build the c++ rundemo app if requested
if env['DEMO']:
@@ -1821,7 +1873,8 @@ if not HELP_REQUESTED:
if env['SVG_RENDERER']:
SConscript('tests/cpp_tests/svg_renderer_tests/build.py')
- SConscript('benchmark/build.py')
+ if env['BENCHMARK']:
+ SConscript('benchmark/build.py')
# install pkg-config script and mapnik-config script
SConscript('utils/mapnik-config/build.py')
diff --git a/bindings/python/build.py b/bindings/python/build.py
index 40bc6c254..2ba242c26 100644
--- a/bindings/python/build.py
+++ b/bindings/python/build.py
@@ -1,7 +1,7 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
-# Copyright (C) 2006 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
@@ -43,19 +43,22 @@ prefix = env['PREFIX']
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
-libraries = ['mapnik',env['BOOST_PYTHON_LIB']]
+py_env = env.Clone()
+py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
+
+py_env['LIBS'] = ['mapnik',env['BOOST_PYTHON_LIB']]
# TODO - do solaris/fedora need direct linking too?
if env['PLATFORM'] == 'Darwin':
if not env['PYTHON_DYNAMIC_LOOKUP']:
if env['PNG']:
- libraries.append('png')
+ py_env.AppendUnique(LIBS = 'png')
if env['JPEG']:
- libraries.append('jpeg')
- libraries.append(env['ICU_LIB_NAME'])
- libraries.append('boost_regex%s' % env['BOOST_APPEND'])
+ 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':
- libraries.append('boost_thread%s' % env['BOOST_APPEND'])
+ py_env.AppendUnique(LIBS = 'boost_thread%s' % env['BOOST_APPEND'])
##### Python linking on OS X is tricky ###
# Confounding problems are:
@@ -115,6 +118,9 @@ 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)."""
@@ -147,9 +153,6 @@ except: pass
# install the shared object beside the module directory
sources = glob.glob('*.cpp')
-py_env = env.Clone()
-py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
-
if 'install' in COMMAND_LINE_TARGETS:
# install the core mapnik python files, including '__init__.py'
init_files = glob.glob('mapnik/*.py')
@@ -177,14 +180,14 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
py_env.Append(CPPPATH = env['CAIRO_CPPPATHS'])
py_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
if env['PLATFORM'] == 'Darwin':
- py_env.Append(LIBS=env['CAIRO_LINKFLAGS'])
+ py_env.Append(LIBS=env['CAIRO_ALL_LIBS'])
if env['HAS_PYCAIRO']:
py_env.ParseConfig('pkg-config --cflags pycairo')
py_env.Append(CPPDEFINES = '-DHAVE_PYCAIRO')
-libraries.append('boost_thread%s' % env['BOOST_APPEND'])
-_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LIBS=libraries, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
+py_env.AppendUnique(LIBS = 'boost_thread%s' % env['BOOST_APPEND'])
+_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
Depends(_mapnik, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py
index eca8c89b8..4c4a1dd89 100644
--- a/bindings/python/mapnik/__init__.py
+++ b/bindings/python/mapnik/__init__.py
@@ -558,44 +558,6 @@ def Osm(**keywords):
keywords['type'] = 'osm'
return CreateDatasource(keywords)
-def Kismet(**keywords):
- """Create a Kismet Datasource.
-
- Required keyword arguments:
- host -- kismet hostname
- port -- kismet port
-
- Optional keyword arguments:
- encoding -- file encoding (default 'utf-8')
- extent -- manually specified data extent (comma delimited string, default None)
-
- >>> from mapnik import Kismet, Layer
- >>> datasource = Kismet(host='localhost',port=2501,extent='-179,-85,179,85')
- >>> lyr = Layer('Kismet Server Layer')
- >>> lyr.datasource = datasource
-
- """
- keywords['type'] = 'kismet'
- return CreateDatasource(keywords)
-
-def Geos(**keywords):
- """Create a GEOS Vector Datasource.
-
- Required keyword arguments:
- wkt -- inline WKT text of the geometry
-
- Optional keyword arguments:
- extent -- manually specified data extent (comma delimited string, default None)
-
- >>> from mapnik import Geos, Layer
- >>> datasource = Geos(wkt='MULTIPOINT(100 100, 50 50, 0 0)')
- >>> lyr = Layer('GEOS Layer from WKT string')
- >>> lyr.datasource = datasource
-
- """
- keywords['type'] = 'geos'
- return CreateDatasource(keywords)
-
def Python(**keywords):
"""Create a Python Datasource.
diff --git a/bindings/python/mapnik_datasource.cpp b/bindings/python/mapnik_datasource.cpp
index 95c495aec..07383b372 100644
--- a/bindings/python/mapnik_datasource.cpp
+++ b/bindings/python/mapnik_datasource.cpp
@@ -48,14 +48,26 @@ namespace
{
//user-friendly wrapper that uses Python dictionary
using namespace boost::python;
-boost::shared_ptr create_datasource(const dict& d)
+boost::shared_ptr create_datasource(dict const& d)
{
mapnik::parameters params;
boost::python::list keys=d.keys();
- for (int i=0; i(keys[i]);
object obj = d[key];
+ if (PyUnicode_Check(obj.ptr()))
+ {
+ PyObject* temp = PyUnicode_AsUTF8String(obj.ptr());
+ if (temp)
+ {
+ char* c_str = PyString_AsString(temp);
+ params[key] = std::string(c_str);
+ Py_DecRef(temp);
+ }
+ continue;
+ }
+
extract ex0(obj);
extract ex1(obj);
extract ex2(obj);
diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp
index d3bd8b1dd..caf4d2525 100644
--- a/bindings/python/mapnik_expression.cpp
+++ b/bindings/python/mapnik_expression.cpp
@@ -34,8 +34,6 @@
#include
#include
-
-using mapnik::Feature;
using mapnik::expression_ptr;
using mapnik::parse_expression;
using mapnik::to_expression_string;
@@ -53,15 +51,15 @@ std::string expression_to_string_(mapnik::expr_node const& expr)
return mapnik::to_expression_string(expr);
}
-mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::Feature const& f)
+mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::feature_impl const& f)
{
// will be auto-converted to proper python type by `mapnik_value_to_python`
- return boost::apply_visitor(mapnik::evaluate(f),expr);
+ return boost::apply_visitor(mapnik::evaluate(f),expr);
}
-bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::Feature const& f)
+bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::feature_impl const& f)
{
- return boost::apply_visitor(mapnik::evaluate(f),expr).to_bool();
+ return boost::apply_visitor(mapnik::evaluate(f),expr).to_bool();
}
// path expression
@@ -75,7 +73,7 @@ std::string path_to_string_(mapnik::path_expression const& expr)
return mapnik::path_processor_type::to_string(expr);
}
-std::string path_evaluate_(mapnik::path_expression const& expr, mapnik::Feature const& f)
+std::string path_evaluate_(mapnik::path_expression const& expr, mapnik::feature_impl const& f)
{
return mapnik::path_processor_type::evaluate(expr, f);
}
diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp
index 0c7e6745e..8f4e4494f 100644
--- a/bindings/python/mapnik_feature.cpp
+++ b/bindings/python/mapnik_feature.cpp
@@ -41,28 +41,27 @@
namespace {
-using mapnik::Feature;
using mapnik::geometry_utils;
using mapnik::from_wkt;
using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;
-mapnik::geometry_type const& (mapnik::Feature::*get_geometry_by_const_ref)(unsigned) const = &mapnik::Feature::get_geometry;
-boost::ptr_vector const& (mapnik::Feature::*get_paths_by_const_ref)() const = &mapnik::Feature::paths;
+mapnik::geometry_type const& (mapnik::feature_impl::*get_geometry_by_const_ref)(unsigned) const = &mapnik::feature_impl::get_geometry;
+boost::ptr_vector const& (mapnik::feature_impl::*get_paths_by_const_ref)() const = &mapnik::feature_impl::paths;
-void feature_add_geometries_from_wkb(Feature &feature, std::string wkb)
+void feature_add_geometries_from_wkb(mapnik::feature_impl &feature, std::string wkb)
{
geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
}
-void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)
+void feature_add_geometries_from_wkt(mapnik::feature_impl &feature, std::string wkt)
{
bool result = mapnik::from_wkt(wkt, feature.paths());
if (!result) throw std::runtime_error("Failed to parse WKT");
}
-std::string feature_to_geojson(Feature const& feature)
+std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
std::string json;
mapnik::json::feature_generator g;
@@ -73,22 +72,22 @@ std::string feature_to_geojson(Feature const& feature)
return json;
}
-mapnik::value __getitem__(Feature const& feature, std::string const& name)
+mapnik::value __getitem__(mapnik::feature_impl const& feature, std::string const& name)
{
return feature.get(name);
}
-mapnik::value __getitem2__(Feature const& feature, std::size_t index)
+mapnik::value __getitem2__(mapnik::feature_impl const& feature, std::size_t index)
{
return feature.get(index);
}
-void __setitem__(Feature & feature, std::string const& name, mapnik::value const& val)
+void __setitem__(mapnik::feature_impl & feature, std::string const& name, mapnik::value const& val)
{
feature.put_new(name,val);
}
-boost::python::dict attributes(Feature const& f)
+boost::python::dict attributes(mapnik::feature_impl const& f)
{
boost::python::dict attributes;
feature_kv_iterator itr = f.begin();
@@ -191,7 +190,6 @@ struct value_null_from_python
void export_feature()
{
using namespace boost::python;
- using mapnik::Feature;
// Python to mapnik::value converters
// NOTE: order matters here. For example value_null must be listed before
@@ -211,25 +209,25 @@ void export_feature()
.def("push", &context_type::push)
;
- class_,
+ class_,
boost::noncopyable>("Feature",init("Default ctor."))
- .def("id",&Feature::id)
- .def("__str__",&Feature::to_string)
+ .def("id",&mapnik::feature_impl::id)
+ .def("__str__",&mapnik::feature_impl::to_string)
.def("add_geometries_from_wkb", &feature_add_geometries_from_wkb)
.def("add_geometries_from_wkt", &feature_add_geometries_from_wkt)
- .def("add_geometry", &Feature::add_geometry)
- .def("num_geometries",&Feature::num_geometries)
+ .def("add_geometry", &mapnik::feature_impl::add_geometry)
+ .def("num_geometries",&mapnik::feature_impl::num_geometries)
.def("get_geometry", make_function(get_geometry_by_const_ref,return_value_policy()))
.def("geometries",make_function(get_paths_by_const_ref,return_value_policy()))
- .def("envelope", &Feature::envelope)
- .def("has_key", &Feature::has_key)
+ .def("envelope", &mapnik::feature_impl::envelope)
+ .def("has_key", &mapnik::feature_impl::has_key)
.add_property("attributes",&attributes)
.def("__setitem__",&__setitem__)
.def("__contains__",&__getitem__)
.def("__getitem__",&__getitem__)
.def("__getitem__",&__getitem2__)
- .def("__len__", &Feature::size)
- .def("context",&Feature::context)
+ .def("__len__", &mapnik::feature_impl::size)
+ .def("context",&mapnik::feature_impl::context)
.def("to_geojson",&feature_to_geojson)
;
}
diff --git a/bindings/python/mapnik_featureset.cpp b/bindings/python/mapnik_featureset.cpp
index 3148d116e..c1f7eecd4 100644
--- a/bindings/python/mapnik_featureset.cpp
+++ b/bindings/python/mapnik_featureset.cpp
@@ -65,10 +65,7 @@ inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr)
void export_featureset()
{
using namespace boost::python;
- using mapnik::Feature;
- using mapnik::Featureset;
-
- class_,
+ class_,
boost::noncopyable>("Featureset",no_init)
.def("__iter__",pass_through)
.def("next",next)
diff --git a/bindings/python/mapnik_markers_symbolizer.cpp b/bindings/python/mapnik_markers_symbolizer.cpp
index 64f6bc394..200c44959 100644
--- a/bindings/python/mapnik_markers_symbolizer.cpp
+++ b/bindings/python/mapnik_markers_symbolizer.cpp
@@ -30,6 +30,8 @@
#include
#include "mapnik_svg.hpp"
#include "mapnik_enumeration.hpp"
+#include "python_optional.hpp"
+
#include // for known_svg_prefix_
using mapnik::markers_symbolizer;
@@ -70,16 +72,6 @@ void set_marker_type(mapnik::markers_symbolizer & symbolizer, std::string const&
}
-
-// https://github.com/mapnik/mapnik/issues/1367
-PyObject* get_fill_opacity_impl(markers_symbolizer & sym)
-{
- boost::optional fill_opacity = sym.get_fill_opacity();
- if (fill_opacity)
- return ::PyFloat_FromDouble(*fill_opacity);
- Py_RETURN_NONE;
-}
-
void export_markers_symbolizer()
{
using namespace boost::python;
@@ -119,7 +111,7 @@ void export_markers_symbolizer()
&markers_symbolizer::set_opacity,
"Set/get the overall opacity")
.add_property("fill_opacity",
- &get_fill_opacity_impl,
+ &markers_symbolizer::get_fill_opacity,
&markers_symbolizer::set_fill_opacity,
"Set/get the fill opacity")
.add_property("ignore_placement",
diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp
index d0b4fbf1e..167fee38e 100644
--- a/bindings/python/mapnik_python.cpp
+++ b/bindings/python/mapnik_python.cpp
@@ -63,6 +63,7 @@ void export_polygon_pattern_symbolizer();
void export_raster_symbolizer();
void export_text_placement();
void export_shield_symbolizer();
+void export_debug_symbolizer();
void export_font_engine();
void export_marker_cache();
void export_projection();
@@ -86,7 +87,6 @@ void export_logger();
#include
#include
#include
-#include
#include
#include
#include
@@ -335,11 +335,6 @@ double scale_denominator(mapnik::Map const &map, bool geographic)
}
// http://docs.python.org/c-api/exceptions.html#standard-exceptions
-void config_error_translator(mapnik::config_error const & ex)
-{
- PyErr_SetString(PyExc_RuntimeError, ex.what());
-}
-
void value_error_translator(mapnik::value_error const & ex)
{
PyErr_SetString(PyExc_ValueError, ex.what());
@@ -435,7 +430,6 @@ BOOST_PYTHON_MODULE(_mapnik)
register_exception_translator(&standard_error_translator);
register_exception_translator(&out_of_range_error_translator);
- register_exception_translator(&config_error_translator);
register_exception_translator(&value_error_translator);
register_exception_translator(&runtime_error_translator);
register_cairo();
@@ -473,6 +467,7 @@ BOOST_PYTHON_MODULE(_mapnik)
export_raster_symbolizer();
export_text_placement();
export_shield_symbolizer();
+ export_debug_symbolizer();
export_font_engine();
export_marker_cache();
export_projection();
diff --git a/bindings/python/mapnik_raster_symbolizer.cpp b/bindings/python/mapnik_raster_symbolizer.cpp
index 54f66a554..20a04a3f3 100644
--- a/bindings/python/mapnik_raster_symbolizer.cpp
+++ b/bindings/python/mapnik_raster_symbolizer.cpp
@@ -28,18 +28,7 @@
#include
#include
-namespace {
-// https://github.com/mapnik/mapnik/issues/1367
-PyObject* get_premultiplied_impl(mapnik::raster_symbolizer & sym)
-{
- boost::optional premultiplied = sym.premultiplied();
- if (premultiplied)
- return ::PyBool_FromLong(*premultiplied);
- Py_RETURN_NONE;
-}
-
-}
using mapnik::raster_symbolizer;
void export_raster_symbolizer()
@@ -132,7 +121,7 @@ void export_raster_symbolizer()
">>> r.mesh_size = 32\n"
)
.add_property("premultiplied",
- &get_premultiplied_impl,
+ &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"
diff --git a/bindings/python/mapnik_rule.cpp b/bindings/python/mapnik_rule.cpp
index bad1f2639..80341ca24 100644
--- a/bindings/python/mapnik_rule.cpp
+++ b/bindings/python/mapnik_rule.cpp
@@ -34,7 +34,6 @@
using mapnik::rule;
using mapnik::expr_node;
using mapnik::expression_ptr;
-using mapnik::Feature;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp
index f1dcefae8..05201326a 100644
--- a/bindings/python/mapnik_text_placement.cpp
+++ b/bindings/python/mapnik_text_placement.cpp
@@ -84,7 +84,7 @@ struct NodeWrap: formatting::node, wrapper
}
- void apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
python_block_auto_unblock b;
this->get_override("apply")(ptr(&p), ptr(&feature), ptr(&output));
@@ -122,7 +122,7 @@ struct TextNodeWrap: formatting::text_node, wrapper
}
- virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ virtual void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
if(override o = this->get_override("apply"))
{
@@ -135,7 +135,7 @@ struct TextNodeWrap: formatting::text_node, wrapper
}
}
- void default_apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ void default_apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
formatting::text_node::apply(p, feature, output);
}
@@ -143,7 +143,7 @@ struct TextNodeWrap: formatting::text_node, wrapper
struct FormatNodeWrap: formatting::format_node, wrapper
{
- virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ virtual void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
if(override o = this->get_override("apply"))
{
@@ -156,7 +156,7 @@ struct FormatNodeWrap: formatting::format_node, wrapper
}
}
- void default_apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ void default_apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
formatting::format_node::apply(p, feature, output);
}
@@ -164,7 +164,7 @@ struct FormatNodeWrap: formatting::format_node, wrapper
struct ExprFormatWrap: formatting::expression_format, wrapper
{
- virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ virtual void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
if(override o = this->get_override("apply"))
{
@@ -177,7 +177,7 @@ struct ExprFormatWrap: formatting::expression_format, wrapper
http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_function */
- virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ virtual void apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
if(override o = this->get_override("apply"))
{
@@ -214,7 +214,7 @@ struct ListNodeWrap: formatting::list_node, wrapper
}
}
- void default_apply(char_properties const& p, Feature const& feature, processed_text &output) const
+ void default_apply(char_properties const& p, feature_impl const& feature, processed_text &output) const
{
formatting::list_node::apply(p, feature, output);
}
diff --git a/bindings/python/python_optional.hpp b/bindings/python/python_optional.hpp
index 0d785b0f3..9bc38d119 100644
--- a/bindings/python/python_optional.hpp
+++ b/bindings/python/python_optional.hpp
@@ -22,7 +22,8 @@
#include
#include
-#include
+
+#include
// boost::optional to/from converter from John Wiegley
@@ -46,7 +47,7 @@ struct register_python_conversion
};
template
-struct python_optional : public boost::noncopyable
+struct python_optional : public mapnik::noncopyable
{
struct optional_to_python
{
@@ -74,7 +75,7 @@ struct python_optional : public boost::noncopyable
rvalue_from_python_stage1(source, converters);
return rvalue_from_python_stage2(source, data, converters);
}
- return NULL;
+ return 0;
}
static void construct(PyObject * source,
@@ -94,17 +95,116 @@ struct python_optional : public boost::noncopyable
}
};
- explicit python_optional() {
+ explicit python_optional()
+ {
register_python_conversion,
optional_to_python, optional_from_python>();
}
};
-/** This class works around a bug in boost python.
+// to/from boost::optional
+template <>
+struct python_optional : public mapnik::noncopyable
+{
+ struct optional_to_python
+ {
+ static PyObject * convert(const boost::optional& value)
+ {
+ return (value ? PyFloat_FromDouble(*value) :
+ boost::python::detail::none());
+ }
+ };
- See http://osdir.com/ml/python.c++/2003-11/msg00158.html
-*/
-template
+ struct optional_from_python
+ {
+ static void * convertible(PyObject * source)
+ {
+ using namespace boost::python::converter;
+
+ if (source == Py_None || PyFloat_Check(source))
+ return source;
+ return 0;
+ }
+
+ static void construct(PyObject * source,
+ boost::python::converter::rvalue_from_python_stage1_data * data)
+ {
+ using namespace boost::python::converter;
+ void * const storage = ((rvalue_from_python_storage > *)
+ data)->storage.bytes;
+ if (source == Py_None) // == None
+ new (storage) boost::optional(); // A Boost uninitialized value
+ else
+ new (storage) boost::optional(PyFloat_AsDouble(source));
+ data->convertible = storage;
+ }
+ };
+
+ explicit python_optional()
+ {
+ register_python_conversion,
+ optional_to_python, optional_from_python>();
+ }
+};
+
+// to/from boost::optional
+template <>
+struct python_optional : public mapnik::noncopyable
+{
+ struct optional_to_python
+ {
+ static PyObject * convert(const boost::optional& value)
+ {
+ if (value)
+ {
+ if (*value) Py_RETURN_TRUE;
+ else Py_RETURN_FALSE;
+ }
+ else return boost::python::detail::none();
+ }
+ };
+ struct optional_from_python
+ {
+ static void * convertible(PyObject * source)
+ {
+ using namespace boost::python::converter;
+
+ if (source == Py_None || PyBool_Check(source))
+ return source;
+ return 0;
+ }
+
+ static void construct(PyObject * source,
+ boost::python::converter::rvalue_from_python_stage1_data * data)
+ {
+ using namespace boost::python::converter;
+ void * const storage = ((rvalue_from_python_storage > *)
+ data)->storage.bytes;
+ if (source == Py_None) // == None
+ new (storage) boost::optional(); // A Boost uninitialized value
+ else
+ {
+ new (storage) boost::optional(source == Py_True ? true : false);
+ }
+ data->convertible = storage;
+ }
+ };
+
+ explicit python_optional()
+ {
+ register_python_conversion,
+ 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
class class_with_converter : public boost::python::class_
{
public:
diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp
index 1d57495d0..839ab154f 100644
--- a/demo/c++/rundemo.cpp
+++ b/demo/c++/rundemo.cpp
@@ -34,7 +34,6 @@
#include
#include
#include
-#include
#if defined(HAVE_CAIRO)
#include
@@ -313,11 +312,6 @@ int main ( int argc , char** argv)
#endif
}
- catch ( const mapnik::config_error & ex )
- {
- std::cerr << "### Configuration error: " << ex.what() << std::endl;
- return EXIT_FAILURE;
- }
catch ( const std::exception & ex )
{
std::cerr << "### std::exception: " << ex.what() << std::endl;
diff --git a/demo/data/test/raw/charplacement.gfs b/demo/data/test/raw/charplacement.gfs
deleted file mode 100644
index b05ad940b..000000000
--- a/demo/data/test/raw/charplacement.gfs
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- charplacement
- charplacement
-
- 1
- 1.00000
- 2.00000
- 1.00000
- 5.00000
-
-
- NAME
- NAME
- String
- 0
-
-
- CLASS
- CLASS
- String
- 0
-
-
-
diff --git a/demo/data/test/raw/charplacement.gml b/demo/data/test/raw/charplacement.gml
deleted file mode 100644
index 8de776840..000000000
--- a/demo/data/test/raw/charplacement.gml
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
-
- 00
- 13-13
-
-
-
-
-
- 2,-1 1,-3 2,-5
- Road Name
- TRIANGLE
-
-
- 3,-1 4,-3 3,-5
- Road Name
- TRIANGLE
-
-
-
-
- 1,-12 13,-12
-
- Road Name
- STRAIGHT
-
-
-
- 1,-13 2,-13 5,-13 10,-13 13,-13
-
- Road Name
- STRAIGHT
-
-
-
- 6,-1 5,-3 5,-5
- Road Name
- BEND
-
-
- 7,-1 8,-3 8,-5
- Road Name
- BEND
-
-
- 5,-6 5,-8 6,-10
- Road Name
- BEND
-
-
- 8,-6 8,-8 7,-10
- Road Name
- BEND
-
-
-
- 10.055915,-1.00031738281 10.6649858,-1.077712483 11.274056,-1.26950068 11.77921,-1.55298308 12.191993,-1.92815928 12.51529,-2.369132 12.746218,-2.8329032 12.884774,-3.2968745 12.930959,-3.875339
- Road Name
- CURVE
-
-
- 10.0555,-8.875339 10.6645708,-8.7979439 11.273641,-8.6061557 11.778795,-8.3226733 12.191578,-7.9474971 12.514875,-7.5065244 12.745803,-7.0427532 12.884359,-6.5787819 12.930544,-6.0003174
- Road Name
- CURVE
-
-
-
-
-9.055915,-2.00031738281 9.6649858,-2.077712483 10.274056,-2.26950068 10.77921,-2.55298308 11.191993,-2.92815928 11.51529,-3.369132 11.746218,-3.8329032 11.884774,-4.2968745 11.930959,-4.875339
-11.930544,-5.0003174 11.884359,-5.5787819 11.745803,-6.0427532 11.514875,-6.5065244 11.191578,-6.9474971 10.778795,-7.3226733 10.273641,-7.6061557 9.6645708,-7.7979439 9.0555,-7.875339
-
- Road Name
- CURVE
-
-
-
-
-9.0435048,-10.5550195 9.480786,-10.2191668 9.963148,-10.0731439 10.540222,-10.2495527 10.968444,-10.525815 11.419238,-10.8336443 12.01882,-10.9565825 12.559787,-10.7996079 12.956495,-10.4089966
-
- Road Name
- SQUIGGLE
-
-
-
-
- 1,-9 1.4,-10 1.8,-9 2.2,-10 2.6,-9 3.0,-10 3.4,-9 3.8,-10 4.2,-9 4.6,-10
-
- Long ZigZag Road Name
- ZIGZAG
-
-
-
-
diff --git a/demo/data/test/raw/charplacement.xsd b/demo/data/test/raw/charplacement.xsd
deleted file mode 100644
index 345905d06..000000000
--- a/demo/data/test/raw/charplacement.xsd
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/data/test/raw/displacement.gfs b/demo/data/test/raw/displacement.gfs
deleted file mode 100644
index 3034d7109..000000000
--- a/demo/data/test/raw/displacement.gfs
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- displacement
- displacement
-
- 1
- 1.00000
- 2.00000
- 1.00000
- 5.00000
-
-
- NAME
- NAME
- String
- 0
-
-
- CLASS
- CLASS
- String
- 0
-
-
-
diff --git a/demo/data/test/raw/displacement.gml b/demo/data/test/raw/displacement.gml
deleted file mode 100644
index 9b3a007ce..000000000
--- a/demo/data/test/raw/displacement.gml
+++ /dev/null
@@ -1,173 +0,0 @@
-
-
-
-
- 00
- 13-13
-
-
-
-
-
- 1,-3 1,-2
- Road
- CLOCKWISE
-
-
- 1,-2 2,-1
- Road
- CLOCKWISE
-
-
- 2,-1 3,-1
- Road
- CLOCKWISE
-
-
- 3,-1 4,-2
- Road
- CLOCKWISE
-
-
- 4,-2 4,-3
- Road
- CLOCKWISE
-
-
- 4,-3 3,-4
- Road
- CLOCKWISE
-
-
- 3,-4 2,-4
- Road
- CLOCKWISE
-
-
- 2,-4 1,-3
- Road
- CLOCKWISE
-
-
-
- 5,-3 6,-4
- Road
- ANTICLOCKWISE
-
-
- 6,-4 7,-4
- Road
- ANTICLOCKWISE
-
-
- 7,-4 8,-3
- Road
- ANTICLOCKWISE
-
-
- 8,-3 8,-2
- Road
- ANTICLOCKWISE
-
-
- 8,-2 7,-1
- Road
- ANTICLOCKWISE
-
-
- 7,-1 6,-1
- Road
- ANTICLOCKWISE
-
-
- 6,-1 5,-2
- Road
- ANTICLOCKWISE
-
-
- 5,-2 5,-3
- Road
- ANTICLOCKWISE
-
-
-
-
- 1,-6.5 2,-5.5 3,-5 4,-5 5,-5.5 6,-6.5
-
- Long Road Name To Go Around The Whole Curve!
- CURVE
-
-
-
-
- 1,-7 2,-8 3,-8.5 4,-8.5 5,-8 6,-7
-
- Long Road Name To Go Around The Whole Curve!
- CURVE
-
-
-
-
- 3,-8.5 2,-9.5 1.5,-10.5 1.5,-11.5 2,-12.5 3,-13.5
-
- Long Road Name To Go Around The Whole Curve!
- VERTCURVE
-
-
-
- 4,-8.5 5,-9.5 5.5,-10.5 5.5,-11.5 5,-12.5 4,-13.5
-
- Long Road Name To Go Around The Whole Curve!
- VERTCURVE
-
-
-
-
- 9.2,-4 9,-3 10,-3 10.2,-4
-
- Road Name
- PARALLELOGRAM
-
-
-
- 9,-2 9.2,-1 10.2,-1 10,-2
-
- Road Name
- PARALLELOGRAM
-
-
-
-
- 11,-1 11,-2 12,-2
-
- Road Name
- CORNER
-
-
-
- 11,-4 12,-4 12,-3
-
- Road Name
- CORNER
-
-
-
- 12.5,-1 13.5,-1 13.5,-2
-
- Road Name
- CORNER
-
-
-
- 12.5,-4 12.5,-3 13.5,-3
-
- Road Name
- CORNER
-
-
-
-
diff --git a/demo/data/test/raw/displacement.xsd b/demo/data/test/raw/displacement.xsd
deleted file mode 100644
index 66f9b90f0..000000000
--- a/demo/data/test/raw/displacement.xsd
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/data/test/raw/overlap.gfs b/demo/data/test/raw/overlap.gfs
deleted file mode 100644
index 67e8c818e..000000000
--- a/demo/data/test/raw/overlap.gfs
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- overlap
- overlap
-
- 1
- 1.00000
- 2.00000
- 1.00000
- 5.00000
-
-
- NAME
- NAME
- String
- 0
-
-
- CLASS
- CLASS
- String
- 0
-
-
-
diff --git a/demo/data/test/raw/overlap.gml b/demo/data/test/raw/overlap.gml
deleted file mode 100644
index 5fe0e85df..000000000
--- a/demo/data/test/raw/overlap.gml
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
-
- 00
- 13-13
-
-
-
-
-
- 1,-1 1,-10
- Road Name
- NETWORK
-
-
- 1,-3 7,-3
- Road Name
- NETWORK
-
-
- 7,-3 7,-7
- Road Name
- NETWORK
-
-
- 3,-2 3,-8
- Road Name
- NETWORK
-
-
- 7,-7 1,-7
- Road Name
- NETWORK
-
-
- 5,-2 5,-8
- Road Name
- NETWORK
-
-
-
- 8,-3 12,-3
- Road Name
- CROSS
-
-
- 10,-1 10,-5
- Road Name
- CROSS
-
-
-
-
- 10,-9 13,-9 13,-11 11,-11 11,-8
-
- Road Name
- SELFOVERLAP
-
-
-
- 4,-9 4,-13
- Road Name
- NETWORK2
-
-
- 8,-9 8,-13
- Road Name
- NETWORK2
-
-
- 1,-11 9,-11
- Road Name
- NETWORK2
-
-
- 2,-9 2,-13
- Road Name
- NETWORK2
-
-
- 6,-9 6,-13
- Road Name
- NETWORK2
-
-
-
-
- 8.8,-6 8.8,-8
- Long Road Name
- BENDOVER
-
-
- 8,-6 8,-7 10,-7 10,-8
- Long Road Name
- BENDUNDER
-
-
-
- 12.2,-6 12.2,-8
- Long Road Name
- BENDOVER
-
-
- 11,-6 11,-7 13,-7 13,-8
- Long Road Name
- BENDUNDER
-
-
-
- 12.2,-3.5 12.2,-5.5
- Long Road Name
- BENDOVER
-
-
- 11,-4.5 13,-4.5
- Long Road Name
- BENDUNDER
-
-
-
-
-
diff --git a/demo/data/test/raw/overlap.xsd b/demo/data/test/raw/overlap.xsd
deleted file mode 100644
index 1a7cf35a2..000000000
--- a/demo/data/test/raw/overlap.xsd
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/data/test/raw/textspacing.gfs b/demo/data/test/raw/textspacing.gfs
deleted file mode 100644
index c589181eb..000000000
--- a/demo/data/test/raw/textspacing.gfs
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- textspacing
- textspacing
-
- 1
- 1.00000
- 2.00000
- 1.00000
- 5.00000
-
-
- NAME
- NAME
- String
- 0
-
-
- CLASS
- CLASS
- String
- 0
-
-
-
diff --git a/demo/data/test/raw/textspacing.gml b/demo/data/test/raw/textspacing.gml
deleted file mode 100644
index 62fff2415..000000000
--- a/demo/data/test/raw/textspacing.gml
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
- 00
- 13-13
-
-
-
-
-
- 2,-1 1,-3 2,-5
- Road Name
- TRIANGLE
-
-
- 3,-1 4,-3 3,-5
- Road Name
- TRIANGLE
-
-
-
- 1,-7 2,-7
- Road Name
- STRAIGHT
-
-
- 1,-8 3,-8
- Road Name
- STRAIGHT
-
-
- 1,-9 4,-9
- Road Name
- STRAIGHT
-
-
- 1,-10 5,-10
- Road Name
- STRAIGHT
-
-
-
- 1,-11 7,-11
- Road Name
- STRAIGHT
-
-
-
- 1,-12 13,-12
-
- Road Name
- STRAIGHT
-
-
-
- 1,-13 2,-13 5,-13 10,-13 13,-13
-
- Road Name
- STRAIGHT
-
-
-
- 6,-1 5,-3 5,-5
- Road Name
- BEND
-
-
- 7,-1 8,-3 8,-5
- Road Name
- BEND
-
-
- 5,-6 5,-8 6,-10
- Road Name
- BEND
-
-
- 8,-6 8,-8 7,-10
- Road Name
- BEND
-
-
-
- 10.055915,-1.00031738281 10.6649858,-1.077712483 11.274056,-1.26950068 11.77921,-1.55298308 12.191993,-1.92815928 12.51529,-2.369132 12.746218,-2.8329032 12.884774,-3.2968745 12.930959,-3.875339
- Road Name
- CURVE
-
-
- 10.0555,-8.875339 10.6645708,-8.7979439 11.273641,-8.6061557 11.778795,-8.3226733 12.191578,-7.9474971 12.514875,-7.5065244 12.745803,-7.0427532 12.884359,-6.5787819 12.930544,-6.0003174
- Road Name
- CURVE
-
-
-
-
-9.055915,-2.00031738281 9.6649858,-2.077712483 10.274056,-2.26950068 10.77921,-2.55298308 11.191993,-2.92815928 11.51529,-3.369132 11.746218,-3.8329032 11.884774,-4.2968745 11.930959,-4.875339
-11.930544,-5.0003174 11.884359,-5.5787819 11.745803,-6.0427532 11.514875,-6.5065244 11.191578,-6.9474971 10.778795,-7.3226733 10.273641,-7.6061557 9.6645708,-7.7979439 9.0555,-7.875339
-
- Road Name
- CURVE
-
-
-
-
-9.0435048,-10.5550195 9.480786,-10.2191668 9.963148,-10.0731439 10.540222,-10.2495527 10.968444,-10.525815 11.419238,-10.8336443 12.01882,-10.9565825 12.559787,-10.7996079 12.956495,-10.4089966
-
- Road Name
- SQUIGGLE
-
-
-
-
diff --git a/demo/data/test/raw/textspacing.xsd b/demo/data/test/raw/textspacing.xsd
deleted file mode 100644
index 2e6a4d755..000000000
--- a/demo/data/test/raw/textspacing.xsd
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/data/test/readme.txt b/demo/data/test/readme.txt
deleted file mode 100644
index c1dc62efd..000000000
--- a/demo/data/test/readme.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-These files are for testing various rendering parts of mapnik, they have been created by hand.
-The raw files are in the raw/ folder (they were created with inkscape to assist!)
-Run the regenerate.sh script to regenerate the shape files from the gml files, this requires ogr2ogr to run.
diff --git a/demo/data/test/regenerate.sh b/demo/data/test/regenerate.sh
deleted file mode 100755
index de1b5babe..000000000
--- a/demo/data/test/regenerate.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-rm -f textspacing.shp textspacing.shx textspacing.dbf
-ogr2ogr -f "ESRI Shapefile" textspacing raw/textspacing.gml
-mv textspacing/* ./
-rmdir textspacing
-
-rm -f overlap.shp overlap.shx overlap.dbf
-ogr2ogr -f "ESRI Shapefile" overlap raw/overlap.gml
-mv overlap/* ./
-rmdir overlap
-
-rm -f displacement.shp displacement.shx displacement.dbf
-ogr2ogr -f "ESRI Shapefile" displacement raw/displacement.gml
-mv displacement/* ./
-rmdir displacement
-
-rm -f charplacement.shp charplacement.shx charplacement.dbf
-ogr2ogr -f "ESRI Shapefile" charplacement raw/charplacement.gml
-mv charplacement/* ./
-rmdir charplacement
diff --git a/demo/viewer/main.cpp b/demo/viewer/main.cpp
index 73af0c95c..6d83c46a9 100644
--- a/demo/viewer/main.cpp
+++ b/demo/viewer/main.cpp
@@ -19,7 +19,7 @@
// qt
-#include
+#include
#include
#include
#include
diff --git a/demo/viewer/mainwindow.cpp b/demo/viewer/mainwindow.cpp
index 996138678..e87e7a0d4 100644
--- a/demo/viewer/mainwindow.cpp
+++ b/demo/viewer/mainwindow.cpp
@@ -32,7 +32,10 @@
#include
#include
#include
-
+#include
+#include
+#include
+#include
// mapnik
#ifndef Q_MOC_RUN // QT moc chokes on BOOST_JOIN
diff --git a/demo/viewer/mainwindow.hpp b/demo/viewer/mainwindow.hpp
index 99936da73..f5f01863f 100644
--- a/demo/viewer/mainwindow.hpp
+++ b/demo/viewer/mainwindow.hpp
@@ -22,7 +22,6 @@
#define MAINWINDOW_HPP
#include
-#include
#include
#include
#include
@@ -78,7 +77,6 @@ private:
LayerTab *layerTab_;
StyleTab * styleTab_;
MapWidget * mapWidget_;
- QPrinter printer;
//actions
QList exportAsActs;
QActionGroup *toolsGroup;
diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp
index 0b8753e44..93be08351 100644
--- a/demo/viewer/mapwidget.cpp
+++ b/demo/viewer/mapwidget.cpp
@@ -26,7 +26,6 @@
#include
#include
-#include
#include
#include
#include
@@ -528,42 +527,7 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
void render_grid(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
- unsigned width=map.width();
- unsigned height=map.height();
-
- mapnik::grid buf(width,height,"F_CODE", 1);
- mapnik::grid_renderer ren(map,buf,scaling_factor);
-
- try
- {
- ren.apply();
- mapnik::value_integer * imdata = static_cast(buf.raw_data());
-
- // Not sure how to display long long values ??
- //QImage image(width,height,QImage::Format_RGB32);
- //for (unsigned i = 0 ; i < height ; ++i)
- //{
- // for (unsigned j = 0 ; j < width ; ++j)
- // {
- // image.setPixel(j,i,qRgb((uint8_t)(imdata[i*width+j]>>8),
- // (uint8_t)(imdata[i*width+j+1]>>8),
- // (uint8_t)(imdata[i*width+j+2]>>8)));
- // }
- //}
- //pix = QPixmap::fromImage(image);
- }
- catch (mapnik::config_error & ex)
- {
- std::cerr << ex.what() << std::endl;
- }
- catch (const std::exception & ex)
- {
- std::cerr << "exception: " << ex.what() << std::endl;
- }
- catch (...)
- {
- std::cerr << "Unknown exception caught!\n";
- }
+ std::cerr << "Not supported" << std::endl;
}
diff --git a/demo/viewer/viewer.pro b/demo/viewer/viewer.pro
index adf2a46be..a19bc9c95 100644
--- a/demo/viewer/viewer.pro
+++ b/demo/viewer/viewer.pro
@@ -2,8 +2,10 @@
# Mapnik viewer - Copyright (C) 2007 Artem Pavlenko
######################################################################
TEMPLATE = app
+QT += core gui widgets
QMAKE_CXX = clang++
QMAKE_CXXFLAGS += $$system(mapnik-config --cxxflags)
+QMAKE_CXXFLAGS += $$system(mapnik-config --includes --dep-includes)
QMAKE_LFLAGS += $$system(mapnik-config --libs)
QMAKE_LFLAGS += $$system(mapnik-config --ldflags --dep-libs)
QMAKE_LFLAGS += -lboost_timer
diff --git a/deps/agg/include/agg_conv_clipper.h b/deps/agg/include/agg_conv_clipper.h
index 1c8e74253..2627cec05 100755
--- a/deps/agg/include/agg_conv_clipper.h
+++ b/deps/agg/include/agg_conv_clipper.h
@@ -1,326 +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
-#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 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 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 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;
- double start_x_;
- double start_y_;
-
- 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),
- start_x_(0),
- start_y_(0)
- {
- m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
- m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
- }
-
- conv_clipper(source_a_type &a,
- clipper_op_e op = clipper_and,
- clipper_PolyFillType subjFillType = clipper_non_zero,
- clipper_PolyFillType clipFillType = clipper_non_zero,
- int scaling_factor = 6) :
- m_src_a(&a),
- m_status(status_move_to),
- m_vertex(-1),
- m_contour(-1),
- m_operation(op),
- m_subjFillType(subjFillType),
- m_clipFillType(clipFillType),
- start_x_(0),
- start_y_(0)
- {
- m_scaling_factor = std::max(std::min(scaling_factor, 6),0);
- m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
- }
-
- ~conv_clipper()
- {
- }
- unsigned type() const { return m_src_a->type(); }
- 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 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
-void conv_clipper::start_extracting()
-{
- m_status = status_move_to;
- m_contour = -1;
- m_vertex = -1;
-}
-//------------------------------------------------------------------------------
-
-template
-void conv_clipper::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
-void conv_clipper::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
-void conv_clipper::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
-bool conv_clipper::next_contour()
-{
- m_contour++;
- if(m_contour >= (int)m_result.size()) return false;
- m_vertex =-1;
- return true;
-}
-//------------------------------------------------------------------------------
-
-template
-bool conv_clipper::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
-unsigned conv_clipper::vertex(double *x, double *y)
-{
- if( m_status == status_move_to )
- {
- if( next_contour() )
- {
- if( next_vertex( x, y ) )
- {
- m_status =status_line_to;
- start_x_ = *x;
- start_y_ = *y;
- return path_cmd_move_to;
- }
- else
- {
- *x = start_x_;
- *y = start_y_;
- 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;
- *x = start_x_;
- *y = start_y_;
- 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
+#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 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 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 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 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
+ void conv_clipper::start_extracting()
+ {
+ m_status = status_move_to;
+ m_contour = -1;
+ m_vertex = -1;
+ }
+ //------------------------------------------------------------------------------
+
+ template
+ void conv_clipper::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
+ void conv_clipper::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
+ void conv_clipper::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
+ bool conv_clipper::next_contour()
+ {
+ m_contour++;
+ if(m_contour >= (int)m_result.size()) return false;
+ m_vertex =-1;
+ return true;
+}
+//------------------------------------------------------------------------------
+
+ template
+ bool conv_clipper::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
+ unsigned conv_clipper::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
diff --git a/deps/clipper/include/clipper.hpp b/deps/clipper/include/clipper.hpp
old mode 100644
new mode 100755
index 5f1952261..78f6b1ca0
--- a/deps/clipper/include/clipper.hpp
+++ b/deps/clipper/include/clipper.hpp
@@ -1,8 +1,8 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
-* Version : 5.1.3 *
-* Date : 27 February 2013 *
+* Version : 5.1.5 *
+* Date : 4 May 2013 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 *
* *
@@ -34,6 +34,8 @@
#ifndef clipper_hpp
#define clipper_hpp
+#include
+
#include
#include
#include
@@ -134,7 +136,6 @@ struct TEdge {
double dx;
long64 deltaX;
long64 deltaY;
- long64 tmpX;
PolyType polyType;
EdgeSide side;
int windDelta; //1 or -1 depending on winding direction
@@ -211,7 +212,7 @@ typedef std::vector < HorzJoinRec* > HorzJoinList;
//ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of
//polygon coordinates into edge objects that are stored in a LocalMinima list.
-class ClipperBase
+class MAPNIK_DECL ClipperBase
{
public:
ClipperBase();
@@ -232,7 +233,7 @@ protected:
EdgeList m_edges;
};
-class Clipper : public virtual ClipperBase
+class MAPNIK_DECL Clipper : public virtual ClipperBase
{
public:
Clipper();
@@ -248,6 +249,8 @@ 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;};
protected:
void Reset();
virtual bool ExecuteInternal();
@@ -265,6 +268,7 @@ private:
PolyFillType m_SubjFillType;
bool m_ReverseOutput;
bool m_UsingPolyTree;
+ bool m_ForceSimple;
void DisposeScanbeamList();
void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const;
@@ -287,10 +291,8 @@ private:
void ProcessHorizontal(TEdge *horzEdge);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
+ OutRec* GetOutRec(int idx);
void AppendPolygon(TEdge *e1, TEdge *e2);
- void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
- void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
- void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
void IntersectEdges(TEdge *e1, TEdge *e2,
const IntPoint &pt, const IntersectProtects protects);
OutRec* CreateOutRec();
@@ -304,12 +306,12 @@ private:
void ProcessEdgesAtTopOfScanbeam(const long64 topY);
void BuildResult(Polygons& polys);
void BuildResult2(PolyTree& polytree);
- void SetHoleState(TEdge *e, OutRec *OutRec);
+ void SetHoleState(TEdge *e, OutRec *outrec);
void DisposeIntersectNodes();
bool FixupIntersectionOrder();
- void FixupOutPolygon(OutRec &outRec);
+ void FixupOutPolygon(OutRec &outrec);
bool IsHole(TEdge *e);
- void FixHoleLinkage(OutRec &outRec);
+ void FixHoleLinkage(OutRec &outrec);
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
void ClearJoins();
void AddHorzJoin(TEdge *e, int idx);
@@ -317,6 +319,7 @@ private:
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
void JoinCommonEdges();
+ void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
};
diff --git a/deps/clipper/src/clipper.cpp b/deps/clipper/src/clipper.cpp
old mode 100644
new mode 100755
index e79e94942..7f4ceceb6
--- a/deps/clipper/src/clipper.cpp
+++ b/deps/clipper/src/clipper.cpp
@@ -1,8 +1,8 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
-* Version : 5.1.3 *
-* Date : 27 February 2013 *
+* Version : 5.1.5 *
+* Date : 4 May 2013 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 *
* *
@@ -79,7 +79,7 @@ void PolyTree::Clear()
PolyNode* PolyTree::GetFirst() const
{
- if (Childs.size() > 0)
+ if (!Childs.empty())
return Childs[0];
else
return 0;
@@ -117,7 +117,7 @@ void PolyNode::AddChild(PolyNode& child)
PolyNode* PolyNode::GetNext() const
{
- if (Childs.size() > 0)
+ if (!Childs.empty())
return Childs[0];
else
return GetNextSiblingUp();
@@ -434,6 +434,40 @@ bool PointIsVertex(const IntPoint &pt, OutPt *pp)
}
//------------------------------------------------------------------------------
+bool PointOnLineSegment(const IntPoint pt,
+ const IntPoint linePt1, const IntPoint linePt2, bool UseFullInt64Range)
+{
+ if (UseFullInt64Range)
+ return ((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) ||
+ ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) ||
+ (((pt.X > linePt1.X) == (pt.X < linePt2.X)) &&
+ ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) &&
+ ((Int128Mul((pt.X - linePt1.X), (linePt2.Y - linePt1.Y)) ==
+ Int128Mul((linePt2.X - linePt1.X), (pt.Y - linePt1.Y)))));
+ else
+ return ((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) ||
+ ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) ||
+ (((pt.X > linePt1.X) == (pt.X < linePt2.X)) &&
+ ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) &&
+ ((pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) ==
+ (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y)));
+}
+//------------------------------------------------------------------------------
+
+bool PointOnPolygon(const IntPoint pt,
+ OutPt *pp, bool UseFullInt64Range)
+{
+ OutPt *pp2 = pp;
+ for (;;)
+ {
+ if (PointOnLineSegment(pt, pp2->pt, pp2->next->pt, UseFullInt64Range))
+ return true;
+ pp2 = pp2->next;
+ if (pp2 == pp) return false;
+ }
+}
+//------------------------------------------------------------------------------
+
bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range)
{
OutPt *pp2 = pp;
@@ -543,14 +577,18 @@ bool IntersectPoint(TEdge &edge1, TEdge &edge2,
IntPoint &ip, bool UseFullInt64Range)
{
double b1, b2;
- if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false;
+ if (SlopesEqual(edge1, edge2, UseFullInt64Range))
+ {
+ if (edge2.ybot > edge1.ybot) ip.Y = edge2.ybot;
+ else ip.Y = edge1.ybot;
+ return false;
+ }
else if (NEAR_ZERO(edge1.dx))
{
ip.X = edge1.xbot;
if (NEAR_EQUAL(edge2.dx, HORIZONTAL))
- {
ip.Y = edge2.ybot;
- } else
+ else
{
b2 = edge2.ybot - (edge2.xbot / edge2.dx);
ip.Y = Round(ip.X / edge2.dx + b2);
@@ -560,14 +598,14 @@ bool IntersectPoint(TEdge &edge1, TEdge &edge2,
{
ip.X = edge2.xbot;
if (NEAR_EQUAL(edge1.dx, HORIZONTAL))
- {
ip.Y = edge1.ybot;
- } else
+ else
{
b1 = edge1.ybot - (edge1.xbot / edge1.dx);
ip.Y = Round(ip.X / edge1.dx + b1);
}
- } else
+ }
+ else
{
b1 = edge1.xbot - edge1.ybot * edge1.dx;
b2 = edge2.xbot - edge2.ybot * edge2.dx;
@@ -586,7 +624,8 @@ bool IntersectPoint(TEdge &edge1, TEdge &edge2,
ip.X = edge1.xtop;
ip.Y = edge1.ytop;
return TopX(edge2, edge1.ytop) < edge1.xtop;
- } else
+ }
+ else
{
ip.X = edge2.xtop;
ip.Y = edge2.ytop;
@@ -620,7 +659,7 @@ void DisposeOutPts(OutPt*& pp)
{
OutPt *tmpPp = pp;
pp = pp->next;
- delete tmpPp ;
+ delete tmpPp;
}
}
//------------------------------------------------------------------------------
@@ -1111,6 +1150,7 @@ Clipper::Clipper() : ClipperBase() //constructor
m_ExecuteLocked = false;
m_UseFullRange = false;
m_ReverseOutput = false;
+ m_ForceSimple = false;
}
//------------------------------------------------------------------------------
@@ -1123,7 +1163,7 @@ Clipper::~Clipper() //destructor
void Clipper::Clear()
{
- if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor
+ if (m_edges.empty()) return; //avoids problems with ClipperBase destructor
DisposeAllPolyPts();
ClipperBase::Clear();
}
@@ -1189,18 +1229,18 @@ bool Clipper::Execute(ClipType clipType, PolyTree& polytree,
}
//------------------------------------------------------------------------------
-void Clipper::FixHoleLinkage(OutRec &outRec)
+void Clipper::FixHoleLinkage(OutRec &outrec)
{
//skip OutRecs that (a) contain outermost polygons or
//(b) already have the correct owner/child linkage ...
- if (!outRec.FirstLeft ||
- (outRec.isHole != outRec.FirstLeft->isHole &&
- outRec.FirstLeft->pts)) return;
+ if (!outrec.FirstLeft ||
+ (outrec.isHole != outrec.FirstLeft->isHole &&
+ outrec.FirstLeft->pts)) return;
- OutRec* orfl = outRec.FirstLeft;
- while (orfl && ((orfl->isHole == outRec.isHole) || !orfl->pts))
+ OutRec* orfl = outrec.FirstLeft;
+ while (orfl && ((orfl->isHole == outrec.isHole) || !orfl->pts))
orfl = orfl->FirstLeft;
- outRec.FirstLeft = orfl;
+ outrec.FirstLeft = orfl;
}
//------------------------------------------------------------------------------
@@ -1240,7 +1280,8 @@ bool Clipper::ExecuteInternal()
ReversePolyPtLinks(outRec->pts);
}
- if (m_Joins.size() > 0) JoinCommonEdges();
+ if (!m_Joins.empty()) JoinCommonEdges();
+ if (m_ForceSimple) DoSimplePolygons();
}
ClearJoins();
@@ -1757,15 +1798,30 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
(e1->polyType != e2->polyType && m_ClipType != ctXor) )
AddLocalMaxPoly(e1, e2, pt);
else
- DoBothEdges( e1, e2, pt );
+ {
+ AddOutPt(e1, pt);
+ AddOutPt(e2, pt);
+ SwapSides( *e1 , *e2 );
+ SwapPolyIndexes( *e1 , *e2 );
+ }
}
else if ( e1Contributing )
{
- if (e2Wc == 0 || e2Wc == 1) DoEdge1(e1, e2, pt);
+ if (e2Wc == 0 || e2Wc == 1)
+ {
+ AddOutPt(e1, pt);
+ SwapSides(*e1, *e2);
+ SwapPolyIndexes(*e1, *e2);
+ }
}
else if ( e2contributing )
{
- if (e1Wc == 0 || e1Wc == 1) DoEdge2(e1, e2, pt);
+ if (e1Wc == 0 || e1Wc == 1)
+ {
+ AddOutPt(e2, pt);
+ SwapSides(*e1, *e2);
+ SwapPolyIndexes(*e1, *e2);
+ }
}
else if ( (e1Wc == 0 || e1Wc == 1) &&
(e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops )
@@ -1823,7 +1879,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
}
//------------------------------------------------------------------------------
-void Clipper::SetHoleState(TEdge *e, OutRec *outRec)
+void Clipper::SetHoleState(TEdge *e, OutRec *outrec)
{
bool isHole = false;
TEdge *e2 = e->prevInAEL;
@@ -1832,18 +1888,22 @@ void Clipper::SetHoleState(TEdge *e, OutRec *outRec)
if (e2->outIdx >= 0)
{
isHole = !isHole;
- if (! outRec->FirstLeft)
- outRec->FirstLeft = m_PolyOuts[e2->outIdx];
+ if (! outrec->FirstLeft)
+ outrec->FirstLeft = m_PolyOuts[e2->outIdx];
}
e2 = e2->prevInAEL;
}
- if (isHole) outRec->isHole = true;
+ if (isHole) outrec->isHole = true;
}
//------------------------------------------------------------------------------
OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
{
//work out which polygon fragment has the correct hole state ...
+ if (!outRec1->bottomPt)
+ outRec1->bottomPt = GetBottomPt(outRec1->pts);
+ if (!outRec2->bottomPt)
+ outRec2->bottomPt = GetBottomPt(outRec2->pts);
OutPt *outPt1 = outRec1->bottomPt;
OutPt *outPt2 = outRec2->bottomPt;
if (outPt1->pt.Y > outPt2->pt.Y) return outRec1;
@@ -1868,6 +1928,15 @@ bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2)
}
//------------------------------------------------------------------------------
+OutRec* Clipper::GetOutRec(int idx)
+{
+ OutRec* outrec = m_PolyOuts[idx];
+ while (outrec != m_PolyOuts[outrec->idx])
+ outrec = m_PolyOuts[outrec->idx];
+ return outrec;
+}
+//------------------------------------------------------------------------------
+
void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
{
//get the start and ends of both output polygons ...
@@ -1931,10 +2000,9 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
side = esRight;
}
+ outRec1->bottomPt = 0;
if (holeStateRec == outRec2)
{
- outRec1->bottomPt = outRec2->bottomPt;
- outRec1->bottomPt->idx = outRec1->idx;
if (outRec2->FirstLeft != outRec1)
outRec1->FirstLeft = outRec2->FirstLeft;
outRec1->isHole = outRec2->isHole;
@@ -1962,18 +2030,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
e = e->nextInAEL;
}
- for (JoinList::size_type i = 0; i < m_Joins.size(); ++i)
- {
- if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx;
- if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx;
- }
-
- for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i)
- {
- if (m_HorizJoins[i]->savedIdx == ObsoleteIdx)
- m_HorizJoins[i]->savedIdx = OKIdx;
- }
-
+ outRec2->idx = outRec1->idx;
}
//------------------------------------------------------------------------------
@@ -1985,6 +2042,8 @@ OutRec* Clipper::CreateOutRec()
result->pts = 0;
result->bottomPt = 0;
result->polyNode = 0;
+ m_PolyOuts.push_back(result);
+ result->idx = (int)m_PolyOuts.size()-1;
return result;
}
//------------------------------------------------------------------------------
@@ -1995,12 +2054,9 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
if( e->outIdx < 0 )
{
OutRec *outRec = CreateOutRec();
- m_PolyOuts.push_back(outRec);
- outRec->idx = (int)m_PolyOuts.size()-1;
e->outIdx = outRec->idx;
OutPt* op = new OutPt;
outRec->pts = op;
- outRec->bottomPt = op;
op->pt = pt;
op->idx = outRec->idx;
op->next = op;
@@ -2016,9 +2072,6 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
OutPt* op2 = new OutPt;
op2->pt = pt;
op2->idx = outRec->idx;
- if (op2->pt.Y == outRec->bottomPt->pt.Y &&
- op2->pt.X < outRec->bottomPt->pt.X)
- outRec->bottomPt = op2;
op2->next = op;
op2->prev = op->prev;
op2->prev->next = op2;
@@ -2053,19 +2106,19 @@ bool Clipper::IsTopHorz(const long64 XPos)
}
//------------------------------------------------------------------------------
-bool IsMinima(TEdge *e)
+inline bool IsMinima(TEdge *e)
{
return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e);
}
//------------------------------------------------------------------------------
-bool IsMaxima(TEdge *e, const long64 Y)
+inline bool IsMaxima(TEdge *e, const long64 Y)
{
return e && e->ytop == Y && !e->nextInLML;
}
//------------------------------------------------------------------------------
-bool IsIntermediate(TEdge *e, const long64 Y)
+inline bool IsIntermediate(TEdge *e, const long64 Y)
{
return e->ytop == Y && e->nextInLML;
}
@@ -2198,28 +2251,28 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
TEdge* e = GetNextInAEL( horzEdge , dir );
while( e )
{
+ if ( e->xcurr == horzEdge->xtop && !eMaxPair )
+ {
+ if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange))
+ {
+ //if output polygons share an edge, they'll need joining later ...
+ if (horzEdge->outIdx >= 0 && e->outIdx >= 0)
+ AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx);
+ break; //we've reached the end of the horizontal line
+ }
+ else if (e->dx < horzEdge->nextInLML->dx)
+ //we really have got to the end of the intermediate horz edge so quit.
+ //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal.
+ break;
+ }
+
TEdge* eNext = GetNextInAEL( e, dir );
if (eMaxPair ||
((dir == dLeftToRight) && (e->xcurr < horzRight)) ||
((dir == dRightToLeft) && (e->xcurr > horzLeft)))
{
- //ok, so far it looks like we're still in range of the horizontal edge
- if ( e->xcurr == horzEdge->xtop && !eMaxPair )
- {
- if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange))
- {
- //if output polygons share an edge, they'll need joining later ...
- if (horzEdge->outIdx >= 0 && e->outIdx >= 0)
- AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx);
- break; //we've reached the end of the horizontal line
- }
- else if (e->dx < horzEdge->nextInLML->dx)
- //we really have got to the end of the intermediate horz edge so quit.
- //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal.
- break;
- }
-
+ //so far we're still in range of the horizontal edge
if( e == eMaxPair )
{
//horzEdge is evidently a maxima horizontal and we've arrived at its end.
@@ -2255,8 +2308,8 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
}
SwapPositionsInAEL( horzEdge, e );
}
- else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) ||
- (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break;
+ else if( (dir == dLeftToRight && e->xcurr >= horzRight) ||
+ (dir == dRightToLeft && e->xcurr <= horzLeft) ) break;
e = eNext;
} //end while
@@ -2304,8 +2357,8 @@ bool Clipper::ProcessIntersections(const long64 botY, const long64 topY)
if( !m_ActiveEdges ) return true;
try {
BuildIntersectList(botY, topY);
- if ( !m_IntersectNodes) return true;
- if ( FixupIntersectionOrder() ) ProcessIntersectList();
+ if (!m_IntersectNodes) return true;
+ if (!m_IntersectNodes->next || FixupIntersectionOrder()) ProcessIntersectList();
else return false;
}
catch(...) {
@@ -2313,6 +2366,7 @@ bool Clipper::ProcessIntersections(const long64 botY, const long64 topY)
DisposeIntersectNodes();
throw clipperException("ProcessIntersections error");
}
+ m_SortedEdges = 0;
return true;
}
//------------------------------------------------------------------------------
@@ -2339,7 +2393,7 @@ void Clipper::BuildIntersectList(const long64 botY, const long64 topY)
{
e->prevInSEL = e->prevInAEL;
e->nextInSEL = e->nextInAEL;
- e->tmpX = TopX( *e, topY );
+ e->xcurr = TopX( *e, topY );
e = e->nextInAEL;
}
@@ -2353,9 +2407,10 @@ void Clipper::BuildIntersectList(const long64 botY, const long64 topY)
{
TEdge *eNext = e->nextInSEL;
IntPoint pt;
- if(e->tmpX > eNext->tmpX &&
- IntersectPoint(*e, *eNext, pt, m_UseFullRange))
+ if(e->xcurr > eNext->xcurr)
{
+ if (!IntersectPoint(*e, *eNext, pt, m_UseFullRange) && e->xcurr > eNext->xcurr +1)
+ throw clipperException("Intersection error");
if (pt.Y > botY)
{
pt.Y = botY;
@@ -2375,27 +2430,6 @@ void Clipper::BuildIntersectList(const long64 botY, const long64 topY)
}
//------------------------------------------------------------------------------
-bool ProcessParam1BeforeParam2(const IntersectNode &node1, const IntersectNode &node2)
-{
- bool result;
- if (node1.pt.Y == node2.pt.Y)
- {
- if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1)
- {
- result = node2.pt.X > node1.pt.X;
- return node2.edge1->dx > 0 ? !result : result;
- }
- else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2)
- {
- result = node2.pt.X > node1.pt.X;
- return node2.edge2->dx > 0 ? !result : result;
- }
- else return node2.pt.X > node1.pt.X;
- }
- else return node1.pt.Y > node2.pt.Y;
-}
-//------------------------------------------------------------------------------
-
void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
{
IntersectNode* newNode = new IntersectNode;
@@ -2404,7 +2438,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
newNode->pt = pt;
newNode->next = 0;
if( !m_IntersectNodes ) m_IntersectNodes = newNode;
- else if( ProcessParam1BeforeParam2(*newNode, *m_IntersectNodes) )
+ else if(newNode->pt.Y > m_IntersectNodes->pt.Y )
{
newNode->next = m_IntersectNodes;
m_IntersectNodes = newNode;
@@ -2412,7 +2446,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
else
{
IntersectNode* iNode = m_IntersectNodes;
- while( iNode->next && ProcessParam1BeforeParam2(*iNode->next, *newNode) )
+ while(iNode->next && newNode->pt.Y <= iNode->next->pt.Y)
iNode = iNode->next;
newNode->next = iNode->next;
iNode->next = newNode;
@@ -2478,8 +2512,9 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
}
else
{
+ bool intermediateVert = IsIntermediate(e, topY);
//2. promote horizontal edges, otherwise update xcurr and ycurr ...
- if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) )
+ if (intermediateVert && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) )
{
if (e->outIdx >= 0)
{
@@ -2502,9 +2537,18 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
AddEdgeToSEL(e);
} else
{
- //this just simplifies horizontal processing ...
e->xcurr = TopX( *e, topY );
e->ycurr = topY;
+
+ if (m_ForceSimple && e->prevInAEL &&
+ e->prevInAEL->xcurr == e->xcurr &&
+ e->outIdx >= 0 && e->prevInAEL->outIdx >= 0)
+ {
+ if (intermediateVert)
+ AddOutPt(e->prevInAEL, IntPoint(e->xcurr, topY));
+ else
+ AddOutPt(e, IntPoint(e->xcurr, topY));
+ }
}
e = e->nextInAEL;
}
@@ -2547,21 +2591,20 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
}
//------------------------------------------------------------------------------
-void Clipper::FixupOutPolygon(OutRec &outRec)
+void Clipper::FixupOutPolygon(OutRec &outrec)
{
//FixupOutPolygon() - removes duplicate points and simplifies consecutive
//parallel edges by removing the middle vertex.
OutPt *lastOK = 0;
- outRec.pts = outRec.bottomPt;
- OutPt *pp = outRec.bottomPt;
+ outrec.bottomPt = 0;
+ OutPt *pp = outrec.pts;
for (;;)
{
if (pp->prev == pp || pp->prev == pp->next )
{
DisposeOutPts(pp);
- outRec.pts = 0;
- outRec.bottomPt = 0;
+ outrec.pts = 0;
return;
}
//test for duplicate points and for same slope (cross-product) ...
@@ -2570,8 +2613,6 @@ void Clipper::FixupOutPolygon(OutRec &outRec)
{
lastOK = 0;
OutPt *tmp = pp;
- if (pp == outRec.bottomPt)
- outRec.bottomPt = 0; //flags need for updating
pp->prev->next = pp->next;
pp->next->prev = pp->prev;
pp = pp->prev;
@@ -2584,35 +2625,28 @@ void Clipper::FixupOutPolygon(OutRec &outRec)
pp = pp->next;
}
}
- if (!outRec.bottomPt) {
- outRec.bottomPt = GetBottomPt(pp);
- outRec.bottomPt->idx = outRec.idx;
- outRec.pts = outRec.bottomPt;
- }
+ outrec.pts = pp;
}
//------------------------------------------------------------------------------
void Clipper::BuildResult(Polygons &polys)
{
- int k = 0;
- polys.resize(m_PolyOuts.size());
+ polys.reserve(m_PolyOuts.size());
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
{
if (m_PolyOuts[i]->pts)
{
- Polygon* pg = &polys[k];
- pg->clear();
+ Polygon pg;
OutPt* p = m_PolyOuts[i]->pts;
do
{
- pg->push_back(p->pt);
+ pg.push_back(p->pt);
p = p->prev;
} while (p != m_PolyOuts[i]->pts);
- //make sure each polygon has at least 3 vertices ...
- if (pg->size() < 3) pg->clear(); else k++;
+ if (pg.size() > 2)
+ polys.push_back(pg);
}
}
- polys.resize(k);
}
//------------------------------------------------------------------------------
@@ -2673,67 +2707,58 @@ void Clipper::BuildResult2(PolyTree& polytree)
void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2)
{
- TEdge *e1 = int1.edge1;
- TEdge *e2 = int1.edge2;
- IntPoint p = int1.pt;
-
+ //just swap the contents (because fIntersectNodes is a single-linked-list)
+ IntersectNode inode = int1; //gets a copy of Int1
int1.edge1 = int2.edge1;
int1.edge2 = int2.edge2;
int1.pt = int2.pt;
+ int2.edge1 = inode.edge1;
+ int2.edge2 = inode.edge2;
+ int2.pt = inode.pt;
+}
+//------------------------------------------------------------------------------
- int2.edge1 = e1;
- int2.edge2 = e2;
- int2.pt = p;
+inline bool EdgesAdjacent(const IntersectNode &inode)
+{
+ return (inode.edge1->nextInSEL == inode.edge2) ||
+ (inode.edge1->prevInSEL == inode.edge2);
}
//------------------------------------------------------------------------------
bool Clipper::FixupIntersectionOrder()
{
- if ( !m_IntersectNodes->next ) return true;
-
+ //pre-condition: intersections are sorted bottom-most (then left-most) first.
+ //Now it's crucial that intersections are made only between adjacent edges,
+ //so to ensure this the order of intersections may need adjusting ...
+ IntersectNode *inode = m_IntersectNodes;
CopyAELToSEL();
- IntersectNode *int1 = m_IntersectNodes;
- IntersectNode *int2 = m_IntersectNodes->next;
- while (int2)
+ while (inode)
{
- TEdge *e1 = int1->edge1;
- TEdge *e2;
- if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL;
- else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL;
- else
+ if (!EdgesAdjacent(*inode))
{
- //The current intersection (Int1) is out of order (since it doesn't
- //contain adjacent edges), so swap it with a subsequent intersection ...
- while (int2)
- {
- if (int2->edge1->nextInSEL == int2->edge2 ||
- int2->edge1->prevInSEL == int2->edge2) break;
- else int2 = int2->next;
- }
- if ( !int2 ) return false; //oops!!!
-
- //found an intersect node (Int2) that does contain adjacent edges,
- //so prepare to process it before Int1 ...
- SwapIntersectNodes(*int1, *int2);
- e1 = int1->edge1;
- e2 = int1->edge2;
+ IntersectNode *nextNode = inode->next;
+ while (nextNode && !EdgesAdjacent(*nextNode))
+ nextNode = nextNode->next;
+ if (!nextNode)
+ return false;
+ SwapIntersectNodes(*inode, *nextNode);
}
- SwapPositionsInSEL(e1, e2);
- int1 = int1->next;
- int2 = int1->next;
+ SwapPositionsInSEL(inode->edge1, inode->edge2);
+ inode = inode->next;
}
-
- m_SortedEdges = 0;
-
- //finally, check the last intersection too ...
- return (int1->edge1->prevInSEL == int1->edge2 ||
- int1->edge1->nextInSEL == int1->edge2);
+ return true;
}
//------------------------------------------------------------------------------
bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2)
{
- return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr;
+ if (e2.xcurr == e1.xcurr)
+ {
+ if (e2.ytop > e1.ytop)
+ return e2.xtop < TopX(e1, e2.ytop);
+ else return e1.xtop > TopX(e2, e1.ytop);
+ }
+ else return e2.xcurr < e1.xcurr;
}
//------------------------------------------------------------------------------
@@ -2763,31 +2788,6 @@ void Clipper::InsertEdgeIntoAEL(TEdge *edge)
}
//----------------------------------------------------------------------
-void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt)
-{
- AddOutPt(edge1, pt);
- SwapSides(*edge1, *edge2);
- SwapPolyIndexes(*edge1, *edge2);
-}
-//----------------------------------------------------------------------
-
-void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt)
-{
- AddOutPt(edge2, pt);
- SwapSides(*edge1, *edge2);
- SwapPolyIndexes(*edge1, *edge2);
-}
-//----------------------------------------------------------------------
-
-void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt)
-{
- AddOutPt(edge1, pt);
- AddOutPt(edge2, pt);
- SwapSides( *edge1 , *edge2 );
- SwapPolyIndexes( *edge1 , *edge2 );
-}
-//----------------------------------------------------------------------
-
bool Clipper::JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2)
{
OutRec *outRec1 = m_PolyOuts[j->poly1Idx];
@@ -2875,24 +2875,17 @@ void Clipper::FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx)
bool Poly2ContainsPoly1(OutPt* outPt1, OutPt* outPt2, bool UseFullInt64Range)
{
- //find the first pt in outPt1 that isn't also a vertex of outPt2 ...
- OutPt* outPt = outPt1;
- do
+ OutPt* pt = outPt1;
+ //Because the polygons may be touching, we need to find a vertex that
+ //isn't touching the other polygon ...
+ if (PointOnPolygon(pt->pt, outPt2, UseFullInt64Range))
{
- if (!PointIsVertex(outPt->pt, outPt2)) break;
- outPt = outPt->next;
+ pt = pt->next;
+ while (pt != outPt1 && PointOnPolygon(pt->pt, outPt2, UseFullInt64Range))
+ pt = pt->next;
+ if (pt == outPt1) return true;
}
- while (outPt != outPt1);
- bool result;
- //sometimes a point on one polygon can be touching the other polygon
- //so to be totally confident outPt1 is inside outPt2 repeat ...
- do
- {
- result = PointInPolygon(outPt->pt, outPt2, UseFullInt64Range);
- outPt = outPt->next;
- }
- while (result && outPt != outPt1);
- return result;
+ return PointInPolygon(pt->pt, outPt2, UseFullInt64Range);
}
//----------------------------------------------------------------------
@@ -2927,8 +2920,8 @@ void Clipper::JoinCommonEdges()
{
JoinRec* j = m_Joins[i];
- OutRec *outRec1 = m_PolyOuts[j->poly1Idx];
- OutRec *outRec2 = m_PolyOuts[j->poly2Idx];
+ OutRec *outRec1 = GetOutRec(j->poly1Idx);
+ OutRec *outRec2 = GetOutRec(j->poly2Idx);
if (!outRec1->pts || !outRec2->pts) continue;
@@ -2947,16 +2940,10 @@ void Clipper::JoinCommonEdges()
{
//instead of joining two polygons, we've just created a new one by
//splitting one polygon into two.
- outRec1->pts = GetBottomPt(p1);
- outRec1->bottomPt = outRec1->pts;
- outRec1->bottomPt->idx = outRec1->idx;
+ outRec1->pts = p1;
+ outRec1->bottomPt = 0;
outRec2 = CreateOutRec();
- m_PolyOuts.push_back(outRec2);
- outRec2->idx = (int)m_PolyOuts.size()-1;
- j->poly2Idx = outRec2->idx;
- outRec2->pts = GetBottomPt(p2);
- outRec2->bottomPt = outRec2->pts;
- outRec2->bottomPt->idx = outRec2->idx;
+ outRec2->pts = p2;
if (Poly2ContainsPoly1(outRec2->pts, outRec1->pts, m_UseFullRange))
{
@@ -3017,25 +3004,15 @@ void Clipper::JoinCommonEdges()
//cleanup redundant edges ...
FixupOutPolygon(*outRec1);
- //delete the obsolete pointer ...
- int OKIdx = outRec1->idx;
- int ObsoleteIdx = outRec2->idx;
outRec2->pts = 0;
outRec2->bottomPt = 0;
+ outRec2->idx = outRec1->idx;
outRec1->isHole = holeStateRec->isHole;
if (holeStateRec == outRec2)
outRec1->FirstLeft = outRec2->FirstLeft;
outRec2->FirstLeft = outRec1;
- //now fixup any subsequent Joins that match this polygon
- for (JoinList::size_type k = i+1; k < m_Joins.size(); k++)
- {
- JoinRec* j2 = m_Joins[k];
- if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx;
- if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx;
- }
-
//fixup FirstLeft pointers that may need reassigning to OutRec1
if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1);
}
@@ -3043,6 +3020,76 @@ void Clipper::JoinCommonEdges()
}
//------------------------------------------------------------------------------
+inline void UpdateOutPtIdxs(OutRec& outrec)
+{
+ OutPt* op = outrec.pts;
+ do
+ {
+ op->idx = outrec.idx;
+ op = op->prev;
+ }
+ while(op != outrec.pts);
+}
+//------------------------------------------------------------------------------
+
+void Clipper::DoSimplePolygons()
+{
+ PolyOutList::size_type i = 0;
+ while (i < m_PolyOuts.size())
+ {
+ OutRec* outrec = m_PolyOuts[i++];
+ OutPt* op = outrec->pts;
+ if (!op) continue;
+ do //for each Pt in Polygon until duplicate found do ...
+ {
+ OutPt* op2 = op->next;
+ while (op2 != outrec->pts)
+ {
+ if (PointsEqual(op->pt, op2->pt) && op2->next != op && op2->prev != op)
+ {
+ //split the polygon into two ...
+ OutPt* op3 = op->prev;
+ OutPt* op4 = op2->prev;
+ op->prev = op4;
+ op4->next = op;
+ op2->prev = op3;
+ op3->next = op2;
+
+ outrec->pts = op;
+ OutRec* outrec2 = CreateOutRec();
+ outrec2->pts = op2;
+ UpdateOutPtIdxs(*outrec2);
+ if (Poly2ContainsPoly1(outrec2->pts, outrec->pts, m_UseFullRange))
+ {
+ //OutRec2 is contained by OutRec1 ...
+ outrec2->isHole = !outrec->isHole;
+ outrec2->FirstLeft = outrec;
+ }
+ else
+ if (Poly2ContainsPoly1(outrec->pts, outrec2->pts, m_UseFullRange))
+ {
+ //OutRec1 is contained by OutRec2 ...
+ outrec2->isHole = outrec->isHole;
+ outrec->isHole = !outrec2->isHole;
+ outrec2->FirstLeft = outrec->FirstLeft;
+ outrec->FirstLeft = outrec2;
+ } else
+ {
+ //the 2 polygons are separate ...
+ outrec2->isHole = outrec->isHole;
+ outrec2->FirstLeft = outrec->FirstLeft;
+ }
+ op2 = op; //ie get ready for the next iteration
+ }
+ op2 = op2->next;
+ }
+ op = op->next;
+ }
+ while (op != outrec->pts);
+ }
+}
+//------------------------------------------------------------------------------
+
void ReversePolygon(Polygon& p)
{
std::reverse(p.begin(), p.end());
@@ -3142,7 +3189,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
if (autoFix)
{
size_t Len = m_p.size(), botI = 0;
- while (botI < Len && m_p[botI].size() == 0) botI++;
+ while (botI < Len && m_p[botI].empty()) botI++;
if (botI == Len) return;
//botPt: used to find the lowermost (in inverted Y-axis) & leftmost point
@@ -3172,14 +3219,14 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
switch (jointype)
{
- case jtRound: //limit defaults to 0.125
- if (limit <= 0) limit = 0.125;
+ case jtRound:
+ if (limit <= 0) limit = 0.25;
else if (limit > std::fabs(delta)) limit = std::fabs(delta);
break;
- case jtMiter: //limit defaults to twice delta's width ...
+ case jtMiter:
if (limit < 2) limit = 2;
break;
- default: //otherwise limit is unused
+ default: //unused
limit = 1;
}
m_RMin = 2.0/(limit*limit);
@@ -3269,9 +3316,8 @@ private:
void AddPoint(const IntPoint& pt)
{
- Polygon::size_type len = m_curr_poly->size();
- if (len == m_curr_poly->capacity())
- m_curr_poly->reserve(len + buffLength);
+ if (m_curr_poly->size() == m_curr_poly->capacity())
+ m_curr_poly->reserve(m_curr_poly->capacity() + buffLength);
m_curr_poly->push_back(pt);
}
//------------------------------------------------------------------------------
@@ -3385,6 +3431,7 @@ void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType)
{
Clipper c;
+ c.ForceSimple(true);
c.AddPolygon(in_poly, ptSubject);
c.Execute(ctUnion, out_polys, fillType, fillType);
}
@@ -3393,6 +3440,7 @@ void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType f
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType)
{
Clipper c;
+ c.ForceSimple(true);
c.AddPolygons(in_polys, ptSubject);
c.Execute(ctUnion, out_polys, fillType, fillType);
}
@@ -3404,38 +3452,76 @@ void SimplifyPolygons(Polygons &polys, PolyFillType fillType)
}
//------------------------------------------------------------------------------
-void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance)
+inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2)
{
- //delta = proximity in units/pixels below which vertices
- //will be stripped. Default ~= sqrt(2) so when adjacent
- //vertices have both x & y coords within 1 unit, then
- //the second vertex will be stripped.
- int len = in_poly.size();
- if (len < 3)
- out_poly.resize(0);
- else
- out_poly.resize(in_poly.size());
-
- int d = (int)(distance * distance);
- IntPoint p = in_poly[0];
- int j = 1;
- for (int i = 1; i < len; i++)
- {
- if ((in_poly[i].X - p.X) * (in_poly[i].X - p.X) +
- (in_poly[i].Y - p.Y) * (in_poly[i].Y - p.Y) <= d)
- continue;
- out_poly[j] = in_poly[i];
- p = in_poly[i];
- j++;
- }
- p = in_poly[j - 1];
- if ((in_poly[0].X - p.X) * (in_poly[0].X - p.X) +
- (in_poly[0].Y - p.Y) * (in_poly[0].Y - p.Y) <= d)
- j--;
- if (j < len)
- out_poly.resize(j);
+ double dx = ((double)pt1.X - pt2.X);
+ double dy = ((double)pt1.Y - pt2.Y);
+ return (dx*dx + dy*dy);
}
//------------------------------------------------------------------------------
+
+DoublePoint ClosestPointOnLine(const IntPoint& pt, const IntPoint& linePt1, const IntPoint& linePt2)
+{
+ double dx = ((double)linePt2.X - linePt1.X);
+ double dy = ((double)linePt2.Y - linePt1.Y);
+ if (dx == 0 && dy == 0)
+ return DoublePoint((double)linePt1.X, (double)linePt1.Y);
+ double q = ((pt.X-linePt1.X)*dx + (pt.Y-linePt1.Y)*dy) / (dx*dx + dy*dy);
+ return DoublePoint(
+ (1-q)*linePt1.X + q*linePt2.X,
+ (1-q)*linePt1.Y + q*linePt2.Y);
+}
+//------------------------------------------------------------------------------
+
+bool SlopesNearColinear(const IntPoint& pt1,
+ const IntPoint& pt2, const IntPoint& pt3, double distSqrd)
+{
+ if (DistanceSqrd(pt1, pt2) > DistanceSqrd(pt1, pt3)) return false;
+ DoublePoint cpol = ClosestPointOnLine(pt2, pt1, pt3);
+ double dx = pt2.X - cpol.X;
+ double dy = pt2.Y - cpol.Y;
+ return (dx*dx + dy*dy) < distSqrd;
+}
+//------------------------------------------------------------------------------
+
+bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd)
+{
+ double dx = (double)pt1.X - pt2.X;
+ double dy = (double)pt1.Y - pt2.Y;
+ return ((dx * dx) + (dy * dy) <= distSqrd);
+}
+//------------------------------------------------------------------------------
+
+void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance)
+{
+ //distance = proximity in units/pixels below which vertices
+ //will be stripped. Default ~= sqrt(2).
+ int highI = in_poly.size() -1;
+ double distSqrd = distance * distance;
+ while (highI > 0 && PointsAreClose(in_poly[highI], in_poly[0], distSqrd)) highI--;
+ if (highI < 2) { out_poly.clear(); return; }
+
+ out_poly.resize(highI + 1);
+ IntPoint pt = in_poly[highI];
+ int i = 0, k = 0;
+ for (;;)
+ {
+ while (i <= highI && PointsAreClose(pt, in_poly[i+1], distSqrd)) i+=2;
+ int i2 = i;
+ while (i <= highI && PointsAreClose(in_poly[i], in_poly[i+1], distSqrd) ||
+ SlopesNearColinear(pt, in_poly[i], in_poly[+1], distSqrd)) i++;
+ if (i >= highI) break;
+ else if (i != i2) continue;
+ pt = in_poly[i++];
+ out_poly[k++] = pt;
+ }
+ if (i <= highI) out_poly[k++] = in_poly[i];
+ if (k > 2 && SlopesNearColinear(out_poly[k -2], out_poly[k -1], out_poly[0], distSqrd)) k--;
+ if (k < 3) out_poly.clear();
+ else if (k <= highI) out_poly.resize(k);
+}
+//------------------------------------------------------------------------------
+
void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance)
{
for (Polygons::size_type i = 0; i < in_polys.size(); ++i)
@@ -3445,7 +3531,7 @@ void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance)
void AddPolyNodeToPolygons(PolyNode& polynode, Polygons& polygons)
{
- if (polynode.Contour.size() > 0)
+ if (!polynode.Contour.empty())
polygons.push_back(polynode.Contour);
for (int i = 0; i < polynode.ChildCount(); ++i)
AddPolyNodeToPolygons(*polynode.Childs[i], polygons);
diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp
index 88399b19c..6e4fe6858 100644
--- a/include/mapnik/config.hpp
+++ b/include/mapnik/config.hpp
@@ -39,9 +39,15 @@
# pragma warning(disable : 4996) //_CRT_SECURE_NO_DEPRECATE
# endif
#else
+# if __GNUC__ >= 4
+# define MAPNIK_EXP __attribute__ ((visibility ("default")))
+# define MAPNIK_DECL __attribute__ ((visibility ("default")))
+# define MAPNIK_IMP __attribute__ ((visibility ("default")))
+# else
# define MAPNIK_EXP
-# define MAPNIK_IMP
# define MAPNIK_DECL
+# define MAPNIK_IMP
+# endif
#endif
#define PROJ_ENVELOPE_POINTS 20
diff --git a/include/mapnik/config_error.hpp b/include/mapnik/config_error.hpp
index c37d5617c..6f590b806 100644
--- a/include/mapnik/config_error.hpp
+++ b/include/mapnik/config_error.hpp
@@ -23,6 +23,8 @@
#ifndef MAPNIK_CONFIG_ERROR_HPP
#define MAPNIK_CONFIG_ERROR_HPP
+#include
+
#include
#include
diff --git a/include/mapnik/css_color_grammar_def.hpp b/include/mapnik/css_color_grammar_impl.hpp
similarity index 95%
rename from include/mapnik/css_color_grammar_def.hpp
rename to include/mapnik/css_color_grammar_impl.hpp
index 028411ba1..5b37f8761 100644
--- a/include/mapnik/css_color_grammar_def.hpp
+++ b/include/mapnik/css_color_grammar_impl.hpp
@@ -20,8 +20,8 @@
*
*****************************************************************************/
-#ifndef MAPNIK_CSS_COLOR_GRAMMAR_DEF_HPP
-#define MAPNIK_CSS_COLOR_GRAMMAR_DEF_HPP
+// NOTE: This is an implementation header file and is only meant to be included
+// from implementation files. It therefore doesn't have an include guard.
// boost
#include
@@ -100,5 +100,3 @@ css_color_grammar::css_color_grammar()
}
#endif
-
-#endif
diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp
index f9a6e0d41..b2edb91d4 100644
--- a/include/mapnik/datasource.hpp
+++ b/include/mapnik/datasource.hpp
@@ -47,7 +47,7 @@ struct MAPNIK_DECL Featureset : private mapnik::noncopyable
virtual ~Featureset() {}
};
-typedef MAPNIK_DECL boost::shared_ptr featureset_ptr;
+typedef boost::shared_ptr featureset_ptr;
class MAPNIK_DECL datasource_exception : public std::exception
{
@@ -134,19 +134,23 @@ public:
typedef boost::shared_ptr datasource_ptr;
-#define DATASOURCE_PLUGIN(classname) \
- extern "C" MAPNIK_EXP const char * datasource_name() \
- { \
- return classname::name(); \
- } \
- extern "C" MAPNIK_EXP datasource* create(parameters const& params) \
- { \
- return new classname(params); \
- } \
- extern "C" MAPNIK_EXP void destroy(datasource *ds) \
- { \
- delete ds; \
- }
+#ifdef MAPNIK_STATIC_PLUGINS
+ #define DATASOURCE_PLUGIN(classname)
+#else
+ #define DATASOURCE_PLUGIN(classname) \
+ extern "C" MAPNIK_EXP const char * datasource_name() \
+ { \
+ return classname::name(); \
+ } \
+ extern "C" MAPNIK_EXP datasource* create(parameters const& params) \
+ { \
+ return new classname(params); \
+ } \
+ extern "C" MAPNIK_EXP void destroy(datasource *ds) \
+ { \
+ delete ds; \
+ }
+#endif
}
diff --git a/include/mapnik/debug_symbolizer.hpp b/include/mapnik/debug_symbolizer.hpp
index 91ea152d2..225b97c54 100644
--- a/include/mapnik/debug_symbolizer.hpp
+++ b/include/mapnik/debug_symbolizer.hpp
@@ -25,14 +25,30 @@
#include
#include
+#include
namespace mapnik
{
+enum debug_symbolizer_mode_enum {
+ DEBUG_SYM_MODE_COLLISION,
+ DEBUG_SYM_MODE_VERTEX,
+ debug_symbolizer_mode_enum_MAX
+};
+
+DEFINE_ENUM( debug_symbolizer_mode_e, debug_symbolizer_mode_enum );
+
struct MAPNIK_DECL debug_symbolizer :
public symbolizer_base
{
- debug_symbolizer() : symbolizer_base() {}
+ debug_symbolizer();
+ debug_symbolizer(debug_symbolizer const& rhs);
+ debug_symbolizer_mode_e get_mode() const;
+ void set_mode(debug_symbolizer_mode_e mode);
+
+private:
+ debug_symbolizer_mode_e mode_;
+
};
}
diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp
index 2702048a3..ed4a43008 100644
--- a/include/mapnik/expression_grammar.hpp
+++ b/include/mapnik/expression_grammar.hpp
@@ -24,6 +24,7 @@
#define MAPNIK_EXPRESSIONS_GRAMMAR_HPP
// mapnik
+#include
#include
#include
#include
diff --git a/include/mapnik/expression_grammar_impl.hpp b/include/mapnik/expression_grammar_impl.hpp
new file mode 100644
index 000000000..5ca2c5eeb
--- /dev/null
+++ b/include/mapnik/expression_grammar_impl.hpp
@@ -0,0 +1,191 @@
+/*****************************************************************************
+ *
+ * This file is part of Mapnik (c++ mapping toolkit)
+ *
+ * Copyright (C) 2012 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
+ *
+ *****************************************************************************/
+
+// NOTE: This is an implementation header file and is only meant to be included
+// from implementation files. It therefore doesn't have an include guard.
+
+// mapnik
+#include
+#include
+#include
+#include
+
+// boost
+#include
+#include
+#include
+#include
+
+// fwd declare
+namespace mapnik {
+ struct attribute;
+ struct geometry_type_attribute;
+}
+
+namespace mapnik
+{
+
+template
+expr_node regex_match_impl::operator() (T0 & node, T1 const& pattern) const
+{
+#if defined(BOOST_REGEX_HAS_ICU)
+ return regex_match_node(node,tr_.transcode(pattern.c_str()));
+#else
+ return regex_match_node(node,pattern);
+#endif
+}
+
+template
+expr_node regex_replace_impl::operator() (T0 & node, T1 const& pattern, T2 const& format) const
+{
+#if defined(BOOST_REGEX_HAS_ICU)
+ return regex_replace_node(node,tr_.transcode(pattern.c_str()),tr_.transcode(format.c_str()));
+#else
+ return regex_replace_node(node,pattern,format);
+#endif
+}
+
+template
+expression_grammar::expression_grammar(mapnik::transcoder const& tr)
+ : expression_grammar::base_type(expr),
+ unicode_(unicode_impl(tr)),
+ regex_match_(regex_match_impl(tr)),
+ regex_replace_(regex_replace_impl(tr))
+{
+ using boost::phoenix::construct;
+ using qi::_1;
+ using qi::_a;
+ using qi::_b;
+ using qi::_r1;
+#if BOOST_VERSION > 104200
+ using qi::no_skip;
+#endif
+ using qi::lexeme;
+ using qi::_val;
+ using qi::lit;
+ using qi::double_;
+ using qi::hex;
+ using qi::omit;
+ using standard_wide::char_;
+ using standard_wide::no_case;
+
+ expr = logical_expr.alias();
+
+ logical_expr = not_expr [_val = _1]
+ >>
+ *( ( ( lit("and") | lit("&&")) >> not_expr [_val && _1] )
+ | (( lit("or") | lit("||")) >> not_expr [_val || _1])
+ )
+ ;
+
+ not_expr =
+ cond_expr [_val = _1 ]
+ | ((lit("not") | lit('!')) >> cond_expr [ _val = !_1 ])
+ ;
+
+ cond_expr = equality_expr [_val = _1] | additive_expr [_val = _1]
+ ;
+
+ equality_expr =
+ relational_expr [_val = _1]
+ >> *( ( (lit("=") | lit("eq") | lit("is")) >> relational_expr [_val == _1])
+ | (( lit("!=") | lit("<>") | lit("neq") ) >> relational_expr [_val != _1])
+ )
+ ;
+
+ regex_match_expr = lit(".match")
+ >> lit('(')
+ >> ustring [_val = _1]
+ >> lit(')')
+ ;
+
+ regex_replace_expr =
+ lit(".replace")
+ >> lit('(')
+ >> ustring [_a = _1]
+ >> lit(',')
+ >> ustring [_b = _1]
+ >> lit(')') [_val = regex_replace_(_r1,_a,_b)]
+ ;
+
+ relational_expr = additive_expr[_val = _1]
+ >>
+ *( ( (lit("<=") | lit("le") ) >> additive_expr [ _val <= _1 ])
+ | ( (lit('<') | lit("lt") ) >> additive_expr [ _val < _1 ])
+ | ( (lit(">=") | lit("ge") ) >> additive_expr [ _val >= _1 ])
+ | ( (lit('>') | lit("gt") ) >> additive_expr [ _val > _1 ])
+ )
+ ;
+
+ additive_expr = multiplicative_expr [_val = _1]
+ >> * ( '+' >> multiplicative_expr[_val += _1]
+ | '-' >> multiplicative_expr[_val -= _1]
+ )
+ ;
+
+ multiplicative_expr = unary_expr [_val = _1]
+ >> *( '*' >> unary_expr [_val *= _1]
+ | '/' >> unary_expr [_val /= _1]
+ | '%' >> unary_expr [_val %= _1]
+ | regex_match_expr[_val = regex_match_(_val, _1)]
+ | regex_replace_expr(_val) [_val = _1]
+ )
+ ;
+
+ unary_expr = primary_expr [_val = _1]
+ | '+' >> primary_expr [_val = _1]
+ | '-' >> primary_expr [_val = -_1]
+ ;
+
+ primary_expr = strict_double [_val = _1]
+ | int__[_val = _1]
+ | no_case[lit("true")] [_val = true]
+ | no_case[lit("false")] [_val = false]
+ | no_case[lit("null")] [_val = value_null() ]
+ | no_case[geom_type][_val = _1 ]
+ | ustring [_val = unicode_(_1) ]
+ | lit("[mapnik::geometry_type]")[_val = construct()]
+ | attr [_val = construct( _1 ) ]
+ | '(' >> expr [_val = _1 ] >> ')'
+ ;
+
+ unesc_char.add("\\a", '\a')("\\b", '\b')("\\f", '\f')("\\n", '\n')
+ ("\\r", '\r')("\\t", '\t')("\\v", '\v')("\\\\", '\\')
+ ("\\\'", '\'')("\\\"", '\"')
+ ;
+
+#if BOOST_VERSION > 104500
+ quote_char %= char_('\'') | char_('"');
+ ustring %= omit[quote_char[_a = _1]]
+ >> *(unesc_char | "\\x" >> hex | (char_ - lit(_a)))
+ >> lit(_a);
+ attr %= '[' >> no_skip[+~char_(']')] >> ']';
+#else
+ ustring %= lit('\'')
+ >> *(unesc_char | "\\x" >> hex | (char_ - lit('\'')))
+ >> lit('\'');
+ attr %= '[' >> lexeme[+(char_ - ']')] >> ']';
+#endif
+
+}
+
+}
diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp
index 352a463c1..ce9a3dc79 100644
--- a/include/mapnik/feature.hpp
+++ b/include/mapnik/feature.hpp
@@ -87,8 +87,8 @@ private:
map_type mapping_;
};
-typedef MAPNIK_DECL context > context_type;
-typedef MAPNIK_DECL boost::shared_ptr context_ptr;
+typedef context > context_type;
+typedef boost::shared_ptr context_ptr;
static const value default_value;
@@ -306,9 +306,10 @@ inline std::ostream& operator<< (std::ostream & out,feature_impl const& f)
return out;
}
+// TODO - remove at Mapnik 3.x
typedef feature_impl Feature;
-typedef MAPNIK_DECL boost::shared_ptr feature_ptr;
+typedef boost::shared_ptr feature_ptr;
}
diff --git a/include/mapnik/feature_factory.hpp b/include/mapnik/feature_factory.hpp
index 9a6574932..7896ef04b 100644
--- a/include/mapnik/feature_factory.hpp
+++ b/include/mapnik/feature_factory.hpp
@@ -35,11 +35,11 @@ namespace mapnik
{
struct feature_factory
{
- static boost::shared_ptr create (context_ptr const& ctx, mapnik::value_integer fid)
+ static boost::shared_ptr create (context_ptr const& ctx, mapnik::value_integer fid)
{
- //return boost::allocate_shared(boost::pool_allocator(),fid);
- //return boost::allocate_shared(boost::fast_pool_allocator(),fid);
- return boost::make_shared(ctx,fid);
+ //return boost::allocate_shared(boost::pool_allocator(),fid);
+ //return boost::allocate_shared(boost::fast_pool_allocator(),fid);
+ return boost::make_shared(ctx,fid);
}
};
}
diff --git a/include/mapnik/feature_style_processor.hpp b/include/mapnik/feature_style_processor.hpp
index 69752b37f..e880c3461 100644
--- a/include/mapnik/feature_style_processor.hpp
+++ b/include/mapnik/feature_style_processor.hpp
@@ -25,6 +25,7 @@
// mapnik
#include // for featureset_ptr
+#include
// stl
#include
@@ -48,7 +49,7 @@ enum eAttributeCollectionPolicy
};
template
-class feature_style_processor
+class MAPNIK_DECL feature_style_processor
{
struct symbol_dispatch;
public:
diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp
index eade195b3..bd7653ae2 100644
--- a/include/mapnik/feature_style_processor_impl.hpp
+++ b/include/mapnik/feature_style_processor_impl.hpp
@@ -606,7 +606,7 @@ void feature_style_processor::render_style(
BOOST_FOREACH(rule const* r, rc.get_if_rules() )
{
expression_ptr const& expr=r->get_filter();
- value_type result = boost::apply_visitor(evaluate(*feature),*expr);
+ value_type result = boost::apply_visitor(evaluate(*feature),*expr);
if (result.to_bool())
{
#if defined(RENDERING_STATS)
diff --git a/include/mapnik/geom_util.hpp b/include/mapnik/geom_util.hpp
index 36f030174..350c797ab 100644
--- a/include/mapnik/geom_util.hpp
+++ b/include/mapnik/geom_util.hpp
@@ -200,10 +200,10 @@ inline bool point_on_path(double x,double y,Iter start,Iter end, double tol)
struct filter_in_box
{
box2d box_;
- explicit filter_in_box(const box2d& box)
+ explicit filter_in_box(box2d const& box)
: box_(box) {}
- bool pass(const box2d& extent) const
+ bool pass(box2d const& extent) const
{
return extent.intersects(box_);
}
@@ -211,23 +211,16 @@ struct filter_in_box
struct filter_at_point
{
- coord2d pt_;
- double tol_;
- explicit filter_at_point(const coord2d& pt, double tol=0)
- : pt_(pt),
- tol_(tol) {}
- bool pass(const box2d& extent) const
+ box2d box_;
+ explicit filter_at_point(coord2d const& pt, double tol=0)
+ : box_(pt,pt)
{
- if (tol_ == 0)
- {
- return extent.contains(pt_);
- }
- else
- {
- box2d extent2 = extent;
- extent2.pad(tol_);
- return extent2.contains(pt_);
- }
+ box_.pad(tol);
+ }
+
+ bool pass(box2d const& extent) const
+ {
+ return extent.intersects(box_);
}
};
diff --git a/include/mapnik/grid/grid.hpp b/include/mapnik/grid/grid.hpp
index d5e1c872a..bdbceae78 100644
--- a/include/mapnik/grid/grid.hpp
+++ b/include/mapnik/grid/grid.hpp
@@ -256,7 +256,7 @@ public:
};
-typedef MAPNIK_DECL hit_grid grid;
+typedef hit_grid grid;
}
#endif //MAPNIK_GRID_HPP
diff --git a/include/mapnik/hit_test_filter.hpp b/include/mapnik/hit_test_filter.hpp
index 792c8c12e..b9c1f6a6b 100644
--- a/include/mapnik/hit_test_filter.hpp
+++ b/include/mapnik/hit_test_filter.hpp
@@ -38,7 +38,7 @@ public:
y_(y),
tol_(tol) {}
- bool pass(Feature & feature)
+ bool pass(feature_impl & feature)
{
BOOST_FOREACH(geometry_type & geom, feature.paths())
{
diff --git a/include/mapnik/json/feature_collection_parser.hpp b/include/mapnik/json/feature_collection_parser.hpp
index 454d69a98..adc91119f 100644
--- a/include/mapnik/json/feature_collection_parser.hpp
+++ b/include/mapnik/json/feature_collection_parser.hpp
@@ -40,7 +40,7 @@ namespace mapnik { namespace json {
template struct feature_collection_grammar;
template
-class feature_collection_parser : private mapnik::noncopyable
+class MAPNIK_DECL feature_collection_parser : private mapnik::noncopyable
{
typedef Iterator iterator_type;
typedef mapnik::feature_impl feature_type;
diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp
index 18c2125e2..a117b53dc 100644
--- a/include/mapnik/json/feature_grammar.hpp
+++ b/include/mapnik/json/feature_grammar.hpp
@@ -133,6 +133,7 @@ struct feature_grammar :
phoenix::function put_property_;
phoenix::function extract_geometry_;
+ boost::phoenix::function where_message_;
geometry_grammar geometry_grammar_;
};
diff --git a/include/mapnik/json/geometry_grammar.hpp b/include/mapnik/json/geometry_grammar.hpp
index 32b05ec3d..9600b4179 100644
--- a/include/mapnik/json/geometry_grammar.hpp
+++ b/include/mapnik/json/geometry_grammar.hpp
@@ -84,6 +84,25 @@ struct cleanup
}
};
+struct where_message
+{
+ template
+ struct result
+ {
+ typedef std::string type;
+ };
+
+ template
+ std::string operator() (Iterator first, Iterator last, std::size_t size) const
+ {
+ std::string str(first, last);
+ if (str.length() > size)
+ return str.substr(0, size) + "..." ;
+ return str;
+ }
+};
+
+
template
struct geometry_grammar :
qi::grammar, void(boost::ptr_vector& )
@@ -118,6 +137,7 @@ struct geometry_grammar :
boost::phoenix::function push_vertex_;
boost::phoenix::function close_path_;
boost::phoenix::function cleanup_;
+ boost::phoenix::function where_message_;
};
}}
diff --git a/include/mapnik/mapped_memory_cache.hpp b/include/mapnik/mapped_memory_cache.hpp
index 6b53481c1..34151b2b6 100644
--- a/include/mapnik/mapped_memory_cache.hpp
+++ b/include/mapnik/mapped_memory_cache.hpp
@@ -41,12 +41,13 @@ using namespace boost::interprocess;
typedef boost::shared_ptr mapped_region_ptr;
-struct MAPNIK_DECL mapped_memory_cache :
+class MAPNIK_DECL mapped_memory_cache :
public singleton,
private mapnik::noncopyable
{
friend class CreateStatic;
boost::unordered_map cache_;
+public:
bool insert(std::string const& key, mapped_region_ptr);
boost::optional find(std::string const& key, bool update_cache = false);
void clear();
diff --git a/include/mapnik/parse_path.hpp b/include/mapnik/parse_path.hpp
index f295d8c77..f3d65c5e5 100644
--- a/include/mapnik/parse_path.hpp
+++ b/include/mapnik/parse_path.hpp
@@ -48,7 +48,7 @@ struct MAPNIK_DECL path_processor
static void collect_attributes(path_expression const& path, std::set& names);
};
-typedef MAPNIK_DECL mapnik::path_processor path_processor_type;
+typedef mapnik::path_processor path_processor_type;
}
diff --git a/include/mapnik/raster_colorizer.hpp b/include/mapnik/raster_colorizer.hpp
index 806af3602..76c09fd94 100644
--- a/include/mapnik/raster_colorizer.hpp
+++ b/include/mapnik/raster_colorizer.hpp
@@ -40,7 +40,6 @@
// mapnik
#include
#include
-#include
#include
// boost
@@ -52,6 +51,10 @@
namespace mapnik
{
+class feature_impl;
+class raster;
+
+
//! \brief Enumerates the modes of interpolation
enum colorizer_mode_enum
{
@@ -197,7 +200,7 @@ public:
//!
//! \param[in, out] raster A raster stored in float32 single channel format, which gets colorized in place.
//! \param[in] f The feature used to find 'NODATA' information if available
- void colorize(raster_ptr const& raster, Feature const& f) const;
+ void colorize(boost::shared_ptr const& raster, feature_impl const& f) const;
//! \brief Perform the translation of input to output
diff --git a/include/mapnik/symbolizer_helpers.hpp b/include/mapnik/symbolizer_helpers.hpp
index c6bc585c2..4da83c360 100644
--- a/include/mapnik/symbolizer_helpers.hpp
+++ b/include/mapnik/symbolizer_helpers.hpp
@@ -57,7 +57,7 @@ class text_symbolizer_helper
{
public:
text_symbolizer_helper(text_symbolizer const& sym,
- Feature const& feature,
+ feature_impl const& feature,
proj_transform const& prj_trans,
unsigned width,
unsigned height,
@@ -104,7 +104,7 @@ protected:
//Input
text_symbolizer const& sym_;
- Feature const& feature_;
+ feature_impl const& feature_;
proj_transform const& prj_trans_;
CoordTransform const& t_;
FaceManagerT & font_manager_;
@@ -142,7 +142,7 @@ class shield_symbolizer_helper: public text_symbolizer_helper
-
-#include
+#include
extern "C"
{
@@ -45,37 +44,89 @@ namespace mapnik {
static tsize_t tiff_write_proc(thandle_t fd, tdata_t buf, tsize_t size)
{
- std::ostream* out = (std::ostream*)fd;
+ std::ostream* out = reinterpret_cast(fd);
+ std::ios::pos_type pos = out->tellp();
+ std::streamsize request_size = size;
+ if (static_cast(request_size) != size)
+ return static_cast(-1);
+ out->write(reinterpret_cast