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(buf), size); - out->write((const char*)buf, size); - - return size; + if( static_cast(pos) == -1 ) + { + return size; + } + else + { + return static_cast(out->tellp()-pos); + } } static toff_t tiff_seek_proc(thandle_t fd, toff_t off, int whence) { - if (off == 0xFFFFFFFF) - { - return 0xFFFFFFFF; - } + std::ostream* out = reinterpret_cast(fd); - std::ostream* out = (std::ostream*)fd; + if( out->fail() ) + return static_cast(-1); + + if( static_cast(out->tellp()) == -1) + return static_cast< toff_t >( 0 ); switch(whence) { + case SEEK_SET: + out->seekp(off, std::ios_base::beg); + break; case SEEK_CUR: out->seekp(off, std::ios_base::cur); break; case SEEK_END: out->seekp(off, std::ios_base::end); break; - case SEEK_SET: - default: - out->seekp(off, std::ios_base::beg); - break; } + // grow std::stringstream buffer (re: libtiff/tif_stream.cxx) + std::ios::pos_type pos = out->tellp(); + // second check needed for clang (libcxx doesn't set failbit when seeking beyond the current buffer size + if( out->fail() || off != pos) + { + std::ios::iostate old_state; + std::ios::pos_type origin; + old_state = out->rdstate(); + // reset the fail bit or else tellp() won't work below + out->clear(out->rdstate() & ~std::ios::failbit); + switch( whence ) + { + case SEEK_SET: + default: + origin = 0L; + break; + case SEEK_CUR: + origin = out->tellp(); + break; + case SEEK_END: + out->seekp(0, std::ios::end); + origin = out->tellp(); + break; + } + // restore original stream state + out->clear(old_state); - return (toff_t)out->tellp(); + // only do something if desired seek position is valid + if( (static_cast(origin) + off) > 0L) + { + uint64_t num_fill; + // clear the fail bit + out->clear(out->rdstate() & ~std::ios::failbit); + // extend the stream to the expected size + out->seekp(0, std::ios::end); + num_fill = (static_cast(origin)) + off - out->tellp(); + for( uint64_t i = 0; i < num_fill; ++i) + out->put('\0'); + + // retry the seek + out->seekp(static_cast(static_cast(origin) + off), std::ios::beg); + } + } + return static_cast(out->tellp()); } static int tiff_close_proc(thandle_t fd) @@ -87,8 +138,12 @@ static int tiff_close_proc(thandle_t fd) static toff_t tiff_size_proc(thandle_t fd) { - std::ostream* out = (std::ostream*)fd; - return (toff_t)out->tellp(); + std::ostream* out = reinterpret_cast(fd); + std::ios::pos_type pos = out->tellp(); + out->seekp(0, std::ios::end); + std::ios::pos_type len = out->tellp(); + out->seekp(pos); + return (toff_t)len; } static tsize_t tiff_dummy_read_proc(thandle_t fd, tdata_t buf, tsize_t size) @@ -113,7 +168,7 @@ void save_as_tiff(T1 & file, T2 const& image) const int scanline_size = sizeof(unsigned char) * width * 3; TIFF* output = RealTIFFOpen("mapnik_tiff_stream", - "w", + "wm", (thandle_t)&file, tiff_dummy_read_proc, tiff_write_proc, @@ -124,7 +179,7 @@ void save_as_tiff(T1 & file, T2 const& image) tiff_dummy_unmap_proc); if (! output) { - // throw ? + throw ImageWriterException("Could not write TIFF"); } TIFFSetField(output, TIFFTAG_IMAGEWIDTH, width); diff --git a/include/mapnik/utils.hpp b/include/mapnik/utils.hpp index 24a5d3d54..a9f013f5b 100644 --- a/include/mapnik/utils.hpp +++ b/include/mapnik/utils.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_UTILS_HPP #define MAPNIK_UTILS_HPP +#include + // boost #ifdef MAPNIK_THREADSAFE #include @@ -38,6 +40,7 @@ namespace mapnik { + #ifdef MAPNIK_THREADSAFE using boost::mutex; #endif @@ -82,86 +85,103 @@ public: return new(&staticMemory) T; } #ifdef __SUNPRO_CC - // Sun C++ Compiler doesn't handle `volatile` keyword same as GCC. +// Sun C++ Compiler doesn't handle `volatile` keyword same as GCC. static void destroy(T* obj) #else - static void destroy(volatile T* obj) + static void destroy(volatile T* obj) #endif { obj->~T(); } }; +#ifdef __GNUC__ template class CreatePolicy=CreateStatic> class singleton + template class CreatePolicy=CreateStatic> class MAPNIK_DECL singleton { -#ifdef __SUNPRO_CC - /* Sun's C++ compiler will issue the following errors if CreatePolicy is used: - Error: A class template name was expected instead of mapnik::CreatePolicy - Error: A "friend" declaration must specify a class or function. - */ - friend class CreatePolicy; #else - friend class CreatePolicy; + template class CreatePolicy=CreateStatic> class singleton + { #endif - static T* pInstance_; - static bool destroyed_; - singleton(const singleton &rhs); - singleton& operator=(const singleton&); - static void onDeadReference() - { - throw std::runtime_error("dead reference!"); - } - - static void DestroySingleton() - { - CreatePolicy::destroy(pInstance_); - pInstance_ = 0; - destroyed_ = true; - } - -protected: -#ifdef MAPNIK_THREADSAFE - static mutex mutex_; +#ifdef __SUNPRO_CC +/* Sun's C++ compiler will issue the following errors if CreatePolicy is used: + Error: A class template name was expected instead of mapnik::CreatePolicy + Error: A "friend" declaration must specify a class or function. +*/ + friend class CreatePolicy; +#else + friend class CreatePolicy; #endif - singleton() {} -public: - static T& instance() - { - if (! pInstance_) + static T* pInstance_; + static bool destroyed_; + singleton(const singleton &rhs); + singleton& operator=(const singleton&); + + static void onDeadReference() { + throw std::runtime_error("dead reference!"); + } + + static void DestroySingleton() + { + CreatePolicy::destroy(pInstance_); + pInstance_ = 0; + destroyed_ = true; + } + + protected: #ifdef MAPNIK_THREADSAFE - mutex::scoped_lock lock(mutex_); + static mutex mutex_; #endif + singleton() {} + public: + static T& instance() + { if (! pInstance_) { - if (destroyed_) +#ifdef MAPNIK_THREADSAFE + mutex::scoped_lock lock(mutex_); +#endif + if (! pInstance_) { - destroyed_ = false; - onDeadReference(); - } - else - { - pInstance_ = CreatePolicy::create(); + if (destroyed_) + { + destroyed_ = false; + onDeadReference(); + } + else + { + pInstance_ = CreatePolicy::create(); - // register destruction - std::atexit(&DestroySingleton); + // register destruction + std::atexit(&DestroySingleton); + } } } + return *pInstance_; } - return *pInstance_; - } -}; + }; #ifdef MAPNIK_THREADSAFE -template class CreatePolicy> mutex singleton::mutex_; + template class CreatePolicy> mutex singleton::mutex_; #endif -template class CreatePolicy> T* singleton::pInstance_=0; -template class CreatePolicy> bool singleton::destroyed_=false; + template class CreatePolicy> T* singleton::pInstance_=0; + template class CreatePolicy> bool singleton::destroyed_=false; + + +#ifdef _WINDOWS + +// UTF8 <--> UTF16 conversion routines + +MAPNIK_DECL std::string utf16_to_utf8(std::wstring const& wstr); +MAPNIK_DECL std::wstring utf8_to_utf16(std::string const& str); + +#endif // _WINDOWS } diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 7ed21948e..d5d6fcfc0 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -40,8 +40,6 @@ #include "hash_variant.hpp" // stl -#include -#include #include #include @@ -670,6 +668,13 @@ struct to_expression_string : public boost::static_visitor return "'" + utf8 + "'"; } + std::string operator() (value_integer val) const + { + std::string output; + util::to_string(output,val); + return output; + } + std::string operator() (value_double val) const { std::string output; @@ -687,14 +692,6 @@ struct to_expression_string : public boost::static_visitor boost::ignore_unused_variable_warning(val); return "null"; } - - template - std::string operator() (T val) const - { - std::stringstream ss; - ss << val; - return ss.str(); - } }; struct to_double : public boost::static_visitor diff --git a/include/mapnik/value_error.hpp b/include/mapnik/value_error.hpp index 08786cf18..aca3c3239 100644 --- a/include/mapnik/value_error.hpp +++ b/include/mapnik/value_error.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_VALUE_ERROR_HPP #define MAPNIK_VALUE_ERROR_HPP +#include + #include #include diff --git a/plugins/input/csv/build.py b/plugins/input/csv/build.py index ae41bf6d1..d3dfdea12 100644 --- a/plugins/input/csv/build.py +++ b/plugins/input/csv/build.py @@ -1,37 +1,62 @@ -#!/usr/bin/env python +# +# This file is part of Mapnik (c++ mapping toolkit) +# +# Copyright (C) 2013 Artem Pavlenko +# +# Mapnik is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# -import os Import ('plugin_base') Import ('env') PLUGIN_NAME = 'csv' -install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] plugin_env = plugin_base.Clone() plugin_sources = Split( """ %(PLUGIN_NAME)s_datasource.cpp """ % locals() - ) +) +# Link Library to Dependencies libraries = [] -libraries.append('mapnik') libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append(env['ICU_LIB_NAME']) - -TARGET = plugin_env.SharedLibrary( - '../%s' % PLUGIN_NAME, - SHLIBPREFIX='', - SHLIBSUFFIX='.input', - source=plugin_sources, - LIBS=libraries, - LINKFLAGS=env.get('CUSTOM_LDFLAGS') - ) -# if the plugin links to libmapnik ensure it is built first -Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(install_dest, TARGET) - env.Alias('install', install_dest) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env.get('CUSTOM_LDFLAGS')) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index b98fdb188..e1478cd36 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -30,6 +30,7 @@ // mapnik #include +#include #include #include #include @@ -119,9 +120,15 @@ csv_datasource::csv_datasource(parameters const& params) } else { +#if defined (_WINDOWS) + std::ifstream in(mapnik::utf8_to_utf16(filename_),std::ios_base::in | std::ios_base::binary); +#else std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary); +#endif if (!in.is_open()) + { throw mapnik::datasource_exception("CSV Plugin: could not open: '" + filename_ + "'"); + } parse_csv(in,escape_, separator_, quote_); in.close(); } @@ -859,7 +866,7 @@ void csv_datasource::parse_csv(T & stream, } } } - if (!feature_count > 0) + if (feature_count < 1) { MAPNIK_LOG_ERROR(csv) << "CSV Plugin: could not parse any lines of data"; } diff --git a/plugins/input/gdal/build.py b/plugins/input/gdal/build.py index 501ff089f..2f2f535e2 100644 --- a/plugins/input/gdal/build.py +++ b/plugins/input/gdal/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 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 @@ -22,35 +22,47 @@ Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'gdal' plugin_env = plugin_base.Clone() -gdal_src = Split( +plugin_sources = Split( """ - gdal_datasource.cpp - gdal_featureset.cpp - """ - ) - -# clear out and rebuild libs -plugin_env['LIBS'] = [env['PLUGINS']['gdal']['lib']] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -plugin_env['LIBS'].append('mapnik') -plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) -plugin_env['LIBS'].append(env['ICU_LIB_NAME']) +libraries = [env['PLUGINS']['gdal']['lib']] +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append(env['ICU_LIB_NAME']) if env['RUNTIME_LINK'] == 'static': cmd = 'gdal-config --dep-libs' plugin_env.ParseConfig(cmd) - plugin_env['LIBS'].append('proj') + libraries.append('proj') -input_plugin = plugin_env.SharedLibrary('../gdal', source=gdal_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/geojson/build.py b/plugins/input/geojson/build.py index f463862a1..73aeb125f 100644 --- a/plugins/input/geojson/build.py +++ b/plugins/input/geojson/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2012 Artem Pavlenko +# 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 @@ -17,7 +17,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # - +# Import ('env') @@ -32,27 +32,45 @@ if not can_build: print 'WARNING: skipping building the optional geojson datasource plugin which requires boost >= 1.47' else: Import ('plugin_base') - prefix = env['PREFIX'] + + PLUGIN_NAME = 'geojson' + plugin_env = plugin_base.Clone() - geojson_src = Split( + + plugin_sources = Split( """ - geojson_datasource.cpp - geojson_featureset.cpp - """ - ) - libraries = [] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() + ) + # Link Library to Dependencies - libraries.append('mapnik') + libraries = [] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) if env['THREADING'] == 'multi': libraries.append('boost_thread%s' % env['BOOST_APPEND']) - input_plugin = plugin_env.SharedLibrary('../geojson', source=geojson_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) + if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') - # if the plugin links to libmapnik ensure it is built first - Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) - if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + + plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + } + + Return('plugin_obj') diff --git a/plugins/input/geojson/geojson_datasource.cpp b/plugins/input/geojson/geojson_datasource.cpp index 153597cda..566cb5ee2 100644 --- a/plugins/input/geojson/geojson_datasource.cpp +++ b/plugins/input/geojson/geojson_datasource.cpp @@ -39,6 +39,7 @@ // mapnik #include +#include #include #include #include @@ -106,7 +107,11 @@ geojson_datasource::geojson_datasource(parameters const& params) typedef std::istreambuf_iterator base_iterator_type; - std::ifstream is(file_.c_str()); +#if defined (_WINDOWS) + std::ifstream is(mapnik::utf8_to_utf16(file_),std::ios_base::in | std::ios_base::binary); +#else + std::ifstream is(file_.c_str(),std::ios_base::in | std::ios_base::binary); +#endif boost::spirit::multi_pass begin = boost::spirit::make_default_multi_pass(base_iterator_type(is)); diff --git a/plugins/input/kismet/build.py b/plugins/input/kismet/build.py deleted file mode 100644 index d85ced8e1..000000000 --- a/plugins/input/kismet/build.py +++ /dev/null @@ -1,51 +0,0 @@ -# -# This file is part of Mapnik (c++ mapping toolkit) -# -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon -# -# Mapnik is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -# - -Import ('plugin_base') -Import ('env') - -prefix = env['PREFIX'] - -plugin_env = plugin_base.Clone() - -kismet_src = Split( - """ - kismet_datasource.cpp - kismet_featureset.cpp - """ - ) - -libraries = [] -# Link Library to Dependencies -libraries.append('mapnik') -libraries.append(env['ICU_LIB_NAME']) -libraries.append('boost_system%s' % env['BOOST_APPEND']) -if env['THREADING'] == 'multi': - libraries.append('boost_thread%s' % env['BOOST_APPEND']) - -input_plugin = plugin_env.SharedLibrary('../kismet', source=kismet_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) - -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) - -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) diff --git a/plugins/input/kismet/kismet_datasource.cpp b/plugins/input/kismet/kismet_datasource.cpp deleted file mode 100644 index 96348e151..000000000 --- a/plugins/input/kismet/kismet_datasource.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2011 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 - * - *****************************************************************************/ - -// network -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// mapnik -#include -#include - -// boost -#include -#include -#include -#include - -#include "kismet_datasource.hpp" -#include "kismet_featureset.hpp" - -#define MAX_TCP_BUFFER 4096 // maximum accepted TCP data block size - -// If you change this also change the according kismet command length ! -#define MAX_KISMET_LINE 1024 // maximum length of a kismet command (assumed) -#define KISMET_COMMAND "*NETWORK: \001%1024[^\001]\001 %1024s %d %lf %lf" - -using mapnik::datasource; -using mapnik::parameters; - -DATASOURCE_PLUGIN(kismet_datasource) - -using mapnik::box2d; -using mapnik::coord2d; -using mapnik::query; -using mapnik::featureset_ptr; -using mapnik::layer_descriptor; -using mapnik::attribute_descriptor; -using mapnik::datasource_exception; - -boost::mutex knd_list_mutex; -std::list knd_list; -const unsigned int queue_size = 20; - -kismet_datasource::kismet_datasource(parameters const& params) - : datasource(params), - extent_(), - extent_initialized_(false), - type_(datasource::Vector), - srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"), - desc_(*params.get("type"), *params.get("encoding","utf-8")) -{ - boost::optional host = params.get("host"); - if (host) - { - host_ = *host; - } - else - { - throw datasource_exception("Kismet Plugin: missing parameter"); - } - - boost::optional port = params.get("port", 2501); - if (port) - { - port_ = static_cast(*port); - } - - boost::optional srs = params.get("srs"); - if (srs) - { - srs_ = *srs; - } - - boost::optional ext = params.get("extent"); - if (ext) - { - extent_initialized_ = extent_.from_string(*ext); - } - - kismet_thread.reset(new boost::thread(boost::bind(&kismet_datasource::run, this, host_, port_))); -} - -kismet_datasource::~kismet_datasource() -{ -} - -const char * kismet_datasource::name() -{ - return "kismet"; -} - -mapnik::datasource::datasource_t kismet_datasource::type() const -{ - return type_; -} - -box2d kismet_datasource::envelope() const -{ - return extent_; -} - -boost::optional kismet_datasource::get_geometry_type() const -{ - return boost::optional(mapnik::datasource::Point); -} - -layer_descriptor kismet_datasource::get_descriptor() const -{ - return desc_; -} - -featureset_ptr kismet_datasource::features(query const& q) const -{ - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource::features()"; - - // TODO: use box2d to filter bbox before adding to featureset_ptr - // mapnik::box2d const& e = q.get_bbox(); - - boost::mutex::scoped_lock lock(knd_list_mutex); - return boost::make_shared(knd_list, - srs_, - desc_.get_encoding()); - - // TODO: if illegal: - // return featureset_ptr(); -} - -featureset_ptr kismet_datasource::features_at_point(coord2d const& pt, double tol) const -{ - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource::features_at_point()"; - - return featureset_ptr(); -} - -void kismet_datasource::run(std::string const& ip_host, const unsigned int port) -{ - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource: Enter run"; - - int sockfd, n; - struct sockaddr_in sock_addr; - struct in_addr inadr; - struct hostent* host; - char buffer[MAX_TCP_BUFFER]; // TCP data send from kismet_server - std::string command; - - if (inet_aton(ip_host.c_str(), &inadr)) - { - host = gethostbyaddr((char*)&inadr, sizeof(inadr), AF_INET); - } - else - { - host = gethostbyname(ip_host.c_str()); - } - - if (host == NULL) - { - MAPNIK_LOG_ERROR(kismet) << "Kismet Plugin: error while searching host"; - return; - } - - sock_addr.sin_family = AF_INET; - sock_addr.sin_port = htons(port); - memcpy(&sock_addr.sin_addr, host->h_addr_list[0], sizeof(sock_addr.sin_addr)); - - if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) - { - MAPNIK_LOG_ERROR(kismet) << "Kismet Plugin: error while creating socket"; - return; - } - - if (connect(sockfd, (struct sockaddr*) &sock_addr, sizeof(sock_addr))) - { - MAPNIK_LOG_ERROR(kismet) << "Kismet Plugin: Error while connecting"; - return; - } - - command = "!1 ENABLE NETWORK ssid,bssid,wep,bestlat,bestlon\n"; - - if (write(sockfd, command.c_str(), command.length()) != (signed)command.length()) - { - MAPNIK_LOG_ERROR(kismet) << "Kismet Plugin: Error sending command to " << ip_host; - - close(sockfd); - return; - } - - char ssid[MAX_KISMET_LINE] = {}; - char bssid[MAX_KISMET_LINE] = {}; - double bestlat = 0; - double bestlon = 0; - int crypt = crypt_none; - - // BUG: if kismet_server is active sending after mapnik was killed and then restarted the - // assert is called. Needs to be analyzed! - while ((n = read(sockfd, buffer, sizeof(buffer))) > 0) - { - assert(n < MAX_TCP_BUFFER); - - buffer[n] = '\0'; - std::string bufferObj(buffer); // TCP data send from kismet_server as STL string - - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource: buffer_obj=" << bufferObj; - - std::string::size_type found = 0; - std::string::size_type search_start = 0; - std::string kismet_line; // contains a line from kismet_server - do - { - found = bufferObj.find('\n', search_start); - if (found != std::string::npos) - { - kismet_line.assign(bufferObj, search_start, found - search_start); - - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource: line=" << kismet_line; - - int param_number = 5; // the number of parameters to parse - - // Attention: string length specified to the constant! - if (sscanf (kismet_line.c_str(), - KISMET_COMMAND, - ssid, - bssid, - &crypt, - &bestlat, - &bestlon) == param_number) - { - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource: ssid=" << ssid - << ", bssid=" << bssid - << ", crypt=" << crypt - << ", bestlat=" << bestlat - << ", bestlon=" << bestlon; - - kismet_network_data knd(ssid, bssid, bestlat, bestlon, crypt); - - boost::mutex::scoped_lock lock(knd_list_mutex); - - // the queue only grows to a max size - if (knd_list.size () >= queue_size) - { - knd_list.pop_front(); - } - - knd_list.push_back(knd); - } - else - { - // do nothing if not matched! - } - - search_start = found + 1; - } - } - while (found != std::string::npos); - } - - if (n < 0) - { - MAPNIK_LOG_ERROR(kismet) << "Kismet Plugin: error while reading from socket"; - } - - close(sockfd); - - MAPNIK_LOG_DEBUG(kismet) << "kismet_datasource: Exit run"; -} - diff --git a/plugins/input/kismet/kismet_datasource.hpp b/plugins/input/kismet/kismet_datasource.hpp deleted file mode 100644 index 272a15ddd..000000000 --- a/plugins/input/kismet/kismet_datasource.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2011 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef KISMET_DATASOURCE_HPP -#define KISMET_DATASOURCE_HPP - -// mapnik -#include -#include -#include -#include -#include -#include -#include - -// boost -#include -#include -#include - -// stl -#include -#include -#include - -#include "kismet_types.hpp" - -class kismet_datasource : public mapnik::datasource -{ -public: - kismet_datasource(mapnik::parameters const& params); - virtual ~kismet_datasource (); - datasource::datasource_t type() const; - static const char * name(); - mapnik::featureset_ptr features(mapnik::query const& q) const; - mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const; - mapnik::box2d envelope() const; - boost::optional get_geometry_type() const; - mapnik::layer_descriptor get_descriptor() const; - -private: - void run (std::string const& host, const unsigned int port); - - mapnik::box2d extent_; - bool extent_initialized_; - std::string host_; - unsigned int port_; - mapnik::datasource::datasource_t type_; - std::string srs_; - mapnik::layer_descriptor desc_; - boost::shared_ptr kismet_thread; -}; - -#endif // KISMET_DATASOURCE_HPP diff --git a/plugins/input/kismet/kismet_featureset.cpp b/plugins/input/kismet/kismet_featureset.cpp deleted file mode 100644 index edd4ec95c..000000000 --- a/plugins/input/kismet/kismet_featureset.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2011 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -// mapnik -#include -#include -#include -#include -#include -#include -#include -#include - -#include "kismet_featureset.hpp" - -// boost -#include - -using mapnik::feature_ptr; -using mapnik::geometry_type; -using mapnik::geometry_utils; -using mapnik::transcoder; -using mapnik::feature_factory; - -kismet_featureset::kismet_featureset(std::list const& knd_list, - std::string const& srs, - std::string const& encoding) - : knd_list_(knd_list), - tr_(new transcoder(encoding)), - feature_id_(1), - knd_list_it(knd_list_.begin()), - source_(srs), - ctx_(boost::make_shared()) -{ - ctx_->push("internet_access"); -} - -kismet_featureset::~kismet_featureset() -{ -} - -feature_ptr kismet_featureset::next() -{ - if (knd_list_it != knd_list_.end ()) - { - const kismet_network_data& knd = *knd_list_it; - const std::string key = "internet_access"; - - std::string value; - if (knd.crypt() == crypt_none) - { - value = "wlan_uncrypted"; - } - else if (knd.crypt() == crypt_wep) - { - value = "wlan_wep"; - } - else - { - value = "wlan_crypted"; - } - - feature_ptr feature(feature_factory::create(ctx_,feature_id_)); - ++feature_id_; - - geometry_type* pt = new geometry_type(mapnik::Point); - pt->move_to(knd.bestlon(), knd.bestlat()); - feature->add_geometry(pt); - - feature->put(key, tr_->transcode(value.c_str())); - - ++knd_list_it; - - return feature; - } - - return feature_ptr(); -} diff --git a/plugins/input/kismet/kismet_featureset.hpp b/plugins/input/kismet/kismet_featureset.hpp deleted file mode 100644 index 91e6afef7..000000000 --- a/plugins/input/kismet/kismet_featureset.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2011 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef KISMET_FEATURESET_HPP -#define KISMET_FEATURESET_HPP - -// mapnik -#include -#include -#include -#include -#include -#include - -// boost -#include -#include - -//STL -#include - -#include "kismet_types.hpp" - -class kismet_featureset : public mapnik::Featureset -{ -public: - kismet_featureset(std::list const& knd_list, - std::string const& srs, - std::string const& encoding); - virtual ~kismet_featureset(); - mapnik::feature_ptr next(); - -private: - std::list const& knd_list_; - boost::scoped_ptr tr_; - mapnik::value_integer feature_id_; - std::list::const_iterator knd_list_it; - mapnik::projection source_; - mapnik::context_ptr ctx_; -}; - -#endif // KISMET_FEATURESET_HPP diff --git a/plugins/input/kismet/kismet_types.hpp b/plugins/input/kismet/kismet_types.hpp deleted file mode 100644 index ea9ff856a..000000000 --- a/plugins/input/kismet/kismet_types.hpp +++ /dev/null @@ -1,111 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2011 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef KISMET_TYPES_HPP -#define KISMET_TYPES_HPP - -// mapnik -#include - -// boost -#include - -// this is a copy from packet.h from kismet 2007.10.R1 -enum crypt_type -{ - crypt_none = 0, - crypt_unknown = 1, - crypt_wep = 2, - crypt_layer3 = 4, - // Derived from WPA headers - crypt_wep40 = 8, - crypt_wep104 = 16, - crypt_tkip = 32, - crypt_wpa = 64, - crypt_psk = 128, - crypt_aes_ocb = 256, - crypt_aes_ccm = 512, - // Derived from data traffic - crypt_leap = 1024, - crypt_ttls = 2048, - crypt_tls = 4096, - crypt_peap = 8192, - crypt_isakmp = 16384, - crypt_pptp = 32768, - crypt_ccmp = 65536 -}; - -class kismet_network_data -{ -public: - kismet_network_data() - : bestlat_(0), bestlon_(0), crypt_(crypt_none) - { - } - - kismet_network_data(std::string ssid, - std::string bssid, - double bestlat, - double bestlon, - int crypt) - : ssid_(ssid), - bssid_(bssid), - bestlat_(bestlat), - bestlon_(bestlon), - crypt_(crypt) - { - } - - std::string const& ssid() const - { - return ssid_; - } - - std::string const& bssid() const - { - return bssid_; - } - - double bestlat() const - { - return bestlat_; - } - - double bestlon() const - { - return bestlon_; - } - - int crypt() const - { - return crypt_; - } - -protected: - std::string ssid_; - std::string bssid_; - double bestlat_; - double bestlon_; - int crypt_; -}; - -#endif // KISMET_TYPES_HPP diff --git a/plugins/input/occi/build.py b/plugins/input/occi/build.py index 050cbce9b..946d32dbb 100644 --- a/plugins/input/occi/build.py +++ b/plugins/input/occi/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 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 @@ -17,35 +17,49 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'occi' plugin_env = plugin_base.Clone() -occi_src = Split( +plugin_sources = Split( """ - occi_types.cpp - occi_datasource.cpp - occi_featureset.cpp + %(PLUGIN_NAME)s_types.cpp + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp spatial_classesm.cpp spatial_classeso.cpp - """ - ) + """ % locals() +) libraries = [ 'occi', 'ociei' ] -libraries.append('mapnik') libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append(env['ICU_LIB_NAME']) -input_plugin = plugin_env.SharedLibrary('../occi', source=occi_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/ogr/build.py b/plugins/input/ogr/build.py index 26512b856..881d20006 100644 --- a/plugins/input/ogr/build.py +++ b/plugins/input/ogr/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 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 @@ -17,50 +17,67 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# - +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'ogr' plugin_env = plugin_base.Clone() -ogr_src = Split( +plugin_sources = Split( """ - ogr_converter.cpp - ogr_datasource.cpp - ogr_featureset.cpp - ogr_index_featureset.cpp - """ - ) - -plugin_env['LIBS'] = [env['PLUGINS']['ogr']['lib']] + %(PLUGIN_NAME)s_converter.cpp + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_index_featureset.cpp + """ % locals() +) # Link Library to Dependencies -plugin_env['LIBS'].append('mapnik') -plugin_env['LIBS'].append(env['ICU_LIB_NAME']) -plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) -plugin_env['LIBS'].append('boost_filesystem%s' % env['BOOST_APPEND']) +libraries = [env['PLUGINS']['ogr']['lib']] +libraries.append(env['ICU_LIB_NAME']) +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) + +cxxflags = [] if env['RUNTIME_LINK'] == 'static': cmd = 'gdal-config --dep-libs' plugin_env.ParseConfig(cmd) - plugin_env['LIBS'].append('proj') + libraries.append('proj') if env.get('BOOST_LIB_VERSION_FROM_HEADER'): boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) if boost_version_from_header < 46: # avoid ubuntu issue with boost interprocess: # https://github.com/mapnik/mapnik/issues/1082 - plugin_env.Append(CXXFLAGS = '-fpermissive') + cxxflags.Append('-fpermissive') -input_plugin = plugin_env.SharedLibrary('../ogr', source=ogr_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS']) +plugin_env.Append(CXXFLAGS=cxxflags) -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'CXXFLAGS': cxxflags, + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/ogr/ogr_datasource.cpp b/plugins/input/ogr/ogr_datasource.cpp index b629d1e3d..8385598f4 100644 --- a/plugins/input/ogr/ogr_datasource.cpp +++ b/plugins/input/ogr/ogr_datasource.cpp @@ -82,7 +82,7 @@ void ogr_datasource::init(mapnik::parameters const& params) // initialize ogr formats OGRRegisterAll(); - + boost::optional file = params.get("file"); boost::optional string = params.get("string"); if (! file && ! string) @@ -525,7 +525,7 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt, double tol) if (indexed_) { - filter_at_point filter(pt); + filter_at_point filter(pt, tol); return featureset_ptr(new ogr_index_featureset (ctx, *layer, diff --git a/plugins/input/ogr/ogr_index_featureset.cpp b/plugins/input/ogr/ogr_index_featureset.cpp index cf95c5899..1f6c62939 100644 --- a/plugins/input/ogr/ogr_index_featureset.cpp +++ b/plugins/input/ogr/ogr_index_featureset.cpp @@ -59,7 +59,8 @@ ogr_index_featureset::ogr_index_featureset(mapnik::context_ptr const & layerdef_(layer.GetLayerDefn()), filter_(filter), tr_(new transcoder(encoding)), - fidcolumn_(layer_.GetFIDColumn()) + fidcolumn_(layer_.GetFIDColumn()), + feature_envelope_() { boost::optional memory = mapnik::mapped_memory_cache::instance().find(index_file, true); @@ -104,6 +105,9 @@ feature_ptr ogr_index_featureset::next() OGRGeometry* geom=poFeature->GetGeometryRef(); if (geom && !geom->IsEmpty()) { + geom->getEnvelope(&feature_envelope_); + if (!filter_.pass(mapnik::box2d(feature_envelope_.MinX,feature_envelope_.MinY, + feature_envelope_.MaxX,feature_envelope_.MaxY))) continue; ogr_converter::convert_geometry (geom, feature); } else diff --git a/plugins/input/ogr/ogr_index_featureset.hpp b/plugins/input/ogr/ogr_index_featureset.hpp index 5e4c6cbc5..9972935e4 100644 --- a/plugins/input/ogr/ogr_index_featureset.hpp +++ b/plugins/input/ogr/ogr_index_featureset.hpp @@ -50,6 +50,7 @@ private: std::vector::iterator itr_; boost::scoped_ptr tr_; const char* fidcolumn_; + OGREnvelope feature_envelope_; }; #endif // OGR_INDEX_FEATURESET_HPP diff --git a/plugins/input/osm/build.py b/plugins/input/osm/build.py index 4cff88aea..f48a930d4 100644 --- a/plugins/input/osm/build.py +++ b/plugins/input/osm/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 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 @@ -17,38 +17,53 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'osm' plugin_env = plugin_base.Clone() -osm_src = Split( +plugin_sources = Split( """ + %(PLUGIN_NAME)s.cpp + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp osmparser.cpp - osm.cpp - osm_datasource.cpp - osm_featureset.cpp dataset_deliverer.cpp basiccurl.cpp - """ - ) + """ % locals() +) +# Link Library to Dependencies libraries = [ 'xml2' ] libraries.append('curl') -libraries.append('mapnik') libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -input_plugin = plugin_env.SharedLibrary('../osm', source=osm_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/postgis/build.py b/plugins/input/postgis/build.py index 271de7caf..2d31a3dc6 100644 --- a/plugins/input/postgis/build.py +++ b/plugins/input/postgis/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 @@ -17,44 +17,57 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'postgis' plugin_env = plugin_base.Clone() -postgis_src = Split( +plugin_sources = Split( """ - postgis_datasource.cpp - postgis_featureset.cpp - """ - ) - -# clear out and rebuild libs -plugin_env['LIBS'] = ['pq'] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -plugin_env['LIBS'].append('mapnik') -plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) -plugin_env['LIBS'].append(env['ICU_LIB_NAME']) +libraries = ['pq'] +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append(env['ICU_LIB_NAME']) + if env['THREADING'] == 'multi': - plugin_env['LIBS'].append('boost_thread%s' % env['BOOST_APPEND']) + libraries.append('boost_thread%s' % env['BOOST_APPEND']) if env['RUNTIME_LINK'] == 'static': #cmd = 'pg_config --libs' #plugin_env.ParseConfig(cmd) # pg_config does not seem to report correct deps of libpq # so resort to hardcoding for now - plugin_env['LIBS'].extend(['ldap','pam','ssl','crypto','krb5']) + libraries.extend(['ldap', 'pam', 'ssl', 'crypto', 'krb5']) -input_plugin = plugin_env.SharedLibrary('../postgis', source=postgis_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 6ca97d660..d23c8edba 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -117,14 +117,21 @@ feature_ptr postgis_featureset::next() ++feature_id_; } + // null geometry is not acceptable + if (rs_->isNull(0)) + { + MAPNIK_LOG_WARN(postgis) << "postgis_featureset: null value encountered for geometry"; + continue; + } + // parse geometry int size = rs_->getFieldLength(0); const char *data = rs_->getValue(0); + if (!geometry_utils::from_wkb(feature->paths(), data, size)) continue; totalGeomSize_ += size; - unsigned num_attrs = ctx_->size() + 1; for (; pos < num_attrs; ++pos) { diff --git a/plugins/input/python/build.py b/plugins/input/python/build.py index 78636adfc..bf5313eb4 100644 --- a/plugins/input/python/build.py +++ b/plugins/input/python/build.py @@ -1,13 +1,29 @@ -#!/usr/bin/env python +# +# This file is part of Mapnik (c++ mapping toolkit) +# +# Copyright (C) 2013 Artem Pavlenko +# +# Mapnik is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# import os - -PLUGIN_NAME = 'python' - Import ('plugin_base') Import ('env') -install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] +PLUGIN_NAME = 'python' plugin_env = plugin_base.Clone() @@ -17,26 +33,32 @@ plugin_sources = Split( %(PLUGIN_NAME)s_featureset.cpp %(PLUGIN_NAME)s_utils.cpp """ % locals() - ) +) -boost_system = 'boost_system%s' % env['BOOST_APPEND'] -libraries = ['mapnik',env['BOOST_PYTHON_LIB'],boost_system,env['ICU_LIB_NAME']] +# Link Library to Dependencies +libraries = [] +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append(env['BOOST_PYTHON_LIB']) +libraries.append(env['ICU_LIB_NAME']) +python_cpppath = env['PYTHON_INCLUDES'] +allcpp_paths = env['CPPPATH'] +allcpp_paths.extend(python_cpppath) # NOTE: explicit linking to libpython is uneeded on most linux version if the # python plugin is used by a app in python using mapnik's python bindings # we explicitly link to libpython here so that this plugin # can be used from a pure C++ calling application or a different binding language if env['PLATFORM'] == 'Darwin' and env['FRAMEWORK_PYTHON']: - if env['FRAMEWORK_SEARCH_PATH']: - python_link_flag = '-F%s -framework Python -Z' % env['FRAMEWORK_SEARCH_PATH'] + if env['FRAMEWORK_SEARCH_PATH']: + python_link_flag = '-F%s -framework Python -Z' % env['FRAMEWORK_SEARCH_PATH'] + else: + link_prefix = env['PYTHON_SYS_PREFIX'] + if '.framework' in link_prefix: + python_link_flag = '-F%s -framework Python -Z' % os.path.dirname(link_prefix.split('.')[0]) + elif '/System' in link_prefix: + python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z' else: - link_prefix = env['PYTHON_SYS_PREFIX'] - if '.framework' in link_prefix: - python_link_flag = '-F%s -framework Python -Z' % os.path.dirname(link_prefix.split('.')[0]) - elif '/System' in link_prefix: - python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z' - else: - python_link_flag = '-F/ -framework Python' + python_link_flag = '-F/ -framework Python' else: # on linux the linkflags end up to early in the compile flags to work correctly python_link_flag = '-L%s' % env['PYTHON_SYS_PREFIX'] + os.path.sep + env['LIBDIR_SCHEMA'] @@ -48,33 +70,31 @@ if env['CUSTOM_LDFLAGS']: else: linkflags = python_link_flag -plugin_env.Append(CPPPATH = env['PYTHON_INCLUDES']) - -TARGET = plugin_env.SharedLibrary( - # the name of the target to build, eg 'sqlite.input' - '../%s' % PLUGIN_NAME, - # prefix - normally none used - SHLIBPREFIX='', - # extension, mapnik expects '.input' - SHLIBSUFFIX='.input', - # list of source files to compile - source=plugin_sources, - # libraries to link to - LIBS=libraries, - # any custom linkflags, eg. LDFLAGS - # in this case CUSTOM_LDFLAGS comes - # from Mapnik's main SConstruct file - # and can be removed here if you do - # not need it - LINKFLAGS=linkflags - ) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + CPPPATH=allcpp_paths, + LIBS=libraries, + LINKFLAGS=linkflags) -# if the plugin links to libmapnik ensure it is built first -Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) -# if 'uninstall' is not passed on the command line -# then we actually create the install targets that -# scons will install if 'install' is passed as an arg -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(install_dest, TARGET) - env.Alias('install', install_dest) + # if 'uninstall' is not passed on the command line + # then we actually create the install targets that + # scons will install if 'install' is passed as an arg + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + 'CPPPATH': python_cpppath, + 'LINKFLAGS': linkflags.replace('-Z','').split(' '), +} + +Return('plugin_obj') diff --git a/plugins/input/raster/build.py b/plugins/input/raster/build.py index 2a3c7dd41..b16028f68 100644 --- a/plugins/input/raster/build.py +++ b/plugins/input/raster/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 @@ -17,35 +17,49 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'raster' plugin_env = plugin_base.Clone() -raster_src = Split( +plugin_sources = Split( """ - raster_datasource.cpp - raster_featureset.cpp - raster_info.cpp - """ - ) + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_info.cpp + """ % locals() +) -libraries = [] # Link Library to Dependencies -libraries.append('mapnik') +libraries = [] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -input_plugin = plugin_env.SharedLibrary('../raster', source=raster_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/rasterlite/build.py b/plugins/input/rasterlite/build.py index cee50da27..b3e6a834b 100644 --- a/plugins/input/rasterlite/build.py +++ b/plugins/input/rasterlite/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 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 @@ -17,35 +17,48 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'rasterlite' plugin_env = plugin_base.Clone() -rasterlite_src = Split( +plugin_sources = Split( """ - rasterlite_datasource.cpp - rasterlite_featureset.cpp - """ - ) - -libraries = [env['PLUGINS']['rasterlite']['lib']] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -libraries.append('mapnik') +libraries = [env['PLUGINS']['rasterlite']['lib']] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -input_plugin = plugin_env.SharedLibrary('../rasterlite', source=rasterlite_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/shape/build.py b/plugins/input/shape/build.py index 5dd9995ac..d837b7fc8 100644 --- a/plugins/input/shape/build.py +++ b/plugins/input/shape/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 @@ -17,50 +17,70 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# - +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'shape' plugin_env = plugin_base.Clone() -shape_src = Split( +plugin_sources = Split( """ - dbfile.cpp - shape_datasource.cpp - shape_featureset.cpp - shape_index_featureset.cpp - shape_io.cpp - shape_utils.cpp - """ - ) - -libraries = [] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_index_featureset.cpp + %(PLUGIN_NAME)s_io.cpp + %(PLUGIN_NAME)s_utils.cpp + dbfile.cpp + """ % locals() +) # Link Library to Dependencies -libraries.append('mapnik') +libraries = [] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) +cppdefines = [] +cxxflags = [] + if env['SHAPE_MEMORY_MAPPED_FILE']: - plugin_env.Append(CPPDEFINES = '-DSHAPE_MEMORY_MAPPED_FILE') + cppdefines.append('-DSHAPE_MEMORY_MAPPED_FILE') if env.get('BOOST_LIB_VERSION_FROM_HEADER'): boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) if boost_version_from_header < 46: # avoid ubuntu issue with boost interprocess: # https://github.com/mapnik/mapnik/issues/1082 - plugin_env.Append(CXXFLAGS = '-fpermissive') + cxxflags.append('-fpermissive') -input_plugin = plugin_env.SharedLibrary('../shape', SHLIBSUFFIX='.input', source=shape_src, SHLIBPREFIX='', LIBS = libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +plugin_env.Append(CXXFLAGS=cxxflags) +plugin_env.Append(CPPDEFINES=cppdefines) -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + TARGET = plugin_env.SharedLibrary('../shape', + SHLIBSUFFIX='.input', + SHLIBPREFIX='', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + 'CXXFLAGS': cxxflags, + 'CPPDEFINES': cppdefines, +} + +Return('plugin_obj') diff --git a/plugins/input/shape/dbfile.cpp b/plugins/input/shape/dbfile.cpp index 7902eb4ab..b6014da2e 100644 --- a/plugins/input/shape/dbfile.cpp +++ b/plugins/input/shape/dbfile.cpp @@ -50,6 +50,8 @@ dbf_file::dbf_file(std::string const& file_name) record_length_(0), #ifdef SHAPE_MEMORY_MAPPED_FILE file_(), +#elif defined(_WINDOWS) + file_(mapnik::utf8_to_utf16(file_name), std::ios::in | std::ios::binary), #else file_(file_name.c_str() ,std::ios::in | std::ios::binary), #endif diff --git a/plugins/input/shape/shape_datasource.cpp b/plugins/input/shape/shape_datasource.cpp index a98121ec8..391d9cb8b 100644 --- a/plugins/input/shape/shape_datasource.cpp +++ b/plugins/input/shape/shape_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2013 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,6 +34,7 @@ // mapnik #include #include +#include #include #include #include @@ -76,18 +77,28 @@ shape_datasource::shape_datasource(const parameters ¶ms) shape_name_ = *file; boost::algorithm::ireplace_last(shape_name_,".shp",""); - +#ifdef _WINDOWS + if (!boost::filesystem::exists(mapnik::utf8_to_utf16(shape_name_) + L".shp")) +#else if (!boost::filesystem::exists(shape_name_ + ".shp")) +#endif { throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".shp' does not exist"); } - +#ifdef _WINDOWS + if (boost::filesystem::is_directory(mapnik::utf8_to_utf16(shape_name_) + L".shp")) +#else if (boost::filesystem::is_directory(shape_name_ + ".shp")) +#endif { throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".shp' appears to be a directory not a file"); } +#ifdef _WINDOWS + if (!boost::filesystem::exists(mapnik::utf8_to_utf16(shape_name_) + L".dbf")) +#else if (!boost::filesystem::exists(shape_name_ + ".dbf")) +#endif { throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".dbf' does not exist"); } diff --git a/plugins/input/shape/shapefile.hpp b/plugins/input/shape/shapefile.hpp index c082b09d4..6e5631824 100644 --- a/plugins/input/shape/shapefile.hpp +++ b/plugins/input/shape/shapefile.hpp @@ -29,6 +29,7 @@ // mapnik #include +#include #include #include #include @@ -149,6 +150,8 @@ public: shape_file(std::string const& file_name) : #ifdef SHAPE_MEMORY_MAPPED_FILE file_() +#elif defined (_WINDOWS) + file_(mapnik::utf8_to_utf16(file_name), std::ios::in | std::ios::binary) #else file_(file_name.c_str(), std::ios::in | std::ios::binary) #endif diff --git a/plugins/input/sqlite/build.py b/plugins/input/sqlite/build.py index 458a885ad..db029e6ab 100644 --- a/plugins/input/sqlite/build.py +++ b/plugins/input/sqlite/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 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 @@ -17,39 +17,54 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'sqlite' plugin_env = plugin_base.Clone() -sqlite_src = Split( +plugin_sources = Split( """ - sqlite_datasource.cpp - sqlite_featureset.cpp - """ - ) - -libraries = [ 'sqlite3' ] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -libraries.append('mapnik') +libraries = [ 'sqlite3' ] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -linkflags = env['CUSTOM_LDFLAGS'] +linkflags = [] if env['SQLITE_LINKFLAGS']: linkflags.append(env['SQLITE_LINKFLAGS']) -input_plugin = plugin_env.SharedLibrary('../sqlite', source=sqlite_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=linkflags) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') + linkflags.append(env['CUSTOM_LDFLAGS']) -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=(' ').join(linkflags)) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + 'LINKFLAGS': linkflags, +} + +Return('plugin_obj') diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index cc84dd3d7..fa021ebf1 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -90,7 +90,11 @@ sqlite_datasource::sqlite_datasource(parameters const& params) else dataset_name_ = *file; +#ifdef _WINDOWS + if ((dataset_name_.compare(":memory:") != 0) && (!boost::filesystem::exists(mapnik::utf8_to_utf16(dataset_name_)))) +#else if ((dataset_name_.compare(":memory:") != 0) && (!boost::filesystem::exists(dataset_name_))) +#endif { throw datasource_exception("Sqlite Plugin: " + dataset_name_ + " does not exist"); } @@ -280,7 +284,11 @@ sqlite_datasource::sqlite_datasource(parameters const& params) mapnik::progress_timer __stats2__(std::clog, "sqlite_datasource::init(use_spatial_index)"); #endif +#ifdef _WINDOWS + if (boost::filesystem::exists(mapnik::utf8_to_utf16(index_db))) +#else if (boost::filesystem::exists(index_db)) +#endif { dataset_->execute("attach database '" + index_db + "' as " + index_table_); } @@ -318,7 +326,11 @@ sqlite_datasource::sqlite_datasource(parameters const& params) { //extent_initialized_ = true; has_spatial_index_ = true; +#ifdef _WINDOWS + if (boost::filesystem::exists(mapnik::utf8_to_utf16(index_db))) +#else if (boost::filesystem::exists(index_db)) +#endif { dataset_->execute("attach database '" + index_db + "' as " + index_table_); } @@ -436,12 +448,20 @@ void sqlite_datasource::parse_attachdb(std::string const& attachdb) const // Normalize the filename and make it relative to dataset_name_ if (filename.compare(":memory:") != 0) { +#ifdef _WINDOWS + boost::filesystem::path child_path(mapnik::utf8_to_utf16(filename)); +#else boost::filesystem::path child_path(filename); +#endif // It is a relative path. Fix it. if (! child_path.has_root_directory() && ! child_path.has_root_name()) { +#ifdef _WINDOWS + boost::filesystem::path absolute_path(mapnik::utf8_to_utf16(dataset_name_)); +#else boost::filesystem::path absolute_path(dataset_name_); +#endif // support symlinks if (boost::filesystem::is_symlink(absolute_path)) diff --git a/plugins/input/sqlite/sqlite_utils.hpp b/plugins/input/sqlite/sqlite_utils.hpp index 90f0446a1..5dfae3a4f 100644 --- a/plugins/input/sqlite/sqlite_utils.hpp +++ b/plugins/input/sqlite/sqlite_utils.hpp @@ -30,6 +30,7 @@ // mapnik #include +#include #include #include #include @@ -235,7 +236,11 @@ public: int flags; #endif +#ifdef _WINDOWS + bool existed = boost::filesystem::exists(mapnik::utf8_to_utf16(index_db)); +#else bool existed = boost::filesystem::exists(index_db); +#endif boost::shared_ptr ds = boost::make_shared(index_db,flags); bool one_success = false; @@ -328,8 +333,12 @@ public: { try { +#ifdef _WINDOWS + boost::filesystem::remove(mapnik::utf8_to_utf16(index_db)); +#else boost::filesystem::remove(index_db); - } +#endif + } catch (...) {}; } throw mapnik::datasource_exception(ex.what()); @@ -344,7 +353,11 @@ public: { try { +#ifdef _WINDOWS + boost::filesystem::remove(mapnik::utf8_to_utf16(index_db)); +#else boost::filesystem::remove(index_db); +#endif } catch (...) {}; } @@ -413,7 +426,13 @@ public: int flags; #endif - bool existed = boost::filesystem::exists(index_db); +#ifdef _WINDOWS + bool existed = boost::filesystem::exists(mapnik::utf8_to_utf16(index_db)); +#else + bool existed = boost::filesystem::exists(index_db);; +#endif + + boost::shared_ptr ds = boost::make_shared(index_db,flags); bool one_success = false; @@ -460,7 +479,11 @@ public: { try { +#ifdef _WINDOWS + boost::filesystem::remove(mapnik::utf8_to_utf16(index_db)); +#else boost::filesystem::remove(index_db); +#endif } catch (...) {}; } @@ -476,7 +499,11 @@ public: { try { +#ifdef _WINDOWS + boost::filesystem::remove(mapnik::utf8_to_utf16(index_db)); +#else boost::filesystem::remove(index_db); +#endif } catch (...) {}; } diff --git a/plugins/input/templates/helloworld/build.py b/plugins/input/templates/helloworld/build.py index 5a974dd4b..d90efa26e 100644 --- a/plugins/input/templates/helloworld/build.py +++ b/plugins/input/templates/helloworld/build.py @@ -11,21 +11,17 @@ import os -# Give this plugin a name -# here this happens to be the same as the directory -PLUGIN_NAME = 'hello' - # Here we pull from the SCons environment exported from the main instance Import ('plugin_base') Import ('env') +# Give this plugin a name +# here this happens to be the same as the directory +PLUGIN_NAME = 'hello' + # the below install details are also pulled from the # main SConstruct file where configuration happens -# plugins can go anywhere, and be registered in custom locations by Mapnik -# but the standard location is '/usr/local/lib/mapnik/input' -install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] - # clone the environment here # so that if we modify the env it in this file # those changes to not pollute other builds later on... @@ -35,7 +31,7 @@ plugin_env = plugin_base.Clone() plugin_sources = Split( """ %(PLUGIN_NAME)s_datasource.cpp - %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_featureset.cpp """ % locals() ) @@ -43,37 +39,54 @@ plugin_sources = Split( # directly link to libraries = [ '' ] # eg 'libfoo' -libraries.append('mapnik') libraries.append('boost_system%s' % env['BOOST_APPEND']) # link libicuuc, but ICU_LIB_NAME is used custom builds of icu can # have different library names like osx which offers /usr/lib/libicucore.dylib libraries.append(env['ICU_LIB_NAME']) - -TARGET = plugin_env.SharedLibrary( - # the name of the target to build, eg 'sqlite.input' - '../%s' % PLUGIN_NAME, - # prefix - normally none used - SHLIBPREFIX='', - # extension, mapnik expects '.input' - SHLIBSUFFIX='.input', - # list of source files to compile - source=plugin_sources, - # libraries to link to - LIBS=libraries, - # any custom linkflags, eg. LDFLAGS - # in this case CUSTOM_LDFLAGS comes - # from Mapnik's main SConstruct file - # and can be removed here if you do - # not need it - LINKFLAGS=env.get('CUSTOM_LDFLAGS') - ) -# if the plugin links to libmapnik ensure it is built first -Depends(TARGET, env.subst('../../../../src/%s' % env['MAPNIK_LIB_NAME'])) +# this is valid if we are building an external plugin as shared library +if env['PLUGIN_LINKING'] == 'shared': + # plugins can go anywhere, and be registered in custom locations by Mapnik + # but the standard location is '/usr/local/lib/mapnik/input' + install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] -# if 'uninstall' is not passed on the command line -# then we actually create the install targets that -# scons will install if 'install' is passed as an arg -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(install_dest, TARGET) - env.Alias('install', install_dest) + # only link mapnik if we are build an external shared object + libraries.append('mapnik') + + TARGET = plugin_env.SharedLibrary( + # the name of the target to build, eg 'sqlite.input' + '../%s' % PLUGIN_NAME, + # prefix - normally none used + SHLIBPREFIX='', + # extension, mapnik expects '.input' + SHLIBSUFFIX='.input', + # list of source files to compile + source=plugin_sources, + # libraries to link to + LIBS=libraries, + # any custom linkflags, eg. LDFLAGS + # in this case CUSTOM_LDFLAGS comes + # from Mapnik's main SConstruct file + # and can be removed here if you do + # not need it + LINKFLAGS=env.get('CUSTOM_LDFLAGS') + ) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + # if 'uninstall' is not passed on the command line + # then we actually create the install targets that + # scons will install if 'install' is passed as an arg + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(install_dest, TARGET) + env.Alias('install', install_dest) + +# Return the plugin building options to scons +# This is used when statically linking the plugin with mapnik) +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/src/agg/process_debug_symbolizer.cpp b/src/agg/process_debug_symbolizer.cpp index 2bf8e276d..277f7fea6 100644 --- a/src/agg/process_debug_symbolizer.cpp +++ b/src/agg/process_debug_symbolizer.cpp @@ -52,10 +52,37 @@ void agg_renderer::process(debug_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - label_collision_detector4::query_iterator itr = detector_->begin(), end = detector_->end(); - for (;itr!=end; itr++) + debug_symbolizer_mode_e mode = sym.get_mode(); + if (mode == DEBUG_SYM_MODE_COLLISION) { - draw_rect(pixmap_, itr->box); + label_collision_detector4::query_iterator itr = detector_->begin(), end = detector_->end(); + for (;itr!=end; itr++) + { + draw_rect(pixmap_, itr->box); + } + } + else if (mode == DEBUG_SYM_MODE_VERTEX) + { + for (unsigned i=0; i const& bbox = (*marker)->bounding_box(); + coord2d center = bbox.center(); + + agg::trans_affine tr; + evaluate_transform(tr, feature, sym.get_image_transform()); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine recenter_tr = recenter * tr; + box2d label_ext = bbox * recenter_tr * agg::trans_affine_scaling(scale_factor_); + for (unsigned i = 0; i < feature.num_geometries(); ++i) { geometry_type const& geom = feature.get_geometry(i); @@ -689,15 +698,7 @@ void cairo_renderer_base::process(point_symbolizer const& sym, prj_trans.backward(x, y, z); t_.forward(&x, &y); - - double dx = 0.5 * (*marker)->width(); - double dy = 0.5 * (*marker)->height(); - agg::trans_affine tr; - evaluate_transform(tr, feature, sym.get_image_transform()); - box2d label_ext (-dx, -dy, dx, dy); - label_ext *= tr; - label_ext *= agg::trans_affine_translation(x,y); - label_ext *= agg::trans_affine_scaling(scale_factor_); + label_ext.re_center(x,y); if (sym.get_allow_overlap() || detector_->has_placement(label_ext)) { diff --git a/src/css_color_grammar.cpp b/src/css_color_grammar.cpp index 6a8be6d1d..df36b5d44 100644 --- a/src/css_color_grammar.cpp +++ b/src/css_color_grammar.cpp @@ -25,7 +25,7 @@ #if BOOST_VERSION >= 104500 -#include +#include namespace mapnik { diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index 70e0f4636..e303d7d6e 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -38,6 +38,9 @@ namespace mapnik { +extern datasource_ptr create_static_datasource(parameters const& params); +extern std::vector get_static_datasource_names(); + bool is_input_plugin(std::string const& filename) { return boost::algorithm::ends_with(filename,std::string(".input")); @@ -62,13 +65,23 @@ datasource_ptr datasource_cache::create(parameters const& params) "parameter 'type' is missing"); } + datasource_ptr ds; + +#ifdef MAPNIK_STATIC_PLUGINS + // return if it's created, raise otherwise + ds = create_static_datasource(params); + if (ds) + { + return ds; + } +#endif + #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif - datasource_ptr ds; std::map >::iterator itr=plugins_.find(*type); - if ( itr == plugins_.end() ) + if (itr == plugins_.end()) { std::string s("Could not create datasource for type: '"); s += *type + "'"; @@ -83,7 +96,7 @@ datasource_ptr datasource_cache::create(parameters const& params) throw config_error(s); } - if (!itr->second->valid()) + if (! itr->second->valid()) { throw std::runtime_error(std::string("Cannot load library: ") + itr->second->get_error()); @@ -95,13 +108,19 @@ datasource_ptr datasource_cache::create(parameters const& params) #endif create_ds* create_datasource = reinterpret_cast(itr->second->get_symbol("create")); - if (!create_datasource) + if (! create_datasource) { throw std::runtime_error(std::string("Cannot load symbols: ") + itr->second->get_error()); } + ds = datasource_ptr(create_datasource(params), datasource_deleter()); + #ifdef MAPNIK_LOG + MAPNIK_LOG_DEBUG(datasource_cache) + << "datasource_cache: Datasource=" + << ds << " type=" << type; + MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Size=" << params.size(); @@ -115,12 +134,6 @@ datasource_ptr datasource_cache::create(parameters const& params) } #endif - ds = datasource_ptr(create_datasource(params), datasource_deleter()); - - MAPNIK_LOG_DEBUG(datasource_cache) - << "datasource_cache: Datasource=" - << ds << " type=" << type; - return ds; } @@ -132,11 +145,17 @@ std::string datasource_cache::plugin_directories() std::vector datasource_cache::plugin_names() { std::vector names; + +#ifdef MAPNIK_STATIC_PLUGINS + names = get_static_datasource_names(); +#endif + std::map >::const_iterator itr; - for (itr = plugins_.begin();itr!=plugins_.end();++itr) + for (itr = plugins_.begin(); itr != plugins_.end(); ++itr) { names.push_back(itr->first); } + return names; } @@ -145,6 +164,7 @@ void datasource_cache::register_datasources(std::string const& str) #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif + boost::filesystem::path path(str); // TODO - only push unique paths plugin_directories_.push_back(str); @@ -152,24 +172,24 @@ void datasource_cache::register_datasources(std::string const& str) if (exists(path) && is_directory(path)) { - for (boost::filesystem::directory_iterator itr(path);itr!=end_itr;++itr ) + for (boost::filesystem::directory_iterator itr(path); itr != end_itr; ++itr ) { #if (BOOST_FILESYSTEM_VERSION == 3) - if (!is_directory( *itr ) && is_input_plugin(itr->path().filename().string())) + if (! is_directory(*itr) && is_input_plugin(itr->path().filename().string())) #else // v2 - if (!is_directory( *itr ) && is_input_plugin(itr->path().leaf())) + if (! is_directory(*itr) && is_input_plugin(itr->path().leaf())) +#endif + { +#if (BOOST_FILESYSTEM_VERSION == 3) + if (register_datasource(itr->path().string())) +#else // v2 + if (register_datasource(itr->string())) #endif { -#if (BOOST_FILESYSTEM_VERSION == 3) - if (register_datasource(itr->path().string())) -#else // v2 - if (register_datasource(itr->string())) -#endif - { - registered_ = true; - } + registered_ = true; } + } } } } @@ -206,9 +226,9 @@ bool datasource_cache::register_datasource(std::string const& filename) } catch (std::exception const& ex) { - MAPNIK_LOG_ERROR(datasource_cache) - << "Exception caught while loading plugin library: " - << filename << " (" << ex.what() << ")"; + MAPNIK_LOG_ERROR(datasource_cache) + << "Exception caught while loading plugin library: " + << filename << " (" << ex.what() << ")"; } return success; } diff --git a/src/datasource_cache_static.cpp b/src/datasource_cache_static.cpp new file mode 100644 index 000000000..02ee005e5 --- /dev/null +++ b/src/datasource_cache_static.cpp @@ -0,0 +1,171 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include + +#ifdef MAPNIK_STATIC_PLUGINS +#include + +// boost +#include +#include +#include +#endif + +// stl +#include + +// static plugin linkage +#ifdef MAPNIK_STATIC_PLUGINS + #if defined(MAPNIK_STATIC_PLUGIN_CSV) + #include "plugins/input/csv/csv_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_GDAL) + #include "plugins/input/gdal/gdal_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_GEOJSON) + #include "plugins/input/geojson/geojson_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_GEOS) + #include "plugins/input/geos/geos_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_KISMET) + #include "plugins/input/kismet/kismet_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_OCCI) + #include "plugins/input/occi/occi_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_OGR) + #include "plugins/input/ogr/ogr_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_OSM) + #include "plugins/input/osm/osm_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_POSTGIS) + #include "plugins/input/postgis/postgis_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_PYTHON) + #include "plugins/input/python/python_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_RASTER) + #include "plugins/input/raster/raster_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_RASTERLITE) + #include "plugins/input/rasterlite/rasterlite_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_SHAPE) + #include "plugins/input/shape/shape_datasource.hpp" + #endif + #if defined(MAPNIK_STATIC_PLUGIN_SQLITE) + #include "plugins/input/sqlite/sqlite_datasource.hpp" + #endif +#endif + +namespace mapnik { + +#ifdef MAPNIK_STATIC_PLUGINS +template +datasource_ptr ds_generator(parameters const& params) +{ + return boost::make_shared(params); +} + +typedef datasource_ptr (*ds_generator_ptr)(parameters const& params); +typedef boost::unordered::unordered_map datasource_map; + +static datasource_map ds_map = boost::assign::map_list_of + #if defined(MAPNIK_STATIC_PLUGIN_CSV) + (std::string("csv"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_GDAL) + (std::string("gdal"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_GEOJSON) + (std::string("geojson"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_OCCI) + (std::string("occi"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_OGR) + (std::string("ogr"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_OSM) + (std::string("osm"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_POSTGIS) + (std::string("postgis"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_PYTHON) + (std::string("python"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_RASTER) + (std::string("raster"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_RASTERLITE) + (std::string("rasterlite"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_SHAPE) + (std::string("shape"), &ds_generator) + #endif + #if defined(MAPNIK_STATIC_PLUGIN_SQLITE) + (std::string("sqlite"), &ds_generator) + #endif +; +#endif + +datasource_ptr create_static_datasource(parameters const& params) +{ + datasource_ptr ds; + +#ifdef MAPNIK_STATIC_PLUGINS + boost::optional type = params.get("type"); + + datasource_map::iterator it = ds_map.find(*type); + + if (it != ds_map.end()) + { + ds = it->second(params); + } +#endif + + return ds; +} + +std::vector get_static_datasource_names() +{ + std::vector names; + +#ifdef MAPNIK_STATIC_PLUGINS + datasource_map::iterator it = ds_map.begin(); + while (it != ds_map.end()) + { + names.push_back(it->first); + + it++; + } +#endif + + return names; +} + +} diff --git a/src/expression_grammar.cpp b/src/expression_grammar.cpp index 0894be1c3..294996361 100644 --- a/src/expression_grammar.cpp +++ b/src/expression_grammar.cpp @@ -21,170 +21,14 @@ *****************************************************************************/ // mapnik -#include -#include -#include -#include +#include -// boost -#include -#include -#include -#include - -// fwd declare -namespace mapnik { - struct attribute; - struct geometry_type_attribute; -} +// stl +#include 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 - -} - template struct mapnik::expression_grammar; } diff --git a/src/feature_type_style.cpp b/src/feature_type_style.cpp index f041b714f..f850a86f8 100644 --- a/src/feature_type_style.cpp +++ b/src/feature_type_style.cpp @@ -22,6 +22,7 @@ #include #include +#include // boost #include diff --git a/src/gamma_method.cpp b/src/gamma_method.cpp index 4a7fad31f..f1adf99e2 100644 --- a/src/gamma_method.cpp +++ b/src/gamma_method.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include namespace mapnik { diff --git a/src/gradient.cpp b/src/gradient.cpp index 3af55050b..41612833b 100644 --- a/src/gradient.cpp +++ b/src/gradient.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include +#include namespace mapnik { diff --git a/src/json/feature_grammar.cpp b/src/json/feature_grammar.cpp index aa83162bc..2930490be 100644 --- a/src/json/feature_grammar.cpp +++ b/src/json/feature_grammar.cpp @@ -134,15 +134,18 @@ feature_grammar::feature_grammar(mapnik::transcoder const& attribute_value %= number | string_ ; + feature.name("Feature"); + properties.name("Properties"); + attributes.name("Attributes"); on_error ( feature , std::clog << phoenix::val("Error! Expecting ") - << _4 // what failed? + << _4 // what failed? << phoenix::val(" here: \"") - << construct(_3, _2) // iterators to error-pos, end + << where_message_(_3, _2, 16) // where? 16 is max chars to output << phoenix::val("\"") << std::endl ); diff --git a/src/json/geometry_grammar.cpp b/src/json/geometry_grammar.cpp index 84700633b..797ef79f2 100644 --- a/src/json/geometry_grammar.cpp +++ b/src/json/geometry_grammar.cpp @@ -144,15 +144,20 @@ geometry_grammar::geometry_grammar() // points points = lit('[')[_a = SEG_MOVETO] > -(point (_a,_r1) % lit(',')[_a = SEG_LINETO]) > lit(']'); + // give some rules names + geometry.name("Geometry"); + geometry_collection.name("GeometryCollection"); + geometry_dispatch.name("Geometry dispatch"); + coordinates.name("Coordinates"); // error handler on_error ( geometry , std::clog << boost::phoenix::val("Error! Expecting ") - << _4 // what failed? + << _4 // what failed? << boost::phoenix::val(" here: \"") - << construct(_3, _2) // iterators to error-pos, end + << where_message_(_3, _2, 16) // max 16 chars << boost::phoenix::val("\"") << std::endl ); diff --git a/src/load_map.cpp b/src/load_map.cpp index a813e2d72..5b5698ab6 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -1531,8 +1531,10 @@ void map_parser::parse_raster_symbolizer(rule & rule, xml_node const & sym) void map_parser::parse_debug_symbolizer(rule & rule, xml_node const & sym) { debug_symbolizer symbol; - parse_symbolizer_base(symbol, sym); + debug_symbolizer_mode_e mode = + sym.get_attr("mode", DEBUG_SYM_MODE_COLLISION); + symbol.set_mode(mode); rule.append(symbol); } diff --git a/src/marker.cpp b/src/marker.cpp index b87d80559..557f8fb73 100644 --- a/src/marker.cpp +++ b/src/marker.cpp @@ -132,7 +132,7 @@ double marker::width() const if (is_bitmap()) return (*bitmap_data_)->width(); else if (is_vector()) - return (*vector_data_)->width(); + return (*vector_data_)->bounding_box().width(); return 0; } diff --git a/src/markers_symbolizer.cpp b/src/markers_symbolizer.cpp index 0bb371cb1..6c48effd2 100644 --- a/src/markers_symbolizer.cpp +++ b/src/markers_symbolizer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace mapnik { diff --git a/src/polygon_pattern_symbolizer.cpp b/src/polygon_pattern_symbolizer.cpp index 4a2e60c31..67449890e 100644 --- a/src/polygon_pattern_symbolizer.cpp +++ b/src/polygon_pattern_symbolizer.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include namespace mapnik { diff --git a/src/raster_colorizer.cpp b/src/raster_colorizer.cpp index 25cacf679..fbacb1212 100644 --- a/src/raster_colorizer.cpp +++ b/src/raster_colorizer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include // stl #include diff --git a/src/stroke.cpp b/src/stroke.cpp index acaf6c93b..deb4ce625 100644 --- a/src/stroke.cpp +++ b/src/stroke.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include +#include namespace mapnik { diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index a62c42e24..6d13d0c21 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -26,6 +26,10 @@ // boost #include #include +// iostreams +#include +#include +#include extern "C" { @@ -35,12 +39,75 @@ extern "C" namespace mapnik { -using std::min; -using std::max; +namespace impl { +static toff_t tiff_seek_proc(thandle_t fd, toff_t off, int whence) +{ + std::istream* in = reinterpret_cast(fd); + + switch(whence) + { + case SEEK_SET: + in->seekg(off, std::ios_base::beg); + break; + case SEEK_CUR: + in->seekg(off, std::ios_base::cur); + break; + case SEEK_END: + in->seekg(off, std::ios_base::end); + break; + } + return static_cast(in->tellg()); +} + +static int tiff_close_proc(thandle_t fd) +{ + return 0; +} + +static toff_t tiff_size_proc(thandle_t fd) +{ + std::istream* in = reinterpret_cast(fd); + std::ios::pos_type pos = in->tellg(); + in->seekg(0, std::ios::end); + std::ios::pos_type len = in->tellg(); + in->seekg(pos); + return static_cast(len); +} + +static tsize_t tiff_read_proc(thandle_t fd, tdata_t buf, tsize_t size) +{ + std::istream * in = reinterpret_cast(fd); + std::streamsize request_size = size; + if (static_cast(request_size) != size) + return static_cast(-1); + in->read(reinterpret_cast(buf), request_size); + return static_cast(in->gcount()); +} + +static tsize_t tiff_write_proc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return 0; +} + +static void tiff_unmap_proc(thandle_t fd, tdata_t base, toff_t size) +{ +} + +static int tiff_map_proc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return 0; +} + +} + +template class tiff_reader : public image_reader { typedef boost::shared_ptr tiff_ptr; + typedef T source_type; + typedef boost::iostreams::stream input_stream; + struct tiff_closer { void operator() (TIFF * tif) @@ -53,10 +120,11 @@ class tiff_reader : public image_reader }; private: - std::string file_name_; + source_type source_; + input_stream stream_; int read_method_; - unsigned width_; - unsigned height_; + std::size_t width_; + std::size_t height_; int rows_per_strip_; int tile_width_; int tile_height_; @@ -69,6 +137,7 @@ public: tiled }; explicit tiff_reader(std::string const& file_name); + tiff_reader(char const* data, std::size_t size); virtual ~tiff_reader(); unsigned width() const; unsigned height() const; @@ -81,22 +150,32 @@ private: void read_generic(unsigned x,unsigned y,image_data_32& image); void read_stripped(unsigned x,unsigned y,image_data_32& image); void read_tiled(unsigned x,unsigned y,image_data_32& image); - TIFF* load_if_exists(std::string const& filename); + TIFF* open(std::istream & input); static void on_error(const char* /*module*/, const char* fmt, va_list argptr); }; namespace { + image_reader* create_tiff_reader(std::string const& file) { - return new tiff_reader(file); + return new tiff_reader(file); +} + +image_reader* create_tiff_reader2(char const * data, std::size_t size) +{ + return new tiff_reader(data, size); } const bool registered = register_image_reader("tiff",create_tiff_reader); +const bool registered2 = register_image_reader("tiff", create_tiff_reader2); + } -tiff_reader::tiff_reader(std::string const& file_name) - : file_name_(file_name), +template +tiff_reader::tiff_reader(std::string const& file_name) + : source_(file_name, std::ios_base::in | std::ios_base::binary), + stream_(source_), read_method_(generic), width_(0), height_(0), @@ -105,25 +184,48 @@ tiff_reader::tiff_reader(std::string const& file_name) tile_height_(0), premultiplied_alpha_(false) { + if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ file_name); init(); } -void tiff_reader::on_error(const char* /*module*/, const char* fmt, va_list argptr) +template +tiff_reader::tiff_reader(char const* data, std::size_t size) + : source_(data, size), + stream_(source_), + read_method_(generic), + width_(0), + height_(0), + rows_per_strip_(0), + tile_width_(0), + tile_height_(0), + premultiplied_alpha_(false) +{ + if (!stream_) throw image_reader_exception("TIFF reader: cannot open image stream "); + stream_.seekg(0, std::ios::beg); + init(); +} + +template +void tiff_reader::on_error(const char* /*module*/, const char* fmt, va_list argptr) { char msg[10240]; vsprintf(msg, fmt, argptr); throw image_reader_exception(msg); } -void tiff_reader::init() +template +void tiff_reader::init() { TIFFSetWarningHandler(0); // Note - we intentially set the error handling to null // when opening the image for the first time to avoid // leaking in TiffOpen: https://github.com/mapnik/mapnik/issues/1783 TIFFSetErrorHandler(0); - TIFF* tif = load_if_exists(file_name_); - if (!tif) throw image_reader_exception( std::string("Can't load tiff file: '") + file_name_ + "'"); + + TIFF* tif = open(stream_); + + if (!tif) throw image_reader_exception("Can't open tiff file"); + TIFFSetErrorHandler(on_error); char msg[1024]; @@ -159,29 +261,31 @@ void tiff_reader::init() } } - -tiff_reader::~tiff_reader() +template +tiff_reader::~tiff_reader() { } - -unsigned tiff_reader::width() const +template +unsigned tiff_reader::width() const { return width_; } - -unsigned tiff_reader::height() const +template +unsigned tiff_reader::height() const { return height_; } -bool tiff_reader::premultiplied_alpha() const +template +bool tiff_reader::premultiplied_alpha() const { return premultiplied_alpha_; } -void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) +template +void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) { if (read_method_==stripped) { @@ -197,20 +301,20 @@ void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) } } - -void tiff_reader::read_generic(unsigned /*x*/,unsigned /*y*/,image_data_32& /*image*/) +template +void tiff_reader::read_generic(unsigned /*x*/,unsigned /*y*/,image_data_32& /*image*/) { - TIFF* tif = load_if_exists(file_name_); + TIFF* tif = open(stream_); if (tif) { MAPNIK_LOG_DEBUG(tiff_reader) << "tiff_reader: TODO - tiff is not stripped or tiled"; } } - -void tiff_reader::read_tiled(unsigned x0,unsigned y0,image_data_32& image) +template +void tiff_reader::read_tiled(unsigned x0,unsigned y0,image_data_32& image) { - TIFF* tif = load_if_exists(file_name_); + TIFF* tif = open(stream_); if (tif) { uint32* buf = (uint32*)_TIFFmalloc(tile_width_*tile_height_*sizeof(uint32)); @@ -226,8 +330,8 @@ void tiff_reader::read_tiled(unsigned x0,unsigned y0,image_data_32& image) for (int y=start_y;y=n0;--n) { @@ -251,10 +355,10 @@ void tiff_reader::read_tiled(unsigned x0,unsigned y0,image_data_32& image) } } - -void tiff_reader::read_stripped(unsigned x0,unsigned y0,image_data_32& image) +template +void tiff_reader::read_stripped(unsigned x0,unsigned y0,image_data_32& image) { - TIFF* tif = load_if_exists(file_name_); + TIFF* tif = open(stream_); if (tif) { uint32* buf = (uint32*)_TIFFmalloc(width_*rows_per_strip_*sizeof(uint32)); @@ -268,12 +372,12 @@ void tiff_reader::read_stripped(unsigned x0,unsigned y0,image_data_32& image) int row,tx0,tx1,ty0,ty1; tx0=x0; - tx1=min(width+x0,(unsigned)width_); + tx1=std::min(width+x0,(unsigned)width_); for (unsigned y=start_y; y < end_y; y+=rows_per_strip_) { - ty0 = max(y0,y)-y; - ty1 = min(height+y0,y+rows_per_strip_)-y; + ty0 = std::max(y0,y)-y; + ty1 = std::min(height+y0,y+rows_per_strip_)-y; if (!TIFFReadRGBAStrip(tif,y,buf)) break; @@ -291,16 +395,20 @@ void tiff_reader::read_stripped(unsigned x0,unsigned y0,image_data_32& image) } } -TIFF* tiff_reader::load_if_exists(std::string const& filename) +template +TIFF* tiff_reader::open(std::istream & input) { if (!tif_) { - boost::filesystem::path path(file_name_); - if (boost::filesystem::is_regular(path)) // exists and regular file - { - // File path is a full file path and does exist - tif_ = tiff_ptr(TIFFOpen(filename.c_str(), "rb"), tiff_closer()); - } + tif_ = tiff_ptr(TIFFClientOpen("tiff_input_stream", "rm", + reinterpret_cast(&input), + impl::tiff_read_proc, + impl::tiff_write_proc, + impl::tiff_seek_proc, + impl::tiff_close_proc, + impl::tiff_size_proc, + impl::tiff_map_proc, + impl::tiff_unmap_proc), tiff_closer()); } return tif_.get(); } diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 000000000..a10102889 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,61 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifdef _WINDOWS +// windows specific methods for UTF8 from/to UTF16 +#include +#include +#include + +#include + +namespace mapnik { + +std::string utf16_to_utf8(std::wstring const& wstr) +{ + std::string str; + int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, 0, 0, 0, 0); + if(size > 0) + { + std::vector buffer(size); + WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &buffer[0], size, 0, 0); + str.assign(buffer.begin(), buffer.end() - 1); + } + return str; +} + +std::wstring utf8_to_utf16 (std::string const& str) +{ + std::wstring wstr; + int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, 0, 0); + if (size > 0) + { + std::vector buffer(size); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &buffer[0], size); + wstr.assign(buffer.begin(), buffer.end() - 1); + } + return wstr; +} + +} // namespace mapnik + +#endif // _WINDOWS diff --git a/src/well_known_srs.cpp b/src/well_known_srs.cpp index a6e8d0ae6..c3163df0d 100644 --- a/src/well_known_srs.cpp +++ b/src/well_known_srs.cpp @@ -23,6 +23,7 @@ // mapnik #include #include +#include // boost #include diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index b9c15d407..53cea607e 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -405,6 +405,7 @@ compile_get_opt_attr(expression_ptr); compile_get_attr(std::string); compile_get_attr(filter_mode_e); compile_get_attr(point_placement_e); +compile_get_attr(debug_symbolizer_mode_e); compile_get_attr(marker_placement_e); compile_get_attr(marker_multi_policy_e); compile_get_attr(pattern_alignment_e); diff --git a/tests/cpp_tests/data/cases.txt b/tests/cpp_tests/data/cases.txt index d161516d2..6ba17a96d 100644 --- a/tests/cpp_tests/data/cases.txt +++ b/tests/cpp_tests/data/cases.txt @@ -3,5 +3,7 @@ # SEG_END=0 SEG_MOVETO = 1 SEG_LINETO = 2 SEG_CLOSE = (0x40 | 0x0f) 50,50,150,150;0 0 1,200 200 2;50 50 1,150 150 2 50,50,150,150;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2 +# points are dropped by line clipper +50,50,150,150;75 75 1; # TODO - should the close path be kept after clipping? # 50,50,150,150;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2,0 0 79;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2 diff --git a/tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png b/tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png index b09606829..cb8e47826 100644 Binary files a/tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png and b/tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png differ diff --git a/tests/data/good_maps/line_symbolizer.xml b/tests/data/good_maps/line_symbolizer.xml index d58791861..7a4944aea 100644 --- a/tests/data/good_maps/line_symbolizer.xml +++ b/tests/data/good_maps/line_symbolizer.xml @@ -6,7 +6,7 @@ - + diff --git a/demo/data/test/charplacement.dbf b/tests/data/shp/charplacement.dbf similarity index 100% rename from demo/data/test/charplacement.dbf rename to tests/data/shp/charplacement.dbf diff --git a/demo/data/test/charplacement.shp b/tests/data/shp/charplacement.shp similarity index 100% rename from demo/data/test/charplacement.shp rename to tests/data/shp/charplacement.shp diff --git a/demo/data/test/charplacement.shx b/tests/data/shp/charplacement.shx similarity index 100% rename from demo/data/test/charplacement.shx rename to tests/data/shp/charplacement.shx diff --git a/demo/data/test/displacement.dbf b/tests/data/shp/displacement.dbf similarity index 100% rename from demo/data/test/displacement.dbf rename to tests/data/shp/displacement.dbf diff --git a/demo/data/test/displacement.shp b/tests/data/shp/displacement.shp similarity index 100% rename from demo/data/test/displacement.shp rename to tests/data/shp/displacement.shp diff --git a/demo/data/test/displacement.shx b/tests/data/shp/displacement.shx similarity index 100% rename from demo/data/test/displacement.shx rename to tests/data/shp/displacement.shx diff --git a/demo/data/test/overlap.dbf b/tests/data/shp/overlap.dbf similarity index 100% rename from demo/data/test/overlap.dbf rename to tests/data/shp/overlap.dbf diff --git a/demo/data/test/overlap.shp b/tests/data/shp/overlap.shp similarity index 100% rename from demo/data/test/overlap.shp rename to tests/data/shp/overlap.shp diff --git a/demo/data/test/overlap.shx b/tests/data/shp/overlap.shx similarity index 100% rename from demo/data/test/overlap.shx rename to tests/data/shp/overlap.shx diff --git a/demo/data/test/textspacing.dbf b/tests/data/shp/textspacing.dbf similarity index 100% rename from demo/data/test/textspacing.dbf rename to tests/data/shp/textspacing.dbf diff --git a/demo/data/test/textspacing.shp b/tests/data/shp/textspacing.shp similarity index 100% rename from demo/data/test/textspacing.shp rename to tests/data/shp/textspacing.shp diff --git a/demo/data/test/textspacing.shx b/tests/data/shp/textspacing.shx similarity index 100% rename from demo/data/test/textspacing.shx rename to tests/data/shp/textspacing.shx diff --git a/tests/python_tests/box2d_test.py b/tests/python_tests/box2d_test.py index ef7a2f95b..8fa9b20b5 100644 --- a/tests/python_tests/box2d_test.py +++ b/tests/python_tests/box2d_test.py @@ -100,8 +100,34 @@ def test_envelope_static_init(): eq_(c.y, 150) def test_envelope_multiplication(): + # no width then no impact of multiplication + a = mapnik.Box2d(100, 100, 100, 100) + a *= 5 + eq_(a.minx,100) + eq_(a.miny,100) + eq_(a.maxx,100) + eq_(a.maxy,100) + + a = mapnik.Box2d(100.0, 100.0, 100.0, 100.0) + a *= 5 + eq_(a.minx,100) + eq_(a.miny,100) + eq_(a.maxx,100) + eq_(a.maxy,100) + + a = mapnik.Box2d(100.0, 100.0, 100.001, 100.001) + a *= 5 + assert_almost_equal(a.minx, 99.9979, places=3) + assert_almost_equal(a.miny, 99.9979, places=3) + assert_almost_equal(a.maxx, 100.0030, places=3) + assert_almost_equal(a.maxy, 100.0030, places=3) + e = mapnik.Box2d(100, 100, 200, 200) e *= 2 + eq_(e.minx,50) + eq_(e.miny,50) + eq_(e.maxx,250) + eq_(e.maxy,250) assert_true(e.contains(50, 50)) assert_true(e.contains(50, 250)) @@ -148,5 +174,4 @@ def test_envelope_clipping(): eq_(e1,e2) if __name__ == "__main__": - setup() [eval(run)() for run in dir() if 'test_' in run] diff --git a/tests/python_tests/extra_map_props_test.py b/tests/python_tests/extra_map_props_test.py index 06ffb97c9..fd5f2606e 100644 --- a/tests/python_tests/extra_map_props_test.py +++ b/tests/python_tests/extra_map_props_test.py @@ -3,11 +3,7 @@ from nose.tools import * from utilities import execution_path -from Queue import Queue -import threading - import os, mapnik -import sqlite3 def setup(): # All of the paths used are relative, if we run the tests diff --git a/tests/python_tests/image_test.py b/tests/python_tests/image_test.py new file mode 100644 index 000000000..9a764a2a4 --- /dev/null +++ b/tests/python_tests/image_test.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import os, mapnik +from timeit import Timer, time +from nose.tools import * +from utilities import execution_path + +def setup(): + # All of the paths used are relative, if we run the tests + # from another directory we need to chdir() + os.chdir(execution_path('.')) + +def test_tiff_round_trip(): + filepath = '/tmp/mapnik-tiff-io.tiff' + im = mapnik.Image(255,267) + im.background = mapnik.Color('rgba(1,2,3,.5)') + im.save(filepath,'tiff') + im2 = mapnik.Image.open(filepath) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff')),len(im2.tostring('tiff'))) + +def test_jpeg_round_trip(): + filepath = '/tmp/mapnik-jpeg-io.jpeg' + im = mapnik.Image(255,267) + im.background = mapnik.Color('rgba(1,2,3,.5)') + im.save(filepath,'jpeg') + im2 = mapnik.Image.open(filepath) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('jpeg')),len(im2.tostring('jpeg'))) + +def test_png_round_trip(): + filepath = '/tmp/mapnik-png-io.png' + im = mapnik.Image(255,267) + im.background = mapnik.Color('rgba(1,2,3,.5)') + im.save(filepath,'png') + im2 = mapnik.Image.open(filepath) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('png')),len(im2.tostring('png'))) + eq_(len(im.tostring('png8')),len(im2.tostring('png8'))) + +def test_image_open_from_string(): + filepath = '../data/images/dummy.png' + im1 = mapnik.Image.open(filepath) + im2 = mapnik.Image.fromstring(open(filepath,'rb').read()) + eq_(im1.width(),im2.width()) + length = len(im1.tostring()) + eq_(length,len(im2.tostring())) + eq_(len(mapnik.Image.fromstring(im1.tostring('png')).tostring()),length) + eq_(len(mapnik.Image.fromstring(im1.tostring('jpeg')).tostring()),length) + eq_(len(mapnik.Image.frombuffer(buffer(im1.tostring('png'))).tostring()),length) + eq_(len(mapnik.Image.frombuffer(buffer(im1.tostring('jpeg'))).tostring()),length) + + # TODO - https://github.com/mapnik/mapnik/issues/1831 + eq_(len(mapnik.Image.fromstring(im1.tostring('tiff')).tostring()),length) + eq_(len(mapnik.Image.frombuffer(buffer(im1.tostring('tiff'))).tostring()),length) + +if __name__ == "__main__": + setup() + [eval(run)() for run in dir() if 'test_' in run] diff --git a/tests/python_tests/images/support/char_placement.png b/tests/python_tests/images/support/char_placement.png new file mode 100644 index 000000000..7abcb6f20 Binary files /dev/null and b/tests/python_tests/images/support/char_placement.png differ diff --git a/tests/python_tests/images/support/displacement.png b/tests/python_tests/images/support/displacement.png new file mode 100644 index 000000000..644aeb6a5 Binary files /dev/null and b/tests/python_tests/images/support/displacement.png differ diff --git a/tests/python_tests/images/support/overlap.png b/tests/python_tests/images/support/overlap.png new file mode 100644 index 000000000..56abfbaa4 Binary files /dev/null and b/tests/python_tests/images/support/overlap.png differ diff --git a/tests/python_tests/images/support/spacing.png b/tests/python_tests/images/support/spacing.png new file mode 100644 index 000000000..8d6bb4026 Binary files /dev/null and b/tests/python_tests/images/support/spacing.png differ diff --git a/tests/python_tests/mapnik_config_test.py b/tests/python_tests/mapnik_config_test.py index b791cffc4..03a5819b5 100644 --- a/tests/python_tests/mapnik_config_test.py +++ b/tests/python_tests/mapnik_config_test.py @@ -33,6 +33,7 @@ def test_mapnik_config_valid_opts(): '--help', '-v', '--version', + '--version-number', '--git-revision', '--git-describe', '--fonts', @@ -46,7 +47,9 @@ def test_mapnik_config_valid_opts(): '--includes', '--dep-includes', '--cxxflags', - '--cflags' + '--cflags', + '--all-flags', + '--cxx' ] for item in valid_args: cmd = 'mapnik-config ' + item diff --git a/tests/python_tests/object_test.py b/tests/python_tests/object_test.py index 0a83ddc95..c18d07e8a 100644 --- a/tests/python_tests/object_test.py +++ b/tests/python_tests/object_test.py @@ -14,6 +14,10 @@ def setup(): # from another directory we need to chdir() os.chdir(execution_path('.')) +def test_debug_symbolizer(): + s = mapnik.DebugSymbolizer() + eq_(s.mode,mapnik.debug_symbolizer_mode.collision) + def test_raster_symbolizer(): s = mapnik.RasterSymbolizer() eq_(s.comp_op,mapnik.CompositeOp.src_over) # note: mode is deprecated diff --git a/tests/python_tests/png_encoding_test.py b/tests/python_tests/png_encoding_test.py index fc571ba28..1cded9073 100644 --- a/tests/python_tests/png_encoding_test.py +++ b/tests/python_tests/png_encoding_test.py @@ -131,6 +131,7 @@ def test_transparency_levels_aerial(): im_in = mapnik.Image.open('./images/support/transparency/aerial_rgb.png') eq_(len(im.tostring('png')),len(im_in.tostring('png'))) eq_(len(im.tostring('png:t=0')),len(im_in.tostring('png:t=0'))) + eq_(len(im.tostring('png:t=0')) == len(im_in.tostring('png')), False) if __name__ == "__main__": diff --git a/tests/visual_tests/data/line-offset.csv b/tests/visual_tests/data/line-offset.csv new file mode 100644 index 000000000..fe557d89f --- /dev/null +++ b/tests/visual_tests/data/line-offset.csv @@ -0,0 +1,9 @@ +wkt,name,nr,ref +"LineString(-5.177724 50.191914,-5.177742 50.191769,-5.17773 50.191624,-5.177689 50.191481,-5.177619 50.191343,-5.177522 50.191212,-5.177398 50.19109,-5.177251 50.190979,-5.177082 50.190882,-5.176895 50.190799,-5.176693 50.190733,-5.176479 50.190685,-5.176257 50.190654,-5.176031 50.190643,-5.175804 50.19065,-5.175581 50.190677,-5.175365 50.190722,-5.17516 50.190784,-5.17497 50.190863,-5.174797 50.190957,-5.174645 50.191065,-5.174516 50.191185,-5.174413 50.191314,-5.174337 50.191451,-5.17429 50.191594,-5.174272 50.191738,-5.174283 50.191884,-5.174324 50.192026,-5.174394 50.192165,-5.174492 50.192296,-5.174615 50.192418,-5.174763 50.192529,-5.174931 50.192626,-5.175118 50.192708,-5.17532 50.192774,-5.175534 50.192823,-5.175756 50.192853,-5.175983 50.192865,-5.176209 50.192857,-5.176433 50.192831,-5.176649 50.192786,-5.176854 50.192724,-5.177044 50.192645,-5.177217 50.19255,-5.177369 50.192442,-5.177498 50.192323,-5.177601 50.192193,-5.177677 50.192056,-5.177724 50.191914)","",,4 +"LineString(-5.182328 50.19193,-5.182346 50.191785,-5.182334 50.19164,-5.182293 50.191497,-5.182223 50.191358,-5.182125 50.191227,-5.182002 50.191105,-5.181854 50.190995,-5.181686 50.190897,-5.181499 50.190815,-5.181297 50.190749,-5.181083 50.1907,-5.180861 50.19067,-5.180634 50.190658,-5.180408 50.190666,-5.180184 50.190692,-5.179968 50.190737,-5.179763 50.190799,-5.179573 50.190878,-5.1794 50.190973,-5.179248 50.191081,-5.179119 50.1912,-5.179016 50.19133,-5.17894 50.191467,-5.178893 50.191609,-5.178875 50.191754,-5.178887 50.191899,-5.178928 50.192042,-5.178998 50.19218,-5.179095 50.192311,-5.179219 50.192433,-5.179366 50.192544,-5.179535 50.192641,-5.179722 50.192724,-5.179924 50.19279,-5.180138 50.192838,-5.18036 50.192869,-5.180586 50.19288,-5.180813 50.192873,-5.181036 50.192846,-5.181252 50.192802,-5.181457 50.192739,-5.181648 50.19266,-5.18182 50.192566,-5.181972 50.192458,-5.182101 50.192338,-5.182204 50.192209,-5.18228 50.192072,-5.182328 50.19193)","",,3 +"LineString(-5.187052 50.191945,-5.187004 50.192087,-5.186928 50.192224,-5.186825 50.192354,-5.186696 50.192473,-5.186544 50.192581,-5.186371 50.192675,-5.186181 50.192755,-5.185976 50.192817,-5.18576 50.192862,-5.185537 50.192888,-5.18531 50.192896,-5.185084 50.192884,-5.184862 50.192854,-5.184648 50.192805,-5.184446 50.192739,-5.184259 50.192657,-5.18409 50.192559,-5.183943 50.192449,-5.183819 50.192327,-5.183722 50.192196,-5.183652 50.192057,-5.183611 50.191914,-5.183599 50.191769,-5.183617 50.191624,-5.183664 50.191482,-5.18374 50.191345,-5.183843 50.191216,-5.183972 50.191096,-5.184124 50.190988,-5.184297 50.190894,-5.184487 50.190815,-5.184692 50.190752,-5.184908 50.190708,-5.185132 50.190681,-5.185358 50.190674,-5.185585 50.190685,-5.185807 50.190716,-5.186021 50.190764,-5.186223 50.19083,-5.18641 50.190913,-5.186578 50.19101,-5.186726 50.191121,-5.186849 50.191243,-5.186947 50.191374,-5.187017 50.191512,-5.187058 50.191655,-5.18707 50.1918,-5.187052 50.191945)","",,2 +"LineString(-5.191775 50.191899,-5.191728 50.192041,-5.191652 50.192178,-5.191549 50.192307,-5.19142 50.192427,-5.191268 50.192535,-5.191095 50.192629,-5.190905 50.192708,-5.1907 50.192771,-5.190484 50.192816,-5.190261 50.192842,-5.190034 50.192849,-5.189808 50.192838,-5.189586 50.192808,-5.189372 50.192759,-5.18917 50.192693,-5.188983 50.19261,-5.188814 50.192513,-5.188667 50.192402,-5.188543 50.192281,-5.188446 50.192149,-5.188376 50.192011,-5.188334 50.191868,-5.188323 50.191723,-5.188341 50.191578,-5.188388 50.191436,-5.188464 50.191299,-5.188567 50.19117,-5.188696 50.19105,-5.188848 50.190942,-5.189021 50.190848,-5.189211 50.190769,-5.189416 50.190706,-5.189632 50.190661,-5.189856 50.190635,-5.190082 50.190627,-5.190309 50.190639,-5.190531 50.190669,-5.190744 50.190718,-5.190947 50.190784,-5.191134 50.190866,-5.191302 50.190964,-5.19145 50.191074,-5.191573 50.191196,-5.191671 50.191328,-5.191741 50.191466,-5.191782 50.191609,-5.191793 50.191754,-5.191775 50.191899)","",,1 +"LineString(-5.177742 50.191769,-5.174272 50.191738)","CCW, dy > 0",, +"LineString(-5.182346 50.191785,-5.178875 50.191754)","CCW, dy < 0",, +"LineString(-5.18707 50.1918,-5.183599 50.191769)","CW, dy > 0",, +"LineString(-5.191793 50.191754,-5.188323 50.191723)","CW, dy < 0",, \ No newline at end of file diff --git a/tests/visual_tests/data/line-offset.osm b/tests/visual_tests/data/line-offset.osm deleted file mode 100644 index 9a568dc30..000000000 --- a/tests/visual_tests/data/line-offset.osm +++ /dev/null @@ -1,435 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/visual_tests/data/lines.csv b/tests/visual_tests/data/lines.csv new file mode 100644 index 000000000..f67763eba --- /dev/null +++ b/tests/visual_tests/data/lines.csv @@ -0,0 +1,10 @@ +wkt,name,nr +"LineString(0.194483 -0.117354,0.23691 -0.137246,0.252846 -0.181313,0.232953 -0.223741,0.188886 -0.239676,0.146458 -0.219784,0.130523 -0.175717,0.150415 -0.133289,0.194483 -0.117354)","Circle",6 +"LineString(0.747335 -0.107159,0.789763 -0.127051,0.805698 -0.171118,0.785806 -0.213546,0.741739 -0.229481,0.699311 -0.209589,0.683376 -0.165522,0.703268 -0.123094,0.747335 -0.107159)","Circle with long name",7 +"LineString(0.346487 -0.240215,0.535306 -0.240215)","Short line with long name",5 +"LineString(0.347059 -0.122112,0.535878 -0.122112)","Short line",4 +"LineString(0 0,0.9 0)","Rendered @ integer pos. ABCDEFGHIJKLMNOPQRSTUVWXYZ",3 +"LineString(0.002268 0.073178,0.902268 0.073178)","Long line with long name",2 +"LineString(0.003411 0.172529,0.103411 0.172529,0.203411 0.172529,0.303411 0.172529,0.403411 0.172529,0.503411 0.172529,0.603411 0.172529,0.703411 0.172529,0.803411 0.172529,0.903411 0.172529)","Long line with long name and many points",1 +"LineString(0.002841 0.250458,0.902841 0.250458)","Short name",8 +"LineString(0 -0.051,0.9 -0.051)","Rendered @ non-integer p. ABCDEFGHIJKLMNOPQRSTUVWXYZ",9 diff --git a/tests/visual_tests/data/lines.osm b/tests/visual_tests/data/lines.osm deleted file mode 100644 index e04b6fb14..000000000 --- a/tests/visual_tests/data/lines.osm +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/visual_tests/data/points.csv b/tests/visual_tests/data/points.csv new file mode 100644 index 000000000..f895b612f --- /dev/null +++ b/tests/visual_tests/data/points.csv @@ -0,0 +1,11 @@ +lat,long,name,nr +0,0,Test one,1 +0,0.1,Test two,2 +0,0.2,Test three,3 +0,0.3,Test four,4 +0,0.4,Test five,5 +0,0.5,Test six,6 +0,0.6,Test seven,7 +0,0.7,Test eight,8 +0,0.8,Test nine,9 +0,0.9,Test ten,10 \ No newline at end of file diff --git a/tests/visual_tests/data/points.osm b/tests/visual_tests/data/points.osm deleted file mode 100644 index 086f0a479..000000000 --- a/tests/visual_tests/data/points.osm +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/visual_tests/grids/expressionformat-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/expressionformat-500-100-1.0-grid-reference.json index dfe52da9e..c5fce6529 100644 --- a/tests/visual_tests/grids/expressionformat-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/expressionformat-500-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/formatting-1-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/formatting-1-500-100-1.0-grid-reference.json index 087556523..2725f745d 100644 --- a/tests/visual_tests/grids/formatting-1-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/formatting-1-500-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/formatting-2-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/formatting-2-500-100-1.0-grid-reference.json index 087556523..2725f745d 100644 --- a/tests/visual_tests/grids/formatting-2-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/formatting-2-500-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/formatting-3-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/formatting-3-500-100-1.0-grid-reference.json index 748a69aa6..ef9f0089b 100644 --- a/tests/visual_tests/grids/formatting-3-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/formatting-3-500-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/formatting-4-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/formatting-4-500-100-1.0-grid-reference.json index db8079a13..8bddd0118 100644 --- a/tests/visual_tests/grids/formatting-4-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/formatting-4-500-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/jalign-auto-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/jalign-auto-200-200-1.0-grid-reference.json index 77a9a0ad3..0a2e7e41a 100644 --- a/tests/visual_tests/grids/jalign-auto-200-200-1.0-grid-reference.json +++ b/tests/visual_tests/grids/jalign-auto-200-200-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/line-offset-900-250-1.0-grid-reference.json b/tests/visual_tests/grids/line-offset-900-250-1.0-grid-reference.json index c0742a097..db3484bdf 100644 --- a/tests/visual_tests/grids/line-offset-900-250-1.0-grid-reference.json +++ b/tests/visual_tests/grids/line-offset-900-250-1.0-grid-reference.json @@ -1,14 +1,14 @@ { "keys": [ "", - "-350", - "-400", - "-461", - "-302", - "-112", - "-115", - "-117", - "-118" + "3", + "2", + "1", + "4", + "8", + "7", + "6", + "5" ], "data": {}, "grid": [ @@ -40,14 +40,14 @@ " % %%%%%%%%%% %%%%%%%% %% !!!! ! !!! #### # ### $ $$$$$$$$$ $$$$$$$ $$ $ ", " % %%%%%%%%%%%%%%%%%% %% % !!! ! ! #### # # $ $$$$$$$$$$ $ $$$$$$$$$ $ ", " % %%% %%% %%% %%% % !!!!! ! ! ##### # # $$$$$ $$$$$$$ $ ", - " % %%%% %%%%% % !!!!! !!!!! ### # ### $ $$$$ $ ", + " % %%%% %%%%% !!!!! !!!!! ### # ### $ $$$$ $ ", " %%%%% %%%%% % !! !!!!! #### ##### $ $$$$ $ ", " % %%%% %%% % ! ! !!! # ### $ $$$ $ ", " %%%% % % % !!!! # ## $$$ $$$ $ ", " %%%%% %%% ! !! # ## $$$ $ $$ ", " %%%% &&&& & && %%% ''''' '''' '''''''' !!!!! # (((((( (((( ((( ### $$$$ )))))) )) ) )) $$$$$ ", " % % &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ! !! '''''''' '''' ! ! # (((((((((( (((( # $$ $ )))))))))) ))))))))))))))) ", - " % &&&&&&&& &&& %%%% !!!! ' ' ! !!! #### ( ( # ### $$$ ))))))))) ) $$ $ ", + " % &&&&&&&& &&& %%%% !!!! ' ! !!! #### ( ( # ### $$$ ))))))))) ) $$ $ ", " % %%%%% !!! !!! #### # ### $$$ $$$ $ ", " %%% % !!! ! ! !!! ## # ### $$$$ $$$ ", " % % % !!! !!!! ### # ### $$$$ $$$$$ ", @@ -56,7 +56,7 @@ " %%%%%%%% % %%%%% % !!!! ! !!!!!! ### # ###### $ $$$$$ $ $$$$$$$$$ ", " % %%%%%%%%%%%%% %%%%%%%%% % !!!!! ! ! !!! ### # # ## ### $ $$$$$$$$$$$$$$$$ $$$$$ $ ", " % %%%%%% %%%%%%%%%%%% % ! !! ! ! ! ## ## # ## ## $$ $$$ $$$$$$$$$$ $ $ ", - " %% %% %%%%%%% %%%% !!!!! !! !!! ! #### ## ## # $$$$$$$$$$$$$$ $$ ", + " %% %% %%%%%%% %%%% !!!!! !!! !!! ! #### ## ## # $ $$$$$$$$$$$$ $$ ", " %%% %%% !!!!!! !!!!!!! !! # ##### ######### ### $$$$$ $$$$$ ", " !!!!! !!! !!!!!!!! ###### ### ######## ", " !! !!!!!!!!!! !!!!!! ## ########## ###### ", diff --git a/tests/visual_tests/grids/lines-1-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/lines-1-200-200-1.0-grid-reference.json index cbab0d249..05e606e8b 100644 --- a/tests/visual_tests/grids/lines-1-200-200-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-1-200-200-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "200", - "206", - "202", - "204" + "8", + "7", + "6", + "5", + "9", + "1", + "4", + "2", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-1-400-400-1.0-grid-reference.json b/tests/visual_tests/grids/lines-1-400-400-1.0-grid-reference.json index 01bba2c59..3859dd6c7 100644 --- a/tests/visual_tests/grids/lines-1-400-400-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-1-400-400-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-1-600-600-1.0-grid-reference.json b/tests/visual_tests/grids/lines-1-600-600-1.0-grid-reference.json index 5d9834d5a..ae13670ff 100644 --- a/tests/visual_tests/grids/lines-1-600-600-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-1-600-600-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-1-800-800-1.0-grid-reference.json b/tests/visual_tests/grids/lines-1-800-800-1.0-grid-reference.json index 8db7d3c07..75c1e0755 100644 --- a/tests/visual_tests/grids/lines-1-800-800-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-1-800-800-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-2-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/lines-2-200-200-1.0-grid-reference.json index 79636ad9b..4b34f29ff 100644 --- a/tests/visual_tests/grids/lines-2-200-200-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-2-200-200-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "200", - "206", - "202", - "204" + "8", + "7", + "6", + "5", + "9", + "1", + "4", + "2", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-2-400-400-1.0-grid-reference.json b/tests/visual_tests/grids/lines-2-400-400-1.0-grid-reference.json index 782c89483..3aa89339a 100644 --- a/tests/visual_tests/grids/lines-2-400-400-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-2-400-400-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-2-600-600-1.0-grid-reference.json b/tests/visual_tests/grids/lines-2-600-600-1.0-grid-reference.json index 7eac49371..6269e3550 100644 --- a/tests/visual_tests/grids/lines-2-600-600-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-2-600-600-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-2-800-800-1.0-grid-reference.json b/tests/visual_tests/grids/lines-2-800-800-1.0-grid-reference.json index 5cfb73770..98a1c1a8c 100644 --- a/tests/visual_tests/grids/lines-2-800-800-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-2-800-800-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-3-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/lines-3-200-200-1.0-grid-reference.json index cbab0d249..05e606e8b 100644 --- a/tests/visual_tests/grids/lines-3-200-200-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-3-200-200-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "200", - "206", - "202", - "204" + "8", + "7", + "6", + "5", + "9", + "1", + "4", + "2", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-3-400-400-1.0-grid-reference.json b/tests/visual_tests/grids/lines-3-400-400-1.0-grid-reference.json index 01bba2c59..3859dd6c7 100644 --- a/tests/visual_tests/grids/lines-3-400-400-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-3-400-400-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-3-600-600-1.0-grid-reference.json b/tests/visual_tests/grids/lines-3-600-600-1.0-grid-reference.json index 11d3e3c47..67b4633c9 100644 --- a/tests/visual_tests/grids/lines-3-600-600-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-3-600-600-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/lines-3-800-800-1.0-grid-reference.json b/tests/visual_tests/grids/lines-3-800-800-1.0-grid-reference.json index 20ded9891..e7bd89e95 100644 --- a/tests/visual_tests/grids/lines-3-800-800-1.0-grid-reference.json +++ b/tests/visual_tests/grids/lines-3-800-800-1.0-grid-reference.json @@ -1,15 +1,15 @@ { "keys": [ "", - "216", - "212", - "210", - "208", - "240", - "202", - "200", - "206", - "204" + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" ], "data": {}, "grid": [ @@ -80,7 +80,7 @@ " #################################################################################################################################################################################### ", " #################################################################################################################################################################################### ", " #################################################################################################################################################################################### ", - " # # # # # # # # ## # # # # # # # # # # # ## # # ", + " # # # # # # # # # ## # # # # # # # # # # # ## # # ", " ", " ", " ", diff --git a/tests/visual_tests/grids/lines-shield-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/lines-shield-200-200-1.0-grid-reference.json new file mode 100644 index 000000000..9fd0cc8c0 --- /dev/null +++ b/tests/visual_tests/grids/lines-shield-200-200-1.0-grid-reference.json @@ -0,0 +1,65 @@ +{ + "keys": [ + "", + "7", + "6", + "5", + "4", + "1", + "2", + "3" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !! !!! !! !!! !! !!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !! !! !! !! !! ", + " ! ! ! ", + " ", + " ", + " ############################################# ", + " ", + " $ $ $ ", + " $$ $$ $$ $$ $$ $$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$ $ $$ $ $$ $ ", + " ", + " ", + " ", + " %% ", + " &&& %%%%%%%%%% ' '' ", + " && & %% '' ' ' ", + " & && '''' ' ", + " & &&&&& '' '' ", + " &&& &&& ' ' ' ", + " & && (( ''' ", + " & (((((((((( ", + " (( ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/lines-shield-400-400-1.0-grid-reference.json b/tests/visual_tests/grids/lines-shield-400-400-1.0-grid-reference.json new file mode 100644 index 000000000..cfac4935e --- /dev/null +++ b/tests/visual_tests/grids/lines-shield-400-400-1.0-grid-reference.json @@ -0,0 +1,117 @@ +{ + "keys": [ + "", + "8", + "7", + "6", + "5", + "9", + "4", + "2", + "1", + "3" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! ! ! ! ! ! ", + " !! !! !! !! !! !! !! !! !! !! !! !! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!! !! !!! !! !!! !! !!! !! !!! !! !!! !! ", + " ", + " ", + " ", + " ", + " # # # # # # ", + " # ## # ## # ## # ## # ## # ## ", + " # ## # ## # ## # ## # ## # ## ", + " ### # ### # ### # ### # ### # ### # ", + " ", + " ", + " ", + " ", + " ", + " ", + " $ $ $ $ $ $ ", + " $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ ", + " $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ ", + " $$$ $$$ $$$ $$$ $$$ $$$ ", + " ", + " ", + " ", + " % % % % % % ", + " %% %% %% %% %% %% %% %% %% %% %% %% ", + " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ", + " % %% % %% % %% % %% % %% % %% ", + " ", + " & & & & & & ", + " & && & && & && & && & && & && ", + " &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ", + " & && & && & && & && & && & && ", + " & & & & & & ", + " ", + " ", + " ", + " '' ' ' (( (((( ( ", + " ))) ))) ''''''''''''''''''' (((( ((( ", + " ))))) ))) '' ' (( ( ", + " )) )) ( ((( ", + " )) ))) ( ( ", + " ( ", + " ) ) ", + " ) ) ( ( ", + " ) (( ", + " ) ) ( (( ", + " )) )) (((( (((( ", + " )))) )))) * (((( (((( ", + " ) ) ) )) ** * ( ", + " ) ) ******************* ", + " ** * ", + " * ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/lines-shield-600-600-1.0-grid-reference.json b/tests/visual_tests/grids/lines-shield-600-600-1.0-grid-reference.json new file mode 100644 index 000000000..a43b5759d --- /dev/null +++ b/tests/visual_tests/grids/lines-shield-600-600-1.0-grid-reference.json @@ -0,0 +1,167 @@ +{ + "keys": [ + "", + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! ", + " ! ! ! ! ! ! ! ! ! ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " # # # # # # # # # ", + " # ## # ## # ## # ## # ## # ## # ## # ## # ## ", + " ######################################################################################################################################## ", + " # ## # ## # ## # ## # ## # ## # ## # ## # ## ", + " # # # # # # # # # ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " $ $ $ $ $ $ $ $ $ ", + " $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$ $$$ $$ $$$ $$ $$$ $$ $$$ $$ $$$ $$ $$$ $$ $$$ $$ $$$ $$ $$$ ", + " $ $ $ $ $ $ $ $ $ ", + " ", + " ", + " ", + " ", + " ", + " ", + " % % % % % % % % % ", + " %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% ", + " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ", + " %% % %% % %% % %% % %% % %% % %% % %% % %% % ", + " ", + " ", + " ", + " ", + " && & & && & & && & & && & & && & & && & & && & & && & & && & & ", + " && & && & && & && & && & && & && & && & && & ", + " && && && && && && && && && && && && && && && && && && ", + " &&& & & &&& & & &&& & & &&& & & &&& & & &&& & & &&& & & &&& & & &&& & & ", + " ", + " ", + " ", + " ", + " ", + " ", + " ' ' '' ' ", + " ( )) ) ))) '' ''' ", + " (( ( (( (( )))))))))))))))))))))))))))) '''' '' ", + " (((( (((( )) )) )) ''' ' ", + " ( ((( ((( ) ) ' ' ", + " ( ( ", + " ( '' ' ", + " ((( ( '''' '' ", + " ( ( ' ' '' ", + " ( (((( ' '' ", + " ((( (( ' ", + " ( ( ' ", + " ( ' ' ", + " ( ''' ", + " ( ( ' '' ", + " (( ( ( ' '''' ", + " ((((( ( ' ' ' ", + " ((( ( ' ' ' '' ", + " ( ( ((( ( * * ''' ", + " (( ( ** ** ** '' ", + " (((( **************************** ", + " ( ( ** ** *** ", + " * * ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/lines-shield-800-800-1.0-grid-reference.json b/tests/visual_tests/grids/lines-shield-800-800-1.0-grid-reference.json new file mode 100644 index 000000000..6ec6c7d12 --- /dev/null +++ b/tests/visual_tests/grids/lines-shield-800-800-1.0-grid-reference.json @@ -0,0 +1,217 @@ +{ + "keys": [ + "", + "8", + "7", + "6", + "5", + "9", + "2", + "1", + "4", + "3" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! ! ! ! ! ! ! ! ! ! ! ! ", + " !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !! ! ! ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " # ### # ### # ### # ### # ### # ### # ### # ### # ### # ### # ### # ### ", + " ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ", + " ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ", + " # # # # # # # # # # # # ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ $$ $ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ $$ ", + " $ $ $ $ $ $ $ $ $ $ $ $ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " % % % % % % % % % % % % ", + " %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% ", + " %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ", + " % %% % %% % %% % %% % %% % %% % %% % %% % %% % %% % %% % %% ", + " ", + " ", + " ", + " ", + " ", + " ", + " & & & & & & & & & & & & ", + " & && & && & && & && & && & && & && & && & && & && & && & && ", + " &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ", + " && && && && && && && && && && && && && && && && && && && && && && && && ", + " & & & & & & & & & & & & ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ' ", + " '''' ' '' ", + " ( ))) ) ) )) ) ) ) ''' ''''' ", + " ( ( ( ( ) ) ) ) )) ' ' ''' ", + " (((( (((( )) )) )) )) )) ' ' ' ", + " (( ((( (((( ) ) '' ' ", + " ( (( ' ''' ", + " ((( '' ''''' ", + " ( (( ' ' ", + " (( (( ' ' ", + " ( (( ' ", + " ( ' ' ", + " ( ", + " '' '' ", + " ( ( '''' '' ", + " ( '' '''' ", + " (((( (( ' '' ", + " (( (((( '' ", + " (( ' ' ", + " ( ' ' ", + " ( ( ' ' ' ' ", + " ( '''' '' ", + " ((( ( ''' ''''' ", + " (( ((( '' ' ' '' ", + " ((( (((( '''''' ' ", + " ( ( (( (( * * * '''' ", + " ((( ( ** ** ** ** ** '' ", + " (((( ************************************** ", + " ( *** ** ** * ** ", + " * * * ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/list-100-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-100-100-1.0-grid-reference.json index e013c4972..b633480e3 100644 --- a/tests/visual_tests/grids/list-100-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-100-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-3", - "-5", - "-7", - "-9", - "-2", - "-4", - "-6", - "-8", - "-10" + "1", + "3", + "5", + "7", + "9", + "2", + "4", + "6", + "8", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/list-150-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-150-100-1.0-grid-reference.json index 9f783721e..aacf5a57b 100644 --- a/tests/visual_tests/grids/list-150-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-150-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-4", - "-6", - "-7", - "-8", - "-9", - "-2", - "-1", - "-3", - "-5", - "-10" + "4", + "6", + "7", + "8", + "9", + "2", + "1", + "3", + "5", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/list-250-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-250-100-1.0-grid-reference.json index 3da38a934..3ead5a120 100644 --- a/tests/visual_tests/grids/list-250-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-250-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-3", - "-5", - "-7", - "-9", - "-2", - "-4", - "-6", - "-8", - "-10" + "1", + "3", + "5", + "7", + "9", + "2", + "4", + "6", + "8", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/list-300-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-300-100-1.0-grid-reference.json index 3a5b45829..91ac6b3da 100644 --- a/tests/visual_tests/grids/list-300-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-300-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-3", - "-5", - "-7", - "-9", - "-2", - "-4", - "-6", - "-8", - "-10" + "1", + "3", + "5", + "7", + "9", + "2", + "4", + "6", + "8", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/list-400-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-400-100-1.0-grid-reference.json index e802ae4f0..ea336f358 100644 --- a/tests/visual_tests/grids/list-400-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-400-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-3", - "-5", - "-7", - "-9", - "-10", - "-2", - "-4", - "-6", - "-8" + "1", + "3", + "5", + "7", + "9", + "10", + "2", + "4", + "6", + "8" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/list-600-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-600-100-1.0-grid-reference.json index 5d40ccd6c..a846513de 100644 --- a/tests/visual_tests/grids/list-600-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-600-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-2", - "-4", - "-6", - "-8", - "-10", - "-1", - "-3", - "-5", - "-7", - "-9" + "2", + "4", + "6", + "8", + "10", + "1", + "3", + "5", + "7", + "9" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/list-800-100-1.0-grid-reference.json b/tests/visual_tests/grids/list-800-100-1.0-grid-reference.json index b9b246738..692e6adac 100644 --- a/tests/visual_tests/grids/list-800-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/list-800-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/rtl-point-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/rtl-point-200-200-1.0-grid-reference.json index c2292c1d4..aa24b0418 100644 --- a/tests/visual_tests/grids/rtl-point-200-200-1.0-grid-reference.json +++ b/tests/visual_tests/grids/rtl-point-200-200-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shield-on-line-spacing-eq-width-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/shield-on-line-spacing-eq-width-600-400-1.0-grid-reference.json new file mode 100644 index 000000000..25c5fc711 --- /dev/null +++ b/tests/visual_tests/grids/shield-on-line-spacing-eq-width-600-400-1.0-grid-reference.json @@ -0,0 +1,109 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !!!!! !! ", + " !!!!! !! ", + " !!!!! ", + " !! !!!!! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + " !! ", + "! ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/shield-on-polygon-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/shield-on-polygon-500-100-1.0-grid-reference.json new file mode 100644 index 000000000..83e2d2aaa --- /dev/null +++ b/tests/visual_tests/grids/shield-on-polygon-500-100-1.0-grid-reference.json @@ -0,0 +1,39 @@ +{ + "keys": [ + "", + "1", + "3", + "2", + "4", + "5", + "6" + ], + "data": {}, + "grid": [ + " ! ", + " !! ", + " !!! ", + " !! # ", + " !!! ", + " !!!! ", + " !!!! !! ", + " !!!!!!!! ", + " !!!!!!!! ", + " !!!!!!!!! ", + " !!!!!!! ", + " !!!! ", + " $$ % !!! ", + " $$$$$!!! ", + " $$$$$$ ! ", + " $$$$$$ ", + " $$$$$$ ", + " $$$$$$ ", + " $$$$$$$$ ", + " $$$$$$$$ ", + " $$$$$$$$$ ", + " $$$$$$$$$ ", + " &$$$$$$$$ ", + " $$$$$$$$ ", + " '' $ " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/shield-on-polygon-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/shield-on-polygon-600-400-1.0-grid-reference.json new file mode 100644 index 000000000..176d251f7 --- /dev/null +++ b/tests/visual_tests/grids/shield-on-polygon-600-400-1.0-grid-reference.json @@ -0,0 +1,115 @@ +{ + "keys": [ + "", + "1", + "3", + "2", + "4", + "7", + "5", + "6" + ], + "data": {}, + "grid": [ + " !!! ", + " !!! ", + " !! ", + " !! ! ", + " !!!!! ", + " !!!!!!!! ", + " !!!!!!!! ! ", + " !!!!!!!!! ", + " !!!!!!!!!! ", + " !!!!!!!!!! ", + " !!!!!!!!! ", + " !!!!!!! ", + " !!!!!!! ", + " !!!!!!! ## ", + " !!!!!!! ## ", + " !!!!!!! ", + " !!!!! ! ", + " !!!!! !! ", + " !!! !!! ", + " !!!!!! !!!! ", + " !!!!!!! !!! ", + " !!!!!!! !!! ", + " !!!!!!!!!!! ", + " !!!!!!!!!!! ", + " !!!!!!!!!!!! !!! ", + " !!!!!!!!!!!! !!!!!!! ", + " !!!!!!!!!!!!!! !!!!!!!! ", + " !!!!!!!!!!!!!!!!!! !!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!! ", + " !!!!!!!!!!!! ", + " $$$ !!!!!!!!!!!! ", + " $$ !!!!!!!!!!! ", + " $$$$$ %% !!!!!!!!!!! ", + " $$$$$$$$ %% !!!!!!!!!!! ", + " $$$$$$$$ $$$$$$ !!!!!!!!!!! ", + " $$$$$$$$ $$$$$$$$ !!!!!!!!!!! ", + " $$$$$$$$$$$$$$$$$$ !!!!!!!!!!! ", + " $$$$$$$$$$$$$$$$$$ !!!!!!!! ", + " $$$$$$$$$$$$$$$$$ !!!! ", + " $$$$$$$$$$$$$$$$$$$ ! ", + " $$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " &&$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " ''$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " ''$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$$$$$$$$$$$$$ ", + " $$$$$$ $$$$$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$$$$$ ", + " $$$$$$$$$$$$ ", + " $$ $$$$$ ", + " ((( ", + " (((( ", + " (((((( ", + " (((((( " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-490-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-490-100-1.0-grid-reference.json index d8dbd6f75..a5d255d4b 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-490-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-490-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-6", - "-7", - "-9", - "-10", - "-3", - "-4" + "8", + "5", + "1", + "2", + "6", + "7", + "9", + "10", + "3", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-495-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-495-100-1.0-grid-reference.json index f6efaf5b4..b0f75845b 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-495-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-495-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-3", - "-6", - "-7", - "-9", - "-10", - "-4" + "8", + "5", + "1", + "2", + "3", + "6", + "7", + "9", + "10", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-497-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-497-100-1.0-grid-reference.json index be04f3405..b190871af 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-497-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-497-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-3", - "-6", - "-7", - "-9", - "-10", - "-4" + "8", + "5", + "1", + "2", + "3", + "6", + "7", + "9", + "10", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-498-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-498-100-1.0-grid-reference.json index 52bf4d53a..ca0db3884 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-498-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-498-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-3", - "-6", - "-7", - "-9", - "-10", - "-4" + "8", + "5", + "1", + "2", + "3", + "6", + "7", + "9", + "10", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-499-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-499-100-1.0-grid-reference.json index e7e48c88a..1b92a2855 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-499-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-499-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-3", - "-6", - "-7", - "-9", - "-10", - "-4" + "8", + "5", + "1", + "2", + "3", + "6", + "7", + "9", + "10", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-500-100-1.0-grid-reference.json index 2a6f9bbaa..26459bd0f 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-500-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-3", - "-6", - "-7", - "-9", - "-10", - "-4" + "8", + "5", + "1", + "2", + "3", + "6", + "7", + "9", + "10", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-501-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-501-100-1.0-grid-reference.json index d72cfe602..88cc49451 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-501-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-501-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-3", - "-6", - "-7", - "-9", - "-10", - "-4" + "8", + "5", + "1", + "2", + "3", + "6", + "7", + "9", + "10", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-502-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-502-100-1.0-grid-reference.json index b48db9f64..050335c81 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-502-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-502-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-6", - "-7", - "-9", - "-10", - "-3", - "-4" + "8", + "5", + "1", + "2", + "6", + "7", + "9", + "10", + "3", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-505-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-505-100-1.0-grid-reference.json index bc8af027f..aa2e746c4 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-505-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-505-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-6", - "-7", - "-9", - "-10", - "-3", - "-4" + "8", + "5", + "1", + "2", + "6", + "7", + "9", + "10", + "3", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/shieldsymbolizer-1-510-100-1.0-grid-reference.json b/tests/visual_tests/grids/shieldsymbolizer-1-510-100-1.0-grid-reference.json index 04693f989..f0706c77d 100644 --- a/tests/visual_tests/grids/shieldsymbolizer-1-510-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/shieldsymbolizer-1-510-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-8", - "-5", - "-1", - "-2", - "-6", - "-7", - "-9", - "-10", - "-3", - "-4" + "8", + "5", + "1", + "2", + "6", + "7", + "9", + "10", + "3", + "4" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-100-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-100-100-1.0-grid-reference.json index a93d7f62e..d250023b9 100644 --- a/tests/visual_tests/grids/simple-100-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-100-100-1.0-grid-reference.json @@ -1,14 +1,14 @@ { "keys": [ "", - "-2", - "-5", - "-8", - "-1", - "-9", - "-10", - "-3", - "-7" + "2", + "5", + "8", + "1", + "9", + "10", + "3", + "7" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-150-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-150-100-1.0-grid-reference.json index 5e3afa8a4..8b25d98e0 100644 --- a/tests/visual_tests/grids/simple-150-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-150-100-1.0-grid-reference.json @@ -1,14 +1,14 @@ { "keys": [ "", - "-2", - "-7", - "-4", - "-10", - "-1", - "-6", - "-3", - "-8" + "2", + "7", + "4", + "10", + "1", + "6", + "3", + "8" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-250-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-250-100-1.0-grid-reference.json index 8f11c4ca2..f52fcbdfa 100644 --- a/tests/visual_tests/grids/simple-250-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-250-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-2", - "-5", - "-8", - "-10", - "-1", - "-4", - "-7", - "-3", - "-6", - "-9" + "2", + "5", + "8", + "10", + "1", + "4", + "7", + "3", + "6", + "9" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-300-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-300-100-1.0-grid-reference.json index d2bcad422..3bf047bed 100644 --- a/tests/visual_tests/grids/simple-300-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-300-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-2", - "-5", - "-8", - "-10", - "-1", - "-4", - "-7", - "-3", - "-6", - "-9" + "2", + "5", + "8", + "10", + "1", + "4", + "7", + "3", + "6", + "9" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-400-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-400-100-1.0-grid-reference.json index a0c3ee225..b88c666e5 100644 --- a/tests/visual_tests/grids/simple-400-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-400-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-2", - "-4", - "-6", - "-8", - "-10", - "-1", - "-3", - "-5", - "-7", - "-9" + "2", + "4", + "6", + "8", + "10", + "1", + "3", + "5", + "7", + "9" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-600-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-600-100-1.0-grid-reference.json index 8fbe2e8ab..a6638f296 100644 --- a/tests/visual_tests/grids/simple-600-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-600-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-3", - "-5", - "-7", - "-9", - "-2", - "-4", - "-6", - "-8", - "-10" + "1", + "3", + "5", + "7", + "9", + "2", + "4", + "6", + "8", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-800-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-800-100-1.0-grid-reference.json index a884777f0..dbd1b4bca 100644 --- a/tests/visual_tests/grids/simple-800-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-800-100-1.0-grid-reference.json @@ -1,16 +1,16 @@ { "keys": [ "", - "-1", - "-2", - "-3", - "-4", - "-5", - "-6", - "-7", - "-8", - "-9", - "-10" + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-E-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-E-500-100-1.0-grid-reference.json index c83d9f9bc..8a1b162de 100644 --- a/tests/visual_tests/grids/simple-E-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-E-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-N-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-N-500-100-1.0-grid-reference.json index ecd2f97d0..b049b10d1 100644 --- a/tests/visual_tests/grids/simple-N-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-N-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-NE-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-NE-500-100-1.0-grid-reference.json index cc5e49b81..aa030d211 100644 --- a/tests/visual_tests/grids/simple-NE-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-NE-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-NW-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-NW-500-100-1.0-grid-reference.json index 3ac668c0d..1d054206d 100644 --- a/tests/visual_tests/grids/simple-NW-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-NW-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-S-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-S-500-100-1.0-grid-reference.json index 60b30e0f4..28fb8011c 100644 --- a/tests/visual_tests/grids/simple-S-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-S-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-SE-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-SE-500-100-1.0-grid-reference.json index 125524dd2..691c6d843 100644 --- a/tests/visual_tests/grids/simple-SE-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-SE-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-SW-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-SW-500-100-1.0-grid-reference.json index 794db25f2..6f39d2c38 100644 --- a/tests/visual_tests/grids/simple-SW-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-SW-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/simple-W-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/simple-W-500-100-1.0-grid-reference.json index 9725865bc..e52b12abb 100644 --- a/tests/visual_tests/grids/simple-W-500-100-1.0-grid-reference.json +++ b/tests/visual_tests/grids/simple-W-500-100-1.0-grid-reference.json @@ -1,7 +1,7 @@ { "keys": [ "", - "-5" + "5" ], "data": {}, "grid": [ diff --git a/tests/visual_tests/grids/text-halo-rasterizer-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/text-halo-rasterizer-600-400-1.0-grid-reference.json index ee24381b3..56a29ed9e 100644 --- a/tests/visual_tests/grids/text-halo-rasterizer-600-400-1.0-grid-reference.json +++ b/tests/visual_tests/grids/text-halo-rasterizer-600-400-1.0-grid-reference.json @@ -1,16 +1,22 @@ { "keys": [ "", - "5", - "10", - "4", - "9", - "3", - "8", - "2", - "7", "1", - "6" + "9", + "2", + "10", + "3", + "11", + "4", + "12", + "5", + "13", + "6", + "14", + "7", + "15", + "8", + "16" ], "data": {}, "grid": [ @@ -22,20 +28,10 @@ " ", " ", " ", - " !!! !!!!!! ### ###### ", - " !!!!!!!!!!!! ########## ", - " !!!!!!!!!!!! ########### ", - " !!!!!!!!!!! ########### ", - " !!!!!!!!!!! ####### ## ", " ", - " ", - " ", - " ", - " ", - " $$ $$$$$$ %% %% %% %%% ", - " $$$$$$$$$$$$$$ %%%%%% %% %%% ", - " $$$$$$$$$$$$$$ %%%%%% %% %%% ", - " $$$$$$$$$$$$$ %%%%%%%%%%%%% ", + " ! ! ! ## ## ", + " ! ! !! ! #### # ", + " !!! ! ! !! #### ### ", " ", " ", " ", @@ -43,6 +39,9 @@ " ", " ", " ", + " $ $ $ %% %% ", + " $ $ $$ $$ %%%% % ", + " $$$ $ $ $$ %%%% %%% ", " ", " ", " ", @@ -50,12 +49,9 @@ " ", " ", " ", - " ", - " ", - " ", - " &&&&&&&&& && '''''' '' '' ", - " &&&&&& & && ' '''' ' ''' ", - " &&&&&&&&&&&&& ' '''' '''''' ", + " & & '' ' ", + " & & && & '''' '' ", + " &&& & & && '''' ''' ", " ", " ", " ", @@ -63,6 +59,9 @@ " ", " ", " ", + " ( ( (( )) )) ", + " ( ( (( )))) ) ", + " ((( ( ( ( )))) ) ", " ", " ", " ", @@ -70,12 +69,9 @@ " ", " ", " ", - " ", - " ", - " ", - " (((((((((( )) ))) ) ", - " (((((( ( )) ))) ) ", - " ((((((((( )))))) )) ", + " ********** ++ +++ + ", + " ****** * ++ +++ + ", + " ********* ++++++ ++ ", " ", " ", " ", @@ -83,21 +79,31 @@ " ", " ", " ", + " ,,,,,,,,, ,, ------ -- -- ", + " ,,,,,, , ,, - ---- - --- ", + " ,,,,,,,,,,,,, - ---- ------ ", " ", " ", " ", " ", " ", " ", + " .. ...... // // // /// ", + " .............. ////// // /// ", + " .............. ////// // /// ", + " ............. ///////////// ", " ", " ", " ", " ", - " * * ++ + ", - " * * ** * ++++ ++ ", - " *** * * ** ++++ +++ ", " ", " ", + " 000 000000 111 111111 ", + " 000000000000 1111111111 ", + " 000000000000 11111111111 ", + " 00000000000 11111111111 ", + " 00000000000 1111111 11 ", + " ", " ", " ", " ", diff --git a/tests/visual_tests/html_report_template.html b/tests/visual_tests/html_report_template.html new file mode 100644 index 000000000..759b8fe40 --- /dev/null +++ b/tests/visual_tests/html_report_template.html @@ -0,0 +1,33 @@ + + + + + + + +
+
expected
+
% difference
+
actual
+{{RESULTS}} +
+ + diff --git a/tests/visual_tests/images/collision-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/collision-600-400-1.0-cairo-reference.png index 4780ab994..c8a3eba8d 100644 Binary files a/tests/visual_tests/images/collision-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/collision-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/collision-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/collision-600-400-2.0-cairo-reference.png index 6bba24c5e..d72f19440 100644 Binary files a/tests/visual_tests/images/collision-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/collision-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/line-offset-900-250-1.0-agg-reference.png b/tests/visual_tests/images/line-offset-900-250-1.0-agg-reference.png index f147141c7..19f85db78 100644 Binary files a/tests/visual_tests/images/line-offset-900-250-1.0-agg-reference.png and b/tests/visual_tests/images/line-offset-900-250-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/line-offset-900-250-1.0-cairo-reference.png b/tests/visual_tests/images/line-offset-900-250-1.0-cairo-reference.png index c93bdbb11..51a7333be 100644 Binary files a/tests/visual_tests/images/line-offset-900-250-1.0-cairo-reference.png and b/tests/visual_tests/images/line-offset-900-250-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/line-offset-900-250-2.0-agg-reference.png b/tests/visual_tests/images/line-offset-900-250-2.0-agg-reference.png index 9c63bf81e..53ffcc28c 100644 Binary files a/tests/visual_tests/images/line-offset-900-250-2.0-agg-reference.png and b/tests/visual_tests/images/line-offset-900-250-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/line-offset-900-250-2.0-cairo-reference.png b/tests/visual_tests/images/line-offset-900-250-2.0-cairo-reference.png index c36588076..b83bd731f 100644 Binary files a/tests/visual_tests/images/line-offset-900-250-2.0-cairo-reference.png and b/tests/visual_tests/images/line-offset-900-250-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-200-200-1.0-cairo-reference.png b/tests/visual_tests/images/lines-1-200-200-1.0-cairo-reference.png index dae174f22..b2d300f0f 100644 Binary files a/tests/visual_tests/images/lines-1-200-200-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-200-200-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-200-200-2.0-cairo-reference.png b/tests/visual_tests/images/lines-1-200-200-2.0-cairo-reference.png index d97b38ca2..81727a68e 100644 Binary files a/tests/visual_tests/images/lines-1-200-200-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-200-200-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-400-400-1.0-agg-reference.png b/tests/visual_tests/images/lines-1-400-400-1.0-agg-reference.png index 25f6452c6..551ae51eb 100644 Binary files a/tests/visual_tests/images/lines-1-400-400-1.0-agg-reference.png and b/tests/visual_tests/images/lines-1-400-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-1-400-400-2.0-cairo-reference.png b/tests/visual_tests/images/lines-1-400-400-2.0-cairo-reference.png index 3c26f266f..249edc709 100644 Binary files a/tests/visual_tests/images/lines-1-400-400-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-400-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-600-600-1.0-cairo-reference.png b/tests/visual_tests/images/lines-1-600-600-1.0-cairo-reference.png index 1f5feb8f4..515daedab 100644 Binary files a/tests/visual_tests/images/lines-1-600-600-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-600-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-600-600-2.0-cairo-reference.png b/tests/visual_tests/images/lines-1-600-600-2.0-cairo-reference.png index b08213070..64faecd1d 100644 Binary files a/tests/visual_tests/images/lines-1-600-600-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-600-600-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-800-800-1.0-agg-reference.png b/tests/visual_tests/images/lines-1-800-800-1.0-agg-reference.png index 0e9080ee8..02209ef2b 100644 Binary files a/tests/visual_tests/images/lines-1-800-800-1.0-agg-reference.png and b/tests/visual_tests/images/lines-1-800-800-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-1-800-800-1.0-cairo-reference.png b/tests/visual_tests/images/lines-1-800-800-1.0-cairo-reference.png index 9af56e9b4..425b01edf 100644 Binary files a/tests/visual_tests/images/lines-1-800-800-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-800-800-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-1-800-800-2.0-agg-reference.png b/tests/visual_tests/images/lines-1-800-800-2.0-agg-reference.png index 46271acdc..c4da4f388 100644 Binary files a/tests/visual_tests/images/lines-1-800-800-2.0-agg-reference.png and b/tests/visual_tests/images/lines-1-800-800-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-1-800-800-2.0-cairo-reference.png b/tests/visual_tests/images/lines-1-800-800-2.0-cairo-reference.png index 734d85c6a..a26355864 100644 Binary files a/tests/visual_tests/images/lines-1-800-800-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-1-800-800-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-200-200-1.0-cairo-reference.png b/tests/visual_tests/images/lines-2-200-200-1.0-cairo-reference.png index ef832ce86..05dbf909a 100644 Binary files a/tests/visual_tests/images/lines-2-200-200-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-200-200-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-200-200-2.0-cairo-reference.png b/tests/visual_tests/images/lines-2-200-200-2.0-cairo-reference.png index d97b38ca2..81727a68e 100644 Binary files a/tests/visual_tests/images/lines-2-200-200-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-200-200-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-400-400-1.0-agg-reference.png b/tests/visual_tests/images/lines-2-400-400-1.0-agg-reference.png index 66679050f..965ad6a45 100644 Binary files a/tests/visual_tests/images/lines-2-400-400-1.0-agg-reference.png and b/tests/visual_tests/images/lines-2-400-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-2-400-400-2.0-cairo-reference.png b/tests/visual_tests/images/lines-2-400-400-2.0-cairo-reference.png index 62ebc42e2..ca17344c8 100644 Binary files a/tests/visual_tests/images/lines-2-400-400-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-400-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-600-600-1.0-agg-reference.png b/tests/visual_tests/images/lines-2-600-600-1.0-agg-reference.png index 409c83542..4c81dc28c 100644 Binary files a/tests/visual_tests/images/lines-2-600-600-1.0-agg-reference.png and b/tests/visual_tests/images/lines-2-600-600-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-2-600-600-1.0-cairo-reference.png b/tests/visual_tests/images/lines-2-600-600-1.0-cairo-reference.png index bf2eeda13..d7f2277cb 100644 Binary files a/tests/visual_tests/images/lines-2-600-600-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-600-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-600-600-2.0-cairo-reference.png b/tests/visual_tests/images/lines-2-600-600-2.0-cairo-reference.png index b946b4903..62a026b9e 100644 Binary files a/tests/visual_tests/images/lines-2-600-600-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-600-600-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-800-800-1.0-agg-reference.png b/tests/visual_tests/images/lines-2-800-800-1.0-agg-reference.png index 07724980c..132acbcaa 100644 Binary files a/tests/visual_tests/images/lines-2-800-800-1.0-agg-reference.png and b/tests/visual_tests/images/lines-2-800-800-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-2-800-800-1.0-cairo-reference.png b/tests/visual_tests/images/lines-2-800-800-1.0-cairo-reference.png index 8732867f1..8a11d0236 100644 Binary files a/tests/visual_tests/images/lines-2-800-800-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-800-800-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-2-800-800-2.0-cairo-reference.png b/tests/visual_tests/images/lines-2-800-800-2.0-cairo-reference.png index 2794e90cf..e4cd18585 100644 Binary files a/tests/visual_tests/images/lines-2-800-800-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-2-800-800-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-200-200-1.0-cairo-reference.png b/tests/visual_tests/images/lines-3-200-200-1.0-cairo-reference.png index dae174f22..b2d300f0f 100644 Binary files a/tests/visual_tests/images/lines-3-200-200-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-200-200-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-200-200-2.0-cairo-reference.png b/tests/visual_tests/images/lines-3-200-200-2.0-cairo-reference.png index d97b38ca2..81727a68e 100644 Binary files a/tests/visual_tests/images/lines-3-200-200-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-200-200-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-400-400-1.0-agg-reference.png b/tests/visual_tests/images/lines-3-400-400-1.0-agg-reference.png index 7c9285efd..a552848a5 100644 Binary files a/tests/visual_tests/images/lines-3-400-400-1.0-agg-reference.png and b/tests/visual_tests/images/lines-3-400-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-3-400-400-2.0-cairo-reference.png b/tests/visual_tests/images/lines-3-400-400-2.0-cairo-reference.png index 3c26f266f..249edc709 100644 Binary files a/tests/visual_tests/images/lines-3-400-400-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-400-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-600-600-1.0-cairo-reference.png b/tests/visual_tests/images/lines-3-600-600-1.0-cairo-reference.png index 752b03977..c6ecf9c73 100644 Binary files a/tests/visual_tests/images/lines-3-600-600-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-600-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-600-600-2.0-cairo-reference.png b/tests/visual_tests/images/lines-3-600-600-2.0-cairo-reference.png index e2cba88af..654a636bc 100644 Binary files a/tests/visual_tests/images/lines-3-600-600-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-600-600-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-800-800-1.0-agg-reference.png b/tests/visual_tests/images/lines-3-800-800-1.0-agg-reference.png index 305e8c700..3a9295667 100644 Binary files a/tests/visual_tests/images/lines-3-800-800-1.0-agg-reference.png and b/tests/visual_tests/images/lines-3-800-800-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-3-800-800-1.0-cairo-reference.png b/tests/visual_tests/images/lines-3-800-800-1.0-cairo-reference.png index 9b49af262..1d94e755c 100644 Binary files a/tests/visual_tests/images/lines-3-800-800-1.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-800-800-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-3-800-800-2.0-agg-reference.png b/tests/visual_tests/images/lines-3-800-800-2.0-agg-reference.png index f003769f5..a8bdfead8 100644 Binary files a/tests/visual_tests/images/lines-3-800-800-2.0-agg-reference.png and b/tests/visual_tests/images/lines-3-800-800-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-3-800-800-2.0-cairo-reference.png b/tests/visual_tests/images/lines-3-800-800-2.0-cairo-reference.png index 53c62c7d5..d1eb38697 100644 Binary files a/tests/visual_tests/images/lines-3-800-800-2.0-cairo-reference.png and b/tests/visual_tests/images/lines-3-800-800-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-200-200-1.0-agg-reference.png b/tests/visual_tests/images/lines-shield-200-200-1.0-agg-reference.png new file mode 100644 index 000000000..0ab97cb12 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-200-200-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-200-200-1.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-200-200-1.0-cairo-reference.png new file mode 100644 index 000000000..2db6719ec Binary files /dev/null and b/tests/visual_tests/images/lines-shield-200-200-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-200-200-2.0-agg-reference.png b/tests/visual_tests/images/lines-shield-200-200-2.0-agg-reference.png new file mode 100644 index 000000000..d7ae2234d Binary files /dev/null and b/tests/visual_tests/images/lines-shield-200-200-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-200-200-2.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-200-200-2.0-cairo-reference.png new file mode 100644 index 000000000..e4d817d6e Binary files /dev/null and b/tests/visual_tests/images/lines-shield-200-200-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-400-400-1.0-agg-reference.png b/tests/visual_tests/images/lines-shield-400-400-1.0-agg-reference.png new file mode 100644 index 000000000..4269b4c06 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-400-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-400-400-1.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-400-400-1.0-cairo-reference.png new file mode 100644 index 000000000..d30efaca0 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-400-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-400-400-2.0-agg-reference.png b/tests/visual_tests/images/lines-shield-400-400-2.0-agg-reference.png new file mode 100644 index 000000000..75a0ec6a2 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-400-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-400-400-2.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-400-400-2.0-cairo-reference.png new file mode 100644 index 000000000..5f32ddaf0 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-400-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-600-600-1.0-agg-reference.png b/tests/visual_tests/images/lines-shield-600-600-1.0-agg-reference.png new file mode 100644 index 000000000..f8fdcadac Binary files /dev/null and b/tests/visual_tests/images/lines-shield-600-600-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-600-600-1.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-600-600-1.0-cairo-reference.png new file mode 100644 index 000000000..20ba67d4e Binary files /dev/null and b/tests/visual_tests/images/lines-shield-600-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-600-600-2.0-agg-reference.png b/tests/visual_tests/images/lines-shield-600-600-2.0-agg-reference.png new file mode 100644 index 000000000..ae0f4d94d Binary files /dev/null and b/tests/visual_tests/images/lines-shield-600-600-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-600-600-2.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-600-600-2.0-cairo-reference.png new file mode 100644 index 000000000..a94c464a2 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-600-600-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-800-800-1.0-agg-reference.png b/tests/visual_tests/images/lines-shield-800-800-1.0-agg-reference.png new file mode 100644 index 000000000..6e05b9255 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-800-800-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-800-800-1.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-800-800-1.0-cairo-reference.png new file mode 100644 index 000000000..54fbbabd4 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-800-800-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-800-800-2.0-agg-reference.png b/tests/visual_tests/images/lines-shield-800-800-2.0-agg-reference.png new file mode 100644 index 000000000..a3797ce56 Binary files /dev/null and b/tests/visual_tests/images/lines-shield-800-800-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/lines-shield-800-800-2.0-cairo-reference.png b/tests/visual_tests/images/lines-shield-800-800-2.0-cairo-reference.png new file mode 100644 index 000000000..4641d23ee Binary files /dev/null and b/tests/visual_tests/images/lines-shield-800-800-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/list-150-100-2.0-cairo-reference.png b/tests/visual_tests/images/list-150-100-2.0-cairo-reference.png index b3e61b44b..99cc5c435 100644 Binary files a/tests/visual_tests/images/list-150-100-2.0-cairo-reference.png and b/tests/visual_tests/images/list-150-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/list-300-100-2.0-cairo-reference.png b/tests/visual_tests/images/list-300-100-2.0-cairo-reference.png index 4cdace7a6..b0c77c6ee 100644 Binary files a/tests/visual_tests/images/list-300-100-2.0-cairo-reference.png and b/tests/visual_tests/images/list-300-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/list-400-100-1.0-cairo-reference.png b/tests/visual_tests/images/list-400-100-1.0-cairo-reference.png index 4219f4411..ed891a4b5 100644 Binary files a/tests/visual_tests/images/list-400-100-1.0-cairo-reference.png and b/tests/visual_tests/images/list-400-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/list-600-100-1.0-cairo-reference.png b/tests/visual_tests/images/list-600-100-1.0-cairo-reference.png index 2d8bff642..5dd736041 100644 Binary files a/tests/visual_tests/images/list-600-100-1.0-cairo-reference.png and b/tests/visual_tests/images/list-600-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/list-800-100-2.0-cairo-reference.png b/tests/visual_tests/images/list-800-100-2.0-cairo-reference.png index 8a716f1d5..1fa3a7bdd 100644 Binary files a/tests/visual_tests/images/list-800-100-2.0-cairo-reference.png and b/tests/visual_tests/images/list-800-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-multi-policy-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-multi-policy-600-400-2.0-cairo-reference.png index 5b157353f..1b2a9ce26 100644 Binary files a/tests/visual_tests/images/marker-multi-policy-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-multi-policy-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png index 0a730a5db..75362bc95 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png index 28f7da078..de0885e9c 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-600-400-1.0-cairo-reference.png index 7bea4f62f..788a1aa36 100644 Binary files a/tests/visual_tests/images/marker-on-line-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-600-400-2.0-cairo-reference.png index 22b1822ee..efafa2799 100644 Binary files a/tests/visual_tests/images/marker-on-line-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png index 5ddd5a620..b73700424 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png index 853ea43cf..9f2e33cb3 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png index 387a35da6..d02bd8e3c 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png index 256ee1918..a7523da64 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-257-256-1.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-257-256-1.0-cairo-reference.png index ffa40ac2d..761743e75 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-257-256-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-with-background-image-257-256-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-400-600-1.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-400-600-1.0-cairo-reference.png index cbfda129c..e991deb99 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-400-600-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-with-background-image-400-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-400-600-2.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-400-600-2.0-cairo-reference.png index fb4489a65..a4aec0749 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-400-600-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-with-background-image-400-600-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-600-400-1.0-cairo-reference.png index cf585a900..a7bc35af6 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-with-background-image-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-600-400-2.0-cairo-reference.png index b242281b5..784c23c62 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-with-background-image-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-cairo-reference.png b/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-cairo-reference.png index 8bb0b7649..8943bfa53 100644 Binary files a/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-cairo-reference.png and b/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-cairo-reference.png b/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-cairo-reference.png index 57e41b1f5..4cf7ae33b 100644 Binary files a/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-cairo-reference.png and b/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png new file mode 100644 index 000000000..7eea9485e Binary files /dev/null and b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png new file mode 100644 index 000000000..49bfde802 Binary files /dev/null and b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png new file mode 100644 index 000000000..627acd957 Binary files /dev/null and b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png new file mode 100644 index 000000000..61e332ddf Binary files /dev/null and b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-500-100-1.0-cairo-reference.png b/tests/visual_tests/images/shield-on-polygon-500-100-1.0-cairo-reference.png new file mode 100644 index 000000000..bcb680333 Binary files /dev/null and b/tests/visual_tests/images/shield-on-polygon-500-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-500-100-2.0-cairo-reference.png b/tests/visual_tests/images/shield-on-polygon-500-100-2.0-cairo-reference.png new file mode 100644 index 000000000..8ebad2380 Binary files /dev/null and b/tests/visual_tests/images/shield-on-polygon-500-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-600-400-1.0-agg-reference.png b/tests/visual_tests/images/shield-on-polygon-600-400-1.0-agg-reference.png new file mode 100644 index 000000000..b5dd8e45e Binary files /dev/null and b/tests/visual_tests/images/shield-on-polygon-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/shield-on-polygon-600-400-1.0-cairo-reference.png new file mode 100644 index 000000000..f486e6c3e Binary files /dev/null and b/tests/visual_tests/images/shield-on-polygon-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png b/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png new file mode 100644 index 000000000..87fa8b772 Binary files /dev/null and b/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/shield-on-polygon-600-400-2.0-cairo-reference.png new file mode 100644 index 000000000..0d4c6a74c Binary files /dev/null and b/tests/visual_tests/images/shield-on-polygon-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shieldsymbolizer-1-498-100-2.0-cairo-reference.png b/tests/visual_tests/images/shieldsymbolizer-1-498-100-2.0-cairo-reference.png index 6a0c1a0fa..3bd5dd3a8 100644 Binary files a/tests/visual_tests/images/shieldsymbolizer-1-498-100-2.0-cairo-reference.png and b/tests/visual_tests/images/shieldsymbolizer-1-498-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shieldsymbolizer-1-501-100-2.0-cairo-reference.png b/tests/visual_tests/images/shieldsymbolizer-1-501-100-2.0-cairo-reference.png index ccc333e4e..f6bd195bb 100644 Binary files a/tests/visual_tests/images/shieldsymbolizer-1-501-100-2.0-cairo-reference.png and b/tests/visual_tests/images/shieldsymbolizer-1-501-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shieldsymbolizer-1-502-100-2.0-cairo-reference.png b/tests/visual_tests/images/shieldsymbolizer-1-502-100-2.0-cairo-reference.png index bafc15711..36cdec4a9 100644 Binary files a/tests/visual_tests/images/shieldsymbolizer-1-502-100-2.0-cairo-reference.png and b/tests/visual_tests/images/shieldsymbolizer-1-502-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simple-400-100-2.0-cairo-reference.png b/tests/visual_tests/images/simple-400-100-2.0-cairo-reference.png index cd18a67df..aab6f1a33 100644 Binary files a/tests/visual_tests/images/simple-400-100-2.0-cairo-reference.png and b/tests/visual_tests/images/simple-400-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simple-600-100-1.0-cairo-reference.png b/tests/visual_tests/images/simple-600-100-1.0-cairo-reference.png index cb1b88e53..1a41fd780 100644 Binary files a/tests/visual_tests/images/simple-600-100-1.0-cairo-reference.png and b/tests/visual_tests/images/simple-600-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simple-800-100-2.0-cairo-reference.png b/tests/visual_tests/images/simple-800-100-2.0-cairo-reference.png index 149f319f7..644d3549e 100644 Binary files a/tests/visual_tests/images/simple-800-100-2.0-cairo-reference.png and b/tests/visual_tests/images/simple-800-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-cairo-reference.png index c4c6ddc7f..05bb4b852 100644 Binary files a/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/text-halo-rasterizer-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/text-halo-rasterizer-600-400-2.0-cairo-reference.png index e5cb5b699..b4fd03c35 100644 Binary files a/tests/visual_tests/images/text-halo-rasterizer-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/text-halo-rasterizer-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/whole-centroid-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/whole-centroid-600-400-1.0-cairo-reference.png index 4dca4fb3f..35f2d678e 100644 Binary files a/tests/visual_tests/images/whole-centroid-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/whole-centroid-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/styles/expressionformat.xml b/tests/visual_tests/styles/expressionformat.xml index 919430f97..81c7b65c3 100644 --- a/tests/visual_tests/styles/expressionformat.xml +++ b/tests/visual_tests/styles/expressionformat.xml @@ -5,8 +5,8 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/styles/formatting-1.xml b/tests/visual_tests/styles/formatting-1.xml index 15f512abf..7bb62f15f 100644 --- a/tests/visual_tests/styles/formatting-1.xml +++ b/tests/visual_tests/styles/formatting-1.xml @@ -5,8 +5,8 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/styles/formatting-2.xml b/tests/visual_tests/styles/formatting-2.xml index 635af6a39..ca7646a47 100644 --- a/tests/visual_tests/styles/formatting-2.xml +++ b/tests/visual_tests/styles/formatting-2.xml @@ -5,8 +5,8 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/styles/formatting-3.xml b/tests/visual_tests/styles/formatting-3.xml index 97a5fb1f2..eb9e449fe 100644 --- a/tests/visual_tests/styles/formatting-3.xml +++ b/tests/visual_tests/styles/formatting-3.xml @@ -5,8 +5,8 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/styles/formatting-4.xml b/tests/visual_tests/styles/formatting-4.xml index b09f59a26..984a654fb 100644 --- a/tests/visual_tests/styles/formatting-4.xml +++ b/tests/visual_tests/styles/formatting-4.xml @@ -5,8 +5,8 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/styles/jalign-auto.xml b/tests/visual_tests/styles/jalign-auto.xml index f59f31cba..2ee79edd5 100644 --- a/tests/visual_tests/styles/jalign-auto.xml +++ b/tests/visual_tests/styles/jalign-auto.xml @@ -5,14 +5,14 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/styles/lines-1.xml b/tests/visual_tests/styles/lines-1.xml index dfd534efb..086f99205 100644 --- a/tests/visual_tests/styles/lines-1.xml +++ b/tests/visual_tests/styles/lines-1.xml @@ -5,13 +5,14 @@ My Style - osm - ../data/lines.osm + csv + ../data/lines.csv + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/shield-on-polygon.xml b/tests/visual_tests/styles/shield-on-polygon.xml new file mode 100644 index 000000000..c4f2f9e55 --- /dev/null +++ b/tests/visual_tests/styles/shield-on-polygon.xml @@ -0,0 +1,49 @@ + + + + + + -180,-85.05112877980659,180,85.05112877980659 + 0,0,2 + png + 0 + 22 + + + + + + + countries-outline + countries + + ../../data/shp/new_zealand/ne_50m_land.shp + + + + + + + places + + ../../data/shp/new_zealand/ne_50m_populated_places_simple.shp + + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/shieldsymbolizer-1.xml b/tests/visual_tests/styles/shieldsymbolizer-1.xml index 815f22920..cc37000d5 100644 --- a/tests/visual_tests/styles/shieldsymbolizer-1.xml +++ b/tests/visual_tests/styles/shieldsymbolizer-1.xml @@ -5,50 +5,50 @@ My Style - osm - ../data/points.osm + csv + ../data/points.csv diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 2eaf44a76..ca90e1a0b 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -4,6 +4,7 @@ import mapnik mapnik.logger.set_severity(mapnik.severity_type.None) +import shutil import sys import os.path from compare import compare, compare_grids @@ -19,8 +20,10 @@ defaults = { 'sizes': [(500, 100)], 'scales':[1.0,2.0], 'agg': True, - 'cairo': False, - 'grid': False, + 'cairo': True, + # disabled for 2.2.x since cairo tests are unstable (springmeyer) + #'cairo': mapnik.has_cairo(), + 'grid': True } sizes_many_in_big_range = [(800, 100), (600, 100), (400, 100), @@ -34,80 +37,81 @@ default_text_box = mapnik.Box2d(-0.05, -0.01, 0.95, 0.01) dirname = os.path.dirname(__file__) -files = [ - {'name': "list", 'sizes': sizes_many_in_big_range,'bbox':default_text_box}, - {'name': "simple", 'sizes': sizes_many_in_big_range,'bbox':default_text_box}, - {'name': "lines-1", 'sizes': sizes_few_square,'bbox':default_text_box}, - {'name': "lines-2", 'sizes': sizes_few_square,'bbox':default_text_box}, - {'name': "lines-3", 'sizes': sizes_few_square,'bbox':default_text_box}, +files = { + 'list': {'sizes': sizes_many_in_big_range,'bbox':default_text_box}, + 'simple': {'sizes': sizes_many_in_big_range,'bbox':default_text_box}, + 'lines-1': {'sizes': sizes_few_square,'bbox':default_text_box}, + 'lines-2': {'sizes': sizes_few_square,'bbox':default_text_box}, + 'lines-3': {'sizes': sizes_few_square,'bbox':default_text_box}, # https://github.com/mapnik/mapnik/issues/1696 # https://github.com/mapnik/mapnik/issues/1521 # fails with clang++ on os x - #{'name': "lines-shield", 'sizes': sizes_few_square,'bbox':default_text_box}, - {'name': "collision", 'sizes':[(600,400)]}, - {'name': "marker-svg-opacity"}, - {'name': "marker-multi-policy", 'sizes':[(600,400)]}, - {'name': "marker-on-line", 'sizes':[(600,400)], + 'lines-shield': {'sizes': sizes_few_square,'bbox':default_text_box}, + 'collision': {'sizes':[(600,400)]}, + 'shield-on-polygon': {'sizes':[(600,400)]}, + 'shield-on-line-spacing-eq-width': {'sizes':[(600,400)]}, + 'marker-svg-opacity':{}, + 'marker-multi-policy': {'sizes':[(600,400)]}, + 'marker-on-line': {'sizes':[(600,400)], 'bbox': mapnik.Box2d(-10, 0, 15, 20)}, - {'name': "marker-on-line-spacing-eq-width", 'sizes':[(600,400)]}, - {'name': "marker-on-line-spacing-eq-width-overlap", 'sizes':[(600,400)]}, - {'name': "marker_line_placement_on_points"}, - {'name': "marker-with-background-image", 'sizes':[(600,400),(400,600),(257,256)]}, - #{'name': "marker-with-background-image-and-hsla-transform", 'sizes':[(600,400),(400,600),(257,256)]}, - {'name': "marker-on-hex-grid", 'sizes':[(600,400),(400,600),(257,256)]}, - {'name': "whole-centroid", 'sizes':[(600,400)], + 'marker-on-line-spacing-eq-width': {'sizes':[(600,400)]}, + 'marker-on-line-spacing-eq-width-overlap': {'sizes':[(600,400)]}, + 'marker_line_placement_on_points':{}, + 'marker-with-background-image': {'sizes':[(600,400),(400,600),(257,256)]}, + #'marker-with-background-image-and-hsla-transform': {'sizes':[(600,400),(400,600),(257,256)]}, + 'marker-on-hex-grid': {'sizes':[(600,400),(400,600),(257,256)]}, + 'whole-centroid': {'sizes':[(600,400)], 'bbox': mapnik.Box2d(736908, 4390316, 2060771, 5942346)}, - {'name': "text-halo-rasterizer", 'sizes':[(600,400)]}, - {'name': "simple-E", 'bbox':mapnik.Box2d(-0.05, -0.01, 0.95, 0.01)}, - {'name': "simple-NE",'bbox':default_text_box}, - {'name': "simple-NW",'bbox':default_text_box}, - {'name': "simple-N",'bbox':default_text_box}, - {'name': "simple-SE",'bbox':default_text_box}, - {'name': "simple-SW",'bbox':default_text_box}, - {'name': "simple-S",'bbox':default_text_box}, - {'name': "simple-W",'bbox':default_text_box}, - {'name': "formatting-1",'bbox':default_text_box}, - {'name': "formatting-2",'bbox':default_text_box}, - {'name': "formatting-3",'bbox':default_text_box}, - {'name': "formatting-4",'bbox':default_text_box}, - {'name': "expressionformat",'bbox':default_text_box}, - {'name': "shieldsymbolizer-1", 'sizes': sizes_many_in_small_range,'bbox':default_text_box}, - {'name': "rtl-point", 'sizes': [(200, 200)],'bbox':default_text_box}, - {'name': "jalign-auto", 'sizes': [(200, 200)],'bbox':default_text_box}, - {'name': "line-offset", 'sizes':[(900, 250)],'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)}, - {'name': "tiff-alpha-gdal", 'sizes':[(600,400)]}, - {'name': "tiff-alpha-broken-assoc-alpha-gdal", 'sizes':[(600,400)]}, - {'name': "tiff-alpha-gradient-gdal", 'sizes':[(600,400)]}, - {'name': "tiff-nodata-edge-gdal", 'sizes':[(600,400),(969,793)]}, - {'name': "tiff-opaque-edge-gdal", 'sizes':[(256,256),(969,793)]}, - {'name': "tiff-opaque-edge-gdal2", 'sizes':[(600,400),(969,793)]}, - {'name': "tiff-opaque-edge-raster2", 'sizes':[(600,400),(969,793)]}, - {'name': "tiff-resampling", 'sizes':[(600,400)]}, + 'text-halo-rasterizer': {'sizes':[(600,400)]}, + 'simple-E': {'bbox':mapnik.Box2d(-0.05, -0.01, 0.95, 0.01)}, + 'simple-NE': {'bbox':default_text_box}, + 'simple-NW': {'bbox':default_text_box}, + 'simple-N': {'bbox':default_text_box}, + 'simple-SE': {'bbox':default_text_box}, + 'simple-SW': {'bbox':default_text_box}, + 'simple-S': {'bbox':default_text_box}, + 'simple-W': {'bbox':default_text_box}, + 'formatting-1': {'bbox':default_text_box}, + 'formatting-2': {'bbox':default_text_box}, + 'formatting-3': {'bbox':default_text_box}, + 'formatting-4': {'bbox':default_text_box}, + 'expressionformat': {'bbox':default_text_box}, + 'shieldsymbolizer-1': {'sizes': sizes_many_in_small_range,'bbox':default_text_box}, + 'rtl-point': {'sizes': [(200, 200)],'bbox':default_text_box}, + 'jalign-auto': {'sizes': [(200, 200)],'bbox':default_text_box}, + 'line-offset': {'sizes':[(900, 250)],'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)}, + 'tiff-alpha-gdal': {'sizes':[(600,400)]}, + 'tiff-alpha-broken-assoc-alpha-gdal': {'sizes':[(600,400)]}, + 'tiff-alpha-gradient-gdal': {'sizes':[(600,400)]}, + 'tiff-nodata-edge-gdal': {'sizes':[(600,400),(969,793)]}, + 'tiff-opaque-edge-gdal': {'sizes':[(256,256),(969,793)]}, + 'tiff-opaque-edge-gdal2': {'sizes':[(600,400),(969,793)]}, + 'tiff-opaque-edge-raster2': {'sizes':[(600,400),(969,793)]}, + 'tiff-resampling': {'sizes':[(600,400)]}, # https://github.com/mapnik/mapnik/issues/1622 - {'name': "tiff-edge-alignment-gdal1", 'sizes':[(256,256),(255,257)], + 'tiff-edge-alignment-gdal1': {'sizes':[(256,256),(255,257)], 'bbox':mapnik.Box2d(-13267022.12540147,4618019.500877209,-13247454.246160466,4637587.380118214) }, - {'name': "tiff-edge-alignment-gdal2", 'sizes':[(256,256),(255,257)], + 'tiff-edge-alignment-gdal2': {'sizes':[(256,256),(255,257)], 'bbox':mapnik.Box2d(-13267022.12540147,4598451.621636203,-13247454.246160466,4618019.500877209) }, # https://github.com/mapnik/mapnik/issues/1520 # commented because these are not critical failures - #{'name': "tiff-alpha-raster", 'sizes':[(600,400)]}, - #{'name': "tiff-alpha-broken-assoc-alpha-raster", 'sizes':[(600,400)]}, - #{'name': "tiff-nodata-edge-raster", 'sizes':[(600,400)]}, - #{'name': "tiff-opaque-edge-raster", 'sizes':[(256,256)]}, - ] + #'tiff-alpha-raster': {'sizes':[(600,400)]}, + #'tiff-alpha-broken-assoc-alpha-raster': {'sizes':[(600,400)]}, + #'tiff-nodata-edge-raster': {'sizes':[(600,400)]}, + #'tiff-opaque-edge-raster': {'sizes':[(256,256)]}, + } class Reporting: DIFF = 1 NOT_FOUND = 2 OTHER = 3 REPLACE = 4 - def __init__(self, quiet, generate = False, overwrite_failures = False): + def __init__(self, quiet, overwrite_failures = False): self.quiet = quiet self.passed = 0 self.failed = 0 - self.generate = generate self.overwrite_failures = overwrite_failures self.errors = [ #(type, actual, expected, diff, message) ] @@ -119,7 +123,7 @@ class Reporting: else: print '\x1b[31m✘\x1b[0m (\x1b[34m%u different pixels\x1b[0m)' % diff - if self.generate: + if self.overwrite_failures: self.errors.append((self.REPLACE, actual, expected, diff, None)) contents = open(actual, 'r').read() open(expected, 'wb').write(contents) @@ -139,10 +143,9 @@ class Reporting: if self.quiet: sys.stderr.write('\x1b[33m.\x1b[0m') else: - print '\x1b[33m?\x1b[0m (\x1b[34mReference file not found\x1b[0m)' - if self.generate: - contents = open(actual, 'r').read() - open(expected, 'wb').write(contents) + print '\x1b[33m?\x1b[0m (\x1b[34mReference file not found, creating\x1b[0m)' + contents = open(actual, 'r').read() + open(expected, 'wb').write(contents) def other_error(self, expected, message): self.failed += 1 @@ -152,24 +155,65 @@ class Reporting: else: print '\x1b[31m✘\x1b[0m (\x1b[34m%s\x1b[0m)' % message - def summary(self, generate=False): + def make_html_item(self,actual,expected,diff): + item = ''' +
+ + + +
+ ''' % (expected,expected,'%') + item += '
%s
' % (diff) + item += ''' +
+ + + +
+ ''' % (actual,actual,'%') + return item + + def summary(self): if len(self.errors) == 0: print '\nAll %s visual tests passed: \x1b[1;32m✓ \x1b[0m' % self.passed return 0 + sortable_errors = [] print "\nVisual rendering: %s failed / %s passed" % (len(self.errors), self.passed) for idx, error in enumerate(self.errors): if error[0] == self.OTHER: print str(idx+1) + ") \x1b[31mfailure to run test:\x1b[0m %s" % error[2] elif error[0] == self.NOT_FOUND: - if self.generate: - print str(idx+1) + ") Generating reference image: '%s'" % error[2] - else: - print str(idx+1) + ")Could not verify %s: No reference image found!" % error[1] + print str(idx+1) + ") Generating reference image: '%s'" % error[2] continue elif error[0] == self.DIFF: print str(idx+1) + ") \x1b[34m%s different pixels\x1b[0m:\n\t%s (\x1b[31mactual\x1b[0m)\n\t%s (\x1b[32mexpected\x1b[0m)" % (error[3], error[1], error[2]) + if '.png' in error[1]: # ignore grids + sortable_errors.append((error[3],error)) elif error[0] == self.REPLACE: print str(idx+1) + ") \x1b[31mreplaced reference with new version:\x1b[0m %s" % error[2] + if len(sortable_errors): + # drop failure results in folder + vdir = os.path.join(visual_output_dir,'visual-test-results') + if not os.path.exists(vdir): + os.makedirs(vdir) + html_template = open(os.path.join(dirname,'html_report_template.html'),'r').read() + name = 'comparison.html' + failures_realpath = os.path.join(vdir,name) + html_out = open(failures_realpath,'w+') + sortable_errors.sort(reverse=True) + html_body = '' + for item in sortable_errors: + # copy images into single directory + actual = item[1][1] + expected = item[1][2] + diff = item[0] + actual_new = os.path.join(vdir,os.path.basename(actual)) + shutil.copy(actual,actual_new) + expected_new = os.path.join(vdir,os.path.basename(expected)) + shutil.copy(expected,expected_new) + html_body += self.make_html_item(os.path.relpath(actual_new,vdir),os.path.relpath(expected_new,vdir),diff) + html_out.write(html_template.replace('{{RESULTS}}',html_body)) + print 'View failures by opening %s' % failures_realpath return 1 def render_cairo(m, output, scale_factor): @@ -196,7 +240,7 @@ renderers = [ { 'name': 'cairo', 'render': render_cairo, 'compare': lambda actual, reference: compare(actual, reference, alpha=False), - 'threshold': 0, + 'threshold': 1, 'filetype': 'png', 'dir': 'images' }, @@ -210,8 +254,7 @@ renderers = [ ] -def render(config, width, height, bbox, scale_factor, reporting): - filename = config['name'] +def render(filename,config, width, height, bbox, scale_factor, reporting): m = mapnik.Map(width, height) postfix = "%s-%d-%d-%s" % (filename, width, height, scale_factor) @@ -263,32 +306,32 @@ if __name__ == "__main__": else: overwrite_failures = False - if len(sys.argv) == 2: - files = [{"name": sys.argv[1], "sizes": sizes_few_square}] - elif len(sys.argv) > 2: - files = [] + select_files = {} + if len(sys.argv) > 1: for name in sys.argv[1:]: - files.append({"name": name}) + if name in files: + select_files[name]=files[name] + else: + select_files[name]={} + if len(select_files) > 0: + files = select_files if not os.path.exists(visual_output_dir): os.makedirs(visual_output_dir) + reporting = Reporting(quiet, overwrite_failures) + for filename in files: + config = dict(defaults) + config.update(files[filename]) + for size in config['sizes']: + for scale_factor in config['scales']: + m = render(filename, + config, + size[0], + size[1], + config.get('bbox'), + scale_factor, + reporting) + mapnik.save_map(m, os.path.join(dirname, 'xml_output', "%s-out.xml" % filename)) - if 'osm' in mapnik.DatasourceCache.plugin_names(): - reporting = Reporting(quiet, overwrite_failures) - for f in files: - config = dict(defaults) - config.update(f) - for size in config['sizes']: - for scale_factor in config['scales']: - m = render(config, - size[0], - size[1], - config.get('bbox'), - scale_factor, - reporting) - mapnik.save_map(m, os.path.join(dirname, 'xml_output', "%s-out.xml" % config['name'])) - - sys.exit(reporting.summary(generate=True)) - else: - print "OSM plugin required" + sys.exit(reporting.summary()) diff --git a/tests/visual_tests/test_python.py b/tests/visual_tests/test_python.py index 00857fbd1..ac5165c1d 100755 --- a/tests/visual_tests/test_python.py +++ b/tests/visual_tests/test_python.py @@ -71,7 +71,7 @@ m.append_style('Style', style) layer = mapnik.Layer('Layer') -layer.datasource = mapnik.Osm(file=os.path.join(dirname,"data/points.osm")) +layer.datasource = mapnik.Datasource(**{file=os.path.join(dirname,"data/points.csv")) layer.styles.append('Style') m.layers.append(layer) @@ -85,7 +85,7 @@ formatnode.fill = mapnik.Color("green") format_trees = [ ('TextNode', mapnik.FormattingText("[name]")), ('MyText', MyText()), - ('IfElse', IfElse("[nr] != '5'", + ('IfElse', IfElse("[nr] != 5", mapnik.FormattingText("[name]"), mapnik.FormattingText("'SPECIAL!'"))), ('Format', formatnode), diff --git a/utils/mapnik-config/build.py b/utils/mapnik-config/build.py index cee0e8eb3..6b94f3c37 100644 --- a/utils/mapnik-config/build.py +++ b/utils/mapnik-config/build.py @@ -9,16 +9,13 @@ Import('env') config_env = env.Clone() -# TODO -# major/minor versions -# git rev-list --max-count=1 HEAD - config_variables = '''#!/bin/sh ## variables CONFIG_PREFIX="$( cd "$( dirname $( dirname "$0" ))" && pwd )" +CONFIG_MAPNIK_VERSION_STRING='%(version_string)s' CONFIG_MAPNIK_VERSION='%(version)s' CONFIG_GIT_REVISION='%(git_revision)s' CONFIG_GIT_DESCRIBE='%(git_describe)s' @@ -32,6 +29,7 @@ CONFIG_MAPNIK_LDFLAGS='%(ldflags)s' CONFIG_MAPNIK_INCLUDE="${CONFIG_PREFIX}/include -I${CONFIG_PREFIX}/include/mapnik/agg" CONFIG_DEP_INCLUDES='%(dep_includes)s' CONFIG_CXXFLAGS='%(cxxflags)s' +CONFIG_CXX='%(cxx)s' ''' @@ -54,6 +52,7 @@ if config_env['HAS_CAIRO']: dep_includes += ''.join([' -I%s' % i for i in env['CAIRO_CPPPATHS'] if not i.startswith('#')]) ldflags = config_env['CUSTOM_LDFLAGS'] + ''.join([' -L%s' % i for i in config_env['LIBPATH'] if not i.startswith('#')]) +ldflags += config_env['LIBMAPNIK_LINKFLAGS'] dep_libs = ''.join([' -l%s' % i for i in env['LIBMAPNIK_LIBS']]) @@ -98,7 +97,8 @@ lib_path = "${CONFIG_PREFIX}/" + config_env['LIBDIR_SCHEMA'] configuration = { "git_revision": git_revision, "git_describe": git_describe, - "version": config_env['MAPNIK_VERSION_STRING'], + "version_string": config_env['MAPNIK_VERSION_STRING'], + "version": config_env['MAPNIK_VERSION'], "mapnik_libname": 'mapnik', "mapnik_libpath": lib_path, "ldflags": ldflags, @@ -107,7 +107,8 @@ configuration = { "fonts": fontspath, "input_plugins": inputpluginspath, "defines":defines, - "cxxflags":cxxflags + "cxxflags":cxxflags, + "cxx":env['CXX'] } ## if we are statically linking depedencies diff --git a/utils/mapnik-config/mapnik-config.template.sh b/utils/mapnik-config/mapnik-config.template.sh index 4ba0ca504..a71fdf642 100755 --- a/utils/mapnik-config/mapnik-config.template.sh +++ b/utils/mapnik-config/mapnik-config.template.sh @@ -9,21 +9,24 @@ Usage: mapnik-config [OPTION] Known values for OPTION are: -h --help display this help and exit - -v --version version information + -v --version version information (MAPNIK_VERSION_STRING) + --version-number version number (MAPNIK_VERSION) (new in 2.2.0) --git-revision git hash from "git rev-list --max-count=1 HEAD" - --git-describe git decribe output (new in 2.2.x) + --git-describe git decribe output (new in 2.2.0) --fonts default fonts directory --input-plugins default input plugins directory - --defines pre-processor defines for Mapnik build (new in 2.2.x) + --defines pre-processor defines for Mapnik build (new in 2.2.0) --prefix Mapnik prefix [default $CONFIG_PREFIX] --lib-name Mapnik library name --libs library linking information --dep-libs library linking information for Mapnik dependencies --ldflags library paths (-L) information - --includes include paths (-I) for Mapnik headers (new in 2.2.x) - --dep-includes include paths (-I) for Mapnik dependencies (new in 2.2.x) - --cxxflags c++ compiler flags and pre-processor defines (new in 2.2.x) + --includes include paths (-I) for Mapnik headers (new in 2.2.0) + --dep-includes include paths (-I) for Mapnik dependencies (new in 2.2.0) + --cxxflags c++ compiler flags and pre-processor defines (new in 2.2.0) --cflags all include paths, compiler flags, and pre-processor defines (for back-compatibility) + --cxx c++ compiler used to build mapnik (new in 2.2.0) + --all-flags all compile and link flags (new in 2.2.0) EOF exit $1 @@ -50,11 +53,15 @@ while test $# -gt 0; do ;; -v) - echo ${CONFIG_MAPNIK_VERSION} + echo ${CONFIG_MAPNIK_VERSION_STRING} ;; --version) - echo $CONFIG_MAPNIK_VERSION + echo ${CONFIG_MAPNIK_VERSION_STRING} + ;; + + --version-number) + echo ${CONFIG_MAPNIK_VERSION} ;; --git-revision) @@ -113,6 +120,14 @@ while test $# -gt 0; do echo -I${CONFIG_MAPNIK_INCLUDE} ${CONFIG_DEP_INCLUDES} ${CONFIG_MAPNIK_DEFINES} ${CONFIG_CXXFLAGS} ;; + --cxx) + echo ${CONFIG_CXX} + ;; + + --all-flags) + echo -I${CONFIG_MAPNIK_INCLUDE} ${CONFIG_DEP_INCLUDES} ${CONFIG_MAPNIK_DEFINES} ${CONFIG_CXXFLAGS} -L${CONFIG_MAPNIK_LIBPATH} -l${CONFIG_MAPNIK_LIBNAME} ${CONFIG_MAPNIK_LDFLAGS} ${CONFIG_DEP_LIBS} + ;; + *) # push to stderr any invalid options echo "unknown option $1" 1>&2;