diff --git a/.travis.yml b/.travis.yml index 433e98a73..967786acd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: c +language: cpp git: depth: 10 @@ -9,16 +9,12 @@ env: - CCACHE_TEMPDIR=/tmp/.ccache-temp - CCACHE_COMPRESS=1 - HEAVY_JOBS="2" + - PREFIX=/tmp/mapnik - secure: "N3a5nzzsgpuu45k8qWdYsHNxrSnqeAGLTOYpfYoAH7B94vuf7pa7XV1tQjXbxrnx2D6ryTdtUtyRKwy7zXbwXxGt4DpczWEo8f6DUd6+obAp3kdnXABg2Sj4oA7KMs0F0CmoADy0jdUZD5YyOJHu64LCIIgzEQ9q49PFMNbU3IE=" - secure: "iQYPNpMtejcgYeUkWZGIWz1msIco5qydJrhZTSCQOYahAQerdT7q5WZEpEo3G6IWOGgO1eo7GFuY8DvqQjw1+jC9b9mhkRNdo3LhGTKS9Gsbl5Q27k0rjlaFZmmQHrfPlQJwhfAIp+KLugHtQw5bCoLh+95E3j0F0DayF1tuJ3s=" + - secure: "F6ivqDNMBQQnrDGA9+7IX+GDswuIqQQd7YPJdQqa2Ked9jddAQDeJClb05ig3JlwfOlYLGZOd43ZX0pKuMtI2Gbkwz211agGP9S3YunwlRg8iWtJlO5kYFUdKCmJNhjg4icfkGELCgwXn+zuEWFSLpkPcjqAFKFlQrIJeAJJgKM=" addons: postgresql: "9.4" - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.6 - packages: - - clang-3.6 cache: directories: @@ -28,22 +24,32 @@ matrix: include: - os: linux sudo: false - compiler: clang - env: JOBS=8 CXX="ccache clang++-3.6 -Qunused-arguments" CC="clang-3.6" MASON_PUBLISH=False BENCH=False + compiler: ": clang" + env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" TRIGGER=true addons: - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ] - packages: [ 'clang-3.6', 'libstdc++-4.9-dev', 'libstdc++6' ] + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6', 'libstdc++-5-dev'] + - os: linux + sudo: false + compiler: ": clang-coverage" + env: JOBS=8 COVERAGE=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++6','libstdc++-5-dev' ] - os: osx - compiler: clang + compiler: ": clang-osx" # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions osx_image: xcode7.3 # upgrades clang from 6 -> 7 - env: JOBS=4 MASON_PUBLISH=False + env: JOBS=4 MASON_PUBLISH=true _CXX="ccache clang++ -Qunused-arguments" before_install: + - if [[ ${_CXX:-false} != false ]]; then export CXX=${_CXX}; fi + - if [[ ${_CC:-false} != false ]]; then export CC=${_CC}; fi - source scripts/travis-common.sh - export PYTHONUSERBASE=$(pwd)/mason_packages/.link - - export PATH=$(pwd)/mason_packages/.link/bin:${PYTHONUSERBASE}/bin:${PATH} + - export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PYTHONUSERBASE}/bin:${PATH} - export COVERAGE=${COVERAGE:-false} - export MASON_PUBLISH=${MASON_PUBLISH:-false} - export BENCH=${BENCH:-false} @@ -52,12 +58,13 @@ before_install: - git_submodule_update --init --depth=10 install: - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then export CCACHE_READONLY=1; fi - on 'linux' export PYTHONPATH=${PYTHONUSERBASE}/lib/python2.7/site-packages - on 'osx' export PYTHONPATH=${PYTHONUSERBASE}/lib/python/site-packages - - on 'osx' brew rm postgis --force - - on 'osx' brew install postgis --force - - on 'osx' pg_ctl -w start -l postgres.log --pgdata /usr/local/var/postgres + - on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres + - on 'osx' rm -rf ${DATA_PATH} + - on 'osx' initdb ${DATA_PATH} -E utf8 + - on 'osx' pg_ctl -w start -l postgres.log --pgdata ${DATA_PATH}; + - on 'osx' cat postgres.log; - on 'osx' createuser -s postgres - psql -c 'create database template_postgis;' -U postgres - psql -c 'create extension postgis;' -d template_postgis -U postgres @@ -65,6 +72,13 @@ install: before_script: - source bootstrap.sh + - | + if [[ $(uname -s) == 'Linux' ]]; then + mason install clang 3.8.0 + export PATH=$(mason prefix clang 3.8.0)/bin:${PATH} + which clang++ + export LLVM_COV="$(mason prefix clang 3.8.0)/bin/llvm-cov" + fi - ccache --version - ccache -p || true - ccache --show-stats || true @@ -73,14 +87,16 @@ before_script: script: - export SCONSFLAGS='--debug=time' - configure BENCHMARK=${BENCH} + - cat config.log - make - make test - enabled ${COVERAGE} coverage - enabled ${BENCH} make bench after_success: + - enabled ${TRIGGER} trigger_downstream - if enabled ${MASON_PUBLISH}; then + source ./.mason/mason.sh && ./mason_latest.sh build && - ./mason_latest.sh link && ./mason_latest.sh publish; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 35925a7b8..45467bc9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,12 +10,16 @@ For a complete change history, see the git log. Released: -(Packaged from ) +(Packaged from 8d9dc27) #### Summary - Raster scaling: fixed crash and clipping negative pixel values of floating point rasters (https://github.com/mapnik/mapnik/pull/3349) - + - Restored support for unquoted strings in expressions (https://github.com/mapnik/mapnik/pull/3390) + - [TWKB](https://github.com/TWKB/) support via https://github.com/mapnik/mapnik/pull/3356 (#3355) + - Visual test runner can render SVG, PDF and Postscript with Cairo renderer (https://github.com/mapnik/mapnik/pull/3418) + - Scale factor is now applied also to `text-line-spacing` and transforms (https://github.com/mapnik/mapnik/pull/3416) + ## 3.0.10 Released: February 25, 2016 diff --git a/INSTALL.md b/INSTALL.md index d27004dbd..8992144b1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -98,7 +98,7 @@ Additional optional dependencies: * PostgreSQL (for PostGIS plugin support) - libpq - PostreSQL libraries - pg_config - PostgreSQL installation capabilities - * libgdal - GDAL/OGR input (For gdal and ogr plugin support) + * libgdal - GDAL/OGR input (For gdal and ogr plugin support) (>= GDAL 2.0.2 for thread safety - https://github.com/mapnik/mapnik/issues/3339) * libsqlite3 - SQLite input (needs RTree support builtin) (sqlite plugin support) Instructions for installing many of these dependencies on diff --git a/README.md b/README.md index b5ebf6a3e..e99df9825 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ _/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/ ``` [![Build Status Linux](https://api.travis-ci.org/mapnik/mapnik.svg?branch=master)](http://travis-ci.org/mapnik/mapnik) +[![CircleCI](https://circleci.com/gh/mapnik/mapnik.svg?style=svg)](https://circleci.com/gh/mapnik/mapnik) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/hc9l7okdjtucfqqn?branch=master&svg=true)](https://ci.appveyor.com/project/Mapbox/mapnik) [![Coverage Status](https://coveralls.io/repos/mapnik/mapnik/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapnik/mapnik?branch=master) @@ -20,7 +21,7 @@ For further information see [http://mapnik.org](http://mapnik.org) and also our # Installation -See [INSTALL.md](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides. +See [INSTALL.md](INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides. # Code of Conduct @@ -28,4 +29,4 @@ Please note that this project is released with a [Contributor Code of Conduct](h # License -Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information. +Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information. diff --git a/SConstruct b/SConstruct index 1e4e156ee..204e5a28f 100644 --- a/SConstruct +++ b/SConstruct @@ -105,28 +105,28 @@ pretty_dep_names = { # Core plugin build configuration # opts.AddVariables still hardcoded however... PLUGINS = { # plugins with external dependencies - # configured by calling project, hence 'path':None - 'postgis': {'default':True,'path':None,'inc':'libpq-fe.h','lib':'pq','lang':'C'}, - 'pgraster': {'default':True,'path':None,'inc':'libpq-fe.h','lib':'pq','lang':'C'}, - 'gdal': {'default':True,'path':None,'inc':'gdal_priv.h','lib':'gdal','lang':'C++'}, - 'ogr': {'default':True,'path':None,'inc':'ogrsf_frmts.h','lib':'gdal','lang':'C++'}, - 'sqlite': {'default':True,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'}, - # plugins without external dependencies requiring CheckLibWithHeader... - 'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'}, - '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++'}, - 'topojson':{'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'} - } + # configured by calling project, hence 'path':None + 'postgis': {'default':True,'path':None,'inc':'libpq-fe.h','lib':'pq','lang':'C'}, + 'pgraster': {'default':True,'path':None,'inc':'libpq-fe.h','lib':'pq','lang':'C'}, + 'gdal': {'default':True,'path':None,'inc':'gdal_priv.h','lib':'gdal','lang':'C++'}, + 'ogr': {'default':True,'path':None,'inc':'ogrsf_frmts.h','lib':'gdal','lang':'C++'}, + 'sqlite': {'default':True,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'}, + # plugins without external dependencies requiring CheckLibWithHeader... + 'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'}, + '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++'}, + 'topojson':{'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'} + } def init_environment(env): env.Decider('MD5-timestamp') env.SourceCode(".", None) if os.environ.get('RANLIB'): - env['RANLIB'] = os.environ['RANLIB'] + env['RANLIB'] = os.environ['RANLIB'] if os.environ.get('AR'): - env['AR'] = os.environ['AR'] + env['AR'] = os.environ['AR'] #### SCons build options and initial setup #### env = Environment(ENV=os.environ) @@ -142,58 +142,58 @@ def color_print(color,text,newline=True): # 4 - blue text = "\033[9%sm%s\033[0m" % (color,text) if not newline: - print text, + print text, else: - print text + print text def regular_print(color,text,newline=True): if not newline: - print text, + print text, else: - print text + print text def call(cmd, silent=False): stdin, stderr = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).communicate() if not stderr: - return stdin.strip() + return stdin.strip() elif not silent: - color_print(1,'Problem encounted with SCons scripts, please post bug report to: https://github.com/mapnik/mapnik/issues \nError was: %s' % stderr) + color_print(1,'Problem encounted with SCons scripts, please post bug report to: https://github.com/mapnik/mapnik/issues \nError was: %s' % stderr) def strip_first(string,find,replace=''): if string.startswith(find): - return string.replace(find,replace,1) + return string.replace(find,replace,1) return string # http://www.scons.org/wiki/InstallTargets def create_uninstall_target(env, path, is_glob=False): if 'uninstall' in COMMAND_LINE_TARGETS: - if is_glob: - all_files = Glob(path,strings=True) - for filei in all_files: - env.Command( "uninstall-"+filei, filei, - [ - Delete("$SOURCE"), - ]) - env.Alias("uninstall", "uninstall-"+filei) - else: - if os.path.exists(path): - env.Command( "uninstall-"+path, path, - [ - Delete("$SOURCE"), - ]) - env.Alias("uninstall", "uninstall-"+path) + if is_glob: + all_files = Glob(path,strings=True) + for filei in all_files: + env.Command( "uninstall-"+filei, filei, + [ + Delete("$SOURCE"), + ]) + env.Alias("uninstall", "uninstall-"+filei) + else: + if os.path.exists(path): + env.Command( "uninstall-"+path, path, + [ + Delete("$SOURCE"), + ]) + env.Alias("uninstall", "uninstall-"+path) def shortest_name(libs): name = '-'*200 for lib in libs: - if len(name) > len(lib): - name = lib + if len(name) > len(lib): + name = lib return name def rm_path(item,set,_env): for i in _env[set]: - if i.startswith(item): - _env[set].remove(i) + if i.startswith(item): + _env[set].remove(i) def sort_paths(items,priority): """Sort paths such that compiling and linking will globally prefer custom or local libs @@ -217,57 +217,57 @@ def sort_paths(items,priority): # parse types of paths into logical/meaningful groups # based on commonly encountered lib directories on linux and osx for i in items: - # internal paths for code kept inside - # the mapnik sources - if i.startswith('#'): - path_types['internal'].append(i) - # Mac OS X user installed frameworks - elif '/Library/Frameworks' in i: - path_types['frameworks'].append(i) - # various 'local' installs like /usr/local or /opt/local - elif 'local' in i or '/sw' in i: - if '/usr/local' in i: - path_types['user'].insert(0,i) - else: - path_types['user'].append(i) - # key system libs (likely others will fall into 'other') - elif '/usr/' in i or '/System' in i or i.startswith('/lib'): - path_types['system'].append(i) - # anything not yet matched... - # likely a combo of rare system lib paths and - # very custom user paths that should ideally be - # in 'user' - else: - path_types['other'].append(i) + # internal paths for code kept inside + # the mapnik sources + if i.startswith('#'): + path_types['internal'].append(i) + # Mac OS X user installed frameworks + elif '/Library/Frameworks' in i: + path_types['frameworks'].append(i) + # various 'local' installs like /usr/local or /opt/local + elif 'local' in i or '/sw' in i: + if '/usr/local' in i: + path_types['user'].insert(0,i) + else: + path_types['user'].append(i) + # key system libs (likely others will fall into 'other') + elif '/usr/' in i or '/System' in i or i.startswith('/lib'): + path_types['system'].append(i) + # anything not yet matched... + # likely a combo of rare system lib paths and + # very custom user paths that should ideally be + # in 'user' + else: + path_types['other'].append(i) # build up new list based on priority list for path in priority: - if path_types.has_key(path): - dirs = path_types[path] - new.extend(dirs) - path_types.pop(path) - else: - color_print(1,'\nSorry, "%s" is NOT a valid value for option "LINK_PRIORITY": values include: %s' % (path,','.join(path_types.keys()))) - color_print(1,'\tinternal: the local directory of the Mapnik sources (prefix #) (eg. used to link internal agg)') - color_print(1,'\tframeworks: on osx the /Library/Frameworks directory') - color_print(1,'\tuser: any path with "local" or "/sw" inside it') - color_print(1,'\tsystem: any path not yet matched with "/usr/","/lib", or "/System" (osx) inside it') - color_print(1,'\tother: any paths you specified not matched by criteria used to parse the others') - color_print(1,'\tother: any paths you specified not matched by criteria used to parse the others') - color_print(1,'The Default priority is: %s' % ','.join(DEFAULT_LINK_PRIORITY)) - color_print(1,'Any priority groups not listed will be appended to the list at the end') - Exit(1) + if path_types.has_key(path): + dirs = path_types[path] + new.extend(dirs) + path_types.pop(path) + else: + color_print(1,'\nSorry, "%s" is NOT a valid value for option "LINK_PRIORITY": values include: %s' % (path,','.join(path_types.keys()))) + color_print(1,'\tinternal: the local directory of the Mapnik sources (prefix #) (eg. used to link internal agg)') + color_print(1,'\tframeworks: on osx the /Library/Frameworks directory') + color_print(1,'\tuser: any path with "local" or "/sw" inside it') + color_print(1,'\tsystem: any path not yet matched with "/usr/","/lib", or "/System" (osx) inside it') + color_print(1,'\tother: any paths you specified not matched by criteria used to parse the others') + color_print(1,'\tother: any paths you specified not matched by criteria used to parse the others') + color_print(1,'The Default priority is: %s' % ','.join(DEFAULT_LINK_PRIORITY)) + color_print(1,'Any priority groups not listed will be appended to the list at the end') + Exit(1) # append remaining paths potentially not requested # by any custom priority list defined by user for k,v in path_types.items(): - new.extend(v) + new.extend(v) return new def pretty_dep(dep): pretty = pretty_dep_names.get(dep) if pretty: - return '%s (%s)' % (dep,pretty) + return '%s (%s)' % (dep,pretty) elif 'boost' in dep: - return '%s (%s)' % (dep,'more info see: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation & http://www.boost.org') + return '%s (%s)' % (dep,'more info see: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation & http://www.boost.org') return dep @@ -319,7 +319,6 @@ opts.AddVariables( ('PATH_REMOVE', 'A path prefix to exclude from all known command and compile paths (create multiple excludes separated by :)', ''), ('PATH_REPLACE', 'Two path prefixes (divided with a :) to search/replace from all known command and compile paths', ''), ('MAPNIK_NAME', 'Name of library', 'mapnik'), - BoolVariable('MAPNIK_BUNDLED_SHARE_DIRECTORY', 'For portable packaging: instruct mapnik-config to report relative paths to bundled GDAL_DATA, PROJ_LIB, and ICU_DATA','False'), # Boost variables # default is '/usr/include', see FindBoost method below @@ -414,74 +413,74 @@ opts.AddVariables( # these include all scons core variables as well as custom # env variables needed in SConscript files pickle_store = [# Scons internal variables - 'CC', # compiler user to check if c deps compile during configure - 'CXX', # C++ compiler to compile mapnik - 'CFLAGS', - 'CPPDEFINES', - 'CPPFLAGS', # c preprocessor flags - 'CPPPATH', - 'CXXFLAGS', # C++ flags built up during configure - 'LIBPATH', - 'LIBS', - 'LINKFLAGS', - 'CUSTOM_LDFLAGS', # user submitted - 'CUSTOM_DEFINES', # user submitted - 'CUSTOM_CXXFLAGS', # user submitted - 'CUSTOM_CFLAGS', # user submitted - 'MAPNIK_LIB_NAME', - 'LINK', - 'RUNTIME_LINK', - # Mapnik's SConstruct build variables - 'PLUGINS', - 'ABI_VERSION', - 'MAPNIK_VERSION_STRING', - 'MAPNIK_VERSION', - 'PLATFORM', - 'BOOST_ABI', - 'BOOST_APPEND', - 'LIBDIR_SCHEMA', - 'REQUESTED_PLUGINS', - 'COLOR_PRINT', - 'HAS_CAIRO', - 'MAPNIK_HAS_DLFCN', - 'HAS_PYCAIRO', - 'PYCAIRO_PATHS', - 'HAS_LIBXML2', - 'PKG_CONFIG_PATH', - 'PATH', - 'PATH_REMOVE', - 'PATH_REPLACE', - 'MAPNIK_LIB_DIR', - 'MAPNIK_LIB_DIR_DEST', - 'INSTALL_PREFIX', - 'MAPNIK_INPUT_PLUGINS', - 'MAPNIK_INPUT_PLUGINS_DEST', - 'MAPNIK_FONTS', - 'MAPNIK_FONTS_DEST', - 'MAPNIK_BUNDLED_SHARE_DIRECTORY', - 'MAPNIK_LIB_BASE', - 'MAPNIK_LIB_BASE_DEST', - 'EXTRA_FREETYPE_LIBS', - 'LIBMAPNIK_CPPATHS', - 'LIBMAPNIK_DEFINES', - 'LIBMAPNIK_CXXFLAGS', - 'CAIRO_LIBPATHS', - 'CAIRO_ALL_LIBS', - 'CAIRO_CPPPATHS', - 'GRID_RENDERER', - 'SVG_RENDERER', - 'SQLITE_LINKFLAGS', - 'BOOST_LIB_VERSION_FROM_HEADER', - 'BIGINT', - 'HOST' - ] + 'CC', # compiler user to check if c deps compile during configure + 'CXX', # C++ compiler to compile mapnik + 'CFLAGS', + 'CPPDEFINES', + 'CPPFLAGS', # c preprocessor flags + 'CPPPATH', + 'CXXFLAGS', # C++ flags built up during configure + 'LIBPATH', + 'LIBS', + 'LINKFLAGS', + 'CUSTOM_LDFLAGS', # user submitted + 'CUSTOM_DEFINES', # user submitted + 'CUSTOM_CXXFLAGS', # user submitted + 'CUSTOM_CFLAGS', # user submitted + 'MAPNIK_LIB_NAME', + 'LINK', + 'RUNTIME_LINK', + # Mapnik's SConstruct build variables + 'PLUGINS', + 'ABI_VERSION', + 'MAPNIK_VERSION_STRING', + 'MAPNIK_VERSION', + 'PLATFORM', + 'BOOST_ABI', + 'BOOST_APPEND', + 'LIBDIR_SCHEMA', + 'REQUESTED_PLUGINS', + 'COLOR_PRINT', + 'HAS_CAIRO', + 'MAPNIK_HAS_DLFCN', + 'HAS_PYCAIRO', + 'PYCAIRO_PATHS', + 'HAS_LIBXML2', + 'PKG_CONFIG_PATH', + 'PATH', + 'PATH_REMOVE', + 'PATH_REPLACE', + 'MAPNIK_LIB_DIR', + 'MAPNIK_LIB_DIR_DEST', + 'INSTALL_PREFIX', + 'MAPNIK_INPUT_PLUGINS', + 'MAPNIK_INPUT_PLUGINS_DEST', + 'MAPNIK_FONTS', + 'MAPNIK_FONTS_DEST', + 'MAPNIK_BUNDLED_SHARE_DIRECTORY', + 'MAPNIK_LIB_BASE', + 'MAPNIK_LIB_BASE_DEST', + 'EXTRA_FREETYPE_LIBS', + 'LIBMAPNIK_CPPATHS', + 'LIBMAPNIK_DEFINES', + 'LIBMAPNIK_CXXFLAGS', + 'CAIRO_LIBPATHS', + 'CAIRO_ALL_LIBS', + 'CAIRO_CPPPATHS', + 'GRID_RENDERER', + 'SVG_RENDERER', + 'SQLITE_LINKFLAGS', + 'BOOST_LIB_VERSION_FROM_HEADER', + 'BIGINT', + 'HOST' + ] # Add all other user configurable options to pickle pickle_store # We add here more options than are needed for the build stage # but helpful so that scons -h shows the exact cached options for opt in opts.options: if opt.key not in pickle_store: - pickle_store.append(opt.key) + pickle_store.append(opt.key) # Method of adding configure behavior to Scons adapted from: # http://freeorion.svn.sourceforge.net/svnroot/freeorion/trunk/FreeOrion/SConstruct @@ -513,24 +512,24 @@ opts.Update(env) # if we are not configuring overwrite environment with pickled settings if not force_configure: if os.path.exists(SCONS_CONFIGURE_CACHE): - try: - pickled_environment = open(SCONS_CONFIGURE_CACHE, 'r') - pickled_values = pickle.load(pickled_environment) - for key, value in pickled_values.items(): - env[key] = value - preconfigured = True - except: - preconfigured = False + try: + pickled_environment = open(SCONS_CONFIGURE_CACHE, 'r') + pickled_values = pickle.load(pickled_environment) + for key, value in pickled_values.items(): + env[key] = value + preconfigured = True + except: + preconfigured = False else: - preconfigured = False + preconfigured = False # check for missing keys in pickled settings # which can occur when keys are added or changed between # rebuilds, e.g. for folks following trunk for opt in pickle_store: if not opt in env: - #print 'missing opt', opt - preconfigured = False + #print 'missing opt', opt + preconfigured = False # if custom arguments are supplied make sure to accept them if opts.args: @@ -543,8 +542,8 @@ if opts.args: elif preconfigured: if not HELP_REQUESTED: - color_print(4,'Using previous successful configuration...') - color_print(4,'Re-configure by running "python scons/scons.py configure".') + color_print(4,'Using previous successful configuration...') + color_print(4,'Re-configure by running "python scons/scons.py configure".') if env.has_key('COLOR_PRINT') and env['COLOR_PRINT'] == False: color_print = regular_print @@ -560,11 +559,11 @@ def prioritize_paths(context,silent=True): env = context.env prefs = env['LINK_PRIORITY'].split(',') if not silent: - context.Message( 'Sorting lib and inc compiler paths...') + context.Message( 'Sorting lib and inc compiler paths...') env['LIBPATH'] = sort_paths(env['LIBPATH'],prefs) env['CPPPATH'] = sort_paths(env['CPPPATH'],prefs) if silent: - context.did_show_result=1 + context.did_show_result=1 ret = context.Result( True ) return ret @@ -591,42 +590,42 @@ def parse_config(context, config, checks='--libs --cflags'): tool = config.lower().replace('_','-') toolname = tool if config in ('GDAL_CONFIG'): - toolname += ' %s' % checks + toolname += ' %s' % checks context.Message( 'Checking for %s... ' % toolname) cmd = '%s %s' % (env[config],checks) ret = context.TryAction(cmd)[0] parsed = False if ret: - try: - if 'gdal-config' in cmd: - env.ParseConfig(cmd) - # hack for potential -framework GDAL syntax - # which will not end up being added to env['LIBS'] - # and thus breaks knowledge below that gdal worked - # TODO - upgrade our scons logic to support Framework linking - if env['PLATFORM'] == 'Darwin': - value = call(cmd,silent=True) - if value and '-framework GDAL' in value: - env['LIBS'].append('gdal') - if os.path.exists('/Library/Frameworks/GDAL.framework/unix/lib'): - env['LIBPATH'].insert(0,'/Library/Frameworks/GDAL.framework/unix/lib') - if 'GDAL' in env.get('FRAMEWORKS',[]): - env["FRAMEWORKS"].remove("GDAL") - else: - env.ParseConfig(cmd) - parsed = True - except OSError, e: - ret = False - print ' (xml2-config not found!)' + try: + if 'gdal-config' in cmd: + env.ParseConfig(cmd) + # hack for potential -framework GDAL syntax + # which will not end up being added to env['LIBS'] + # and thus breaks knowledge below that gdal worked + # TODO - upgrade our scons logic to support Framework linking + if env['PLATFORM'] == 'Darwin': + value = call(cmd,silent=True) + if value and '-framework GDAL' in value: + env['LIBS'].append('gdal') + if os.path.exists('/Library/Frameworks/GDAL.framework/unix/lib'): + env['LIBPATH'].insert(0,'/Library/Frameworks/GDAL.framework/unix/lib') + if 'GDAL' in env.get('FRAMEWORKS',[]): + env["FRAMEWORKS"].remove("GDAL") + else: + env.ParseConfig(cmd) + parsed = True + except OSError, e: + ret = False + print ' (xml2-config not found!)' if not parsed: - if config in ('GDAL_CONFIG'): - # optional deps... - if tool not in env['SKIPPED_DEPS']: - env['SKIPPED_DEPS'].append(tool) - conf.rollback_option(config) - else: # freetype and libxml2, not optional - if tool not in env['MISSING_DEPS']: - env['MISSING_DEPS'].append(tool) + if config in ('GDAL_CONFIG'): + # optional deps... + if tool not in env['SKIPPED_DEPS']: + env['SKIPPED_DEPS'].append(tool) + conf.rollback_option(config) + else: # freetype and libxml2, not optional + if tool not in env['MISSING_DEPS']: + env['MISSING_DEPS'].append(tool) context.Result( ret ) return ret @@ -639,22 +638,22 @@ def get_pkg_lib(context, config, lib): ret = context.TryAction(cmd)[0] parsed = False if ret: - try: - value = call(cmd,silent=True) - if ' ' in value: - parts = value.split(' ') - if len(parts) > 1: - value = parts[1] - libnames = re.findall(libpattern,value) - if libnames: - libname = libnames[0] - else: - # osx 1.8 install gives '-framework GDAL' - libname = 'gdal' - except Exception, e: - ret = False - print ' unable to determine library name:'# %s' % str(e) - return None + try: + value = call(cmd,silent=True) + if ' ' in value: + parts = value.split(' ') + if len(parts) > 1: + value = parts[1] + libnames = re.findall(libpattern,value) + if libnames: + libname = libnames[0] + else: + # osx 1.8 install gives '-framework GDAL' + libname = 'gdal' + except Exception, e: + ret = False + print ' unable to determine library name:'# %s' % str(e) + return None context.Result( libname ) return libname @@ -665,15 +664,15 @@ def parse_pg_config(context, config): context.Message( 'Checking for %s... ' % tool) ret = context.TryAction(env[config])[0] if ret: - lib_path = call('%s --libdir' % env[config]) - inc_path = call('%s --includedir' % env[config]) - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) - lpq = env['PLUGINS']['postgis']['lib'] - env.Append(LIBS = lpq) + lib_path = call('%s --libdir' % env[config]) + inc_path = call('%s --includedir' % env[config]) + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) + lpq = env['PLUGINS']['postgis']['lib'] + env.Append(LIBS = lpq) else: - env['SKIPPED_DEPS'].append(tool) - conf.rollback_option(config) + env['SKIPPED_DEPS'].append(tool) + conf.rollback_option(config) context.Result( ret ) return ret @@ -682,8 +681,8 @@ def ogr_enabled(context): context.Message( 'Checking if gdal is ogr enabled... ') ret = context.TryAction('%s --ogr-enabled' % env['GDAL_CONFIG'])[0] if not ret: - if 'ogr' not in env['SKIPPED_DEPS']: - env['SKIPPED_DEPS'].append('ogr') + if 'ogr' not in env['SKIPPED_DEPS']: + env['SKIPPED_DEPS'].append('ogr') context.Result( ret ) return ret @@ -691,8 +690,8 @@ def rollback_option(context,variable): global opts env = context.env for item in opts.options: - if item.key == variable: - env[variable] = item.default + if item.key == variable: + env[variable] = item.default def FindBoost(context, prefixes, thread_flag): """Routine to auto-find boost header dir, lib dir, and library naming structure. @@ -705,74 +704,70 @@ def FindBoost(context, prefixes, thread_flag): BOOST_INCLUDE_DIR = None BOOST_APPEND = None env['BOOST_APPEND'] = str() - - if env['THREADING'] == 'multi': - search_lib = 'libboost_thread' - else: - search_lib = 'libboost_filesystem' + search_lib = 'libboost_filesystem' # note: must call normpath to strip trailing slash otherwise dirname # does not remove 'lib' and 'include' prefixes.insert(0,os.path.dirname(os.path.normpath(env['BOOST_INCLUDES']))) prefixes.insert(0,os.path.dirname(os.path.normpath(env['BOOST_LIBS']))) for searchDir in prefixes: - libItems = glob(os.path.join(searchDir, env['LIBDIR_SCHEMA'], '%s*.*' % search_lib)) - if not libItems: - libItems = glob(os.path.join(searchDir, 'lib/%s*.*' % search_lib)) - incItems = glob(os.path.join(searchDir, 'include/boost*/')) - if len(libItems) >= 1 and len(incItems) >= 1: - BOOST_LIB_DIR = os.path.dirname(libItems[0]) - BOOST_INCLUDE_DIR = incItems[0].rstrip('boost/') - shortest_lib_name = shortest_name(libItems) - match = re.search(r'%s(.*)\..*' % search_lib, shortest_lib_name) - if hasattr(match,'groups'): - BOOST_APPEND = match.groups()[0] - break + libItems = glob(os.path.join(searchDir, env['LIBDIR_SCHEMA'], '%s*.*' % search_lib)) + if not libItems: + libItems = glob(os.path.join(searchDir, 'lib/%s*.*' % search_lib)) + incItems = glob(os.path.join(searchDir, 'include/boost*/')) + if len(libItems) >= 1 and len(incItems) >= 1: + BOOST_LIB_DIR = os.path.dirname(libItems[0]) + BOOST_INCLUDE_DIR = incItems[0].rstrip('boost/') + shortest_lib_name = shortest_name(libItems) + match = re.search(r'%s(.*)\..*' % search_lib, shortest_lib_name) + if hasattr(match,'groups'): + BOOST_APPEND = match.groups()[0] + break msg = str() if BOOST_LIB_DIR: - msg += '\nFound boost libs: %s' % BOOST_LIB_DIR - env['BOOST_LIBS'] = BOOST_LIB_DIR + msg += '\nFound boost libs: %s' % BOOST_LIB_DIR + env['BOOST_LIBS'] = BOOST_LIB_DIR elif not env['BOOST_LIBS']: - env['BOOST_LIBS'] = '/usr/' + env['LIBDIR_SCHEMA'] - msg += '\nUsing default boost lib dir: %s' % env['BOOST_LIBS'] + env['BOOST_LIBS'] = '/usr/' + env['LIBDIR_SCHEMA'] + msg += '\nUsing default boost lib dir: %s' % env['BOOST_LIBS'] else: - msg += '\nUsing boost lib dir: %s' % env['BOOST_LIBS'] + msg += '\nUsing boost lib dir: %s' % env['BOOST_LIBS'] if BOOST_INCLUDE_DIR: - msg += '\nFound boost headers: %s' % BOOST_INCLUDE_DIR - env['BOOST_INCLUDES'] = BOOST_INCLUDE_DIR + msg += '\nFound boost headers: %s' % BOOST_INCLUDE_DIR + env['BOOST_INCLUDES'] = BOOST_INCLUDE_DIR elif not env['BOOST_INCLUDES']: - env['BOOST_INCLUDES'] = '/usr/include' - msg += '\nUsing default boost include dir: %s' % env['BOOST_INCLUDES'] + env['BOOST_INCLUDES'] = '/usr/include' + msg += '\nUsing default boost include dir: %s' % env['BOOST_INCLUDES'] else: - msg += '\nUsing boost include dir: %s' % env['BOOST_INCLUDES'] + msg += '\nUsing 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 += '\nFound boost lib name extension: %s' % BOOST_APPEND - env['BOOST_APPEND'] = BOOST_APPEND + if BOOST_APPEND: + msg += '\nFound boost lib name extension: %s' % BOOST_APPEND + env['BOOST_APPEND'] = BOOST_APPEND else: - # Creating BOOST_APPEND according to the Boost library naming order, - # which goes ---. See: - # http://www.boost.org/doc/libs/1_35_0/more/getting_started/unix-variants.html#library-naming - append_params = [''] - if env['BOOST_TOOLKIT']: append_params.append(env['BOOST_TOOLKIT']) - if thread_flag: append_params.append(thread_flag) - if env['BOOST_ABI']: append_params.append(env['BOOST_ABI']) - if env['BOOST_VERSION']: append_params.append(env['BOOST_VERSION']) + # Creating BOOST_APPEND according to the Boost library naming order, + # which goes ---. See: + # http://www.boost.org/doc/libs/1_35_0/more/getting_started/unix-variants.html#library-naming + append_params = [''] + if env['BOOST_TOOLKIT']: append_params.append(env['BOOST_TOOLKIT']) + if thread_flag: append_params.append(thread_flag) + if env['BOOST_ABI']: append_params.append(env['BOOST_ABI']) + if env['BOOST_VERSION']: append_params.append(env['BOOST_VERSION']) - # Constructing the BOOST_APPEND setting that will be used to find the - # Boost libraries. - if len(append_params) > 1: - env['BOOST_APPEND'] = '-'.join(append_params) - msg += '\nFound boost lib name extension: %s' % env['BOOST_APPEND'] + # Constructing the BOOST_APPEND setting that will be used to find the + # Boost libraries. + if len(append_params) > 1: + env['BOOST_APPEND'] = '-'.join(append_params) + msg += '\nFound boost lib name extension: %s' % env['BOOST_APPEND'] env.AppendUnique(CPPPATH = fix_path(env['BOOST_INCLUDES'])) env.AppendUnique(LIBPATH = fix_path(env['BOOST_LIBS'])) if env['COLOR_PRINT']: - msg = "\033[94m%s\033[0m" % (msg) + msg = "\033[94m%s\033[0m" % (msg) ret = context.Result(msg) return ret @@ -781,14 +776,14 @@ def CheckBoost(context, version, silent=False): v_arr = version.split(".") version_n = 0 if len(v_arr) > 0: - version_n += int(v_arr[0])*100000 + version_n += int(v_arr[0])*100000 if len(v_arr) > 1: - version_n += int(v_arr[1])*100 + version_n += int(v_arr[1])*100 if len(v_arr) > 2: - version_n += int(v_arr[2]) + version_n += int(v_arr[2]) if not silent: - context.Message('Checking for Boost version >= %s... ' % (version)) + context.Message('Checking for Boost version >= %s... ' % (version)) ret = context.TryRun(""" #include @@ -800,13 +795,13 @@ int main() """ % version_n, '.cpp')[0] if silent: - context.did_show_result=1 + context.did_show_result=1 context.Result(ret) return ret def CheckCairoHasFreetype(context, silent=False): if not silent: - context.Message('Checking for cairo freetype font support ... ') + context.Message('Checking for cairo freetype font support ... ') context.env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS'])) ret = context.TryRun(""" @@ -824,15 +819,15 @@ int main() """, '.cpp')[0] if silent: - context.did_show_result=1 + context.did_show_result=1 context.Result(ret) for item in env['CAIRO_CPPPATHS']: - rm_path(item,'CPPPATH',context.env) + rm_path(item,'CPPPATH',context.env) return ret def CheckHasDlfcn(context, silent=False): if not silent: - context.Message('Checking for dlfcn.h support ... ') + context.Message('Checking for dlfcn.h support ... ') ret = context.TryCompile(""" #include @@ -844,7 +839,7 @@ int main() """, '.cpp') if silent: - context.did_show_result=1 + context.did_show_result=1 context.Result(ret) return ret @@ -869,7 +864,7 @@ return 0; def CheckBoostScopedEnum(context, silent=False): if not silent: - context.Message('Checking whether Boost was compiled with C++11 scoped enums ... ') + context.Message('Checking whether Boost was compiled with C++11 scoped enums ... ') ret = context.TryLink(""" #include @@ -881,7 +876,7 @@ int main() } """, '.cpp') if silent: - context.did_show_result=1 + context.did_show_result=1 context.Result(ret) return ret @@ -903,13 +898,13 @@ int main() context.did_show_result=1 result = ret[1].strip() if not result: - context.Result('error, could not get major and minor version from unicode/uversion.h') - return False + context.Result('error, could not get major and minor version from unicode/uversion.h') + return False major, minor = map(int,result.split('.')) if major >= 4 and minor >= 0: - color_print(4,'found: icu %s' % result) - return True + color_print(4,'found: icu %s' % result) + return True color_print(1,'\nFound insufficient icu version... %s' % result) return False @@ -932,13 +927,13 @@ int main() context.did_show_result=1 result = ret[1].strip() if not result: - context.Result('error, could not get version from hb.h') - return False + context.Result('error, could not get version from hb.h') + return False items = result.split(';') if items[0] == '1': - color_print(4,'found: HarfBuzz %s' % items[1]) - return True + color_print(4,'found: HarfBuzz %s' % items[1]) + return True color_print(1,'\nHarfbuzz >= %s required but found ... %s' % (HARFBUZZ_MIN_VERSION_STRING,items[1])) return False @@ -958,16 +953,16 @@ int main() context.Message('Checking for HarfBuzz with freetype support\n') context.Result(ret[0]) if ret[0]: - return True + return True return False def boost_regex_has_icu(context): if env['RUNTIME_LINK'] == 'static': - # re-order icu libs to ensure linux linker is happy - for lib_name in ['icui18n',env['ICU_LIB_NAME'],'icudata']: - if lib_name in context.env['LIBS']: - context.env['LIBS'].remove(lib_name) - context.env.Append(LIBS=lib_name) + # re-order icu libs to ensure linux linker is happy + for lib_name in ['icui18n',env['ICU_LIB_NAME'],'icudata']: + if lib_name in context.env['LIBS']: + context.env['LIBS'].remove(lib_name) + context.env.Append(LIBS=lib_name) ret = context.TryRun(""" #include @@ -977,12 +972,12 @@ int main() { U_NAMESPACE_QUALIFIER UnicodeString ustr; try { - boost::u32regex pattern = boost::make_u32regex(ustr); + boost::u32regex pattern = boost::make_u32regex(ustr); } // an exception is fine, still indicates support is // likely compiled into regex catch (...) { - return 0; + return 0; } return 0; } @@ -991,7 +986,7 @@ int main() context.Message('Checking if boost_regex was built with ICU unicode support... ') context.Result(ret[0]) if ret[0]: - return True + return True return False def sqlite_has_rtree(context, silent=False): @@ -1013,20 +1008,20 @@ int main() rc = sqlite3_open(":memory:", &db); if (rc != SQLITE_OK) { - printf("error 1: %s\\n", sqlite3_errmsg(db)); + printf("error 1: %s\\n", sqlite3_errmsg(db)); } const char * sql = "create virtual table foo using rtree(pkid, xmin, xmax, ymin, ymax)"; rc = sqlite3_exec(db, sql, 0, 0, 0); if (rc != SQLITE_OK) { - printf("error 2: %s\\n", sqlite3_errmsg(db)); - sqlite3_close(db); + printf("error 2: %s\\n", sqlite3_errmsg(db)); + sqlite3_close(db); } else { - printf("yes, has rtree!\\n"); - sqlite3_close(db); - return 0; + printf("yes, has rtree!\\n"); + sqlite3_close(db); + return 0; } return -1; @@ -1034,12 +1029,12 @@ int main() """, '.c') if not silent: - context.Message('Checking if SQLite supports RTREE... ') + context.Message('Checking if SQLite supports RTREE... ') if silent: - context.did_show_result=1 + context.did_show_result=1 context.Result(ret[0]) if ret[0]: - return True + return True return False def supports_cxx11(context,silent=False): @@ -1056,48 +1051,48 @@ int main() """, '.cpp') if not silent: - context.Message('Checking if compiler (%s) supports -std=c++11 flag... ' % context.env.get('CXX','CXX')) + context.Message('Checking if compiler (%s) supports -std=c++11 flag... ' % context.env.get('CXX','CXX')) if silent: - context.did_show_result=1 + context.did_show_result=1 context.Result(ret[0]) if ret[0]: - return True + return True return False conf_tests = { 'prioritize_paths' : prioritize_paths, - 'CheckPKGConfig' : CheckPKGConfig, - 'CheckPKG' : CheckPKG, - 'CheckPKGVersion' : CheckPKGVersion, - 'FindBoost' : FindBoost, - 'CheckBoost' : CheckBoost, - 'CheckCairoHasFreetype' : CheckCairoHasFreetype, - 'CheckHasDlfcn' : CheckHasDlfcn, - 'GetBoostLibVersion' : GetBoostLibVersion, - 'parse_config' : parse_config, - 'parse_pg_config' : parse_pg_config, - 'ogr_enabled' : ogr_enabled, - 'get_pkg_lib' : get_pkg_lib, - 'rollback_option' : rollback_option, - 'icu_at_least_four_two' : icu_at_least_four_two, - 'harfbuzz_version' : harfbuzz_version, - 'harfbuzz_with_freetype_support': harfbuzz_with_freetype_support, - 'boost_regex_has_icu' : boost_regex_has_icu, - 'sqlite_has_rtree' : sqlite_has_rtree, - 'supports_cxx11' : supports_cxx11, - 'CheckBoostScopedEnum' : CheckBoostScopedEnum, - } + 'CheckPKGConfig' : CheckPKGConfig, + 'CheckPKG' : CheckPKG, + 'CheckPKGVersion' : CheckPKGVersion, + 'FindBoost' : FindBoost, + 'CheckBoost' : CheckBoost, + 'CheckCairoHasFreetype' : CheckCairoHasFreetype, + 'CheckHasDlfcn' : CheckHasDlfcn, + 'GetBoostLibVersion' : GetBoostLibVersion, + 'parse_config' : parse_config, + 'parse_pg_config' : parse_pg_config, + 'ogr_enabled' : ogr_enabled, + 'get_pkg_lib' : get_pkg_lib, + 'rollback_option' : rollback_option, + 'icu_at_least_four_two' : icu_at_least_four_two, + 'harfbuzz_version' : harfbuzz_version, + 'harfbuzz_with_freetype_support': harfbuzz_with_freetype_support, + 'boost_regex_has_icu' : boost_regex_has_icu, + 'sqlite_has_rtree' : sqlite_has_rtree, + 'supports_cxx11' : supports_cxx11, + 'CheckBoostScopedEnum' : CheckBoostScopedEnum, + } def GetMapnikLibVersion(): ver = [] for line in open('include/mapnik/version.hpp').readlines(): - if line.startswith('#define MAPNIK_MAJOR_VERSION'): - ver.append(line.split(' ')[2].strip()) - if line.startswith('#define MAPNIK_MINOR_VERSION'): - ver.append(line.split(' ')[2].strip()) - if line.startswith('#define MAPNIK_PATCH_VERSION'): - ver.append(line.split(' ')[2].strip()) + if line.startswith('#define MAPNIK_MAJOR_VERSION'): + ver.append(line.split(' ')[2].strip()) + if line.startswith('#define MAPNIK_MINOR_VERSION'): + ver.append(line.split(' ')[2].strip()) + if line.startswith('#define MAPNIK_PATCH_VERSION'): + ver.append(line.split(' ')[2].strip()) version_string = ".".join(ver) return version_string @@ -1106,43 +1101,43 @@ if not preconfigured: color_print(4,'Configuring build environment...') if not env['FAST']: - SetCacheMode('force') + SetCacheMode('force') if env['USE_CONFIG']: - if not env['CONFIG'].endswith('.py'): - color_print(1,'SCons CONFIG file specified is not a python file, will not be read...') - else: - # Accept more than one file as comma-delimited list - user_confs = env['CONFIG'].split(',') - # If they exist add the files to the existing `opts` - for conf in user_confs: - if os.path.exists(conf): - opts.files.append(conf) - color_print(4,"SCons CONFIG found: '%s', variables will be inherited..." % conf) - optfile = file(conf) - #print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=") - optfile.close() + if not env['CONFIG'].endswith('.py'): + color_print(1,'SCons CONFIG file specified is not a python file, will not be read...') + else: + # Accept more than one file as comma-delimited list + user_confs = env['CONFIG'].split(',') + # If they exist add the files to the existing `opts` + for conf in user_confs: + if os.path.exists(conf): + opts.files.append(conf) + color_print(4,"SCons CONFIG found: '%s', variables will be inherited..." % conf) + optfile = file(conf) + #print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=") + optfile.close() - elif not conf == SCONS_LOCAL_CONFIG: - # if default missing, no worries - # but if the default is overridden and the file is not found, give warning - color_print(1,"SCons CONFIG not found: '%s'" % conf) - # Recreate the base environment using modified `opts` - env = Environment(ENV=os.environ,options=opts) - init_environment(env) - env['USE_CONFIG'] = True + elif not conf == SCONS_LOCAL_CONFIG: + # if default missing, no worries + # but if the default is overridden and the file is not found, give warning + color_print(1,"SCons CONFIG not found: '%s'" % conf) + # Recreate the base environment using modified `opts` + env = Environment(ENV=os.environ,options=opts) + init_environment(env) + env['USE_CONFIG'] = True else: - color_print(4,'SCons USE_CONFIG specified as false, will not inherit variables python config file...') + color_print(4,'SCons USE_CONFIG specified as false, will not inherit variables python config file...') conf = Configure(env, custom_tests = conf_tests) if env['DEBUG']: - mode = 'debug mode' + mode = 'debug mode' else: - mode = 'release mode' + mode = 'release mode' if env['COVERAGE']: - mode += ' (with coverage)' + mode += ' (with coverage)' env['PLATFORM'] = platform.uname()[0] color_print(4,"Configuring on %s in *%s*..." % (env['PLATFORM'],mode)) @@ -1167,7 +1162,7 @@ if not preconfigured: # previously a leading / was expected for LIB_DIR_NAME # now strip it to ensure expected behavior if env['LIB_DIR_NAME'].startswith(os.path.sep): - env['LIB_DIR_NAME'] = strip_first(env['LIB_DIR_NAME'],os.path.sep) + env['LIB_DIR_NAME'] = strip_first(env['LIB_DIR_NAME'],os.path.sep) # base install location env['MAPNIK_LIB_BASE'] = os.path.join(env['PREFIX'],env['LIBDIR_SCHEMA']) @@ -1177,9 +1172,9 @@ if not preconfigured: env['MAPNIK_INPUT_PLUGINS'] = os.path.join(env['MAPNIK_LIB_DIR'],'input') # fonts sub directory if env['SYSTEM_FONTS']: - env['MAPNIK_FONTS'] = os.path.normpath(env['SYSTEM_FONTS']) + env['MAPNIK_FONTS'] = os.path.normpath(env['SYSTEM_FONTS']) else: - env['MAPNIK_FONTS'] = os.path.join(env['MAPNIK_LIB_DIR'],'fonts') + env['MAPNIK_FONTS'] = os.path.join(env['MAPNIK_LIB_DIR'],'fonts') # install prefix is a pre-pended base location to # re-route the install and only intended for package building @@ -1192,9 +1187,9 @@ if not preconfigured: env['MAPNIK_LIB_DIR_DEST'] = os.path.join(env['MAPNIK_LIB_BASE_DEST'],env['LIB_DIR_NAME']) env['MAPNIK_INPUT_PLUGINS_DEST'] = os.path.join(env['MAPNIK_LIB_DIR_DEST'],'input') if env['SYSTEM_FONTS']: - env['MAPNIK_FONTS_DEST'] = os.path.normpath(env['SYSTEM_FONTS']) + env['MAPNIK_FONTS_DEST'] = os.path.normpath(env['SYSTEM_FONTS']) else: - env['MAPNIK_FONTS_DEST'] = os.path.join(env['MAPNIK_LIB_DIR_DEST'],'fonts') + env['MAPNIK_FONTS_DEST'] = os.path.join(env['MAPNIK_LIB_DIR_DEST'],'fonts') if env['LINKING'] == 'static': env['MAPNIK_LIB_NAME'] = '${LIBPREFIX}${MAPNIK_NAME}${LIBSUFFIX}' @@ -1202,15 +1197,15 @@ if not preconfigured: env['MAPNIK_LIB_NAME'] = '${SHLIBPREFIX}${MAPNIK_NAME}${SHLIBSUFFIX}' if env['PKG_CONFIG_PATH']: - env['ENV']['PKG_CONFIG_PATH'] = fix_path(env['PKG_CONFIG_PATH']) - # otherwise this variable == os.environ["PKG_CONFIG_PATH"] + env['ENV']['PKG_CONFIG_PATH'] = fix_path(env['PKG_CONFIG_PATH']) + # otherwise this variable == os.environ["PKG_CONFIG_PATH"] if env['PATH']: - env['ENV']['PATH'] = fix_path(env['PATH']) + ':' + env['ENV']['PATH'] + env['ENV']['PATH'] = fix_path(env['PATH']) + ':' + env['ENV']['PATH'] if env['SYSTEM_FONTS']: - if not os.path.isdir(env['SYSTEM_FONTS']): - color_print(1,'Warning: Directory specified for SYSTEM_FONTS does not exist!') + if not os.path.isdir(env['SYSTEM_FONTS']): + color_print(1,'Warning: Directory specified for SYSTEM_FONTS does not exist!') # Set up for libraries and headers dependency checks env['CPPPATH'] = ['#include'] @@ -1218,8 +1213,8 @@ if not preconfigured: # set any custom cxxflags and ldflags to come first if sys.platform == 'darwin' and not env['HOST']: - DEFAULT_CXX11_CXXFLAGS += ' -stdlib=libc++' - DEFAULT_CXX11_LINKFLAGS = ' -stdlib=libc++' + DEFAULT_CXX11_CXXFLAGS += ' -stdlib=libc++' + DEFAULT_CXX11_LINKFLAGS = ' -stdlib=libc++' env.Append(CPPDEFINES = env['CUSTOM_DEFINES']) env.Append(CXXFLAGS = DEFAULT_CXX11_CXXFLAGS) env.Append(CXXFLAGS = env['CUSTOM_CXXFLAGS']) @@ -1231,11 +1226,11 @@ if not preconfigured: thread_suffix = 'mt' if env['PLATFORM'] == 'FreeBSD': - thread_suffix = '' - env.Append(LIBS = 'pthread') + thread_suffix = '' + env.Append(LIBS = 'pthread') if env['MEMORY_MAPPED_FILE']: - env.Append(CPPDEFINES = '-DMAPNIK_MEMORY_MAPPED_FILE') + env.Append(CPPDEFINES = '-DMAPNIK_MEMORY_MAPPED_FILE') # allow for mac osx /usr/lib/libicucore.dylib compatibility # requires custom supplied headers since Apple does not include them @@ -1244,610 +1239,603 @@ if not preconfigured: # http://www.opensource.apple.com/tarballs/ICU/ # then copy the headers to a location that mapnik will find if 'core' in env['ICU_LIB_NAME']: - env.Append(CPPDEFINES = '-DU_HIDE_DRAFT_API') - env.Append(CPPDEFINES = '-DUDISABLE_RENAMING') - if os.path.exists(env['ICU_LIB_NAME']): - #-sICU_LINK=" -L/usr/lib -licucore - env['ICU_LIB_NAME'] = os.path.basename(env['ICU_LIB_NAME']).replace('.dylib','').replace('lib','') + env.Append(CPPDEFINES = '-DU_HIDE_DRAFT_API') + env.Append(CPPDEFINES = '-DUDISABLE_RENAMING') + if os.path.exists(env['ICU_LIB_NAME']): + #-sICU_LINK=" -L/usr/lib -licucore + env['ICU_LIB_NAME'] = os.path.basename(env['ICU_LIB_NAME']).replace('.dylib','').replace('lib','') # Adding the required prerequisite library directories to the include path for # compiling and the library path for linking, respectively. for required in ('ICU', 'SQLITE', 'HB'): - inc_path = env['%s_INCLUDES' % required] - lib_path = env['%s_LIBS' % required] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) + inc_path = env['%s_INCLUDES' % required] + lib_path = env['%s_LIBS' % required] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) REQUIRED_LIBSHEADERS = [ - ['z', 'zlib.h', True,'C'], - [env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'], - ['harfbuzz', 'harfbuzz/hb.h',True,'C++'] + ['z', 'zlib.h', True,'C'], + [env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'], + ['harfbuzz', 'harfbuzz/hb.h',True,'C++'] ] if env.get('FREETYPE_LIBS') or env.get('FREETYPE_INCLUDES'): - REQUIRED_LIBSHEADERS.insert(0,['freetype','ft2build.h',True,'C']) - if env.get('FREETYPE_INCLUDES'): - inc_path = env['FREETYPE_INCLUDES'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - if env.get('FREETYPE_LIBS'): - lib_path = env['FREETYPE_LIBS'] - env.AppendUnique(LIBPATH = fix_path(lib_path)) + REQUIRED_LIBSHEADERS.insert(0,['freetype','ft2build.h',True,'C']) + if env.get('FREETYPE_INCLUDES'): + inc_path = env['FREETYPE_INCLUDES'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + if env.get('FREETYPE_LIBS'): + lib_path = env['FREETYPE_LIBS'] + env.AppendUnique(LIBPATH = fix_path(lib_path)) elif conf.parse_config('FREETYPE_CONFIG'): - # check if freetype links to bz2 - if env['RUNTIME_LINK'] == 'static': - temp_env = env.Clone() - temp_env['LIBS'] = [] - try: - # TODO - freetype-config accepts --static as of v2.5.3 - temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG']) - if 'bz2' in temp_env['LIBS']: - env['EXTRA_FREETYPE_LIBS'].append('bz2') - except OSError,e: - pass + # check if freetype links to bz2 + if env['RUNTIME_LINK'] == 'static': + temp_env = env.Clone() + temp_env['LIBS'] = [] + try: + # TODO - freetype-config accepts --static as of v2.5.3 + temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG']) + if 'bz2' in temp_env['LIBS']: + env['EXTRA_FREETYPE_LIBS'].append('bz2') + except OSError,e: + pass # libxml2 should be optional but is currently not # https://github.com/mapnik/mapnik/issues/913 if env.get('XMLPARSER') and env['XMLPARSER'] == 'libxml2': - if env.get('XML2_LIBS') or env.get('XML2_INCLUDES'): - OPTIONAL_LIBSHEADERS.insert(0,['libxml2','libxml/parser.h',True,'C']) - if env.get('XML2_INCLUDES'): - inc_path = env['XML2_INCLUDES'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - if env.get('XML2_LIBS'): - lib_path = env['XML2_LIBS'] - env.AppendUnique(LIBPATH = fix_path(lib_path)) - elif conf.parse_config('XML2_CONFIG',checks='--cflags'): - env['HAS_LIBXML2'] = True - else: - env['MISSING_DEPS'].append('libxml2') + if env.get('XML2_LIBS') or env.get('XML2_INCLUDES'): + OPTIONAL_LIBSHEADERS.insert(0,['libxml2','libxml/parser.h',True,'C']) + if env.get('XML2_INCLUDES'): + inc_path = env['XML2_INCLUDES'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + if env.get('XML2_LIBS'): + lib_path = env['XML2_LIBS'] + env.AppendUnique(LIBPATH = fix_path(lib_path)) + elif conf.parse_config('XML2_CONFIG',checks='--cflags'): + env['HAS_LIBXML2'] = True + else: + env['MISSING_DEPS'].append('libxml2') if not env['HOST']: - if conf.CheckHasDlfcn(): - env.Append(CPPDEFINES = '-DMAPNIK_HAS_DLCFN') - else: - env['SKIPPED_DEPS'].extend(['dlfcn']) + if conf.CheckHasDlfcn(): + env.Append(CPPDEFINES = '-DMAPNIK_HAS_DLCFN') + else: + env['SKIPPED_DEPS'].extend(['dlfcn']) OPTIONAL_LIBSHEADERS = [] if env['JPEG']: - OPTIONAL_LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], False,'C','-DHAVE_JPEG']) - inc_path = env['%s_INCLUDES' % 'JPEG'] - lib_path = env['%s_LIBS' % 'JPEG'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) + OPTIONAL_LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], False,'C','-DHAVE_JPEG']) + inc_path = env['%s_INCLUDES' % 'JPEG'] + lib_path = env['%s_LIBS' % 'JPEG'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) else: - env['SKIPPED_DEPS'].extend(['jpeg']) + env['SKIPPED_DEPS'].extend(['jpeg']) if env['PROJ']: - OPTIONAL_LIBSHEADERS.append(['proj', 'proj_api.h', False,'C','-DMAPNIK_USE_PROJ4']) - inc_path = env['%s_INCLUDES' % 'PROJ'] - lib_path = env['%s_LIBS' % 'PROJ'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) + OPTIONAL_LIBSHEADERS.append(['proj', 'proj_api.h', False,'C','-DMAPNIK_USE_PROJ4']) + inc_path = env['%s_INCLUDES' % 'PROJ'] + lib_path = env['%s_LIBS' % 'PROJ'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) else: - env['SKIPPED_DEPS'].extend(['proj']) + env['SKIPPED_DEPS'].extend(['proj']) if env['PNG']: - OPTIONAL_LIBSHEADERS.append(['png', 'png.h', False,'C','-DHAVE_PNG']) - inc_path = env['%s_INCLUDES' % 'PNG'] - lib_path = env['%s_LIBS' % 'PNG'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) + OPTIONAL_LIBSHEADERS.append(['png', 'png.h', False,'C','-DHAVE_PNG']) + inc_path = env['%s_INCLUDES' % 'PNG'] + lib_path = env['%s_LIBS' % 'PNG'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) else: - env['SKIPPED_DEPS'].extend(['png']) + env['SKIPPED_DEPS'].extend(['png']) if env['WEBP']: - OPTIONAL_LIBSHEADERS.append(['webp', 'webp/decode.h', False,'C','-DHAVE_WEBP']) - inc_path = env['%s_INCLUDES' % 'WEBP'] - lib_path = env['%s_LIBS' % 'WEBP'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) + OPTIONAL_LIBSHEADERS.append(['webp', 'webp/decode.h', False,'C','-DHAVE_WEBP']) + inc_path = env['%s_INCLUDES' % 'WEBP'] + lib_path = env['%s_LIBS' % 'WEBP'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) else: - env['SKIPPED_DEPS'].extend(['webp']) + env['SKIPPED_DEPS'].extend(['webp']) if env['TIFF']: - OPTIONAL_LIBSHEADERS.append(['tiff', 'tiff.h', False,'C','-DHAVE_TIFF']) - inc_path = env['%s_INCLUDES' % 'TIFF'] - lib_path = env['%s_LIBS' % 'TIFF'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - env.AppendUnique(LIBPATH = fix_path(lib_path)) + OPTIONAL_LIBSHEADERS.append(['tiff', 'tiff.h', False,'C','-DHAVE_TIFF']) + inc_path = env['%s_INCLUDES' % 'TIFF'] + lib_path = env['%s_LIBS' % 'TIFF'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + env.AppendUnique(LIBPATH = fix_path(lib_path)) else: - env['SKIPPED_DEPS'].extend(['tiff']) + env['SKIPPED_DEPS'].extend(['tiff']) # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests if env['PRIORITIZE_LINKING']: - conf.prioritize_paths(silent=True) + conf.prioritize_paths(silent=True) # test for C++11 support, which is required if not env['HOST'] and not conf.supports_cxx11(): - color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler to at least g++ 4.7 (ideally 4.8)") - Exit(1) + color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler") + Exit(1) if not env['HOST']: - for libname, headers, required, lang in REQUIRED_LIBSHEADERS: - if not conf.CheckLibWithHeader(libname, headers, lang): - if required: - color_print(1, 'Could not find required header or shared library for %s' % libname) - env['MISSING_DEPS'].append(libname) - else: - color_print(4, 'Could not find optional header or shared library for %s' % libname) - env['SKIPPED_DEPS'].append(libname) - else: - if libname == env['ICU_LIB_NAME']: - if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']: - if not conf.icu_at_least_four_two(): - # expression_string.cpp and map.cpp use fromUTF* function only available in >= ICU 4.2 - env['MISSING_DEPS'].append(env['ICU_LIB_NAME']) - elif libname == 'harfbuzz': - if not conf.harfbuzz_version(): - env['SKIPPED_DEPS'].append('harfbuzz-min-version') - if not conf.harfbuzz_with_freetype_support(): - env['MISSING_DEPS'].append('harfbuzz-with-freetype-support') + for libname, headers, required, lang in REQUIRED_LIBSHEADERS: + if not conf.CheckLibWithHeader(libname, headers, lang): + if required: + color_print(1, 'Could not find required header or shared library for %s' % libname) + env['MISSING_DEPS'].append(libname) + else: + color_print(4, 'Could not find optional header or shared library for %s' % libname) + env['SKIPPED_DEPS'].append(libname) + else: + if libname == env['ICU_LIB_NAME']: + if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']: + if not conf.icu_at_least_four_two(): + # expression_string.cpp and map.cpp use fromUTF* function only available in >= ICU 4.2 + env['MISSING_DEPS'].append(env['ICU_LIB_NAME']) + elif libname == 'harfbuzz': + if not conf.harfbuzz_version(): + env['SKIPPED_DEPS'].append('harfbuzz-min-version') + if not conf.harfbuzz_with_freetype_support(): + env['MISSING_DEPS'].append('harfbuzz-with-freetype-support') if env['BIGINT']: - env.Append(CPPDEFINES = '-DBIGINT') + env.Append(CPPDEFINES = '-DBIGINT') if env['THREADING'] == 'multi': - thread_flag = thread_suffix + thread_flag = thread_suffix else: - thread_flag = '' + thread_flag = '' conf.FindBoost(BOOST_SEARCH_PREFIXES,thread_flag) has_boost_devel = True if not env['HOST']: - if not conf.CheckHeader(header='boost/version.hpp',language='C++'): - env['MISSING_DEPS'].append('boost development headers') - has_boost_devel = False + if not conf.CheckHeader(header='boost/version.hpp',language='C++'): + env['MISSING_DEPS'].append('boost development headers') + has_boost_devel = False if has_boost_devel: - if not env['HOST']: - env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion() + if not env['HOST']: + env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion() - # The other required boost headers. - BOOST_LIBSHEADERS = [ - ['system', 'boost/system/system_error.hpp', True], - ['filesystem', 'boost/filesystem/operations.hpp', True], - ['regex', 'boost/regex.hpp', True], - ['program_options', 'boost/program_options.hpp', False] - ] + # The other required boost headers. + BOOST_LIBSHEADERS = [ + ['system', 'boost/system/system_error.hpp', True], + ['filesystem', 'boost/filesystem/operations.hpp', True], + ['regex', 'boost/regex.hpp', True], + ['program_options', 'boost/program_options.hpp', False] + ] - if env['THREADING'] == 'multi': - BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True]) - # on solaris the configure checks for boost_thread - # require the -pthreads flag to be able to check for - # threading support, so we add as a global library instead - # of attaching to cxxflags after configure - if env['PLATFORM'] == 'SunOS': - env.Append(CXXFLAGS = '-pthreads') + # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests + if env['PRIORITIZE_LINKING']: + conf.prioritize_paths(silent=True) - # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests - if env['PRIORITIZE_LINKING']: - conf.prioritize_paths(silent=True) + if not env['HOST']: + # if the user is not setting custom boost configuration + # enforce boost version greater than or equal to BOOST_MIN_VERSION + if not conf.CheckBoost(BOOST_MIN_VERSION): + color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') ) + color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION) + if not env['BOOST_VERSION']: + env['MISSING_DEPS'].append('boost version >= %s' % BOOST_MIN_VERSION) + else: + color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') ) - if not env['HOST']: - # if the user is not setting custom boost configuration - # enforce boost version greater than or equal to BOOST_MIN_VERSION - if not conf.CheckBoost(BOOST_MIN_VERSION): - color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') ) - color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION) - if not env['BOOST_VERSION']: - env['MISSING_DEPS'].append('boost version >= %s' % BOOST_MIN_VERSION) - else: - color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') ) + if not env['HOST']: + for count, libinfo in enumerate(BOOST_LIBSHEADERS): + if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'): + if libinfo[2]: + color_print(1,'Could not find required header or shared library for boost %s' % libinfo[0]) + env['MISSING_DEPS'].append('boost ' + libinfo[0]) + else: + color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0]) + env['SKIPPED_DEPS'].append('boost ' + libinfo[0]) - if not env['HOST']: - for count, libinfo in enumerate(BOOST_LIBSHEADERS): - if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'): - if libinfo[2]: - color_print(1,'Could not find required header or shared library for boost %s' % libinfo[0]) - env['MISSING_DEPS'].append('boost ' + libinfo[0]) - else: - color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0]) - env['SKIPPED_DEPS'].append('boost ' + libinfo[0]) - - # Boost versions before 1.57 are broken when the system package and - # Mapnik are compiled against different standards. On Ubuntu 14.04 - # using boost 1.54, it breaks scoped enums. It's a bit of a hack to - # just turn it off like this, but seems the only available work- - # around. See https://svn.boost.org/trac/boost/ticket/6779 for more - # details. - boost_version = [int(x) for x in env.get('BOOST_LIB_VERSION_FROM_HEADER').split('_')] - if not conf.CheckBoostScopedEnum(): - if boost_version < [1, 51]: - env.Append(CXXFLAGS = '-DBOOST_NO_SCOPED_ENUMS') - elif boost_version < [1, 57]: - env.Append(CXXFLAGS = '-DBOOST_NO_CXX11_SCOPED_ENUMS') + # Boost versions before 1.57 are broken when the system package and + # Mapnik are compiled against different standards. On Ubuntu 14.04 + # using boost 1.54, it breaks scoped enums. It's a bit of a hack to + # just turn it off like this, but seems the only available work- + # around. See https://svn.boost.org/trac/boost/ticket/6779 for more + # details. + if not env['HOST']: + boost_version = [int(x) for x in env.get('BOOST_LIB_VERSION_FROM_HEADER').split('_')] + if not conf.CheckBoostScopedEnum(): + if boost_version < [1, 51]: + env.Append(CXXFLAGS = '-DBOOST_NO_SCOPED_ENUMS') + elif boost_version < [1, 57]: + env.Append(CXXFLAGS = '-DBOOST_NO_CXX11_SCOPED_ENUMS') if not env['HOST'] and env['ICU_LIB_NAME'] not in env['MISSING_DEPS']: - # http://lists.boost.org/Archives/boost/2009/03/150076.php - # we need libicui18n if using static boost libraries, so it is - # important to try this check with the library linked - if conf.boost_regex_has_icu(): - # TODO - should avoid having this be globally defined... - env.Append(CPPDEFINES = '-DBOOST_REGEX_HAS_ICU') - else: - env['SKIPPED_DEPS'].append('boost_regex_icu') + # http://lists.boost.org/Archives/boost/2009/03/150076.php + # we need libicui18n if using static boost libraries, so it is + # important to try this check with the library linked + if conf.boost_regex_has_icu(): + # TODO - should avoid having this be globally defined... + env.Append(CPPDEFINES = '-DBOOST_REGEX_HAS_ICU') + else: + env['SKIPPED_DEPS'].append('boost_regex_icu') - for libname, headers, required, lang, define in OPTIONAL_LIBSHEADERS: - if not env['HOST']: - if not conf.CheckLibWithHeader(libname, headers, lang): - if required: - color_print(1, 'Could not find required header or shared library for %s' % libname) - env['MISSING_DEPS'].append(libname) - else: - color_print(4, 'Could not find optional header or shared library for %s' % libname) - env['SKIPPED_DEPS'].append(libname) - else: - env.Append(CPPDEFINES = define) - else: - env.Append(CPPDEFINES = define) + for libname, headers, required, lang, define in OPTIONAL_LIBSHEADERS: + if not env['HOST']: + if not conf.CheckLibWithHeader(libname, headers, lang): + if required: + color_print(1, 'Could not find required header or shared library for %s' % libname) + env['MISSING_DEPS'].append(libname) + else: + color_print(4, 'Could not find optional header or shared library for %s' % libname) + env['SKIPPED_DEPS'].append(libname) + else: + env.Append(CPPDEFINES = define) + else: + env.Append(CPPDEFINES = define) env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])] SQLITE_HAS_RTREE = None if env['HOST']: - SQLITE_HAS_RTREE = True + SQLITE_HAS_RTREE = True CHECK_PKG_CONFIG = conf.CheckPKGConfig('0.15.0') if len(env['REQUESTED_PLUGINS']): - if env['HOST']: - for plugin in env['REQUESTED_PLUGINS']: - details = env['PLUGINS'][plugin] - if details['lib']: - env.AppendUnique(LIBS=details['lib']) - else: - color_print(4,'Checking for requested plugins dependencies...') - for plugin in env['REQUESTED_PLUGINS']: - details = env['PLUGINS'][plugin] - if plugin == 'gdal': - if conf.parse_config('GDAL_CONFIG',checks='--libs'): - conf.parse_config('GDAL_CONFIG',checks='--cflags') - libname = conf.get_pkg_lib('GDAL_CONFIG','gdal') - if libname: - if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']): - env['SKIPPED_DEPS'].append('gdal') - if libname in env['LIBS']: - env['LIBS'].remove(libname) - else: - details['lib'] = libname - elif plugin == 'postgis' or plugin == 'pgraster': - if env.get('PG_LIBS') or env.get('PG_INCLUDES'): - libname = details['lib'] - if env.get('PG_INCLUDES'): - inc_path = env['PG_INCLUDES'] - env.AppendUnique(CPPPATH = fix_path(inc_path)) - if env.get('PG_LIBS'): - lib_path = env['PG_LIBS'] - env.AppendUnique(LIBPATH = fix_path(lib_path)) - if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']): - env['SKIPPED_DEPS'].append(libname) - if libname in env['LIBS']: - env['LIBS'].remove(libname) - else: - details['lib'] = libname - else: - conf.parse_pg_config('PG_CONFIG') - elif plugin == 'ogr': - if conf.ogr_enabled(): - if conf.parse_config('GDAL_CONFIG',checks='--libs'): - conf.parse_config('GDAL_CONFIG',checks='--cflags') - libname = conf.get_pkg_lib('GDAL_CONFIG','ogr') - if libname: - if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']): - if 'gdal' not in env['SKIPPED_DEPS']: - env['SKIPPED_DEPS'].append('gdal') - if libname in env['LIBS']: - env['LIBS'].remove(libname) - else: - details['lib'] = libname - elif details['path'] and details['lib'] and details['inc']: - backup = env.Clone().Dictionary() - # Note, the 'delete_existing' keyword makes sure that these paths are prepended - # to the beginning of the path list even if they already exist - incpath = env['%s_INCLUDES' % details['path']] - libpath = env['%s_LIBS' % details['path']] - env.PrependUnique(CPPPATH = fix_path(incpath),delete_existing=True) - env.PrependUnique(LIBPATH = fix_path(libpath),delete_existing=True) - if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']): - env.Replace(**backup) - env['SKIPPED_DEPS'].append(details['lib']) - if plugin == 'sqlite': - sqlite_backup = env.Clone().Dictionary() - # if statically linking, on linux we likely - # need to link sqlite to pthreads and dl - if env['RUNTIME_LINK'] == 'static' and not env['PLATFORM'] == 'Darwin': - if CHECK_PKG_CONFIG and conf.CheckPKG('sqlite3'): - sqlite_env = env.Clone() - try: - sqlite_env.ParseConfig('pkg-config --static --libs sqlite3') - for lib in sqlite_env['LIBS']: - if not lib in env['LIBS']: - env["SQLITE_LINKFLAGS"].append(lib) - env.Append(LIBS=lib) - except OSError,e: - for lib in ["sqlite3","dl","pthread"]: - if not lib in env['LIBS']: - env["SQLITE_LINKFLAGS"].append("lib") - env.Append(LIBS=lib) - else: - for lib in ["sqlite3","dl","pthread"]: - if not lib in env['LIBS']: - env["SQLITE_LINKFLAGS"].append("lib") - env.Append(LIBS=lib) - SQLITE_HAS_RTREE = conf.sqlite_has_rtree() - if not SQLITE_HAS_RTREE: - env.Replace(**sqlite_backup) - if details['lib'] in env['LIBS']: - env['LIBS'].remove(details['lib']) - env['SKIPPED_DEPS'].append('sqlite_rtree') - else: - env.Replace(**sqlite_backup) - elif details['lib'] and details['inc']: - if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']): - env['SKIPPED_DEPS'].append(details['lib']) + if env['HOST']: + for plugin in env['REQUESTED_PLUGINS']: + details = env['PLUGINS'][plugin] + if details['lib']: + env.AppendUnique(LIBS=details['lib']) + else: + color_print(4,'Checking for requested plugins dependencies...') + for plugin in env['REQUESTED_PLUGINS']: + details = env['PLUGINS'][plugin] + if plugin == 'gdal': + if conf.parse_config('GDAL_CONFIG',checks='--libs'): + conf.parse_config('GDAL_CONFIG',checks='--cflags') + libname = conf.get_pkg_lib('GDAL_CONFIG','gdal') + if libname: + if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']): + env['SKIPPED_DEPS'].append('gdal') + if libname in env['LIBS']: + env['LIBS'].remove(libname) + else: + details['lib'] = libname + elif plugin == 'postgis' or plugin == 'pgraster': + if env.get('PG_LIBS') or env.get('PG_INCLUDES'): + libname = details['lib'] + if env.get('PG_INCLUDES'): + inc_path = env['PG_INCLUDES'] + env.AppendUnique(CPPPATH = fix_path(inc_path)) + if env.get('PG_LIBS'): + lib_path = env['PG_LIBS'] + env.AppendUnique(LIBPATH = fix_path(lib_path)) + if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']): + env['SKIPPED_DEPS'].append(libname) + if libname in env['LIBS']: + env['LIBS'].remove(libname) + else: + details['lib'] = libname + else: + conf.parse_pg_config('PG_CONFIG') + elif plugin == 'ogr': + if conf.ogr_enabled(): + if conf.parse_config('GDAL_CONFIG',checks='--libs'): + conf.parse_config('GDAL_CONFIG',checks='--cflags') + libname = conf.get_pkg_lib('GDAL_CONFIG','ogr') + if libname: + if not conf.CheckLibWithHeader(libname, details['inc'], details['lang']): + if 'gdal' not in env['SKIPPED_DEPS']: + env['SKIPPED_DEPS'].append('gdal') + if libname in env['LIBS']: + env['LIBS'].remove(libname) + else: + details['lib'] = libname + elif details['path'] and details['lib'] and details['inc']: + backup = env.Clone().Dictionary() + # Note, the 'delete_existing' keyword makes sure that these paths are prepended + # to the beginning of the path list even if they already exist + incpath = env['%s_INCLUDES' % details['path']] + libpath = env['%s_LIBS' % details['path']] + env.PrependUnique(CPPPATH = fix_path(incpath),delete_existing=True) + env.PrependUnique(LIBPATH = fix_path(libpath),delete_existing=True) + if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']): + env.Replace(**backup) + env['SKIPPED_DEPS'].append(details['lib']) + if plugin == 'sqlite': + sqlite_backup = env.Clone().Dictionary() + # if statically linking, on linux we likely + # need to link sqlite to pthreads and dl + if env['RUNTIME_LINK'] == 'static' and not env['PLATFORM'] == 'Darwin': + if CHECK_PKG_CONFIG and conf.CheckPKG('sqlite3'): + sqlite_env = env.Clone() + try: + sqlite_env.ParseConfig('pkg-config --static --libs sqlite3') + for lib in sqlite_env['LIBS']: + if not lib in env['LIBS']: + env["SQLITE_LINKFLAGS"].append(lib) + env.Append(LIBS=lib) + except OSError,e: + for lib in ["sqlite3","dl","pthread"]: + if not lib in env['LIBS']: + env["SQLITE_LINKFLAGS"].append("lib") + env.Append(LIBS=lib) + else: + for lib in ["sqlite3","dl","pthread"]: + if not lib in env['LIBS']: + env["SQLITE_LINKFLAGS"].append("lib") + env.Append(LIBS=lib) + SQLITE_HAS_RTREE = conf.sqlite_has_rtree() + if not SQLITE_HAS_RTREE: + env.Replace(**sqlite_backup) + if details['lib'] in env['LIBS']: + env['LIBS'].remove(details['lib']) + env['SKIPPED_DEPS'].append('sqlite_rtree') + else: + env.Replace(**sqlite_backup) + elif details['lib'] and details['inc']: + if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']): + env['SKIPPED_DEPS'].append(details['lib']) - # re-append the local paths for mapnik sources to the beginning of the list - # to make sure they come before any plugins that were 'prepended' - env.PrependUnique(CPPPATH = '#include', delete_existing=True) - env.PrependUnique(LIBPATH = '#src', delete_existing=True) + # re-append the local paths for mapnik sources to the beginning of the list + # to make sure they come before any plugins that were 'prepended' + env.PrependUnique(CPPPATH = '#include', delete_existing=True) + env.PrependUnique(LIBPATH = '#src', delete_existing=True) if not env['HOST']: - if env['PGSQL2SQLITE']: - if 'sqlite3' not in env['LIBS']: - env.AppendUnique(LIBS='sqlite3') - env.AppendUnique(CPPPATH = fix_path(env['SQLITE_INCLUDES'])) - env.AppendUnique(LIBPATH = fix_path(env['SQLITE_LIBS'])) - if 'pq' not in env['LIBS']: - if not conf.parse_pg_config('PG_CONFIG'): - env['PGSQL2SQLITE'] = False - if not SQLITE_HAS_RTREE: - env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree') - env['PGSQL2SQLITE'] = False + if env['PGSQL2SQLITE']: + if 'sqlite3' not in env['LIBS']: + env.AppendUnique(LIBS='sqlite3') + env.AppendUnique(CPPPATH = fix_path(env['SQLITE_INCLUDES'])) + env.AppendUnique(LIBPATH = fix_path(env['SQLITE_LIBS'])) + if 'pq' not in env['LIBS']: + if not conf.parse_pg_config('PG_CONFIG'): + env['PGSQL2SQLITE'] = False + if not SQLITE_HAS_RTREE: + env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree') + env['PGSQL2SQLITE'] = False # we rely on an internal, patched copy of agg with critical fixes # prepend to make sure we link locally env.Prepend(CPPPATH = '#deps/agg/include') env.Prepend(LIBPATH = '#deps/agg') + env.Prepend(CPPPATH = '#deps/mapbox/variant/include') # prepend deps dir for auxillary headers env.Prepend(CPPPATH = '#deps') if env['CAIRO']: - if env['CAIRO_LIBS'] or env['CAIRO_INCLUDES']: - c_inc = env['CAIRO_INCLUDES'] - if env['CAIRO_LIBS']: - env["CAIRO_LIBPATHS"].append(fix_path(env['CAIRO_LIBS'])) - if not env['CAIRO_INCLUDES']: - c_inc = env['CAIRO_LIBS'].replace('lib','',1) - if c_inc: - c_inc = os.path.normpath(fix_path(env['CAIRO_INCLUDES'])) - if c_inc.endswith('include'): - c_inc = os.path.dirname(c_inc) - env["CAIRO_CPPPATHS"].extend( - [ - os.path.join(c_inc,'include/cairo'), - os.path.join(c_inc,'include/pixman-1'), - #os.path.join(c_inc,'include/freetype2'), - #os.path.join(c_inc,'include/libpng'), - ] - ) - env["CAIRO_ALL_LIBS"] = ['cairo'] - if env['RUNTIME_LINK'] == 'static': - env["CAIRO_ALL_LIBS"].extend( - ['pixman-1'] - ) - # todo - run actual checkLib? - env['HAS_CAIRO'] = True - else: - if not CHECK_PKG_CONFIG: - env['HAS_CAIRO'] = False - env['SKIPPED_DEPS'].append('pkg-config') - env['SKIPPED_DEPS'].append('cairo') - elif not conf.CheckPKG('cairo'): - env['HAS_CAIRO'] = False - env['SKIPPED_DEPS'].append('cairo') - else: - print 'Checking for cairo lib and include paths... ', - cmd = 'pkg-config --libs --cflags cairo' - if env['RUNTIME_LINK'] == 'static': - cmd += ' --static' - cairo_env = env.Clone() - try: - cairo_env.ParseConfig(cmd) - for lib in cairo_env['LIBS']: - if not lib in env['LIBS']: - env["CAIRO_ALL_LIBS"].append(lib) - for lpath in cairo_env['LIBPATH']: - if not lpath in env['LIBPATH']: - env["CAIRO_LIBPATHS"].append(lpath) - for inc in cairo_env['CPPPATH']: - if not inc in env['CPPPATH']: - env["CAIRO_CPPPATHS"].append(inc) - env['HAS_CAIRO'] = True - print 'yes' - except OSError,e: - color_print(1,'no') - env['SKIPPED_DEPS'].append('cairo') - color_print(1,'pkg-config reported: %s' % e) + if env['CAIRO_LIBS'] or env['CAIRO_INCLUDES']: + c_inc = env['CAIRO_INCLUDES'] + if env['CAIRO_LIBS']: + env["CAIRO_LIBPATHS"].append(fix_path(env['CAIRO_LIBS'])) + if not env['CAIRO_INCLUDES']: + c_inc = env['CAIRO_LIBS'].replace('lib','',1) + if c_inc: + c_inc = os.path.normpath(fix_path(env['CAIRO_INCLUDES'])) + if c_inc.endswith('include'): + c_inc = os.path.dirname(c_inc) + env["CAIRO_CPPPATHS"].extend( + [ + os.path.join(c_inc,'include/cairo'), + os.path.join(c_inc,'include/pixman-1'), + #os.path.join(c_inc,'include/freetype2'), + #os.path.join(c_inc,'include/libpng'), + ] + ) + env["CAIRO_ALL_LIBS"] = ['cairo'] + if env['RUNTIME_LINK'] == 'static': + env["CAIRO_ALL_LIBS"].extend( + ['pixman-1'] + ) + # todo - run actual checkLib? + env['HAS_CAIRO'] = True + else: + if not CHECK_PKG_CONFIG: + env['HAS_CAIRO'] = False + env['SKIPPED_DEPS'].append('pkg-config') + env['SKIPPED_DEPS'].append('cairo') + elif not conf.CheckPKG('cairo'): + env['HAS_CAIRO'] = False + env['SKIPPED_DEPS'].append('cairo') + else: + print 'Checking for cairo lib and include paths... ', + cmd = 'pkg-config --libs --cflags cairo' + if env['RUNTIME_LINK'] == 'static': + cmd += ' --static' + cairo_env = env.Clone() + try: + cairo_env.ParseConfig(cmd) + for lib in cairo_env['LIBS']: + if not lib in env['LIBS']: + env["CAIRO_ALL_LIBS"].append(lib) + for lpath in cairo_env['LIBPATH']: + if not lpath in env['LIBPATH']: + env["CAIRO_LIBPATHS"].append(lpath) + for inc in cairo_env['CPPPATH']: + if not inc in env['CPPPATH']: + env["CAIRO_CPPPATHS"].append(inc) + env['HAS_CAIRO'] = True + print 'yes' + except OSError,e: + color_print(1,'no') + env['SKIPPED_DEPS'].append('cairo') + color_print(1,'pkg-config reported: %s' % e) else: - color_print(4,'Not building with cairo support, pass CAIRO=True to enable') + color_print(4,'Not building with cairo support, pass CAIRO=True to enable') if not env['HOST'] and env['HAS_CAIRO']: - if not conf.CheckCairoHasFreetype(): - env['SKIPPED_DEPS'].append('cairo') - env['HAS_CAIRO'] = False + if not conf.CheckCairoHasFreetype(): + env['SKIPPED_DEPS'].append('cairo') + env['HAS_CAIRO'] = False #### End Config Stage for Required Dependencies #### if env['MISSING_DEPS']: - # if required dependencies are missing, print warnings and then let SCons finish without building or saving local config - color_print(1,'\nExiting... the following required dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['MISSING_DEPS']])) - color_print(1,"\nSee '%s' for details on possible problems." % (fix_path(SCONS_LOCAL_LOG))) - if env['SKIPPED_DEPS']: - color_print(4,'\nAlso, these OPTIONAL dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']])) - color_print(4,"\nSet custom paths to these libraries and header files on the command-line or in a file called '%s'" % SCONS_LOCAL_CONFIG) - color_print(4," ie. $ python scons/scons.py BOOST_INCLUDES=/usr/local/include BOOST_LIBS=/usr/local/lib") - color_print(4, "\nOnce all required dependencies are found a local '%s' will be saved and then install:" % SCONS_LOCAL_CONFIG) - color_print(4," $ sudo python scons/scons.py install") - color_print(4,"\nTo view available path variables:\n $ python scons/scons.py --help or -h") - color_print(4,'\nTo view overall SCons help options:\n $ python scons/scons.py --help-options or -H\n') - color_print(4,'More info: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation') - if not HELP_REQUESTED: - Exit(1) + # if required dependencies are missing, print warnings and then let SCons finish without building or saving local config + color_print(1,'\nExiting... the following required dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['MISSING_DEPS']])) + color_print(1,"\nSee '%s' for details on possible problems." % (fix_path(SCONS_LOCAL_LOG))) + if env['SKIPPED_DEPS']: + color_print(4,'\nAlso, these OPTIONAL dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']])) + color_print(4,"\nSet custom paths to these libraries and header files on the command-line or in a file called '%s'" % SCONS_LOCAL_CONFIG) + color_print(4," ie. $ python scons/scons.py BOOST_INCLUDES=/usr/local/include BOOST_LIBS=/usr/local/lib") + color_print(4, "\nOnce all required dependencies are found a local '%s' will be saved and then install:" % SCONS_LOCAL_CONFIG) + color_print(4," $ sudo python scons/scons.py install") + color_print(4,"\nTo view available path variables:\n $ python scons/scons.py --help or -h") + color_print(4,'\nTo view overall SCons help options:\n $ python scons/scons.py --help-options or -H\n') + color_print(4,'More info: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation') + if not HELP_REQUESTED: + Exit(1) else: - # Save the custom variables in a SCONS_LOCAL_CONFIG - # that will be reloaded to allow for `install` without re-specifying custom variables - color_print(4,"\nAll Required dependencies found!\n") - if env['USE_CONFIG']: - if os.path.exists(SCONS_LOCAL_CONFIG): - action = 'Overwriting and re-saving' - os.unlink(SCONS_LOCAL_CONFIG) - else: - action = 'Saving new' - color_print(4,"%s file '%s'..." % (action,SCONS_LOCAL_CONFIG)) - color_print(4,"Will hold custom path variables from commandline and python config file(s)...") - opts.Save(SCONS_LOCAL_CONFIG,env) - else: - color_print(4,"Did not use user config file, no custom path variables will be saved...") + # Save the custom variables in a SCONS_LOCAL_CONFIG + # that will be reloaded to allow for `install` without re-specifying custom variables + color_print(4,"\nAll Required dependencies found!\n") + if env['USE_CONFIG']: + if os.path.exists(SCONS_LOCAL_CONFIG): + action = 'Overwriting and re-saving' + os.unlink(SCONS_LOCAL_CONFIG) + else: + action = 'Saving new' + color_print(4,"%s file '%s'..." % (action,SCONS_LOCAL_CONFIG)) + color_print(4,"Will hold custom path variables from commandline and python config file(s)...") + opts.Save(SCONS_LOCAL_CONFIG,env) + else: + color_print(4,"Did not use user config file, no custom path variables will be saved...") - if env['SKIPPED_DEPS']: - color_print(4,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']])) - print + if env['SKIPPED_DEPS']: + color_print(4,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']])) + print - # fetch the mapnik version header in order to set the - # ABI version used to build libmapnik.so on linux in src/build.py - abi = GetMapnikLibVersion() - abi_split = abi.split('.') - env['ABI_VERSION'] = abi_split - env['MAPNIK_VERSION_STRING'] = abi - env['MAPNIK_VERSION'] = str(int(abi_split[0])*100000+int(abi_split[1])*100+int(abi_split[2])) + # fetch the mapnik version header in order to set the + # ABI version used to build libmapnik.so on linux in src/build.py + abi = GetMapnikLibVersion() + abi_split = abi.split('.') + env['ABI_VERSION'] = abi_split + env['MAPNIK_VERSION_STRING'] = abi + env['MAPNIK_VERSION'] = str(int(abi_split[0])*100000+int(abi_split[1])*100+int(abi_split[2])) - # Common DEFINES. - env.Append(CPPDEFINES = '-D%s' % env['PLATFORM'].upper()) - if env['THREADING'] == 'multi': - env.Append(CPPDEFINES = '-DMAPNIK_THREADSAFE') + # Common DEFINES. + env.Append(CPPDEFINES = '-D%s' % env['PLATFORM'].upper()) + if env['THREADING'] == 'multi': + env.Append(CPPDEFINES = '-DMAPNIK_THREADSAFE') - if env['NO_ATEXIT']: - env.Append(CPPDEFINES = '-DMAPNIK_NO_ATEXIT') + if env['NO_ATEXIT']: + env.Append(CPPDEFINES = '-DMAPNIK_NO_ATEXIT') - if env['NO_DLCLOSE'] or env['COVERAGE']: - env.Append(CPPDEFINES = '-DMAPNIK_NO_DLCLOSE') + if env['NO_DLCLOSE'] or env['COVERAGE']: + env.Append(CPPDEFINES = '-DMAPNIK_NO_DLCLOSE') - # Mac OSX (Darwin) special settings - if env['PLATFORM'] == 'Darwin': - pthread = '' - else: - pthread = '-pthread' + # Mac OSX (Darwin) special settings + if env['PLATFORM'] == 'Darwin': + pthread = '' + else: + pthread = '-pthread' - # Common debugging flags. - # http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html - debug_flags = ['-g', '-fno-omit-frame-pointer'] - debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG'] - ndebug_defines = ['-DNDEBUG'] + # Common debugging flags. + # http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html + debug_flags = ['-g', '-fno-omit-frame-pointer'] + debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG'] + ndebug_defines = ['-DNDEBUG'] - # faster compile - # http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/what_s_new/spirit_2_5.html#spirit.what_s_new.spirit_2_5.breaking_changes - env.Append(CPPDEFINES = '-DBOOST_SPIRIT_NO_PREDEFINED_TERMINALS=1') - env.Append(CPPDEFINES = '-DBOOST_PHOENIX_NO_PREDEFINED_TERMINALS=1') - # c++11 support / https://github.com/mapnik/mapnik/issues/1683 - # - upgrade to PHOENIX_V3 since that is needed for c++11 compile - env.Append(CPPDEFINES = '-DBOOST_SPIRIT_USE_PHOENIX_V3=1') + # faster compile + # http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/what_s_new/spirit_2_5.html#spirit.what_s_new.spirit_2_5.breaking_changes + env.Append(CPPDEFINES = '-DBOOST_SPIRIT_NO_PREDEFINED_TERMINALS=1') + env.Append(CPPDEFINES = '-DBOOST_PHOENIX_NO_PREDEFINED_TERMINALS=1') + # c++11 support / https://github.com/mapnik/mapnik/issues/1683 + # - upgrade to PHOENIX_V3 since that is needed for c++11 compile + env.Append(CPPDEFINES = '-DBOOST_SPIRIT_USE_PHOENIX_V3=1') - # Enable logging in debug mode (always) and release mode (when specified) - if env['DEFAULT_LOG_SEVERITY']: - if env['DEFAULT_LOG_SEVERITY'] not in severities: - severities_list = ', '.join(["'%s'" % s for s in severities]) - color_print(1,"Cannot set default logger severity to '%s', available options are %s." % (env['DEFAULT_LOG_SEVERITY'], severities_list)) - Exit(1) - else: - log_severity = severities.index(env['DEFAULT_LOG_SEVERITY']) - else: - severities_list = ', '.join(["'%s'" % s for s in severities]) - color_print(1,"No logger severity specified, available options are %s." % severities_list) - Exit(1) + # Enable logging in debug mode (always) and release mode (when specified) + if env['DEFAULT_LOG_SEVERITY']: + if env['DEFAULT_LOG_SEVERITY'] not in severities: + severities_list = ', '.join(["'%s'" % s for s in severities]) + color_print(1,"Cannot set default logger severity to '%s', available options are %s." % (env['DEFAULT_LOG_SEVERITY'], severities_list)) + Exit(1) + else: + log_severity = severities.index(env['DEFAULT_LOG_SEVERITY']) + else: + severities_list = ', '.join(["'%s'" % s for s in severities]) + color_print(1,"No logger severity specified, available options are %s." % severities_list) + Exit(1) - log_enabled = ['-DMAPNIK_LOG', '-DMAPNIK_DEFAULT_LOG_SEVERITY=%d' % log_severity] + log_enabled = ['-DMAPNIK_LOG', '-DMAPNIK_DEFAULT_LOG_SEVERITY=%d' % log_severity] - if env['DEBUG']: - debug_defines += log_enabled - else: - if env['ENABLE_LOG']: - ndebug_defines += log_enabled + if env['DEBUG']: + debug_defines += log_enabled + else: + if env['ENABLE_LOG']: + ndebug_defines += log_enabled - # Enable statistics reporting - if env['ENABLE_STATS']: - debug_defines.append('-DMAPNIK_STATS') - ndebug_defines.append('-DMAPNIK_STATS') + # Enable statistics reporting + if env['ENABLE_STATS']: + debug_defines.append('-DMAPNIK_STATS') + ndebug_defines.append('-DMAPNIK_STATS') - # Add rdynamic to allow using statics between application and plugins - # http://stackoverflow.com/questions/8623657/multiple-instances-of-singleton-across-shared-libraries-on-linux - if env['PLATFORM'] != 'Darwin' and env['CXX'] == 'g++': - env.MergeFlags('-rdynamic') + # Add rdynamic to allow using statics between application and plugins + # http://stackoverflow.com/questions/8623657/multiple-instances-of-singleton-across-shared-libraries-on-linux + if env['PLATFORM'] != 'Darwin' and env['CXX'] == 'g++': + env.MergeFlags('-rdynamic') - if env['DEBUG']: - env.Append(CXXFLAGS = debug_flags) - env.Append(CPPDEFINES = debug_defines) - else: - env.Append(CPPDEFINES = ndebug_defines) + if env['DEBUG']: + env.Append(CXXFLAGS = debug_flags) + env.Append(CPPDEFINES = debug_defines) + else: + env.Append(CPPDEFINES = ndebug_defines) - # Common flags for g++/clang++ CXX compiler. - # TODO: clean up code more to make -Wextra -Wsign-compare -Wsign-conversion -Wconversion viable - common_cxx_flags = '-fvisibility=hidden -fvisibility-inlines-hidden -Wall %s %s -ftemplate-depth-300 -Wsign-compare -Wshadow ' % (env['WARNING_CXXFLAGS'], pthread) + # Common flags for g++/clang++ CXX compiler. + # TODO: clean up code more to make -Wextra -Wsign-compare -Wsign-conversion -Wconversion viable + # -Wfloat-equal -Wold-style-cast -Wexit-time-destructors -Wglobal-constructors -Wreserved-id-macro -Wheader-hygiene -Wmissing-noreturn + common_cxx_flags = '-fvisibility=hidden -fvisibility-inlines-hidden -Wall %s %s -ftemplate-depth-300 -Wsign-compare -Wshadow ' % (env['WARNING_CXXFLAGS'], pthread) - if 'clang++' in env['CXX']: - common_cxx_flags += ' -Wno-unsequenced -Wc++14-extensions ' + if 'clang++' in env['CXX']: + common_cxx_flags += ' -Wno-unsequenced -Wtautological-compare -Wheader-hygiene -Wc++14-extensions ' + if env['DEBUG']: + env.Append(CXXFLAGS = common_cxx_flags + '-O0') + else: + env.Append(CXXFLAGS = common_cxx_flags + '-O%s' % (env['OPTIMIZATION'])) + if env['DEBUG_UNDEFINED']: + env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv') - if env['DEBUG']: - env.Append(CXXFLAGS = common_cxx_flags + '-O0') - else: - env.Append(CXXFLAGS = common_cxx_flags + '-O%s' % (env['OPTIMIZATION'])) - if env['DEBUG_UNDEFINED']: - env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv') - - if env['DEBUG_SANITIZE']: - env.Append(CXXFLAGS = ['-fsanitize=address']) - env.Append(LINKFLAGS = ['-fsanitize=address']) + if env['DEBUG_SANITIZE']: + env.Append(CXXFLAGS = ['-fsanitize=address']) + env.Append(LINKFLAGS = ['-fsanitize=address']) - # if requested, sort LIBPATH and CPPPATH one last time before saving... - if env['PRIORITIZE_LINKING']: - conf.prioritize_paths(silent=True) + # if requested, sort LIBPATH and CPPPATH one last time before saving... + if env['PRIORITIZE_LINKING']: + conf.prioritize_paths(silent=True) - # finish config stage and pickle results - env = conf.Finish() - env_cache = open(SCONS_CONFIGURE_CACHE, 'w') - pickle_dict = {} - for i in pickle_store: - pickle_dict[i] = env.get(i) - pickle.dump(pickle_dict,env_cache) - env_cache.close() - # fix up permissions on configure outputs - # this is hackish but avoids potential problems - # with a non-root configure following a root install - # that also triggered a re-configure - try: - os.chmod(SCONS_CONFIGURE_CACHE,0666) - except: pass - try: - os.chmod(SCONS_LOCAL_CONFIG,0666) - except: pass - try: - os.chmod('.sconsign.dblite',0666) - except: pass - try: - os.chmod(SCONS_LOCAL_LOG,0666) - except: pass - try: - for item in glob('%s/*' % SCONF_TEMP_DIR): - os.chmod(item,0666) - except: pass + # finish config stage and pickle results + env = conf.Finish() + env_cache = open(SCONS_CONFIGURE_CACHE, 'w') + pickle_dict = {} + for i in pickle_store: + pickle_dict[i] = env.get(i) + pickle.dump(pickle_dict,env_cache) + env_cache.close() + # fix up permissions on configure outputs + # this is hackish but avoids potential problems + # with a non-root configure following a root install + # that also triggered a re-configure + try: + os.chmod(SCONS_CONFIGURE_CACHE,0666) + except: pass + try: + os.chmod(SCONS_LOCAL_CONFIG,0666) + except: pass + try: + os.chmod('.sconsign.dblite',0666) + except: pass + try: + os.chmod(SCONS_LOCAL_LOG,0666) + except: pass + try: + for item in glob('%s/*' % SCONF_TEMP_DIR): + os.chmod(item,0666) + except: pass - if 'configure' in command_line_args: - color_print(4,'\nConfigure completed: run `make` to build or `make install`') - if not HELP_REQUESTED: - Exit(0) + if 'configure' in command_line_args: + color_print(4,'\nConfigure completed: run `make` to build or `make install`') + if not HELP_REQUESTED: + Exit(0) # autogenerate help on default/current SCons options Help(opts.GenerateHelpText(env)) @@ -1856,43 +1844,43 @@ Help(opts.GenerateHelpText(env)) if not HELP_REQUESTED: if 'uninstall' in COMMAND_LINE_TARGETS: - # dummy action in case there is nothing to uninstall, to avoid phony error.. - env.Alias("uninstall", "") + # dummy action in case there is nothing to uninstall, to avoid phony error.. + env.Alias("uninstall", "") env['create_uninstall_target'] = create_uninstall_target if env['PKG_CONFIG_PATH']: - env['ENV']['PKG_CONFIG_PATH'] = fix_path(env['PKG_CONFIG_PATH']) - # otherwise this variable == os.environ["PKG_CONFIG_PATH"] + env['ENV']['PKG_CONFIG_PATH'] = fix_path(env['PKG_CONFIG_PATH']) + # otherwise this variable == os.environ["PKG_CONFIG_PATH"] if env['PATH']: - env['ENV']['PATH'] = fix_path(env['PATH']) + ':' + env['ENV']['PATH'] + env['ENV']['PATH'] = fix_path(env['PATH']) + ':' + env['ENV']['PATH'] if env['PATH_REMOVE']: - for p in env['PATH_REMOVE'].split(':'): - if p in env['ENV']['PATH']: - env['ENV']['PATH'].replace(p,'') - rm_path(p,'LIBPATH',env) - rm_path(p,'CPPPATH',env) - rm_path(p,'CXXFLAGS',env) - rm_path(p,'CAIRO_LIBPATHS',env) - rm_path(p,'CAIRO_CPPPATHS',env) + for p in env['PATH_REMOVE'].split(':'): + if p in env['ENV']['PATH']: + env['ENV']['PATH'].replace(p,'') + rm_path(p,'LIBPATH',env) + rm_path(p,'CPPPATH',env) + rm_path(p,'CXXFLAGS',env) + rm_path(p,'CAIRO_LIBPATHS',env) + rm_path(p,'CAIRO_CPPPATHS',env) if env['PATH_REPLACE']: - searches,replace = env['PATH_REPLACE'].split(':') - for search in searches.split(','): - if search in env['ENV']['PATH']: - env['ENV']['PATH'] = os.path.abspath(env['ENV']['PATH'].replace(search,replace)) - def replace_path(set,s,r): - idx = 0 - for i in env[set]: - if s in i: - env[set][idx] = os.path.abspath(env[set][idx].replace(s,r)) - idx +=1 - replace_path('LIBPATH',search,replace) - replace_path('CPPPATH',search,replace) - replace_path('CXXFLAGS',search,replace) - replace_path('CAIRO_LIBPATHS',search,replace) - replace_path('CAIRO_CPPPATHS',search,replace) + searches,replace = env['PATH_REPLACE'].split(':') + for search in searches.split(','): + if search in env['ENV']['PATH']: + env['ENV']['PATH'] = os.path.abspath(env['ENV']['PATH'].replace(search,replace)) + def replace_path(set,s,r): + idx = 0 + for i in env[set]: + if s in i: + env[set][idx] = os.path.abspath(env[set][idx].replace(s,r)) + idx +=1 + replace_path('LIBPATH',search,replace) + replace_path('CPPPATH',search,replace) + replace_path('CXXFLAGS',search,replace) + replace_path('CAIRO_LIBPATHS',search,replace) + replace_path('CAIRO_CPPPATHS',search,replace) # export env so it is available in build.py files Export('env') @@ -1900,21 +1888,21 @@ if not HELP_REQUESTED: plugin_base = env.Clone() if env['COVERAGE']: - plugin_base.Append(LINKFLAGS='--coverage') - plugin_base.Append(CXXFLAGS='--coverage') + plugin_base.Append(LINKFLAGS='--coverage') + plugin_base.Append(CXXFLAGS='--coverage') Export('plugin_base') if env['FAST']: - # caching is 'auto' by default in SCons - # But let's also cache implicit deps... - EnsureSConsVersion(0,98) - SetOption('implicit_cache', 1) - SetOption('max_drift', 1) + # caching is 'auto' by default in SCons + # But let's also cache implicit deps... + EnsureSConsVersion(0,98) + SetOption('implicit_cache', 1) + SetOption('max_drift', 1) # Build agg first, doesn't need anything special if env['RUNTIME_LINK'] == 'shared': - SConscript('deps/agg/build.py') + SConscript('deps/agg/build.py') # Build spirit grammars SConscript('src/json/build.py') @@ -1935,78 +1923,78 @@ if not HELP_REQUESTED: POSTGIS_BUILT = False PGRASTER_BUILT = False for plugin in env['PLUGINS']: - if env['PLUGIN_LINKING'] == 'static' or plugin not in env['REQUESTED_PLUGINS']: - if os.path.exists('plugins/input/%s.input' % plugin): - os.unlink('plugins/input/%s.input' % plugin) - elif plugin in env['REQUESTED_PLUGINS']: - details = env['PLUGINS'][plugin] - if details['lib'] in env['LIBS']: - if env['PLUGIN_LINKING'] == 'shared': - SConscript('plugins/input/%s/build.py' % plugin) - # hack to avoid breaking on plugins with the same dep - if plugin == 'ogr': OGR_BUILT = True - if plugin == 'gdal': GDAL_BUILT = True - if plugin == 'postgis': POSTGIS_BUILT = True - if plugin == 'pgraster': PGRASTER_BUILT = True - if plugin == 'ogr' or plugin == 'gdal': - if GDAL_BUILT and OGR_BUILT: - env['LIBS'].remove(details['lib']) - elif plugin == 'postgis' or plugin == 'pgraster': - if POSTGIS_BUILT and PGRASTER_BUILT: - env['LIBS'].remove(details['lib']) - else: - env['LIBS'].remove(details['lib']) - elif not details['lib']: - 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) - if os.path.exists('plugins/input/%s.input' % plugin): - os.unlink('plugins/input/%s.input' % plugin) + if env['PLUGIN_LINKING'] == 'static' or plugin not in env['REQUESTED_PLUGINS']: + if os.path.exists('plugins/input/%s.input' % plugin): + os.unlink('plugins/input/%s.input' % plugin) + elif plugin in env['REQUESTED_PLUGINS']: + details = env['PLUGINS'][plugin] + if details['lib'] in env['LIBS']: + if env['PLUGIN_LINKING'] == 'shared': + SConscript('plugins/input/%s/build.py' % plugin) + # hack to avoid breaking on plugins with the same dep + if plugin == 'ogr': OGR_BUILT = True + if plugin == 'gdal': GDAL_BUILT = True + if plugin == 'postgis': POSTGIS_BUILT = True + if plugin == 'pgraster': PGRASTER_BUILT = True + if plugin == 'ogr' or plugin == 'gdal': + if GDAL_BUILT and OGR_BUILT: + env['LIBS'].remove(details['lib']) + elif plugin == 'postgis' or plugin == 'pgraster': + if POSTGIS_BUILT and PGRASTER_BUILT: + env['LIBS'].remove(details['lib']) + else: + env['LIBS'].remove(details['lib']) + elif not details['lib']: + 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) + if os.path.exists('plugins/input/%s.input' % plugin): + os.unlink('plugins/input/%s.input' % plugin) create_uninstall_target(env, env['MAPNIK_LIB_DIR_DEST'], False) create_uninstall_target(env, env['MAPNIK_INPUT_PLUGINS_DEST'] , False) if 'install' in COMMAND_LINE_TARGETS: - # if statically linking plugins still make sure - # to create the dynamic plugins directory - if env['PLUGIN_LINKING'] == 'static': - if not os.path.exists(env['MAPNIK_INPUT_PLUGINS_DEST']): - os.makedirs(env['MAPNIK_INPUT_PLUGINS_DEST']) - # before installing plugins, wipe out any previously - # installed plugins that we are no longer building - for plugin in PLUGINS.keys(): - 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(4,"Notice: removing out of date plugin: '%s'" % plugin_path) - os.unlink(plugin_path) + # if statically linking plugins still make sure + # to create the dynamic plugins directory + if env['PLUGIN_LINKING'] == 'static': + if not os.path.exists(env['MAPNIK_INPUT_PLUGINS_DEST']): + os.makedirs(env['MAPNIK_INPUT_PLUGINS_DEST']) + # before installing plugins, wipe out any previously + # installed plugins that we are no longer building + for plugin in PLUGINS.keys(): + 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(4,"Notice: removing out of date plugin: '%s'" % plugin_path) + os.unlink(plugin_path) # Build the c++ rundemo app if requested if not env['HOST']: - if env['DEMO']: - SConscript('demo/c++/build.py') + if env['DEMO']: + SConscript('demo/c++/build.py') # Build shapeindex and remove its dependency from the LIBS if not env['HOST']: - if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']: - if env['SHAPEINDEX']: - SConscript('utils/shapeindex/build.py') - if env['MAPNIK_INDEX']: - SConscript('utils/mapnik-index/build.py') - # Build the pgsql2psqlite app if requested - if env['PGSQL2SQLITE']: - SConscript('utils/pgsql2sqlite/build.py') - if env['SVG2PNG']: - SConscript('utils/svg2png/build.py') - if env['MAPNIK_RENDER']: - SConscript('utils/mapnik-render/build.py') - # devtools not ready for public - #SConscript('utils/ogrindex/build.py') - env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND']) - else : - color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available") + if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']: + if env['SHAPEINDEX']: + SConscript('utils/shapeindex/build.py') + if env['MAPNIK_INDEX']: + SConscript('utils/mapnik-index/build.py') + # Build the pgsql2psqlite app if requested + if env['PGSQL2SQLITE']: + SConscript('utils/pgsql2sqlite/build.py') + if env['SVG2PNG']: + SConscript('utils/svg2png/build.py') + if env['MAPNIK_RENDER']: + SConscript('utils/mapnik-render/build.py') + # devtools not ready for public + #SConscript('utils/ogrindex/build.py') + env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND']) + else : + color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available") # Configure fonts and if requested install the bundled DejaVu fonts SConscript('fonts/build.py') @@ -2015,10 +2003,10 @@ if not HELP_REQUESTED: SConscript('test/build.py') if env['BENCHMARK']: - SConscript('benchmark/build.py') + SConscript('benchmark/build.py') if os.path.exists('./bindings/python/build.py'): - SConscript('./bindings/python/build.py') + SConscript('./bindings/python/build.py') # install mapnik-config script SConscript('utils/mapnik-config/build.py') diff --git a/appveyor.yml b/appveyor.yml index e9d278c6b..34ddc3b6a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ environment: msvs_toolset: 14 - BOOST_VERSION: 59 + BOOST_VERSION: 60 FASTBUILD: 1 matrix: - platform: x64 @@ -19,8 +19,13 @@ install: - SET PGUSER=postgres - SET PGPASSWORD=Password12! - SET PATH=C:\Program Files\PostgreSQL\9.4\bin\;%PATH% + +build_script: - scripts\build-appveyor.bat +after_build: + - 7z a mapnik-visual-images.zip C:\tmp\mapnik-visual-images + artifacts: - path: mapnik-gyp\msbuild-summary.txt name: msbuild-summary.txt @@ -28,7 +33,8 @@ artifacts: name: msbuild-errors.txt - path: mapnik-gyp\msbuild-warnings.txt name: msbuild-warnings.txt + - path: mapnik-visual-images.zip + name: mapnik-visual-images.zip -build: off test: off deploy: off diff --git a/benchmark/bench_framework.hpp b/benchmark/bench_framework.hpp index c5f280207..a3de4fdd9 100644 --- a/benchmark/bench_framework.hpp +++ b/benchmark/bench_framework.hpp @@ -1,5 +1,5 @@ -#ifndef __MAPNIK_BENCH_FRAMEWORK_HPP__ -#define __MAPNIK_BENCH_FRAMEWORK_HPP__ +#ifndef MAPNIK_BENCH_FRAMEWORK_HPP +#define MAPNIK_BENCH_FRAMEWORK_HPP // mapnik #include @@ -52,7 +52,6 @@ public: } virtual bool validate() const = 0; virtual bool operator()() const = 0; - virtual ~test_case() {} }; // gathers --long-option values in 'params'; @@ -288,4 +287,4 @@ protected: } -#endif // __MAPNIK_BENCH_FRAMEWORK_HPP__ +#endif // MAPNIK_BENCH_FRAMEWORK_HPP diff --git a/benchmark/compare_images.hpp b/benchmark/compare_images.hpp index fb0e4ac95..ff90e01a0 100644 --- a/benchmark/compare_images.hpp +++ b/benchmark/compare_images.hpp @@ -1,11 +1,10 @@ -#ifndef __MAPNIK_COMPARE_IMAGES_HPP__ -#define __MAPNIK_COMPARE_IMAGES_HPP__ +#ifndef MAPNIK_COMPARE_IMAGES_HPP +#define MAPNIK_COMPARE_IMAGES_HPP #include #include #include -using namespace mapnik; namespace benchmark { @@ -23,15 +22,15 @@ namespace benchmark { throw mapnik::image_reader_exception("Failed to load: " + src_fn); } - const image_any desc_any = reader1->read(0,0,reader1->width(), reader1->height()); - const image_any src_any = reader2->read(0,0,reader2->width(), reader2->height()); + const mapnik::image_any desc_any = reader1->read(0,0,reader1->width(), reader1->height()); + const mapnik::image_any src_any = reader2->read(0,0,reader2->width(), reader2->height()); - image_rgba8 const& dest = util::get(desc_any); - image_rgba8 const& src = util::get(src_any); + mapnik::image_rgba8 const& dest = mapnik::util::get(desc_any); + mapnik::image_rgba8 const& src = mapnik::util::get(src_any); return compare(dest, src, 0, true) == 0; } } -#endif // __MAPNIK_COMPARE_IMAGES_HPP__ +#endif // MAPNIK_COMPARE_IMAGES_HPP diff --git a/bootstrap.sh b/bootstrap.sh old mode 100644 new mode 100755 index 040034f68..fd877a644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -10,14 +10,16 @@ todo - shrink icu data ' +MASON_VERSION="b709931" + function setup_mason() { if [[ ! -d ./.mason ]]; then - git clone --depth 1 https://github.com/mapbox/mason.git ./.mason + git clone https://github.com/mapbox/mason.git ./.mason + (cd ./.mason && git checkout ${MASON_VERSION}) else echo "Updating to latest mason" - (cd ./.mason && git pull) + (cd ./.mason && git fetch && git checkout ${MASON_VERSION}) fi - export MASON_DIR=$(pwd)/.mason export PATH=$(pwd)/.mason:$PATH export CXX=${CXX:-clang++} export CC=${CC:-clang} @@ -28,8 +30,8 @@ function install() { if [[ ! -d ./mason_packages/${MASON_PLATFORM_ID}/${1}/${2} ]]; then mason install $1 $2 mason link $1 $2 - if [[ $3 ]]; then - LA_FILE=$(${MASON_DIR:-~/.mason}/mason prefix $1 $2)/lib/$3.la + if [[ ${3:-false} != false ]]; then + LA_FILE=$(mason prefix $1 $2)/lib/$3.la if [[ -f ${LA_FILE} ]]; then perl -i -p -e 's:\Q$ENV{HOME}/build/mapbox/mason\E:$ENV{PWD}:g' ${LA_FILE} else @@ -60,8 +62,11 @@ function install_mason_deps() { wait install webp 0.4.2 libwebp & install gdal 1.11.2 libgdal & - install boost 1.59.0 & - install boost_liball 1.59.0 & + install boost 1.61.0 & + install boost_libsystem 1.61.0 & + install boost_libfilesystem 1.61.0 & + install boost_libprogram_options 1.61.0 & + install boost_libregex 1.61.0 & install freetype 2.6 libfreetype & install harfbuzz 0.9.41 libharfbuzz & wait diff --git a/circle.yml b/circle.yml new file mode 100644 index 000000000..cf3e31cb1 --- /dev/null +++ b/circle.yml @@ -0,0 +1,45 @@ +machine: + xcode: + version: 7.3 + environment: + XCODE_SCHEME: "no" + XCODE_WORKSPACE: "no" + JOBS: 8 + CCACHE_TEMPDIR: /tmp/.ccache-temp + CCACHE_COMPRESS: 1 + LLVM_VERSION: 3.8 + pre: + - echo "here" + post: + - echo "there" + +checkout: + post: + - git submodule update --init + +dependencies: + cache_directories: + - "~/.ccache" + - "~/.apt-cache" + - "mason_packages" + pre: + # https://discuss.circleci.com/t/add-ability-to-cache-apt-get-programs/598/3 + - sudo rm -rf /var/cache/apt/archives && sudo ln -s ~/.apt-cache /var/cache/apt/archives && mkdir -p ~/.apt-cache/partial + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + override: + - sudo apt-get update -y + +database: + pre: + - ./bootstrap.sh + - ./.mason/mason install clang ${LLVM_VERSION}.0 + - ./.mason/mason link clang ${LLVM_VERSION}.0 + - ./configure CC="$(pwd)/mason_packages/.link/bin/clang-${LLVM_VERSION}" CXX="$(pwd)/mason_packages/.link/bin/ccache $(pwd)/mason_packages/.link/bin/clang++-${LLVM_VERSION} -Qunused-arguments" + - make + override: + - psql -c 'create database template_postgis;' + - psql -c 'create extension postgis;' -d template_postgis + +test: + override: + - make test diff --git a/demo/c++/README.md b/demo/c++/README.md index daa4198c1..548508ee0 100644 --- a/demo/c++/README.md +++ b/demo/c++/README.md @@ -52,11 +52,11 @@ If you do not have svn installed you can grab gyp from: Simply type: - make + make Then to run do: - ./rundemo `mapnik-config --prefix` + ./rundemo `mapnik-config --prefix` On OS X you can also create an xcode project: diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index c07bd5c31..c20c288cf 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -55,7 +55,7 @@ int main ( int, char** ) try { std::cout << " running demo ... \n"; datasource_cache::instance().register_datasources("plugins/input/"); - freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.34/ttf/DejaVuSans.ttf"); + freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf"); Map m(800,600); m.set_background(parse_color("white")); @@ -230,7 +230,7 @@ int main ( int, char** ) parameters p; p["type"]="shape"; p["file"]="demo/data/boundaries"; - p["encoding"]="latin1"; + p["encoding"]="utf8"; layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance().create(p)); @@ -295,7 +295,7 @@ int main ( int, char** ) parameters p; p["type"]="shape"; p["file"]="demo/data/popplaces"; - p["encoding"] = "latin1"; + p["encoding"] = "utf8"; layer lyr("Populated Places"); lyr.set_srs(srs_lcc); lyr.set_datasource(datasource_cache::instance().create(p)); diff --git a/demo/data/boundaries.dbf b/demo/data/boundaries.dbf index aeed23561..04d2ed661 100644 Binary files a/demo/data/boundaries.dbf and b/demo/data/boundaries.dbf differ diff --git a/demo/data/boundaries.prj b/demo/data/boundaries.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/boundaries.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/boundaries.sbx b/demo/data/boundaries.sbx deleted file mode 100644 index c66e6e334..000000000 Binary files a/demo/data/boundaries.sbx and /dev/null differ diff --git a/demo/data/boundaries_l.dbf b/demo/data/boundaries_l.dbf index e6bc20c98..44d4ca8e1 100644 Binary files a/demo/data/boundaries_l.dbf and b/demo/data/boundaries_l.dbf differ diff --git a/demo/data/boundaries_l.prj b/demo/data/boundaries_l.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/boundaries_l.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/boundaries_l.sbx b/demo/data/boundaries_l.sbx deleted file mode 100644 index e609d80c5..000000000 Binary files a/demo/data/boundaries_l.sbx and /dev/null differ diff --git a/demo/data/ontdrainage.dbf b/demo/data/ontdrainage.dbf index 33d8004b6..819265027 100644 Binary files a/demo/data/ontdrainage.dbf and b/demo/data/ontdrainage.dbf differ diff --git a/demo/data/ontdrainage.prj b/demo/data/ontdrainage.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/ontdrainage.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/ontdrainage.sbx b/demo/data/ontdrainage.sbx deleted file mode 100644 index 3739c6198..000000000 Binary files a/demo/data/ontdrainage.sbx and /dev/null differ diff --git a/demo/data/popplaces.dbf b/demo/data/popplaces.dbf index 408968e85..d385b6f1d 100644 Binary files a/demo/data/popplaces.dbf and b/demo/data/popplaces.dbf differ diff --git a/demo/data/popplaces.prj b/demo/data/popplaces.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/popplaces.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/popplaces.sbx b/demo/data/popplaces.sbx deleted file mode 100644 index c02888185..000000000 Binary files a/demo/data/popplaces.sbx and /dev/null differ diff --git a/demo/data/qcdrainage.dbf b/demo/data/qcdrainage.dbf index 95ce20f20..04fcf8541 100644 Binary files a/demo/data/qcdrainage.dbf and b/demo/data/qcdrainage.dbf differ diff --git a/demo/data/qcdrainage.prj b/demo/data/qcdrainage.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/qcdrainage.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/qcdrainage.sbx b/demo/data/qcdrainage.sbx deleted file mode 100644 index c73534e78..000000000 Binary files a/demo/data/qcdrainage.sbx and /dev/null differ diff --git a/demo/data/roads.dbf b/demo/data/roads.dbf index 73c1db9dd..709f88182 100644 Binary files a/demo/data/roads.dbf and b/demo/data/roads.dbf differ diff --git a/demo/data/roads.prj b/demo/data/roads.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/roads.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/roads.sbx b/demo/data/roads.sbx deleted file mode 100644 index b804cb3b2..000000000 Binary files a/demo/data/roads.sbx and /dev/null differ diff --git a/deps/agg/include/agg_rasterizer_scanline_aa.h b/deps/agg/include/agg_rasterizer_scanline_aa.h index 77bc41bc7..b2d4e3e12 100644 --- a/deps/agg/include/agg_rasterizer_scanline_aa.h +++ b/deps/agg/include/agg_rasterizer_scanline_aa.h @@ -2,15 +2,15 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // -// The author gratefully acknowleges the support of David Turner, -// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details. // //---------------------------------------------------------------------------- @@ -19,12 +19,12 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Adaptation for 32-bit screen coordinates has been sponsored by +// Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. -// +// //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED #define AGG_RASTERIZER_SCANLINE_AA_INCLUDED @@ -39,8 +39,8 @@ namespace agg //-----------------------------------------------------------------cell_aa - // A pixel cell. There're no constructors defined and it was done - // intentionally in order to avoid extra overhead when allocating an + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an // array of cells. struct cell_aa { @@ -67,10 +67,10 @@ namespace agg //==================================================rasterizer_scanline_aa - // Polygon rasterizer that is used to render filled polygons with - // high-quality Anti-Aliasing. Internally, by default, the class uses - // integer coordinates in format 24.8, i.e. 24 bits for integer part - // and 8 bits for fractional - see poly_subpixel_shift. This class can be + // Polygon rasterizer that is used to render filled polygons with + // high-quality Anti-Aliasing. Internally, by default, the class uses + // integer coordinates in format 24.8, i.e. 24 bits for integer part + // and 8 bits for fractional - see poly_subpixel_shift. This class can be // used in the following way: // // 1. filling_rule(filling_rule_e ft) - optional. @@ -79,20 +79,20 @@ namespace agg // // 3. reset() // - // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create + // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create // more than one contour, but each contour must consist of at least 3 // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); // is the absolute minimum of vertices that define a triangle. // The algorithm does not check either the number of vertices nor - // coincidence of their coordinates, but in the worst case it just + // coincidence of their coordinates, but in the worst case it just // won't draw anything. - // The orger of the vertices (clockwise or counterclockwise) + // The orger of the vertices (clockwise or counterclockwise) // is important when using the non-zero filling rule (fill_non_zero). // In this case the vertex order of all the contours must be the same // if you want your intersecting polygons to be without "holes". - // You actually can use different vertices order. If the contours do not - // intersect each other the order is not important anyway. If they do, - // contours with the same vertex order will be rendered without "holes" + // You actually can use different vertices order. If the contours do not + // intersect each other the order is not important anyway. If they do, + // contours with the same vertex order will be rendered without "holes" // while the intersecting contours with different orders will have "holes". // // filling_rule() and gamma() can be called anytime before "sweeping". @@ -122,7 +122,7 @@ namespace agg }; //-------------------------------------------------------------------- - rasterizer_scanline_aa() : + rasterizer_scanline_aa() : m_outline(), m_clipper(), m_filling_rule(fill_non_zero), @@ -136,8 +136,8 @@ namespace agg } //-------------------------------------------------------------------- - template - rasterizer_scanline_aa(const GammaF& gamma_function) : + template + rasterizer_scanline_aa(const GammaF& gamma_function) : m_outline(), m_clipper(m_outline), m_filling_rule(fill_non_zero), @@ -150,7 +150,7 @@ namespace agg } //-------------------------------------------------------------------- - void reset(); + void reset(); void reset_clipping(); void clip_box(double x1, double y1, double x2, double y2); void filling_rule(filling_rule_e filling_rule); @@ -158,7 +158,7 @@ namespace agg //-------------------------------------------------------------------- template void gamma(const GammaF& gamma_function) - { + { int i; for(i = 0; i < aa_scale; i++) { @@ -167,9 +167,9 @@ namespace agg } //-------------------------------------------------------------------- - unsigned apply_gamma(unsigned cover) const - { - return m_gamma[cover]; + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; } //-------------------------------------------------------------------- @@ -198,7 +198,7 @@ namespace agg add_vertex(x, y, cmd); } } - + //-------------------------------------------------------------------- int min_x() const { return m_outline.min_x(); } int min_y() const { return m_outline.min_y(); } @@ -237,7 +237,7 @@ namespace agg sl.reset_spans(); unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); - int cover = 0; + unsigned cover = 0; while(num_cells) { @@ -276,7 +276,7 @@ namespace agg } } } - + if(sl.num_spans()) break; ++m_scan_y; } @@ -294,7 +294,7 @@ namespace agg //-------------------------------------------------------------------- // Disable copying rasterizer_scanline_aa(const rasterizer_scanline_aa&); - const rasterizer_scanline_aa& + const rasterizer_scanline_aa& operator = (const rasterizer_scanline_aa&); private: @@ -321,32 +321,32 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::reset() - { - m_outline.reset(); + template + void rasterizer_scanline_aa::reset() + { + m_outline.reset(); m_status = status_initial; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) - { - m_filling_rule = filling_rule; + template + void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::clip_box(double x1, double y1, + template + void rasterizer_scanline_aa::clip_box(double x1, double y1, double x2, double y2) { reset(); - m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), conv_type::upscale(x2), conv_type::upscale(y2)); } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::reset_clipping() { reset(); @@ -354,7 +354,7 @@ namespace agg } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::close_polygon() { if(m_status == status_line_to) @@ -365,56 +365,56 @@ namespace agg } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::move_to(int x, int y) { if(m_outline.sorted()) reset(); if(m_auto_close) close_polygon(); - m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_clipper.move_to(m_start_x = conv_type::downscale(x), m_start_y = conv_type::downscale(y)); m_status = status_move_to; } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::line_to(int x, int y) { - m_clipper.line_to(m_outline, - conv_type::downscale(x), + m_clipper.line_to(m_outline, + conv_type::downscale(x), conv_type::downscale(y)); m_status = status_line_to; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to_d(double x, double y) - { + template + void rasterizer_scanline_aa::move_to_d(double x, double y) + { if(m_outline.sorted()) reset(); if(m_auto_close) close_polygon(); - m_clipper.move_to(m_start_x = conv_type::upscale(x), - m_start_y = conv_type::upscale(y)); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); m_status = status_move_to; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to_d(double x, double y) - { - m_clipper.line_to(m_outline, - conv_type::upscale(x), - conv_type::upscale(y)); + template + void rasterizer_scanline_aa::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); m_status = status_line_to; } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::add_vertex(double x, double y, unsigned cmd) { - if(is_move_to(cmd)) + if(is_move_to(cmd)) { move_to_d(x, y); } - else + else if(is_vertex(cmd)) { line_to_d(x, y); @@ -427,32 +427,32 @@ namespace agg } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::edge(int x1, int y1, int x2, int y2) { if(m_outline.sorted()) reset(); m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); - m_clipper.line_to(m_outline, - conv_type::downscale(x2), + m_clipper.line_to(m_outline, + conv_type::downscale(x2), conv_type::downscale(y2)); m_status = status_move_to; } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::edge_d(double x1, double y1, - double x2, double y2) - { - if(m_outline.sorted()) reset(); - m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); - m_clipper.line_to(m_outline, - conv_type::upscale(x2), - conv_type::upscale(y2)); - m_status = status_move_to; - } //------------------------------------------------------------------------ - template + template + void rasterizer_scanline_aa::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template void rasterizer_scanline_aa::sort() { if(m_auto_close) close_polygon(); @@ -460,12 +460,12 @@ namespace agg } //------------------------------------------------------------------------ - template + template AGG_INLINE bool rasterizer_scanline_aa::rewind_scanlines() { if(m_auto_close) close_polygon(); m_outline.sort_cells(); - if(m_outline.total_cells() == 0) + if(m_outline.total_cells() == 0) { return false; } @@ -475,14 +475,14 @@ namespace agg //------------------------------------------------------------------------ - template + template AGG_INLINE bool rasterizer_scanline_aa::navigate_scanline(int y) { if(m_auto_close) close_polygon(); m_outline.sort_cells(); - if(m_outline.total_cells() == 0 || - y < m_outline.min_y() || - y > m_outline.max_y()) + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) { return false; } @@ -491,7 +491,7 @@ namespace agg } //------------------------------------------------------------------------ - template + template bool rasterizer_scanline_aa::hit_test(int tx, int ty) { if(!navigate_scanline(ty)) return false; @@ -507,4 +507,3 @@ namespace agg #endif - diff --git a/deps/mapbox/variant b/deps/mapbox/variant index 5aab5df0d..b5728ad76 160000 --- a/deps/mapbox/variant +++ b/deps/mapbox/variant @@ -1 +1 @@ -Subproject commit 5aab5df0dc899b484c04ce9c649645787ee0bc5c +Subproject commit b5728ad76e1402c130a9330aa44b6f4b655b13b4 diff --git a/deps/mapnik/build.py b/deps/mapnik/build.py index 0d6dc8486..76529fbda 100644 --- a/deps/mapnik/build.py +++ b/deps/mapnik/build.py @@ -7,7 +7,7 @@ subdirs = { './sparsehash':{'dir':'sparsehash','glob':'*'}, './sparsehash/internal':{'dir':'sparsehash/internal','glob':'*'}, '../agg/include':{'dir':'agg','glob':'agg*'}, - '../mapbox':{'dir':'mapbox/variant','glob':'*/*.hpp'} + '../mapbox/variant/include':{'dir':'mapbox','glob':'*/*.hpp'} } if 'install' in COMMAND_LINE_TARGETS: diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp index 139405cd9..ff87ce0ef 100644 --- a/include/mapnik/agg_helpers.hpp +++ b/include/mapnik/agg_helpers.hpp @@ -26,8 +26,10 @@ // mapnik #include -// agg +#pragma GCC diagnostic push +#include #include "agg_gamma_functions.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/agg_pattern_source.hpp b/include/mapnik/agg_pattern_source.hpp index a0000204f..42dd7f36f 100644 --- a/include/mapnik/agg_pattern_source.hpp +++ b/include/mapnik/agg_pattern_source.hpp @@ -27,8 +27,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_color_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/agg_rasterizer.hpp b/include/mapnik/agg_rasterizer.hpp index 51cf4cd5d..66da59fd6 100644 --- a/include/mapnik/agg_rasterizer.hpp +++ b/include/mapnik/agg_rasterizer.hpp @@ -26,8 +26,11 @@ // mapnik #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/agg_render_marker.hpp b/include/mapnik/agg_render_marker.hpp index 65e531cfd..283807a93 100644 --- a/include/mapnik/agg_render_marker.hpp +++ b/include/mapnik/agg_render_marker.hpp @@ -30,7 +30,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_color_rgba.h" #include "agg_renderer_base.h" #include "agg_renderer_scanline.h" @@ -43,6 +44,7 @@ #include "agg_pixfmt_rgba.h" #include "agg_span_image_filter_rgba.h" #include "agg_span_interpolator_linear.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/box2d.hpp b/include/mapnik/box2d.hpp index 4471c281c..267120111 100644 --- a/include/mapnik/box2d.hpp +++ b/include/mapnik/box2d.hpp @@ -27,8 +27,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // agg // forward declare so that apps using mapnik do not need agg headers @@ -38,9 +40,8 @@ struct trans_affine; namespace mapnik { -/*! - * A spatial envelope (i.e. bounding box) which also defines some basic operators. - */ +// A spatial envelope (i.e. bounding box) which also defines some basic operators. + template class MAPNIK_DECL box2d : boost::equality_comparable , boost::addable, @@ -48,7 +49,8 @@ template class MAPNIK_DECL box2d boost::multipliable2, T > > > > { public: - using box2d_type = box2d; + using value_type = T; + using box2d_type = box2d; private: T minx_; T miny_; @@ -63,12 +65,22 @@ private: swap(lhs.maxy_, rhs.maxy_); } public: + box2d(); box2d(T minx,T miny,T maxx,T maxy); box2d(coord const& c0, coord const& c1); box2d(box2d_type const& rhs); box2d(box2d_type const& rhs, agg::trans_affine const& tr); + // move box2d(box2d_type&& rhs); + // converting ctor + template + explicit box2d(box2d other) + : minx_(static_cast(other.minx())), + miny_(static_cast(other.miny())), + maxx_(static_cast(other.maxx())), + maxy_(static_cast(other.maxy())) + {} box2d_type& operator=(box2d_type other); T minx() const; T miny() const; @@ -97,6 +109,7 @@ public: void re_center(T cx,T cy); void re_center(coord const& c); void init(T x0,T y0,T x1,T y1); + void init(T x, T y); void clip(box2d_type const& other); void pad(T padding); bool from_string(std::string const& str); diff --git a/include/mapnik/box2d_impl.hpp b/include/mapnik/box2d_impl.hpp new file mode 100644 index 000000000..7f3e9d1e7 --- /dev/null +++ b/include/mapnik/box2d_impl.hpp @@ -0,0 +1,496 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 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 + +// stl +#include +#include +#include + +#include + +#pragma GCC diagnostic push +#include +#include +#include +#include +#pragma GCC diagnostic pop + +// agg +#include "agg_trans_affine.h" + +BOOST_FUSION_ADAPT_TPL_ADT( + (T), + (mapnik::box2d)(T), + (T, T, obj.minx(), obj.set_minx(mapnik::safe_cast(val))) + (T, T, obj.miny(), obj.set_miny(mapnik::safe_cast(val))) + (T, T, obj.maxx(), obj.set_maxx(mapnik::safe_cast(val))) + (T, T, obj.maxy(), obj.set_maxy(mapnik::safe_cast(val)))) + +namespace mapnik +{ +template +box2d::box2d() + :minx_( std::numeric_limits::max()), + miny_( std::numeric_limits::max()), + maxx_(-std::numeric_limits::max()), + maxy_(-std::numeric_limits::max()) {} + +template +box2d::box2d(T minx,T miny,T maxx,T maxy) +{ + init(minx,miny,maxx,maxy); +} + +template +box2d::box2d(coord const& c0, coord const& c1) +{ + init(c0.x,c0.y,c1.x,c1.y); +} + +template +box2d::box2d(box2d_type const& rhs) + : minx_(rhs.minx_), + miny_(rhs.miny_), + maxx_(rhs.maxx_), + maxy_(rhs.maxy_) {} + +template +box2d::box2d(box2d_type && rhs) + : minx_(std::move(rhs.minx_)), + miny_(std::move(rhs.miny_)), + maxx_(std::move(rhs.maxx_)), + maxy_(std::move(rhs.maxy_)) {} + +template +box2d& box2d::operator=(box2d_type other) +{ + swap(*this, other); + return *this; +} + +template +box2d::box2d(box2d_type const& rhs, agg::trans_affine const& tr) +{ + double x0 = rhs.minx_, y0 = rhs.miny_; + double x1 = rhs.maxx_, y1 = rhs.miny_; + double x2 = rhs.maxx_, y2 = rhs.maxy_; + double x3 = rhs.minx_, y3 = rhs.maxy_; + tr.transform(&x0, &y0); + tr.transform(&x1, &y1); + tr.transform(&x2, &y2); + tr.transform(&x3, &y3); + init(static_cast(x0), static_cast(y0), + static_cast(x2), static_cast(y2)); + expand_to_include(static_cast(x1), static_cast(y1)); + expand_to_include(static_cast(x3), static_cast(y3)); +} + +template +bool box2d::operator==(box2d const& other) const +{ + return minx_==other.minx_ && + miny_==other.miny_ && + maxx_==other.maxx_ && + maxy_==other.maxy_; +} + +template +T box2d::minx() const +{ + return minx_; +} + +template +T box2d::maxx() const +{ + return maxx_; +} + +template +T box2d::miny() const +{ + return miny_; +} + +template +T box2d::maxy() const +{ + return maxy_; +} + +template +void box2d::set_minx(T v) +{ + minx_ = v; +} + +template +void box2d::set_miny(T v) +{ + miny_ = v; +} + +template +void box2d::set_maxx(T v) +{ + maxx_ = v; +} + +template +void box2d::set_maxy(T v) +{ + maxy_ = v; +} + +template +T box2d::width() const +{ + return maxx_-minx_; +} + +template +T box2d::height() const +{ + return maxy_-miny_; +} + +template +void box2d::width(T w) +{ + T cx=center().x; + minx_=static_cast(cx-w*0.5); + maxx_=static_cast(cx+w*0.5); +} + +template +void box2d::height(T h) +{ + T cy=center().y; + miny_=static_cast(cy-h*0.5); + maxy_=static_cast(cy+h*0.5); +} + +template +coord box2d::center() const +{ + return coord(static_cast(0.5*(minx_+maxx_)), + static_cast(0.5*(miny_+maxy_))); +} + +template +void box2d::expand_to_include(coord const& c) +{ + expand_to_include(c.x,c.y); +} + +template +void box2d::expand_to_include(T x,T y) +{ + if (xmaxx_) maxx_=x; + if (ymaxy_) maxy_=y; +} + +template +void box2d::expand_to_include(box2d const& other) +{ + if (other.minx_maxx_) maxx_=other.maxx_; + if (other.miny_maxy_) maxy_=other.maxy_; +} + +template +bool box2d::contains(coord const& c) const +{ + return contains(c.x,c.y); +} + +template +bool box2d::contains(T x,T y) const +{ + return x>=minx_ && x<=maxx_ && y>=miny_ && y<=maxy_; +} + +template +bool box2d::contains(box2d const& other) const +{ + return other.minx_>=minx_ && + other.maxx_<=maxx_ && + other.miny_>=miny_ && + other.maxy_<=maxy_; +} + +template +bool box2d::intersects(coord const& c) const +{ + return intersects(c.x,c.y); +} + +template +bool box2d::intersects(T x,T y) const +{ + return !(x>maxx_ || xmaxy_ || y +bool box2d::intersects(box2d const& other) const +{ + return !(other.minx_>maxx_ || other.maxx_maxy_ || other.maxy_ +box2d box2d::intersect(box2d_type const& other) const +{ + if (intersects(other)) + { + T x0=std::max(minx_,other.minx_); + T y0=std::max(miny_,other.miny_); + T x1=std::min(maxx_,other.maxx_); + T y1=std::min(maxy_,other.maxy_); + return box2d(x0,y0,x1,y1); + } + else + { + return box2d(); + } +} + +template +void box2d::re_center(T cx,T cy) +{ + T dx=cx-center().x; + T dy=cy-center().y; + minx_+=dx; + miny_+=dy; + maxx_+=dx; + maxy_+=dy; +} + +template +void box2d::re_center(coord const& c) +{ + re_center(c.x,c.y); +} + +template +void box2d::init(T x0, T y0, T x1, T y1) +{ + if (x0 < x1) + { + minx_ = x0; + maxx_ = x1; + } + else + { + minx_ = x1; + maxx_ = x0; + } + if (y0 < y1) + { + miny_ = y0; + maxy_ = y1; + } + else + { + miny_ = y1; + maxy_ = y0; + } +} + +template +void box2d::init(T x, T y) +{ + init(x, y, x, y); +} + +template +void box2d::clip(box2d_type const& other) +{ + minx_ = std::max(minx_, other.minx()); + miny_ = std::max(miny_, other.miny()); + maxx_ = std::min(maxx_, other.maxx()); + maxy_ = std::min(maxy_, other.maxy()); +} + +template +void box2d::pad(T padding) +{ + minx_ -= padding; + miny_ -= padding; + maxx_ += padding; + maxy_ += padding; +} + +template +bool box2d::from_string(std::string const& str) +{ + boost::spirit::qi::lit_type lit; + boost::spirit::qi::double_type double_; + boost::spirit::ascii::space_type space; + bool r = boost::spirit::qi::phrase_parse(str.begin(), + str.end(), + double_ >> -lit(',') >> double_ >> -lit(',') >> double_ >> -lit(',') >> double_, + space, + *this); + return r; +} + +template +bool box2d::valid() const +{ + return (minx_ <= maxx_ && miny_ <= maxy_) ; +} + +template +void box2d::move(T x, T y) +{ + minx_ += x; + maxx_ += x; + miny_ += y; + maxy_ += y; +} + +template +std::string box2d::to_string() const +{ + std::ostringstream s; + if (valid()) + { + s << "box2d(" << std::fixed << std::setprecision(16) + << minx_ << ',' << miny_ << ',' + << maxx_ << ',' << maxy_ << ')'; + } + else + { + s << "box2d(INVALID)"; + } + return s.str(); +} + + +template +box2d& box2d::operator+=(box2d const& other) +{ + expand_to_include(other); + return *this; +} + +template +box2d box2d::operator+ (T other) const +{ + return box2d(minx_ - other, miny_ - other, maxx_ + other, maxy_ + other); +} + +template +box2d& box2d::operator+= (T other) +{ + minx_ -= other; + miny_ -= other; + maxx_ += other; + maxy_ += other; + return *this; +} + + +template +box2d& box2d::operator*=(T t) +{ + coord c = center(); + T sx = static_cast(0.5 * width() * t); + T sy = static_cast(0.5 * height() * t); + minx_ = c.x - sx; + maxx_ = c.x + sx; + miny_ = c.y - sy; + maxy_ = c.y + sy; + return *this; +} + +template +box2d& box2d::operator/=(T t) +{ + coord c = center(); + T sx = static_cast(0.5 * width() / t); + T sy = static_cast(0.5 * height() / t); + minx_ = c.x - sx; + maxx_ = c.x + sx; + miny_ = c.y - sy; + maxy_ = c.y + sy; + return *this; +} + +template +T box2d::operator[] (int index) const +{ + switch(index) + { + case 0: + return minx_; + case 1: + return miny_; + case 2: + return maxx_; + case 3: + return maxy_; + case -4: + return minx_; + case -3: + return miny_; + case -2: + return maxx_; + case -1: + return maxy_; + default: + throw std::out_of_range("index out of range, max value is 3, min value is -4 "); + } +} + +template +box2d box2d::operator*(agg::trans_affine const& tr) const +{ + return box2d(*this, tr); +} + +template +box2d& box2d::operator*=(agg::trans_affine const& tr) +{ + double x0 = minx_, y0 = miny_; + double x1 = maxx_, y1 = miny_; + double x2 = maxx_, y2 = maxy_; + double x3 = minx_, y3 = maxy_; + tr.transform(&x0, &y0); + tr.transform(&x1, &y1); + tr.transform(&x2, &y2); + tr.transform(&x3, &y3); + init(static_cast(x0), static_cast(y0), + static_cast(x2), static_cast(y2)); + expand_to_include(static_cast(x1), static_cast(y1)); + expand_to_include(static_cast(x3), static_cast(y3)); + return *this; +} +} diff --git a/include/mapnik/cairo/cairo_context.hpp b/include/mapnik/cairo/cairo_context.hpp index 3f065db36..9733efbd6 100644 --- a/include/mapnik/cairo/cairo_context.hpp +++ b/include/mapnik/cairo/cairo_context.hpp @@ -38,18 +38,20 @@ #include #include +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + // stl #include - -// cairo -#include - -// stl #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/color.hpp b/include/mapnik/color.hpp index e80ddb23c..39bcc2eac 100644 --- a/include/mapnik/color.hpp +++ b/include/mapnik/color.hpp @@ -27,8 +27,10 @@ #include #include -//boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp index 6461a6c08..5b4c82be1 100644 --- a/include/mapnik/config.hpp +++ b/include/mapnik/config.hpp @@ -52,7 +52,10 @@ #define PROJ_ENVELOPE_POINTS 20 +#ifndef BOOST_MPL_LIMIT_VECTOR_SIZE #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 - +#else +#warning "WARNING: BOOST_MPL_LIMIT_VECTOR_SIZE is already defined. Ensure config.hpp is included before any Boost headers" +#endif #endif // MAPNIK_CONFIG_HPP diff --git a/include/mapnik/coord.hpp b/include/mapnik/coord.hpp index fcdfa9090..f8ea3f161 100644 --- a/include/mapnik/coord.hpp +++ b/include/mapnik/coord.hpp @@ -23,8 +23,10 @@ #ifndef MAPNIK_COORD_HPP #define MAPNIK_COORD_HPP -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { template diff --git a/include/mapnik/debug.hpp b/include/mapnik/debug.hpp index cf5e5b9c9..84290958b 100644 --- a/include/mapnik/debug.hpp +++ b/include/mapnik/debug.hpp @@ -69,15 +69,15 @@ public: static void set_severity(severity_type severity_level) { -//#ifdef MAPNIK_THREADSAFE -// std::lock_guard lock(severity_mutex_); -//#endif severity_level_ = severity_level; } // per object security levels static severity_type get_object_severity(std::string const& object_name) { +#ifdef MAPNIK_THREADSAFE + std::lock_guard lock(severity_mutex_); +#endif severity_map::iterator it = object_severity_level_.find(object_name); if (object_name.empty() || it == object_severity_level_.end()) { diff --git a/include/mapnik/feature_kv_iterator.hpp b/include/mapnik/feature_kv_iterator.hpp index 37093a897..77b292fd5 100644 --- a/include/mapnik/feature_kv_iterator.hpp +++ b/include/mapnik/feature_kv_iterator.hpp @@ -27,12 +27,14 @@ #include #include #include -// boost +#pragma GCC diagnostic push +#include #include #include #include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/feature_type_style.hpp b/include/mapnik/feature_type_style.hpp index 68240af3a..9f9f1aec9 100644 --- a/include/mapnik/feature_type_style.hpp +++ b/include/mapnik/feature_type_style.hpp @@ -29,8 +29,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 7063685d7..f97e9e6c6 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -24,43 +24,41 @@ #define MAPNIK_GEOMETRY_HPP #include -#include #include #include #include - - namespace mapnik { namespace geometry { template struct point { - using value_type = T; + using coord_type = T; point() {} point(T x_, T y_) : x(x_), y(y_) {} - // temp - remove when geometry is templated on value_type - point(mapnik::coord const& c) - : x(c.x), y(c.y) {} - friend inline bool operator== (point const& a, point const& b) - { - return a.x == b.x && a.y == b.y; - } - friend inline bool operator!= (point const& a, point const& b) - { - return a.x != b.x || a.y != b.y; - } - value_type x; - value_type y; + coord_type x; + coord_type y; }; +template +bool operator==(point const& lhs, point const& rhs) +{ + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +template +bool operator!=(point const& lhs, point const& rhs) +{ + return !(lhs == rhs); +} template struct line_string : std::vector > { + using coord_type = T; line_string() = default; explicit line_string(std::size_t size) : std::vector >(size) {} @@ -71,6 +69,7 @@ struct line_string : std::vector > template struct linear_ring : line_string { + using coord_type = T; linear_ring() = default; explicit linear_ring(std::size_t size) : line_string(size) {} @@ -86,8 +85,9 @@ using rings_container = std::vector>; template class InteriorRings = rings_container> struct polygon { - linear_ring exterior_ring; + using coord_type = T; using rings_container = InteriorRings; + linear_ring exterior_ring; rings_container interior_rings; inline void set_exterior_ring(linear_ring && ring) @@ -109,13 +109,22 @@ struct polygon }; template -struct multi_point : line_string {}; +struct multi_point : line_string +{ + using coord_type = T; +}; template -struct multi_line_string : std::vector> {}; +struct multi_line_string : std::vector> +{ + using coord_type = T; +}; template -struct multi_polygon : std::vector> {}; +struct multi_polygon : std::vector> +{ + using coord_type = T; +}; template struct geometry_collection; @@ -131,11 +140,11 @@ using geometry_base = mapnik::util::variant, multi_line_string, multi_polygon, - mapnik::util::recursive_wrapper > >; + geometry_collection >; template struct geometry : geometry_base { - using value_type = T; + using coord_type = T; geometry() : geometry_base() {} // empty @@ -147,7 +156,10 @@ struct geometry : geometry_base }; template -struct geometry_collection : std::vector> {}; +struct geometry_collection : std::vector> +{ + using coord_type = T; +}; }} diff --git a/include/mapnik/geometry_envelope.hpp b/include/mapnik/geometry_envelope.hpp index 17b8fcb44..981b97849 100644 --- a/include/mapnik/geometry_envelope.hpp +++ b/include/mapnik/geometry_envelope.hpp @@ -26,11 +26,11 @@ #include #include -namespace mapnik { +namespace mapnik { namespace geometry { template -MAPNIK_DECL mapnik::box2d envelope(T const& geom); +MAPNIK_DECL auto envelope(T const& geom) -> box2d; } // end ns geometry } // end ns mapnik diff --git a/include/mapnik/geometry_envelope_impl.hpp b/include/mapnik/geometry_envelope_impl.hpp index 5c39bc386..2ebddb9d9 100644 --- a/include/mapnik/geometry_envelope_impl.hpp +++ b/include/mapnik/geometry_envelope_impl.hpp @@ -28,23 +28,24 @@ namespace mapnik { namespace geometry { namespace detail { +template struct geometry_envelope { - using bbox_type = box2d; + using coord_type = T; + using bbox_type = box2d; bbox_type & bbox; geometry_envelope(bbox_type & bbox_) : bbox(bbox_) {} - template - void operator() (T const& geom) const + template + void operator() (U const& geom) const { return mapnik::util::apply_visitor(*this, geom); } void operator() (mapnik::geometry::geometry_empty const&) const {} - template void operator() (mapnik::geometry::point const& pt) const { if (!bbox.valid()) @@ -54,7 +55,6 @@ struct geometry_envelope bbox.expand_to_include(pt.x, pt.y); } - template void operator() (mapnik::geometry::line_string const& line) const { bool first = true; @@ -72,13 +72,11 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::linear_ring const& ring) const { (*this)(static_cast const&>(ring)); } - template void operator() (mapnik::geometry::polygon const& poly) const { bool first = true; @@ -96,7 +94,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_point const& multi_point) const { bool first = true; @@ -114,7 +111,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_line_string const& multi_line) const { for (auto const& line : multi_line) @@ -123,7 +119,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_polygon const& multi_poly) const { for (auto const& poly : multi_poly) @@ -132,7 +127,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::geometry_collection const& collection) const { for (auto const& geom : collection) @@ -145,10 +139,11 @@ struct geometry_envelope } // end ns detail template -mapnik::box2d envelope(T const& geom) +auto envelope(T const& geom) -> box2d { - box2d bbox; - detail::geometry_envelope op(bbox); + using coord_type = typename T::coord_type; + box2d bbox; + detail::geometry_envelope op(bbox); op(geom); return bbox; } diff --git a/include/mapnik/global.hpp b/include/mapnik/global.hpp index aa5be35f5..39a8c5ff7 100644 --- a/include/mapnik/global.hpp +++ b/include/mapnik/global.hpp @@ -99,14 +99,14 @@ inline void read_int32_xdr(const char* data, std::int32_t & val) // read double XDR (big endian) inline void read_double_xdr(const char* data, double & val) { - std::int64_t bits = ((std::int64_t)data[7] & 0xff) | - ((std::int64_t)data[6] & 0xff) << 8 | - ((std::int64_t)data[5] & 0xff) << 16 | - ((std::int64_t)data[4] & 0xff) << 24 | - ((std::int64_t)data[3] & 0xff) << 32 | - ((std::int64_t)data[2] & 0xff) << 40 | - ((std::int64_t)data[1] & 0xff) << 48 | - ((std::int64_t)data[0] & 0xff) << 56 ; + std::int64_t bits = (static_cast(data[7]) & 0xff) | + (static_cast(data[6]) & 0xff) << 8 | + (static_cast(data[5]) & 0xff) << 16 | + (static_cast(data[4]) & 0xff) << 24 | + (static_cast(data[3]) & 0xff) << 32 | + (static_cast(data[2]) & 0xff) << 40 | + (static_cast(data[1]) & 0xff) << 48 | + (static_cast(data[0]) & 0xff) << 56 ; std::memcpy(&val,&bits,8); } diff --git a/include/mapnik/gradient.hpp b/include/mapnik/gradient.hpp index f151ebe8f..ae9acb5a3 100644 --- a/include/mapnik/gradient.hpp +++ b/include/mapnik/gradient.hpp @@ -23,8 +23,10 @@ #ifndef MAPNIK_GRADIENT_HPP #define MAPNIK_GRADIENT_HPP -// agg +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // mapnik #include diff --git a/include/mapnik/grid/grid_rasterizer.hpp b/include/mapnik/grid/grid_rasterizer.hpp index 98a6dd31f..612944799 100644 --- a/include/mapnik/grid/grid_rasterizer.hpp +++ b/include/mapnik/grid/grid_rasterizer.hpp @@ -24,7 +24,11 @@ #define MAPNIK_GRID_RASTERIZER_HPP #include + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/grid/grid_render_marker.hpp b/include/mapnik/grid/grid_render_marker.hpp index 8f345e301..5ad5fea13 100644 --- a/include/mapnik/grid/grid_render_marker.hpp +++ b/include/mapnik/grid/grid_render_marker.hpp @@ -26,7 +26,8 @@ // mapnik #include -// agg +#pragma GCC diagnostic push +#include #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_image_filters.h" @@ -34,7 +35,7 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_span_image_filter_gray.h" - +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/grid/grid_renderer_base.hpp b/include/mapnik/grid/grid_renderer_base.hpp index 1000083df..bcc2e18c1 100644 --- a/include/mapnik/grid/grid_renderer_base.hpp +++ b/include/mapnik/grid/grid_renderer_base.hpp @@ -24,11 +24,11 @@ #define MAPNIK_GRID_RENDERER_BASE_HPP #pragma GCC diagnostic push -#include -#include "agg_renderer_base.h" +#include #include -#pragma GCC diagnostic pop #include +#include "agg_renderer_base.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/grid/grid_rendering_buffer.hpp b/include/mapnik/grid/grid_rendering_buffer.hpp index 4282e3bb9..8ab12cfc0 100644 --- a/include/mapnik/grid/grid_rendering_buffer.hpp +++ b/include/mapnik/grid/grid_rendering_buffer.hpp @@ -24,7 +24,11 @@ #define MAPNIK_GRID_RENDERING_BUFFER_HPP #include + +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index 466462404..5d8adc1da 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -365,20 +365,20 @@ private: if (r->count>0) { printf("%d: (+%d/%d/%.5f) (%d %d %d %d)\n", - id, (int)r->count, (int)r->pixel_count, r->reduce_cost, - (int)round(gamma(r->reds / r->count, gamma_)), - (int)round(gamma(r->greens / r->count, gamma_)), - (int)round(gamma(r->blues / r->count, gamma_)), - (int)(r->alphas / r->count)); + id, static_cast(r->count), static_cast(r->pixel_count), r->reduce_cost, + static_cast(round(gamma(r->reds / r->count, gamma_))), + static_cast(round(gamma(r->greens / r->count, gamma_))), + static_cast(round(gamma(r->blues / r->count, gamma_))), + static_cast((r->alphas / r->count))); } else { printf("%d: (%d/%d/%.5f) (%d %d %d %d)\n", id, - (int)r->count, (int)r->pixel_count, r->reduce_cost, - (int)round(gamma(r->reds / r->pixel_count, gamma_)), - (int)round(gamma(r->greens / r->pixel_count, gamma_)), - (int)round(gamma(r->blues / r->pixel_count, gamma_)), - (int)(r->alphas / r->pixel_count)); + static_cast(r->count), static_cast(r->pixel_count), r->reduce_cost, + static_cast(round(gamma(r->reds / r->pixel_count, gamma_))), + static_cast(round(gamma(r->greens / r->pixel_count, gamma_))), + static_cast(round(gamma(r->blues / r->pixel_count, gamma_))), + static_cast((r->alphas / r->pixel_count))); } for (unsigned idx=0; idx < 16; ++idx) { @@ -399,9 +399,9 @@ private: std::uint8_t a = std::uint8_t(itr->alphas/float(count)); if (a > InsertPolicy::MAX_ALPHA) a = 255; if (a < InsertPolicy::MIN_ALPHA) a = 0; - palette.push_back(rgba((std::uint8_t)round(gamma(itr->reds / count, gamma_)), - (std::uint8_t)round(gamma(itr->greens / count, gamma_)), - (std::uint8_t)round(gamma(itr->blues / count, gamma_)), a)); + palette.push_back(rgba(static_cast(round(gamma(itr->reds / count, gamma_))), + static_cast(round(gamma(itr->greens / count, gamma_))), + static_cast(round(gamma(itr->blues / count, gamma_))), a)); } for (unsigned idx=0; idx < 16; ++idx) { diff --git a/include/mapnik/image_compositing.hpp b/include/mapnik/image_compositing.hpp index 2967be780..82b89a398 100644 --- a/include/mapnik/image_compositing.hpp +++ b/include/mapnik/image_compositing.hpp @@ -26,8 +26,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 150741330..c8870d412 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -34,7 +34,8 @@ #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_color_rgba.h" @@ -42,6 +43,8 @@ #include "agg_scanline_u.h" #include "agg_blur.h" #include "agg_gradient_lut.h" +#pragma GCC diagnostic pop + // stl #include diff --git a/include/mapnik/image_options.hpp b/include/mapnik/image_options.hpp index fc8f9f1a5..d44b2bf35 100644 --- a/include/mapnik/image_options.hpp +++ b/include/mapnik/image_options.hpp @@ -25,7 +25,12 @@ #include #include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace mapnik { diff --git a/include/mapnik/image_reader.hpp b/include/mapnik/image_reader.hpp index a15d7c9dd..6c1c2329c 100644 --- a/include/mapnik/image_reader.hpp +++ b/include/mapnik/image_reader.hpp @@ -29,8 +29,12 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + // stl #include #include diff --git a/include/mapnik/image_scaling.hpp b/include/mapnik/image_scaling.hpp index ddae3689f..461e99f27 100644 --- a/include/mapnik/image_scaling.hpp +++ b/include/mapnik/image_scaling.hpp @@ -30,8 +30,11 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace mapnik { diff --git a/include/mapnik/image_scaling_traits.hpp b/include/mapnik/image_scaling_traits.hpp index 81ddf54e4..b8daff152 100644 --- a/include/mapnik/image_scaling_traits.hpp +++ b/include/mapnik/image_scaling_traits.hpp @@ -28,7 +28,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_image_accessors.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" @@ -36,6 +37,7 @@ #include "agg_span_image_filter_gray.h" #include "agg_span_image_filter_rgba.h" #include "agg_span_interpolator_linear.h" +#pragma GCC diagnostic pop namespace mapnik { namespace detail { diff --git a/include/mapnik/json/attribute_value_visitor.hpp b/include/mapnik/json/attribute_value_visitor.hpp new file mode 100644 index 000000000..206530cae --- /dev/null +++ b/include/mapnik/json/attribute_value_visitor.hpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP +#define MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP + +// mapnik +#include +#include +#include +#include + +namespace mapnik { namespace json { + +struct attribute_value_visitor +{ +public: + attribute_value_visitor(mapnik::transcoder const& tr) + : tr_(tr) {} + + mapnik::value operator()(std::string const& val) const + { + return mapnik::value(tr_.transcode(val.c_str())); + } + + mapnik::value operator()(std::vector const& array) const + { + std::string str = stringifier()(array); + return mapnik::value(tr_.transcode(str.c_str())); + } + + mapnik::value operator()(std::vector > const& object) const + { + std::string str = stringifier()(object); + return mapnik::value(tr_.transcode(str.c_str())); + } + + template + mapnik::value operator()(T const& val) const + { + return mapnik::value(val); + } + + mapnik::transcoder const& tr_; +}; + +}} + +#endif //MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP diff --git a/include/mapnik/json/extract_bounding_box_grammar.hpp b/include/mapnik/json/extract_bounding_box_grammar.hpp index bb7bdca07..906e7126d 100644 --- a/include/mapnik/json/extract_bounding_box_grammar.hpp +++ b/include/mapnik/json/extract_bounding_box_grammar.hpp @@ -32,69 +32,31 @@ #pragma GCC diagnostic push #include #include -#include #pragma GCC diagnostic pop namespace mapnik { namespace json { -using position_type = mapnik::geometry::point; -using boxes_type = std::vector, std::pair>>; - namespace qi = boost::spirit::qi; -struct calculate_bounding_box_impl -{ - using result_type = void; - template - result_type operator() (T0 & bbox, T1 const& pos) const - { - if (pos) - { - double x = pos->x; - double y = pos->y; - if (!bbox.valid()) - { - bbox.init(x, y, x, y); //TODO: add init(x,y) convinience method - } - else - { - bbox.expand_to_include(x, y); - } - } - } -}; - -struct push_box_impl -{ - using result_type = void; - template - void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const - { - if (box.valid()) boxes.emplace_back(box, std::make_pair(std::distance(begin, range.begin()), std::distance(range.begin(), range.end()))); - } -}; - -template > +template > struct extract_bounding_box_grammar : - qi::grammar + qi::grammar { + using position_type = mapnik::geometry::point; + using boxes_type = Boxes; + using box_type = typename Boxes::value_type::first_type; extract_bounding_box_grammar(); // rules qi::rule start; qi::rule, void(boxes_type&), space_type> features; - qi::rule>, void(boxes_type&, Iterator const&), space_type> feature; - qi::rule>, box2d(), space_type> coords; + qi::rule, void(boxes_type&, Iterator const&), space_type> feature; + qi::rule, box_type(), space_type> coords; qi::rule(), space_type> pos; - qi::rule&), space_type> ring; - qi::rule&), space_type> rings; - qi::rule&), space_type> rings_array; + qi::rule ring; + qi::rule rings; + qi::rule rings_array; // generic JSON support json::generic_json json; - // phoenix functions - boost::phoenix::function push_box; - boost::phoenix::function calculate_bounding_box; - // error handler - boost::phoenix::function const error_handler; }; }} diff --git a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp index 45787d2dd..9e21baa08 100644 --- a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp +++ b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp @@ -29,17 +29,53 @@ #include #include #include +#include // stl #include #include namespace mapnik { namespace json { +struct calculate_bounding_box_impl +{ + using result_type = void; + template + result_type operator() (T0 & bbox, T1 const& pos) const + { + if (pos) + { + typename T0::value_type x = pos->x; + typename T0::value_type y = pos->y; + if (!bbox.valid()) + { + bbox.init(x, y); + } + else + { + bbox.expand_to_include(x, y); + } + } + } +}; + +struct push_box_impl +{ + using result_type = void; + template + void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const + { + if (box.valid()) boxes.emplace_back(box, + std::make_pair(std::distance(begin, + range.begin()), + std::distance(range.begin(), range.end()))); + } +}; + namespace repo = boost::spirit::repository; -template -extract_bounding_box_grammar::extract_bounding_box_grammar() - : extract_bounding_box_grammar::base_type(start,"bounding boxes") +template +extract_bounding_box_grammar::extract_bounding_box_grammar() + : extract_bounding_box_grammar::base_type(start, "GeoJSON bounding boxes") { qi::lit_type lit; qi::double_type double_; @@ -61,6 +97,12 @@ extract_bounding_box_grammar::extract_bounding_box_gramm using qi::fail; using qi::on_error; + // phoenix functions + boost::phoenix::function push_box; + boost::phoenix::function calculate_bounding_box; + // error handler + boost::phoenix::function const error_handler; + start = features(_r1) ; @@ -106,13 +148,10 @@ extract_bounding_box_grammar::extract_bounding_box_gramm json.value = json.object | json.array | json.string_ | json.number ; - json.pairs = json.key_value % lit(',') + json.key_value = json.string_ >> lit(':') >> json.value ; - json.key_value = (json.string_ >> lit(':') >> json.value) - ; - - json.object = lit('{') >> *json.pairs >> lit('}') + json.object = lit('{') >> json.key_value % lit(',') >> lit('}') ; json.array = lit('[') diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index ae59e3bf0..c329eb7f5 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -24,14 +24,10 @@ #define MAPNIK_FEATURE_GRAMMAR_HPP // mapnik -#include #include #include -#include -#include -#include -#include - +#include +#include #pragma GCC diagnostic push #include #include @@ -45,27 +41,6 @@ namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; namespace fusion = boost::fusion; -class attribute_value_visitor - -{ -public: - attribute_value_visitor(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value operator()(std::string const& val) const - { - return mapnik::value(tr_.transcode(val.c_str())); - } - - template - mapnik::value operator()(T const& val) const - { - return mapnik::value(val); - } - - mapnik::transcoder const& tr_; -}; - struct put_property { using result_type = void; @@ -101,9 +76,6 @@ struct feature_grammar : qi::grammar qi::rule feature_type; qi::rule properties; qi::rule, void(FeatureType &),space_type> attributes; - qi::rule attribute_value; - qi::rule, std::string(), space_type> stringify_object; - qi::rule, std::string(), space_type> stringify_array; // functions phoenix::function put_property_; phoenix::function set_geometry; diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index 61a23f985..0fc4205ad 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -50,23 +50,22 @@ feature_grammar::feature_grammar(mapnik::tran using phoenix::construct; // generic json types - json_.value = json_.object | json_.array | json_.string_ | json_.number + json_.value = json_.object | json_.array | json_.string_ | json_.number ; - json_.pairs = json_.key_value % lit(',') - ; - - json_.key_value = (json_.string_ > lit(':') > json_.value) + json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > *json_.pairs + > -(json_.key_value % lit(',')) > lit('}') ; + json_.array = lit('[') - > json_.value > *(lit(',') > json_.value) + > -(json_.value % lit(',')) > lit(']') ; + json_.number = json_.strict_double[_val = json_.double_converter(_1)] | json_.int__[_val = json_.integer_converter(_1)] | lit("true") [_val = true] @@ -95,24 +94,13 @@ feature_grammar::feature_grammar(mapnik::tran > lit(':') > ((lit('{') > -attributes(_r1) > lit('}')) | lit("null")) ; - attributes = (json_.string_ [_a = _1] > lit(':') > attribute_value [put_property_(_r1,_a,_1)]) % lit(',') - ; - - attribute_value %= json_.number | json_.string_ | stringify_object | stringify_array - ; - - stringify_object %= char_('{')[_a = 1 ] > *(eps(_a > 0) > (char_('{')[_a +=1] | char_('}')[_a -=1] | char_)) - ; - - stringify_array %= char_('[')[_a = 1 ] > *(eps(_a > 0) > (char_('[')[_a +=1] | char_(']')[_a -=1] | char_)) + attributes = (json_.string_ [_a = _1] > lit(':') > json_.value [put_property_(_r1,_a,_1)]) % lit(',') ; feature.name("Feature"); feature_type.name("type"); properties.name("properties"); attributes.name("Attributes"); - attribute_value.name("Attribute Value"); - on_error(feature, error_handler(_1, _2, _3, _4)); } diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 331341066..bc71eb67c 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -31,15 +31,44 @@ #include #include #include +#include #pragma GCC diagnostic pop +#include + namespace mapnik { namespace json { namespace qi = boost::spirit::qi; namespace standard = boost::spirit::standard; namespace phoenix = boost::phoenix; using space_type = standard::space_type; -using json_value = mapnik::util::variant; + +struct json_value; + +using json_array = std::vector; +using json_object_element = std::pair; +using json_object = std::vector; +using json_value_base = mapnik::util::variant, + mapnik::util::recursive_wrapper >; +struct json_value : json_value_base +{ + +#ifdef _WINDOWS + json_value() = default; + template + json_value(T && val) + : json_value_base(std::forward(val)) {} +#else + // MSVC 2015 inheriting constructors is not working in this context (support is apparently planned) + using json_value_base::json_value_base; +#endif +}; + using uchar = std::uint32_t; // a unicode code point // unicode string grammar via boost/libs/spirit/example/qi/json/json/parser/grammar.hpp @@ -121,10 +150,14 @@ unicode_string::unicode_string() escape = ('x' > hex) [push_utf8(_r1, _1)] - | ('u' > hex4) [push_utf8(_r1, _1)] - | ('U' > hex8) [push_utf8(_r1, _1)] - | char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)] - | eol // continue to next line + | + ('u' > hex4) [push_utf8(_r1, _1)] + | + ('U' > hex8) [push_utf8(_r1, _1)] + | + char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)] + | + eol // continue to next line ; char_esc = @@ -132,7 +165,7 @@ unicode_string::unicode_string() ; double_quoted = - '"' + '"' > *(char_esc(_val) | (~char_('"')) [_val += _1]) > '"' ; @@ -141,18 +174,17 @@ unicode_string::unicode_string() template struct generic_json { - qi::rule value; - qi::int_parser int__; + qi::rule value; + qi::int_parser int__; unicode_string string_; - qi::rule key_value; - qi::rule number; - qi::rule object; - qi::rule array; - qi::rule pairs; - qi::real_parser > strict_double; + qi::rule key_value; + qi::rule number; + qi::rule object; + qi::rule array; + qi::real_parser> strict_double; // conversions - boost::phoenix::function > integer_converter; - boost::phoenix::function > double_converter; + boost::phoenix::function> integer_converter; + boost::phoenix::function> double_converter; }; }} diff --git a/include/mapnik/json/geometry_generator_grammar.hpp b/include/mapnik/json/geometry_generator_grammar.hpp index 5b2c59da9..0e314650b 100644 --- a/include/mapnik/json/geometry_generator_grammar.hpp +++ b/include/mapnik/json/geometry_generator_grammar.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #include // for vc++ and android whose c++11 libs lack std::trunc #include #pragma GCC diagnostic pop diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index 3c5693f91..285be2744 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -47,7 +47,6 @@ geometry_grammar::geometry_grammar() qi::_a_type _a; qi::_b_type _b; qi::eps_type eps; - qi::omit_type omit; using qi::fail; using qi::on_error; using phoenix::push_back; @@ -58,26 +57,26 @@ geometry_grammar::geometry_grammar() json_.value = json_.object | json_.array | json_.string_ | json_.number ; - json_.pairs = json_.key_value % lit(',') - ; - - json_.key_value = (json_.string_ > lit(':') > json_.value) + json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > *json_.pairs + > -(json_.key_value % lit(',')) > lit('}') ; + json_.array = lit('[') - > json_.value > *(lit(',') > json_.value) + > -(json_.value % lit(',')) > lit(']') ; + json_.number = json_.strict_double | json_.int__ | lit("true") | lit ("false") | lit("null") ; + geometry = lit('{')[_a = 0] > (((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) | @@ -85,7 +84,7 @@ geometry_grammar::geometry_grammar() | (lit("\"geometries\"") > lit(':') > lit('[') > geometry_collection[_val = _1] > lit(']')) | - omit[json_.key_value]) % lit(',')) [create_geometry(_val,_a,_b)] + json_.key_value) % lit(',')) [create_geometry(_val,_a,_b)] > lit('}') ; diff --git a/include/mapnik/json/positions_grammar.hpp b/include/mapnik/json/positions_grammar.hpp index bc8104611..75a6b21b6 100644 --- a/include/mapnik/json/positions_grammar.hpp +++ b/include/mapnik/json/positions_grammar.hpp @@ -32,7 +32,6 @@ #pragma GCC diagnostic push #include #include -#include #pragma GCC diagnostic pop @@ -40,26 +39,6 @@ namespace mapnik { namespace json { namespace qi = boost::spirit::qi; -struct set_position_impl -{ - using result_type = void; - template - result_type operator() (T0 & coords, T1 const& pos) const - { - if (pos) coords = *pos; - } -}; - -struct push_position_impl -{ - using result_type = void; - template - result_type operator() (T0 & coords, T1 const& pos) const - { - if (pos) coords.emplace_back(*pos); - } -}; - template > struct positions_grammar : qi::grammar @@ -70,8 +49,6 @@ struct positions_grammar : qi::rule ring; qi::rule(), space_type> rings; qi::rule >(), space_type> rings_array; - boost::phoenix::function set_position; - boost::phoenix::function push_position; }; }} diff --git a/include/mapnik/json/positions_grammar_impl.hpp b/include/mapnik/json/positions_grammar_impl.hpp index 90df172c5..65f2a93c0 100644 --- a/include/mapnik/json/positions_grammar_impl.hpp +++ b/include/mapnik/json/positions_grammar_impl.hpp @@ -28,12 +28,33 @@ #include #include #include +#include // stl #include #include namespace mapnik { namespace json { +struct set_position_impl +{ + using result_type = void; + template + result_type operator() (T0 & coords, T1 const& pos) const + { + if (pos) coords = *pos; + } +}; + +struct push_position_impl +{ + using result_type = void; + template + result_type operator() (T0 & coords, T1 const& pos) const + { + if (pos) coords.emplace_back(*pos); + } +}; + template positions_grammar::positions_grammar(ErrorHandler & error_handler) : positions_grammar::base_type(coords,"coordinates") @@ -49,6 +70,9 @@ positions_grammar::positions_grammar(ErrorHandler & erro using qi::fail; using qi::on_error; + boost::phoenix::function set_position; + boost::phoenix::function push_position; + coords = rings_array[_val = _1] | rings [_val = _1] | ring[_val = _1] | pos[set_position(_val,_1)] ; pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']') diff --git a/include/mapnik/json/properties_generator_grammar.hpp b/include/mapnik/json/properties_generator_grammar.hpp index e0f7be632..69145b8ab 100644 --- a/include/mapnik/json/properties_generator_grammar.hpp +++ b/include/mapnik/json/properties_generator_grammar.hpp @@ -25,23 +25,20 @@ #include #include -#include #pragma GCC diagnostic push #include #include -#include #include -#include -#include -#include -#include -#include -#include #pragma GCC diagnostic pop +#include +#include + namespace mapnik { namespace json { +namespace karma = boost::spirit::karma; + template struct escaped_string : karma::grammar diff --git a/include/mapnik/json/stringifier.hpp b/include/mapnik/json/stringifier.hpp new file mode 100644 index 000000000..93906f6ec --- /dev/null +++ b/include/mapnik/json/stringifier.hpp @@ -0,0 +1,101 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_JSON_STRINGIFIER_HPP +#define MAPNIK_JSON_STRINGIFIER_HPP + +// mapnik +#include +#include +#include +// stl +#include + + +namespace mapnik { namespace json { + +struct stringifier +{ + std::string operator()(std::string const& val) const + { + return "\"" + val + "\""; + } + + std::string operator()(value_null) const + { + return "null"; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_integer val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(std::vector const& array) const + { + std::string str = "["; + bool first = true; + for (auto const& val : array) + { + if (first) first = false; + else str += ","; + str += mapnik::util::apply_visitor(*this, val); + } + str += "]"; + return str; + } + + std::string operator()(std::vector> const& object) const + { + std::string str = "{"; + bool first = true; + for (auto const& kv : object) + { + if (first) first = false; + else str += ","; + str += kv.first; + str += ":"; + str += mapnik::util::apply_visitor(*this, kv.second); + } + str += "}"; + return str; + } +}; + +}} + + +#endif // MAPNIK_JSON_STRINGIFIER_HPP diff --git a/include/mapnik/json/symbolizer_grammar.hpp b/include/mapnik/json/symbolizer_grammar.hpp deleted file mode 100644 index 494b81f96..000000000 --- a/include/mapnik/json/symbolizer_grammar.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_SYMBOLIZER_GRAMMAR_HPP -#define MAPNIK_SYMBOLIZER_GRAMMAR_HPP - -#include - -// boost -#include -#include - -// mapnik -#include -#include -#include -#include -#include - -namespace mapnik { namespace json { - -namespace qi = boost::spirit::qi; -namespace phoenix = boost::phoenix; -namespace fusion = boost::fusion; -namespace standard_wide = boost::spirit::standard_wide; -using standard_wide::space_type; - -template -struct json_value_visitor -{ - json_value_visitor(Symbolizer & sym, mapnik::keys key) - : sym_(sym), key_(key) {} - - void operator() (value_bool val) const - { - put(sym_, key_, val); - } - - void operator() (value_integer val) const - { - put(sym_, key_, val); - } - - void operator() (value_double val) const - { - put(sym_, key_, val); - } - - void operator() (std::string const& val) const - { - set_property(sym_, key_, val); - } - - template - void operator() (T const& val) const - { - std::cerr << std::get<0>(get_meta(key_)) << ":" << val << std::endl; - //put(sym_, key_, val); - } - - Symbolizer & sym_; - keys key_; -}; - -template -struct put_property_visitor -{ - using value_type = T; - - put_property_visitor(mapnik::keys key, value_type const& val) - : key_(key), val_(val) {} - - template - void operator() (Symbolizer & sym) const - { - mapnik::util::apply_visitor(json_value_visitor(sym, key_), val_); - } - - keys key_; - value_type const& val_; -}; - -struct put_property -{ - using result_type = void; - template - result_type operator() (T0 & sym, T1 const& name, T2 const& val) const - { - try - { - mapnik::util::apply_visitor(put_property_visitor(get_key(name),val), sym); - } - catch (std::runtime_error const& err) - { - std::cerr << err.what() << std::endl; - } - } -}; - -template > -struct symbolizer_grammar : qi::grammar -{ - using json_value_type = util::variant; - symbolizer_grammar() - : symbolizer_grammar::base_type(sym, "symbolizer"), - json_() - { - qi::lit_type lit; - qi::double_type double_; - qi::int_type int_; - qi::no_skip_type no_skip; - qi::_val_type _val; - qi::_a_type _a; - qi::_r1_type _r1; - qi::_1_type _1; - standard_wide::char_type char_; - using phoenix::construct; - - // generic json types - json_.value = json_.object | json_.array | json_.string_ - | json_.number - ; - - json_.pairs = json_.key_value % lit(',') - ; - - json_.key_value = (json_.string_ >> lit(':') >> json_.value) - ; - - json_.object = lit('{') - >> *json_.pairs - >> lit('}') - ; - - json_.array = lit('[') - >> json_.value >> *(lit(',') >> json_.value) - >> lit(']') - ; - - json_.number %= json_.strict_double - | json_.int__ - | lit("true") [_val = true] - | lit ("false") [_val = false] - | lit("null")[_val = construct()] - ; - json_.unesc_char.add - ("\\\"", '\"') // quotation mark - ("\\\\", '\\') // reverse solidus - ("\\/", '/') // solidus - ("\\b", '\b') // backspace - ("\\f", '\f') // formfeed - ("\\n", '\n') // newline - ("\\r", '\r') // carrige return - ("\\t", '\t') // tab - ; - - json_.string_ %= lit('"') >> no_skip[*(json_.unesc_char | "\\u" >> json_.hex4 | (char_ - lit('"')))] >> lit('"') - ; - - sym = lit('{') - >> lit("\"type\"") >> lit(':') - >> (lit("\"PointSymbolizer\"")[_val = construct()] - | - lit("\"LineSymbolizer\"")[_val = construct()] - | - lit("\"PolygonSymbolizer\"")[_val = construct()] - ) - >> lit(',') - >> lit("\"properties\"") >> lit(':') - >> ((lit('{') >> *property(_val) >> lit('}')) | lit("null")) - >> lit('}') - ; - - property = (json_.string_ [_a = _1] >> lit(':') >> property_value [put_property_(_r1,_a,_1)]) % lit(',') - ; - - property_value %= json_.number | json_.string_ ; - - - } - - // generic JSON - generic_json json_; - // symbolizer - qi::rule sym; - qi::rule, void(mapnik::symbolizer&),space_type> property; - qi::rule property_value; - - phoenix::function put_property_; - // error - //qi::on_error(sym, error_handler(_1, _2, _3, _4)); -}; - - -}} - -#endif // MAPNIK_SYMBOLIZER_GRAMMAR_HPP diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index c1ad44ab4..c21be95fe 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -42,35 +42,163 @@ namespace qi = boost::spirit::qi; namespace fusion = boost::fusion; using space_type = mapnik::json::space_type; +struct create_point +{ + using result_type = mapnik::topojson::point; + template + result_type operator()(T0 & coord, T1 & props) const + { + mapnik::topojson::point pt; + if (coord.template is()) + { + auto const& coord_ = coord.template get(); + pt.coord = coord_; + pt.props = props; + } + return pt; + } +}; + +struct create_multi_point +{ + using result_type = mapnik::topojson::multi_point; + template + result_type operator()(T0 & coords, T1 & props) const + { + mapnik::topojson::multi_point mpt; + if (coords.template is>()) + { + auto const& points = coords.template get>(); + mpt. points = points; + mpt.props = props; + } + return mpt; + } +}; + +struct create_line_string +{ + using result_type = mapnik::topojson::linestring; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::linestring line; + if (arcs.template is>()) + { + auto const& arcs_ = arcs.template get>(); + line.rings = arcs_; + line.props = props; + } + return line; + } +}; + +struct create_multi_line_string +{ + using result_type = mapnik::topojson::multi_linestring; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::multi_linestring mline; + if (arcs.template is>>()) + { + auto const& arcs_ = arcs.template get>>(); + mline.lines = arcs_; + mline.props = props; + } + return mline; + } +}; + +struct create_polygon +{ + using result_type = mapnik::topojson::polygon; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::polygon poly; + if (arcs.template is>>()) + { + auto const& arcs_ = arcs.template get>>(); + poly.rings = arcs_; + poly.props = props; + } + return poly; + } +}; + +struct create_multi_polygon +{ + using result_type = mapnik::topojson::multi_polygon; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::multi_polygon mpoly; + if (arcs.template is>>>()) + { + auto const& arcs_ = arcs.template get>>>(); + mpoly.polygons = arcs_; + mpoly.props = props; + } + return mpoly; + } +}; + + +struct create_geometry_impl +{ + using result_type = mapnik::topojson::geometry; + template + result_type operator()(T0 geom_type, T1 & coord, T2 & arcs, T3 & props) const + { + switch (geom_type) + { + case 1: //Point + return create_point()(coord, props); + case 2: //LineString + return create_line_string()(arcs, props); + case 3: //Polygon + return create_polygon()(arcs, props); + case 4: //MultiPoint + return create_multi_point()(coord, props); + case 5: //MultiLineString + return create_multi_line_string()(arcs, props); + case 6: //MultiPolygon + return create_multi_polygon()(arcs, props); + default: + break; + } + return mapnik::topojson::geometry(); //empty + } +}; + +using coordinates_type = util::variant>; +using arcs_type = util::variant, std::vector>, std::vector>>>; template > struct topojson_grammar : qi::grammar { topojson_grammar(); private: + // generic JSON support + json::generic_json json; // topoJSON qi::rule topology; qi::rule()> objects; qi::rule()> arcs; qi::rule arc; - qi::rule coordinate; + qi::rule coordinate_; + qi::rule coordinates; qi::rule transform; qi::rule bbox; - qi::rule geometry; - qi::rule point; - qi::rule multi_point; - qi::rule linestring; - qi::rule multi_linestring; - qi::rule polygon; - qi::rule multi_polygon; + qi::rule, mapnik::topojson::geometry(), space_type> geometry; qi::rule&)> geometry_collection; qi::rule()> ring; + qi::rule>()> rings; + qi::rule rings_array; // properties - qi::rule properties; - qi::rule attributes; - qi::rule attribute_value; - // id - qi::rule id; + qi::rule properties_; + qi::symbols geometry_type_dispatch; }; }} diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index d1dfc5474..f868cefc4 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -57,42 +57,6 @@ BOOST_FUSION_ADAPT_STRUCT( (double, maxy) ) -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::point, - (mapnik::topojson::coordinate, coord) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_point, - (std::vector, points) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::linestring, - (mapnik::topojson::index_type, ring) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_linestring, - (std::vector, rings) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::polygon, - (std::vector >, rings) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_polygon, - (std::vector > >, polygons) - (boost::optional, props) - ) - BOOST_FUSION_ADAPT_STRUCT( mapnik::topojson::topology, (std::vector, geometries) @@ -101,6 +65,8 @@ BOOST_FUSION_ADAPT_STRUCT( (boost::optional, bbox) ) + + namespace mapnik { namespace topojson { namespace qi = boost::spirit::qi; @@ -121,32 +87,43 @@ topojson_grammar::topojson_grammar() qi::_3_type _3; qi::_4_type _4; qi::_r1_type _r1; + qi::_a_type _a; + qi::_b_type _b; + qi::_c_type _c; + qi::_d_type _d; using qi::fail; using qi::on_error; using phoenix::push_back; using phoenix::construct; + geometry_type_dispatch.add + ("\"Point\"",1) + ("\"LineString\"",2) + ("\"Polygon\"",3) + ("\"MultiPoint\"",4) + ("\"MultiLineString\"",5) + ("\"MultiPolygon\"",6) + ("\"GeometryCollection\"",7) + ; + // error handler boost::phoenix::function const error_handler; - - // generic JSON support - json::generic_json json; + boost::phoenix::function const create_geometry; // generic JSON types json.value = json.object | json.array | json.string_ | json.number ; - json.pairs = json.key_value % lit(',') + json.key_value = json.string_ > lit(':') > json.value ; - json.key_value = (json.string_ >> lit(':') >> json.value) - ; - - json.object = lit('{') >> *json.pairs >> lit('}') + json.object = lit('{') + > -(json.key_value % lit(',')) + > lit('}') ; json.array = lit('[') - >> json.value >> *(lit(',') >> json.value) - >> lit(']') + > -(json.value % lit(',')) + > lit(']') ; json.number = json.strict_double[_val = json.double_converter(_1)] @@ -183,101 +160,58 @@ topojson_grammar::topojson_grammar() >> lit('{') >> -((omit[json.string_] >> lit(':') - >> (geometry_collection(_val) | geometry)) % lit(',')) + >> (geometry_collection(_val) | geometry[push_back(_val, _1)]) % lit(','))) >> lit('}') ; - geometry = - point | - linestring | - polygon | - multi_point | - multi_linestring | - multi_polygon | - omit[json.object] + geometry = lit('{')[_a = 0] + > ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) + | + (lit("\"coordinates\"") > lit(':') > coordinates[_b = _1]) + | + (lit("\"arcs\"") > lit(':') > rings_array[_c = _1]) + | + properties_[_d = _1] + | + json.key_value) % lit(',') + > lit('}')[_val = create_geometry(_a, _b, _c, _d)] ; + geometry_collection = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") - >> -(lit(',') >> omit[bbox]) - >> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(',')) - >> lit(']') - >> lit('}') - ; - point = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"Point\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') >> coordinate) - ^ (lit(',') >> properties) /*^ (lit(',') >> omit[id])*/) + >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") + >> lit(',') >> lit("\"geometries\"") >> lit(':') + >> lit('[') + >> -(geometry[push_back(_r1, _1)] % lit(',')) + >> lit(']') >> lit('}') ; - multi_point = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiPoint\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') - >> lit('[') >> -(coordinate % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - linestring = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"LineString\"") - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') >> int_ >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - multi_linestring = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiLineString\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') - >> -((lit('[') >> int_ >> lit(']')) % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - polygon = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"Polygon\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') >> -(ring % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - multi_polygon = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiPolygon\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') - >> -((lit('[') >> -(ring % lit(',')) >> lit(']')) % lit(',')) - >> lit(']')) ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - id = lit("\"id\"") >> lit(':') >> omit[json.value] - ; - ring = lit('[') >> -(int_ % lit(',')) >> lit(']') ; + rings = lit('[') >> -(ring % lit(',')) >> lit(']') + ; + rings_array = lit('[') >> -(rings % lit(',')) >> lit(']') + | + rings + | + ring + ; - properties = lit("\"properties\"") + properties_ = lit("\"properties\"") >> lit(':') - >> (( lit('{') >> attributes >> lit('}')) | json.object) + >> lit('{') >> (json.string_ >> lit(':') >> json.value) % lit(',') >> lit('}') ; - attributes = (json.string_ >> lit(':') >> attribute_value) % lit(',') - ; - - attribute_value %= json.number | json.string_ ; - arcs = lit("\"arcs\"") >> lit(':') >> lit('[') >> -( arc % lit(',')) >> lit(']') ; - arc = lit('[') >> -(coordinate % lit(',')) >> lit(']') ; + arc = lit('[') >> -(coordinate_ % lit(',')) >> lit(']') ; - coordinate = lit('[') >> double_ >> lit(',') >> double_ >> lit(']'); + coordinate_ = lit('[') > double_ > lit(',') > double_ > lit(']'); + + coordinates = (lit('[') >> coordinate_ % lit(',') > lit(']')) + | coordinate_; topology.name("topology"); transform.name("transform"); @@ -285,13 +219,9 @@ topojson_grammar::topojson_grammar() arc.name("arc"); arcs.name("arcs"); json.value.name("value"); - coordinate.name("coordinate"); - - point.name("point"); - multi_point.name("multi_point"); - linestring.name("linestring"); - polygon.name("polygon"); - multi_polygon.name("multi_polygon"); + coordinate_.name("coordinate"); + geometry.name("geometry"); + properties_.name("properties"); geometry_collection.name("geometry_collection"); // error handler on_error(topology, error_handler(_1, _2, _3, _4)); diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index be6a83a2c..40a2c91ff 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * Copyright (C) 2016 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,12 @@ // mapnik #include +#include #include +#include +#include +#include +#include namespace mapnik { namespace topojson { @@ -35,6 +40,11 @@ struct bounding_box_visitor : topo_(topo), num_arcs_(topo_.arcs.size()) {} + box2d operator() (mapnik::topojson::empty const&) const + { + return box2d(); + } + box2d operator() (mapnik::topojson::point const& pt) const { double x = pt.coord.x; @@ -50,27 +60,25 @@ struct bounding_box_visitor box2d operator() (mapnik::topojson::multi_point const& multi_pt) const { box2d bbox; - if (num_arcs_ > 0) + bool first = true; + double px = 0, py = 0; + for (auto const& pt : multi_pt.points) { - bool first = true; - for (auto const& pt : multi_pt.points) + double x = pt.x; + double y = pt.y; + if (topo_.tr) { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; // TODO : delta encoded ? - } - if (first) - { - first = false; - bbox.init(x,y,x,y); - } - else - { - bbox.expand_to_include(x,y); - } + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + if (first) + { + first = false; + bbox.init(x,y,x,y); + } + else + { + bbox.expand_to_include(x,y); } } return bbox; @@ -79,50 +87,15 @@ struct bounding_box_visitor box2d operator() (mapnik::topojson::linestring const& line) const { box2d bbox; + bool first = true; if (num_arcs_ > 0) { - index_type index = line.ring; - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - bool first = true; - double px = 0, py = 0; - auto const& arcs = topo_.arcs[arc_index]; - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - if (first) - { - first = false; - bbox.init(x, y, x, y); - } - else - { - bbox.expand_to_include(x, y); - } - } - } - } - return bbox; - } - - box2d operator() (mapnik::topojson::multi_linestring const& multi_line) const - { - box2d bbox; - if (num_arcs_ > 0) - { - bool first = true; - for (auto index : multi_line.rings) + for (auto index : line.rings) { index_type arc_index = index < 0 ? std::abs(index) - 1 : index; if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) { + double px = 0, py = 0; auto const& arcs = topo_.arcs[arc_index]; for (auto pt : arcs.coordinates) @@ -150,6 +123,47 @@ struct bounding_box_visitor return bbox; } + box2d operator() (mapnik::topojson::multi_linestring const& multi_line) const + { + box2d bbox; + if (num_arcs_ > 0) + { + bool first = true; + for (auto const& line : multi_line.lines) + { + for (auto index : line) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + double px = 0, py = 0; + auto const& arcs = topo_.arcs[arc_index]; + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + if (first) + { + first = false; + bbox.init(x, y, x, y); + } + else + { + bbox.expand_to_include(x, y); + } + } + } + } + } + } + return bbox; + } + box2d operator() (mapnik::topojson::polygon const& poly) const { box2d bbox; @@ -243,6 +257,321 @@ private: std::size_t num_arcs_; }; +namespace { + +template +void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::transcoder const& tr) +{ + if ( geom.props) + { + for (auto const& p : *geom.props) + { + feature.put_new(std::get<0>(p), mapnik::util::apply_visitor(mapnik::json::attribute_value_visitor(tr),std::get<1>(p))); + } + } +} + +} + +template +struct feature_generator +{ + feature_generator(Context & ctx, mapnik::transcoder const& tr, topology const& topo, std::size_t feature_id) + : ctx_(ctx), + tr_(tr), + topo_(topo), + num_arcs_(topo.arcs.size()), + feature_id_(feature_id) {} + + feature_ptr operator() (point const& pt) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + double x = pt.coord.x; + double y = pt.coord.y; + if (topo_.tr) + { + x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + mapnik::geometry::point point(x, y); + feature->set_geometry(std::move(point)); + assign_properties(*feature, pt, tr_); + return feature; + } + + feature_ptr operator() (multi_point const& multi_pt) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + mapnik::geometry::multi_point multi_point; + multi_point.reserve(multi_pt.points.size()); + for (auto const& pt : multi_pt.points) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + multi_point.add_coord(x, y); + } + feature->set_geometry(std::move(multi_point)); + assign_properties(*feature, multi_pt, tr_); + return feature; + } + + feature_ptr operator() (linestring const& line) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + mapnik::geometry::line_string line_string; + + for (auto index : line.rings) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + auto const& arcs = topo_.arcs[arc_index]; + double px = 0, py = 0; + line_string.reserve(line_string.size() + arcs.coordinates.size()); + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + line_string.add_coord(x,y); + } + } + } + feature->set_geometry(std::move(line_string)); + assign_properties(*feature, line, tr_); + } + return feature; + } + + feature_ptr operator() (multi_linestring const& multi_line) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + mapnik::geometry::multi_line_string multi_line_string; + bool hit = false; + for (auto const& line : multi_line.lines) + { + multi_line_string.reserve(multi_line_string.size() + line.size()); + mapnik::geometry::line_string line_string; + for (auto index : line) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + hit = true; + double px = 0, py = 0; + auto const& arcs = topo_.arcs[arc_index]; + line_string.reserve(line_string.size() + arcs.coordinates.size()); + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + line_string.add_coord(x, y); + } + + } + } + multi_line_string.push_back(std::move(line_string)); + } + if (hit) + { + feature->set_geometry(std::move(multi_line_string)); + assign_properties(*feature, multi_line, tr_); + } + } + return feature; + } + + feature_ptr operator() (polygon const& poly) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + std::vector processed_coords; + mapnik::geometry::polygon polygon; + if (poly.rings.size() > 1) polygon.interior_rings.reserve(poly.rings.size() - 1); + bool first = true; + bool hit = false; + for (auto const& ring : poly.rings) + { + mapnik::geometry::linear_ring linear_ring; + for (auto const& index : ring) + { + double px = 0, py = 0; + bool reverse = index < 0; + index_type arc_index = reverse ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + hit = true; + auto const& arcs = topo_.arcs[arc_index]; + auto const& coords = arcs.coordinates; + processed_coords.clear(); + processed_coords.reserve(coords.size()); + for (auto const& pt : coords ) + { + double x = pt.x; + double y = pt.y; + + if (topo_.tr) + { + transform const& tr = *topo_.tr; + x = (px += x) * tr.scale_x + tr.translate_x; + y = (py += y) * tr.scale_y + tr.translate_y; + } + processed_coords.emplace_back(coordinate{x,y}); + } + linear_ring.reserve(linear_ring.size() + processed_coords.size()); + if (reverse) + { + for (auto const& c : processed_coords | boost::adaptors::reversed) + { + linear_ring.emplace_back(c.x, c.y); + } + } + else + { + for (auto const& c : processed_coords) + { + linear_ring.emplace_back(c.x, c.y); + } + } + } + } + if (first) + { + first = false; + polygon.set_exterior_ring(std::move(linear_ring)); + } + else + { + polygon.add_hole(std::move(linear_ring)); + } + } + if (hit) + { + mapnik::geometry::correct(polygon); + feature->set_geometry(std::move(polygon)); + assign_properties(*feature, poly, tr_); + } + } + return feature; + } + + feature_ptr operator() (multi_polygon const& multi_poly) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + std::vector processed_coords; + mapnik::geometry::multi_polygon multi_polygon; + multi_polygon.reserve(multi_poly.polygons.size()); + bool hit = false; + for (auto const& poly : multi_poly.polygons) + { + bool first = true; + mapnik::geometry::polygon polygon; + if (poly.size() > 1) polygon.interior_rings.reserve(poly.size() - 1); + + for (auto const& ring : poly) + { + mapnik::geometry::linear_ring linear_ring; + for (auto const& index : ring) + { + double px = 0, py = 0; + bool reverse = index < 0; + index_type arc_index = reverse ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + hit = true; + auto const& arcs = topo_.arcs[arc_index]; + auto const& coords = arcs.coordinates; + processed_coords.clear(); + processed_coords.reserve(coords.size()); + for (auto const& pt : coords ) + { + double x = pt.x; + double y = pt.y; + + if (topo_.tr) + { + transform const& tr = *topo_.tr; + x = (px += x) * tr.scale_x + tr.translate_x; + y = (py += y) * tr.scale_y + tr.translate_y; + } + processed_coords.emplace_back(coordinate{x,y}); + } + + using namespace boost::adaptors; + linear_ring.reserve(linear_ring.size() + processed_coords.size()); + if (reverse) + { + for (auto const& c : (processed_coords | reversed)) + { + linear_ring.add_coord(c.x, c.y); + } + } + else + { + for (auto const& c : processed_coords) + { + linear_ring.add_coord(c.x, c.y); + } + } + } + } + if (first) + { + first = false; + polygon.set_exterior_ring(std::move(linear_ring)); + } + else + { + polygon.add_hole(std::move(linear_ring)); + } + } + multi_polygon.push_back(std::move(polygon)); + } + if (hit) + { + mapnik::geometry::correct(multi_polygon); + feature->set_geometry(std::move(multi_polygon)); + assign_properties(*feature, multi_poly, tr_); + } + } + return feature; + } + + template + feature_ptr operator() (T const& ) const + { + return feature_ptr(); + } + + Context & ctx_; + mapnik::transcoder const& tr_; + topology const& topo_; + std::size_t num_arcs_; + std::size_t feature_id_; +}; + + }} #endif //MAPNIK_TOPOJSON_UTILS_HPP diff --git a/include/mapnik/json/topology.hpp b/include/mapnik/json/topology.hpp index 05f35b4ad..048c85528 100644 --- a/include/mapnik/json/topology.hpp +++ b/include/mapnik/json/topology.hpp @@ -62,13 +62,13 @@ struct multi_point struct linestring { - index_type ring ; + std::vector rings ; boost::optional props; }; struct multi_linestring { - std::vector rings; + std::vector > lines; boost::optional props; }; @@ -84,7 +84,10 @@ struct multi_polygon boost::optional props; }; -using geometry = util::variant #include -// icu +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 23ea96a7c..9f582791b 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -34,8 +34,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/mapped_memory_cache.hpp b/include/mapnik/mapped_memory_cache.hpp index c67d63ad7..1ac8d877e 100644 --- a/include/mapnik/mapped_memory_cache.hpp +++ b/include/mapnik/mapped_memory_cache.hpp @@ -31,7 +31,12 @@ #include #include #include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace boost { namespace interprocess { class mapped_region; } } diff --git a/include/mapnik/marker.hpp b/include/mapnik/marker.hpp index 8ba117ec3..1feb0fecf 100644 --- a/include/mapnik/marker.hpp +++ b/include/mapnik/marker.hpp @@ -29,8 +29,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_array.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 9f055da9a..8ba3c6f4b 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -37,8 +37,11 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/markers_placements/basic.hpp b/include/mapnik/markers_placements/basic.hpp index 2889c8041..abcef5ea6 100644 --- a/include/mapnik/markers_placements/basic.hpp +++ b/include/mapnik/markers_placements/basic.hpp @@ -29,9 +29,11 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/params.hpp b/include/mapnik/params.hpp index a154cf731..a38fa54e7 100644 --- a/include/mapnik/params.hpp +++ b/include/mapnik/params.hpp @@ -27,8 +27,11 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/path_expression_grammar_impl.hpp b/include/mapnik/path_expression_grammar_impl.hpp index bc2fcfb52..22002bf33 100644 --- a/include/mapnik/path_expression_grammar_impl.hpp +++ b/include/mapnik/path_expression_grammar_impl.hpp @@ -24,10 +24,13 @@ #include #include -// boost + +#pragma GCC diagnostic push +#include #include #include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/plugin.hpp b/include/mapnik/plugin.hpp index a3428de81..68e7de620 100644 --- a/include/mapnik/plugin.hpp +++ b/include/mapnik/plugin.hpp @@ -38,7 +38,8 @@ using mapnik_lib_t = struct _mapnik_lib_t; class PluginInfo : util::noncopyable { public: - using name_func = const char* (*) (); + using callable_returning_string = const char* (*) (); + using callable_returning_void = void (*) (); PluginInfo (std::string const& filename, std::string const& library_name); ~PluginInfo(); diff --git a/include/mapnik/png_io.hpp b/include/mapnik/png_io.hpp index f17f85759..051ea6b4e 100644 --- a/include/mapnik/png_io.hpp +++ b/include/mapnik/png_io.hpp @@ -29,17 +29,19 @@ #include #include +#pragma GCC diagnostic push +#include + // zlib #include // for Z_DEFAULT_COMPRESSION -// boost - - extern "C" { #include } +#pragma GCC diagnostic pop + #define MAX_OCTREE_LEVELS 4 namespace mapnik { @@ -99,10 +101,10 @@ void save_as_png(T1 & file, png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)0); + png_destroy_write_struct(&png_ptr,static_cast(0)); return; } - jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); + jmp_buf* jmp_context = static_cast(png_get_error_ptr(png_ptr)); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); @@ -120,7 +122,7 @@ void save_as_png(T1 & file, const std::unique_ptr row_pointers(new png_bytep[image.height()]); for (unsigned int i = 0; i < image.height(); i++) { - row_pointers[i] = (png_bytep)image.get_row(i); + row_pointers[i] = const_cast(reinterpret_cast(image.get_row(i))); } png_set_rows(png_ptr, info_ptr, row_pointers.get()); png_write_png(png_ptr, info_ptr, (opts.trans_mode == 0) ? PNG_TRANSFORM_STRIP_FILLER_AFTER : PNG_TRANSFORM_IDENTITY, nullptr); @@ -161,7 +163,7 @@ void reduce_8(T const& in, break; } } - if (idx>=0 && idx<(int)alpha.size()) + if (idx>=0 && idx < static_cast(alpha.size())) { alpha[idx]+=U2ALPHA(val); alphaCount[idx]++; @@ -212,7 +214,7 @@ void reduce_4(T const& in, break; } } - if (idx>=0 && idx<(int)alpha.size()) + if (idx>=0 && idx < static_cast(alpha.size())) { alpha[idx]+=U2ALPHA(val); alphaCount[idx]++; @@ -273,10 +275,10 @@ void save_as_png(T & file, std::vector const& palette, png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)0); + png_destroy_write_struct(&png_ptr,static_cast(0)); return; } - jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); + jmp_buf* jmp_context = static_cast(png_get_error_ptr(png_ptr)); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); @@ -310,14 +312,14 @@ void save_as_png(T & file, std::vector const& palette, } if (alphaSize>0) { - png_set_tRNS(png_ptr, info_ptr, (png_bytep)&trans[0], alphaSize, 0); + png_set_tRNS(png_ptr, info_ptr, static_cast(&trans[0]), alphaSize, 0); } } png_write_info(png_ptr, info_ptr); for (unsigned i=0;i(image.get_row(i))); } png_write_end(png_ptr, info_ptr); @@ -352,7 +354,7 @@ void save_as_png8_oct(T1 & file, { for (unsigned x = 0; x < width; ++x) { - unsigned val = U2ALPHA((unsigned)image.get_row(y)[x]); + unsigned val = U2ALPHA(static_cast(image.get_row(y)[x])); alphaHist[val]++; meanAlpha += val; if (val>0 && val<255) diff --git a/include/mapnik/projection.hpp b/include/mapnik/projection.hpp index cb4284fb0..0869bb2d6 100644 --- a/include/mapnik/projection.hpp +++ b/include/mapnik/projection.hpp @@ -27,8 +27,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/ptree_helpers.hpp b/include/mapnik/ptree_helpers.hpp index 3062d7115..6a9c91e56 100644 --- a/include/mapnik/ptree_helpers.hpp +++ b/include/mapnik/ptree_helpers.hpp @@ -26,8 +26,10 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/quad_tree.hpp b/include/mapnik/quad_tree.hpp index f6e48c42b..a44962ec1 100644 --- a/include/mapnik/quad_tree.hpp +++ b/include/mapnik/quad_tree.hpp @@ -38,26 +38,27 @@ namespace mapnik { -template +template > class quad_tree : util::noncopyable { - using value_type = T; + using value_type = T0; + using bbox_type = T1; struct node { - using cont_type = std::vector; + using cont_type = std::vector; using iterator = typename cont_type::iterator; using const_iterator = typename cont_type::const_iterator; - box2d extent_; + bbox_type extent_; cont_type cont_; node * children_[4]; - explicit node(box2d const& ext) + explicit node(bbox_type const& ext) : extent_(ext) { std::fill(children_, children_ + 4, nullptr); } - box2d const& extent() const + bbox_type const& extent() const { return extent_; } @@ -101,10 +102,10 @@ class quad_tree : util::noncopyable public: using iterator = typename nodes_type::iterator; using const_iterator = typename nodes_type::const_iterator; - using result_type = typename std::vector >; + using result_type = typename std::vector >; using query_iterator = typename result_type::iterator; - explicit quad_tree(box2d const& ext, + explicit quad_tree(bbox_type const& ext, unsigned int max_depth = 8, double ratio = 0.55) : max_depth_(max_depth), @@ -116,13 +117,13 @@ public: root_ = nodes_[0].get(); } - void insert(T data, box2d const& box) + void insert(value_type data, bbox_type const& box) { - unsigned int depth=0; - do_insert_data(data,box,root_,depth); + unsigned int depth = 0; + do_insert_data(data, box, root_, depth); } - query_iterator query_in_box(box2d const& box) + query_iterator query_in_box(bbox_type const& box) { query_result_.clear(); query_node(box, query_result_, root_); @@ -147,13 +148,13 @@ public: void clear () { - box2d ext = root_->extent_; + bbox_type ext = root_->extent_; nodes_.clear(); nodes_.push_back(std::make_unique(ext)); root_ = nodes_[0].get(); } - box2d const& extent() const + bbox_type const& extent() const { return root_->extent_; } @@ -187,11 +188,11 @@ public: } private: - void query_node(box2d const& box, result_type & result, node * node_) const + void query_node(bbox_type const& box, result_type & result, node * node_) const { if (node_) { - box2d const& node_extent = node_->extent(); + bbox_type const& node_extent = node_->extent(); if (box.intersects(node_extent)) { for (auto & n : *node_) @@ -206,7 +207,7 @@ private: } } - void do_insert_data(T data, box2d const& box, node * n, unsigned int& depth) + void do_insert_data(value_type data, bbox_type const& box, node * n, unsigned int& depth) { if (++depth >= max_depth_) { @@ -214,8 +215,8 @@ private: } else { - box2d const& node_extent = n->extent(); - box2d ext[4]; + bbox_type const& node_extent = n->extent(); + bbox_type ext[4]; split_box(node_extent,ext); for (int i = 0; i < 4; ++i) { @@ -234,20 +235,19 @@ private: } } - void split_box(box2d const& node_extent,box2d * ext) + void split_box(bbox_type const& node_extent,bbox_type * ext) { - double width=node_extent.width(); - double height=node_extent.height(); + typename bbox_type::value_type width = node_extent.width(); + typename bbox_type::value_type height = node_extent.height(); + typename bbox_type::value_type lox = node_extent.minx(); + typename bbox_type::value_type loy = node_extent.miny(); + typename bbox_type::value_type hix = node_extent.maxx(); + typename bbox_type::value_type hiy = node_extent.maxy(); - double lox=node_extent.minx(); - double loy=node_extent.miny(); - double hix=node_extent.maxx(); - double hiy=node_extent.maxy(); - - ext[0]=box2d(lox,loy,lox + width * ratio_,loy + height * ratio_); - ext[1]=box2d(hix - width * ratio_,loy,hix,loy + height * ratio_); - ext[2]=box2d(lox,hiy - height*ratio_,lox + width * ratio_,hiy); - ext[3]=box2d(hix - width * ratio_,hiy - height*ratio_,hix,hiy); + ext[0] = bbox_type(lox, loy, lox + width * ratio_, loy + height * ratio_); + ext[1] = bbox_type(hix - width * ratio_, loy, hix, loy + height * ratio_); + ext[2] = bbox_type(lox, hiy - height * ratio_, lox + width * ratio_, hiy); + ext[3] = bbox_type(hix - width * ratio_, hiy - height * ratio_, hix, hiy); } void trim_tree(node *& n) @@ -306,7 +306,7 @@ private: { if (n->children_[i]) { - offset +=sizeof(box2d) + (n->children_[i]->cont_.size() * sizeof(value_type)) + 3 * sizeof(int); + offset +=sizeof(bbox_type) + (n->children_[i]->cont_.size() * sizeof(value_type)) + 3 * sizeof(int); offset +=subnode_offset(n->children_[i]); } } @@ -318,17 +318,17 @@ private: { if (n) { - int offset=subnode_offset(n); - int shape_count=n->cont_.size(); - int recsize=sizeof(box2d) + 3 * sizeof(int) + shape_count * sizeof(value_type); + int offset = subnode_offset(n); + int shape_count = n->cont_.size(); + int recsize = sizeof(bbox_type) + 3 * sizeof(int) + shape_count * sizeof(value_type); std::unique_ptr node_record(new char[recsize]); std::memset(node_record.get(), 0, recsize); std::memcpy(node_record.get(), &offset, 4); - std::memcpy(node_record.get() + 4, &n->extent_, sizeof(box2d)); - std::memcpy(node_record.get() + 36, &shape_count, 4); + std::memcpy(node_record.get() + 4, &n->extent_, sizeof(bbox_type)); + std::memcpy(node_record.get() + 4 + sizeof(bbox_type), &shape_count, 4); for (int i=0; i < shape_count; ++i) { - memcpy(node_record.get() + 40 + i * sizeof(value_type), &(n->cont_[i]),sizeof(value_type)); + memcpy(node_record.get() + 8 + sizeof(bbox_type) + i * sizeof(value_type), &(n->cont_[i]), sizeof(value_type)); } int num_subnodes=0; for (int i = 0; i < 4; ++i) @@ -338,7 +338,7 @@ private: ++num_subnodes; } } - std::memcpy(node_record.get() + 40 + shape_count * sizeof(value_type),&num_subnodes,4); + std::memcpy(node_record.get() + 8 + sizeof(bbox_type) + shape_count * sizeof(value_type), &num_subnodes, 4); out.write(node_record.get(),recsize); for (int i = 0; i < 4; ++i) { diff --git a/include/mapnik/raster.hpp b/include/mapnik/raster.hpp index ee17946b4..8ed30e5a2 100644 --- a/include/mapnik/raster.hpp +++ b/include/mapnik/raster.hpp @@ -28,8 +28,11 @@ #include #include #include - // boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/raster_colorizer.hpp b/include/mapnik/raster_colorizer.hpp index c1e83aba1..86a85def2 100644 --- a/include/mapnik/raster_colorizer.hpp +++ b/include/mapnik/raster_colorizer.hpp @@ -41,12 +41,13 @@ #include #include #include - // boost -#include -// boost -#include -// stl +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +#include #include namespace mapnik @@ -164,7 +165,7 @@ public: void set_default_mode(colorizer_mode mode) { - default_mode_ = (mode == COLORIZER_INHERIT) ? COLORIZER_LINEAR:(colorizer_mode_enum)mode; + default_mode_ = (mode == COLORIZER_INHERIT) ? COLORIZER_LINEAR : static_cast(mode); } void set_default_mode_enum(colorizer_mode_enum mode) { set_default_mode(mode); } diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index 12ffba508..ef0863fd6 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -61,7 +61,7 @@ void render_point_symbolizer(point_symbolizer const &sym, agg::trans_affine tr; auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform, common.scale_factor_); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp index f8ce32d84..7ca90a0af 100644 --- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp @@ -32,13 +32,15 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/simplify.hpp b/include/mapnik/simplify.hpp index 71b7711bf..dd75fcf2d 100644 --- a/include/mapnik/simplify.hpp +++ b/include/mapnik/simplify.hpp @@ -7,8 +7,10 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/simplify_converter.hpp b/include/mapnik/simplify_converter.hpp index 92f81b461..248842504 100644 --- a/include/mapnik/simplify_converter.hpp +++ b/include/mapnik/simplify_converter.hpp @@ -41,7 +41,7 @@ struct weighted_vertex : private util::noncopyable vertex2d const& A = prev->coord; vertex2d const& B = next->coord; vertex2d const& C = coord; - return std::abs((double)((A.x - C.x) * (B.y - A.y) - (A.x - B.x) * (C.y - A.y))) / 2.0; + return std::abs(static_cast((A.x - C.x) * (B.y - A.y) - (A.x - B.x) * (C.y - A.y))) / 2.0; } struct ascending_sort diff --git a/include/mapnik/span_image_filter.hpp b/include/mapnik/span_image_filter.hpp index 1a056198f..950f76c08 100644 --- a/include/mapnik/span_image_filter.hpp +++ b/include/mapnik/span_image_filter.hpp @@ -23,15 +23,21 @@ #ifndef MAPNIK_SPAN_IMAGE_FILTER_INCLUDED #define MAPNIK_SPAN_IMAGE_FILTER_INCLUDED +#include + +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +#pragma GCC diagnostic push +#include #include "agg_span_image_filter_gray.h" #include "agg_span_image_filter_rgba.h" - -#include +#pragma GCC diagnostic pop #include -#include - namespace mapnik { diff --git a/include/mapnik/stringify_macro.hpp b/include/mapnik/stringify_macro.hpp new file mode 100644 index 000000000..41f947467 --- /dev/null +++ b/include/mapnik/stringify_macro.hpp @@ -0,0 +1,26 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_STRINGIFY +#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n) +#define MAPNIK_STRINGIFY_HELPER(n) #n +#endif \ No newline at end of file diff --git a/include/mapnik/svg/geometry_svg_generator.hpp b/include/mapnik/svg/geometry_svg_generator.hpp index 11aa5c9c1..7594c26dd 100644 --- a/include/mapnik/svg/geometry_svg_generator.hpp +++ b/include/mapnik/svg/geometry_svg_generator.hpp @@ -36,15 +36,13 @@ #pragma GCC diagnostic push #include #include -#include -#include -#include #include -#include +#include #include #include #pragma GCC diagnostic pop +#include // adapted to conform to the concepts // required by Karma to be recognized as a container of diff --git a/include/mapnik/svg/svg_converter.hpp b/include/mapnik/svg/svg_converter.hpp index 50d7708b2..9cf3c9c16 100644 --- a/include/mapnik/svg/svg_converter.hpp +++ b/include/mapnik/svg/svg_converter.hpp @@ -29,7 +29,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_path_storage.h" #include "agg_conv_transform.h" #include "agg_conv_stroke.h" @@ -37,6 +38,7 @@ #include "agg_conv_curve.h" #include "agg_color_rgba.h" #include "agg_bounding_rect.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/svg/svg_path_adapter.hpp b/include/mapnik/svg/svg_path_adapter.hpp index 3b09af4bc..8b4fb6bf2 100644 --- a/include/mapnik/svg/svg_path_adapter.hpp +++ b/include/mapnik/svg/svg_path_adapter.hpp @@ -28,10 +28,12 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_math.h" #include "agg_array.h" #include "agg_bezier_arc.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/svg/svg_path_attributes.hpp b/include/mapnik/svg/svg_path_attributes.hpp index d1b48aa8f..80bf46349 100644 --- a/include/mapnik/svg/svg_path_attributes.hpp +++ b/include/mapnik/svg/svg_path_attributes.hpp @@ -23,15 +23,17 @@ #ifndef MAPNIK_SVG_PATH_ATTRIBUTES_HPP #define MAPNIK_SVG_PATH_ATTRIBUTES_HPP -// agg -#include "agg_math_stroke.h" -#include "agg_color_rgba.h" -#include "agg_trans_affine.h" - // mapnik #include #include // dash_array +#pragma GCC diagnostic push +#include +#include "agg_math_stroke.h" +#include "agg_color_rgba.h" +#include "agg_trans_affine.h" +#pragma GCC diagnostic pop + namespace mapnik { namespace svg { diff --git a/include/mapnik/svg/svg_path_commands.hpp b/include/mapnik/svg/svg_path_commands.hpp index d0fa70462..7e7ab5fef 100644 --- a/include/mapnik/svg/svg_path_commands.hpp +++ b/include/mapnik/svg/svg_path_commands.hpp @@ -29,16 +29,12 @@ #pragma GCC diagnostic push #include -#include -#include -#include -#include +#include #pragma GCC diagnostic pop namespace mapnik { namespace svg { -using namespace boost::fusion; inline double deg2rad(double deg) { @@ -52,7 +48,7 @@ struct move_to template void operator()(PathType& path, T0 v, T1 rel) const { - path.move_to(at_c<0>(v), at_c<1>(v), rel); // impl + path.move_to(boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v), rel); // impl } }; @@ -82,7 +78,7 @@ struct line_to template void operator()(PathType& path, T0 const& v, T1 rel) const { - path.line_to(at_c<0>(v), at_c<1>(v), rel); // impl + path.line_to(boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v), rel); // impl } }; @@ -92,9 +88,9 @@ struct curve4 template void operator()(PathType& path, T0 const& v0, T1 const& v1, T2 const& v2, T3 rel) const { - path.curve4(at_c<0>(v0), at_c<1>(v0), - at_c<0>(v1), at_c<1>(v1), - at_c<0>(v2), at_c<1>(v2), + path.curve4(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + boost::fusion::at_c<0>(v1), boost::fusion::at_c<1>(v1), + boost::fusion::at_c<0>(v2), boost::fusion::at_c<1>(v2), rel); // impl } }; @@ -105,8 +101,8 @@ struct curve4_smooth template void operator()(PathType& path, T0 const& v0, T1 const& v1, T2 rel) const { - path.curve4(at_c<0>(v0), at_c<1>(v0), - at_c<0>(v1), at_c<1>(v1), + path.curve4(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + boost::fusion::at_c<0>(v1), boost::fusion::at_c<1>(v1), rel); // impl } }; @@ -117,8 +113,8 @@ struct curve3 template void operator()(PathType& path, T0 const& v0, T1 const& v1, T2 rel) const { - path.curve3(at_c<0>(v0), at_c<1>(v0), - at_c<0>(v1), at_c<1>(v1), + path.curve3(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + boost::fusion::at_c<0>(v1), boost::fusion::at_c<1>(v1), rel); // impl } }; @@ -129,7 +125,7 @@ struct curve3_smooth template void operator()(PathType& path, T0 const& v0, T1 rel) const { - path.curve3(at_c<0>(v0), at_c<1>(v0), + path.curve3(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), rel); // impl } }; @@ -140,9 +136,9 @@ struct arc_to template void operator()(PathType& path, T0 const& rv, T1 const& angle, T2 large_arc_flag, T3 sweep_flag, T4 const& v, T5 rel) const { - path.arc_to(at_c<0>(rv), at_c<1>(rv), + path.arc_to(boost::fusion::at_c<0>(rv), boost::fusion::at_c<1>(rv), deg2rad(angle), large_arc_flag, sweep_flag, - at_c<0>(v), at_c<1>(v), + boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v), rel); } }; diff --git a/include/mapnik/svg/svg_renderer_agg.hpp b/include/mapnik/svg/svg_renderer_agg.hpp index 3c714cd68..d99575b4d 100644 --- a/include/mapnik/svg/svg_renderer_agg.hpp +++ b/include/mapnik/svg/svg_renderer_agg.hpp @@ -37,7 +37,8 @@ #pragma GCC diagnostic pop #endif -// agg +#pragma GCC diagnostic push +#include #include "agg_path_storage.h" #include "agg_conv_transform.h" #include "agg_conv_stroke.h" @@ -57,6 +58,7 @@ #include "agg_gradient_lut.h" #include "agg_gamma_lut.h" #include "agg_span_interpolator_linear.h" +#pragma GCC diagnostic pop namespace mapnik { namespace svg { diff --git a/include/mapnik/svg/svg_transform_grammar_impl.hpp b/include/mapnik/svg/svg_transform_grammar_impl.hpp index f0bd54260..65c05ab2c 100644 --- a/include/mapnik/svg/svg_transform_grammar_impl.hpp +++ b/include/mapnik/svg/svg_transform_grammar_impl.hpp @@ -24,8 +24,6 @@ // from implementation files. It therefore doesn't have an include guard. // mapnik #include -// agg -#include #pragma GCC diagnostic push #include @@ -35,6 +33,11 @@ #include #pragma GCC diagnostic pop +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + namespace mapnik { namespace svg { using namespace boost::spirit; diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 39d650d32..9308ecd7b 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -51,8 +51,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/symbolizer_base.hpp b/include/mapnik/symbolizer_base.hpp index 8ac446265..fc88c579c 100644 --- a/include/mapnik/symbolizer_base.hpp +++ b/include/mapnik/symbolizer_base.hpp @@ -58,7 +58,7 @@ MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, attributes const& vars, transform_type const& trans_expr, - double scale_factor=1.0); + double scale_factor); struct enumeration_wrapper { diff --git a/include/mapnik/text/face.hpp b/include/mapnik/text/face.hpp index 87692ca5c..3d797a1f2 100644 --- a/include/mapnik/text/face.hpp +++ b/include/mapnik/text/face.hpp @@ -27,7 +27,9 @@ #include #include -// freetype2 +#pragma GCC diagnostic push +#include + extern "C" { #include @@ -35,6 +37,8 @@ extern "C" #include FT_STROKER_H } +#pragma GCC diagnostic pop + //stl #include #include diff --git a/include/mapnik/text/font_feature_settings.hpp b/include/mapnik/text/font_feature_settings.hpp index 9d945fbe5..8bc3e33c6 100644 --- a/include/mapnik/text/font_feature_settings.hpp +++ b/include/mapnik/text/font_feature_settings.hpp @@ -31,8 +31,11 @@ #include #include #include -// harfbuzz + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // EqualityComparable inline bool operator==(hb_feature_t const& lhs, hb_feature_t const& rhs) @@ -86,7 +89,10 @@ inline bool operator==(font_feature_settings const& lhs, font_feature_settings c constexpr unsigned int font_feature_range_global_start = 0u; static const unsigned int font_feature_range_global_end = std::numeric_limits::max(); +#pragma GCC diagnostic push +#include constexpr hb_feature_t font_feature_liga_off = { HB_TAG('l', 'i', 'g', 'a'), 0, font_feature_range_global_start, font_feature_range_global_end }; +#pragma GCC diagnostic pop } // mapnik namespace diff --git a/include/mapnik/text/formatting/layout.hpp b/include/mapnik/text/formatting/layout.hpp index dd7f4b011..6892ce72b 100644 --- a/include/mapnik/text/formatting/layout.hpp +++ b/include/mapnik/text/formatting/layout.hpp @@ -26,7 +26,10 @@ #include #include +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace formatting { diff --git a/include/mapnik/text/glyph_positions.hpp b/include/mapnik/text/glyph_positions.hpp index 72314c319..aa08e3376 100644 --- a/include/mapnik/text/glyph_positions.hpp +++ b/include/mapnik/text/glyph_positions.hpp @@ -30,8 +30,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop //stl #include diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index 0f23bc844..8b574b095 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -36,12 +36,12 @@ #include #include -// harfbuzz +#pragma GCC diagnostic push +#include #include #include - -// icu #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/text/icu_shaper.hpp b/include/mapnik/text/icu_shaper.hpp index bcd822b27..39bc590bb 100644 --- a/include/mapnik/text/icu_shaper.hpp +++ b/include/mapnik/text/icu_shaper.hpp @@ -36,11 +36,12 @@ // stl #include -// icu +#pragma GCC diagnostic push +#include #include #include #include - +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/text/itemizer.hpp b/include/mapnik/text/itemizer.hpp index b8589448d..5087ce06f 100644 --- a/include/mapnik/text/itemizer.hpp +++ b/include/mapnik/text/itemizer.hpp @@ -34,10 +34,12 @@ #include #include -// ICU +#pragma GCC diagnostic push +#include #include #include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/text/placement_finder.hpp b/include/mapnik/text/placement_finder.hpp index f35a5d50b..3b02d8924 100644 --- a/include/mapnik/text/placement_finder.hpp +++ b/include/mapnik/text/placement_finder.hpp @@ -78,7 +78,6 @@ private: // Maps upright==auto, left-only and right-only to left,right to simplify processing. // angle = angle of at start of line (to estimate best option for upright==auto) text_upright_e simplify_upright(text_upright_e upright, double angle) const; - box2d get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot); feature_impl const& feature_; attributes const& attr_; DetectorType & detector_; diff --git a/include/mapnik/text/properties_util.hpp b/include/mapnik/text/properties_util.hpp index 0fff84e7b..5b92ed306 100644 --- a/include/mapnik/text/properties_util.hpp +++ b/include/mapnik/text/properties_util.hpp @@ -26,11 +26,14 @@ #include #include #include -#include + #include -// boost +#pragma GCC diagnostic push +#include +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace detail { diff --git a/include/mapnik/text/renderer.hpp b/include/mapnik/text/renderer.hpp index a4cd76ed7..692ada3cd 100644 --- a/include/mapnik/text/renderer.hpp +++ b/include/mapnik/text/renderer.hpp @@ -28,7 +28,10 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include + #include // freetype2 @@ -39,6 +42,8 @@ extern "C" #include FT_STROKER_H } +#pragma GCC diagnostic pop + namespace mapnik { diff --git a/include/mapnik/text/scrptrun.hpp b/include/mapnik/text/scrptrun.hpp index 67942b0a8..2161c510d 100644 --- a/include/mapnik/text/scrptrun.hpp +++ b/include/mapnik/text/scrptrun.hpp @@ -17,9 +17,12 @@ #ifndef __SCRPTRUN_H #define __SCRPTRUN_H +#pragma GCC diagnostic push +#include #include #include #include +#pragma GCC diagnostic pop struct ScriptRecord { @@ -102,7 +105,7 @@ private: inline ScriptRun::ScriptRun() { - reset(NULL, 0, 0); + reset(nullptr, 0, 0); } inline ScriptRun::ScriptRun(const UChar chars[], int32_t length) diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index 6d6fbdc49..8fd3c155a 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -158,6 +158,10 @@ protected: void init_marker() const; }; -} //namespace +namespace geometry { +MAPNIK_DECL mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom); +} + +} //namespace mapnik #endif // SYMBOLIZER_HELPERS_HPP diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index 654921eb2..511ba3a28 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -36,9 +36,11 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/tiff_io.hpp b/include/mapnik/tiff_io.hpp index df2b25a7a..b80142906 100644 --- a/include/mapnik/tiff_io.hpp +++ b/include/mapnik/tiff_io.hpp @@ -28,6 +28,9 @@ #include #include +#pragma GCC diagnostic push +#include + extern "C" { #include @@ -35,6 +38,9 @@ extern "C" #define RealTIFFClose TIFFClose } +#pragma GCC diagnostic pop + + //std #include diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index 2e4bfa3ed..b1d8eab73 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -29,8 +29,11 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/util/char_array_buffer.hpp b/include/mapnik/util/char_array_buffer.hpp new file mode 100644 index 000000000..e5b834baa --- /dev/null +++ b/include/mapnik/util/char_array_buffer.hpp @@ -0,0 +1,87 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_UTIL_CHAR_ARRAY_BUFFER_HPP +#define MAPNIK_UTIL_CHAR_ARRAY_BUFFER_HPP + +#include + +namespace mapnik { namespace util { + +// ref https://artofcode.wordpress.com/2010/12/12/deriving-from-stdstreambuf/ + +class char_array_buffer : public std::streambuf +{ +public: + char_array_buffer(char const* data, std::size_t size) + : begin_(data), end_(data + size), current_(data) {} + +private: + int_type underflow() + { + if (current_ == end_) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*current_); + } + + int_type uflow() + { + if (current_ == end_) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*current_++); + } + + int_type pbackfail(int_type ch) + { + if (current_ == begin_ || (ch != traits_type::eof() && ch != current_[-1])) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*--current_); + } + + std::streamsize showmanyc() + { + return end_ - current_; + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode which = std::ios_base::in | std::ios_base::out ) + { + if (dir == std::ios_base::beg) current_ = std::min(begin_ + off, end_); + else if (dir == std::ios_base::cur) current_ = std::min(current_ + off, end_); + else current_ = std::max(end_ - off, begin_); // dir == std::ios_base::end + return pos_type(off_type(current_ - begin_)); + } + char const * const begin_; + char const * const end_; + char const * current_; +}; + +}} + + +#endif // MAPNIK_UTIL_CHAR_ARRAY_BUFFER_HPP diff --git a/include/mapnik/util/const_rendering_buffer.hpp b/include/mapnik/util/const_rendering_buffer.hpp index 360eea564..97b98ca65 100644 --- a/include/mapnik/util/const_rendering_buffer.hpp +++ b/include/mapnik/util/const_rendering_buffer.hpp @@ -25,7 +25,10 @@ #include +#pragma GCC diagnostic push +#include #include "agg_basics.h" +#pragma GCC diagnostic pop #include diff --git a/include/mapnik/util/file_io.hpp b/include/mapnik/util/file_io.hpp index d3ffe9034..b8bc22f01 100644 --- a/include/mapnik/util/file_io.hpp +++ b/include/mapnik/util/file_io.hpp @@ -58,11 +58,16 @@ public: } } - inline bool open() const + inline bool is_open() const { return file_ ? true : false; } + explicit operator bool() const + { + return this->is_open(); + } + inline std::FILE * get() const { return file_.get(); diff --git a/include/mapnik/util/geometry_to_ds_type.hpp b/include/mapnik/util/geometry_to_ds_type.hpp index 58fc89df2..e09808f3e 100644 --- a/include/mapnik/util/geometry_to_ds_type.hpp +++ b/include/mapnik/util/geometry_to_ds_type.hpp @@ -28,8 +28,13 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#include +#include +#pragma GCC diagnostic pop namespace mapnik { namespace util { diff --git a/include/mapnik/util/is_clockwise.hpp b/include/mapnik/util/is_clockwise.hpp index 248372722..93951df38 100644 --- a/include/mapnik/util/is_clockwise.hpp +++ b/include/mapnik/util/is_clockwise.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_UTIL_IS_CLOCKWISE_HPP #define MAPNIK_UTIL_IS_CLOCKWISE_HPP +#include + namespace mapnik { namespace util { template @@ -30,11 +32,18 @@ bool is_clockwise(T const& ring) { double area = 0.0; std::size_t num_points = ring.size(); + assert(num_points > 2); + double orig_x = ring[0].x; + double orig_y = ring[0].y; for (std::size_t i = 0; i < num_points; ++i) { auto const& p0 = ring[i]; auto const& p1 = ring[(i + 1) % num_points]; - area += p0.x * p1.y - p0.y * p1.x; + double x0 = p0.x - orig_x; + double y0 = p0.y - orig_y; + double x1 = p1.x - orig_x; + double y1 = p1.y - orig_y; + area += x0 * y1 - x1 * y0; } return (area < 0.0) ? true : false; } diff --git a/include/mapnik/util/path_iterator.hpp b/include/mapnik/util/path_iterator.hpp index 319c3461a..19b69ce26 100644 --- a/include/mapnik/util/path_iterator.hpp +++ b/include/mapnik/util/path_iterator.hpp @@ -26,8 +26,11 @@ // mapnik #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/util/spatial_index.hpp b/include/mapnik/util/spatial_index.hpp index d207dbab4..720667768 100644 --- a/include/mapnik/util/spatial_index.hpp +++ b/include/mapnik/util/spatial_index.hpp @@ -47,12 +47,13 @@ bool check_spatial_index(InputStream& in) return (std::strncmp(header, "mapnik-index",12) == 0); } -template +template > class spatial_index { + using bbox_type = BBox; public: static void query(Filter const& filter, InputStream& in,std::vector& pos); - static box2d bounding_box( InputStream& in ); + static bbox_type bounding_box( InputStream& in ); static void query_first_n(Filter const& filter, InputStream & in, std::vector& pos, std::size_t count); private: spatial_index(); @@ -60,25 +61,25 @@ private: spatial_index(spatial_index const&); spatial_index& operator=(spatial_index const&); static int read_ndr_integer(InputStream& in); - static void read_envelope(InputStream& in, box2d& envelope); + static void read_envelope(InputStream& in, bbox_type& envelope); static void query_node(Filter const& filter, InputStream& in, std::vector & results); static void query_first_n_impl(Filter const& filter, InputStream& in, std::vector & results, std::size_t count); }; -template -box2d spatial_index::bounding_box(InputStream& in) +template +BBox spatial_index::bounding_box(InputStream& in) { static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); if (!check_spatial_index(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)"); in.seekg(16 + 4, std::ios::beg); - box2d box; + typename spatial_index::bbox_type box; read_envelope(in, box); in.seekg(0, std::ios::beg); return box; } -template -void spatial_index::query(Filter const& filter, InputStream& in, std::vector& results) +template +void spatial_index::query(Filter const& filter, InputStream& in, std::vector& results) { static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); if (!check_spatial_index(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)"); @@ -86,11 +87,11 @@ void spatial_index::query(Filter const& filter, Inpu query_node(filter, in, results); } -template -void spatial_index::query_node(Filter const& filter, InputStream& in, std::vector& results) +template +void spatial_index::query_node(Filter const& filter, InputStream& in, std::vector& results) { int offset = read_ndr_integer(in); - box2d node_ext; + typename spatial_index::bbox_type node_ext; read_envelope(in, node_ext); int num_shapes = read_ndr_integer(in); if (!filter.pass(node_ext)) @@ -113,8 +114,8 @@ void spatial_index::query_node(Filter const& filter, } } -template -void spatial_index::query_first_n(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) +template +void spatial_index::query_first_n(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) { static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); if (!check_spatial_index(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)"); @@ -122,12 +123,12 @@ void spatial_index::query_first_n(Filter const& filt query_first_n_impl(filter, in, results, count); } -template -void spatial_index::query_first_n_impl(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) +template +void spatial_index::query_first_n_impl(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) { if (results.size() == count) return; int offset = read_ndr_integer(in); - box2d node_ext; + typename spatial_index::bbox_type node_ext; read_envelope(in, node_ext); int num_shapes = read_ndr_integer(in); if (!filter.pass(node_ext)) @@ -149,16 +150,16 @@ void spatial_index::query_first_n_impl(Filter const& } } -template -int spatial_index::read_ndr_integer(InputStream& in) +template +int spatial_index::read_ndr_integer(InputStream& in) { char b[4]; in.read(b, 4); return (b[0] & 0xff) | (b[1] & 0xff) << 8 | (b[2] & 0xff) << 16 | (b[3] & 0xff) << 24; } -template -void spatial_index::read_envelope(InputStream& in, box2d& envelope) +template +void spatial_index::read_envelope(InputStream& in, BBox& envelope) { in.read(reinterpret_cast(&envelope), sizeof(envelope)); } diff --git a/include/mapnik/util/variant.hpp b/include/mapnik/util/variant.hpp index 61832a0b7..3fb00b388 100644 --- a/include/mapnik/util/variant.hpp +++ b/include/mapnik/util/variant.hpp @@ -24,8 +24,12 @@ #define MAPNIK_UTIL_VARIANT_HPP #include +#include + +#pragma GCC diagnostic push +#include #include // spirit support -#include +#pragma GCC diagnostic pop namespace mapnik { namespace util { diff --git a/include/mapnik/value_hash.hpp b/include/mapnik/value_hash.hpp index c1f1d60fc..80e10d855 100644 --- a/include/mapnik/value_hash.hpp +++ b/include/mapnik/value_hash.hpp @@ -26,20 +26,20 @@ // mapnik #include #include - // stl #include -// icu +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace mapnik { namespace detail { -template -inline void hash_combine(std::size_t & seed, T const& v) +inline void hash_combine(std::size_t & seed, std::size_t val) { - std::hash hasher; - seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + seed ^= val + 0x9e3779b9 + (seed << 6) + (seed >> 2); } struct value_hasher @@ -54,6 +54,11 @@ struct value_hasher return static_cast(val.hashCode()); } + std::size_t operator()(value_integer val) const + { + return static_cast(val); + } + template std::size_t operator()(T const& val) const { @@ -67,7 +72,8 @@ struct value_hasher template std::size_t mapnik_hash_value(T const& val) { - std::size_t seed = util::apply_visitor(detail::value_hasher(), val); + std::size_t seed = 0; + detail::hash_combine(seed, util::apply_visitor(detail::value_hasher(), val)); detail::hash_combine(seed, val.which()); return seed; } diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index 85a015ba1..235133a34 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -27,8 +27,11 @@ #include #include -// icu + +#pragma GCC diagnostic push +#include #include // for U_NAMESPACE_QUALIFIER +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/version.hpp b/include/mapnik/version.hpp index 3298d75b8..deba4287c 100644 --- a/include/mapnik/version.hpp +++ b/include/mapnik/version.hpp @@ -23,17 +23,14 @@ #ifndef MAPNIK_VERSION_HPP #define MAPNIK_VERSION_HPP +#include + #define MAPNIK_MAJOR_VERSION 3 #define MAPNIK_MINOR_VERSION 0 -#define MAPNIK_PATCH_VERSION 11 +#define MAPNIK_PATCH_VERSION 12 #define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION) -#ifndef MAPNIK_STRINGIFY -#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n) -#define MAPNIK_STRINGIFY_HELPER(n) #n -#endif - #define MAPNIK_VERSION_STRING MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \ MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \ MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION) diff --git a/include/mapnik/vertex_adapters.hpp b/include/mapnik/vertex_adapters.hpp index 3a41beee0..0c77d7550 100644 --- a/include/mapnik/vertex_adapters.hpp +++ b/include/mapnik/vertex_adapters.hpp @@ -32,10 +32,10 @@ namespace mapnik { namespace geometry { template struct point_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; point_vertex_adapter(point const& pt); - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; void rewind(unsigned) const; geometry_types type () const; point const& pt_; @@ -45,9 +45,9 @@ struct point_vertex_adapter template struct line_string_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; line_string_vertex_adapter(line_string const& line); - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; void rewind(unsigned) const; geometry_types type () const; line_string const& line_; @@ -58,10 +58,10 @@ struct line_string_vertex_adapter template struct polygon_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; polygon_vertex_adapter(polygon const& poly); void rewind(unsigned) const; - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; geometry_types type () const; private: polygon const& poly_; @@ -75,10 +75,10 @@ private: template struct ring_vertex_adapter { - using value_type = typename point::value_type; + using coord_type = typename point::coord_type; ring_vertex_adapter(linear_ring const& ring); void rewind(unsigned) const; - unsigned vertex(value_type * x, value_type * y) const; + unsigned vertex(coord_type * x, coord_type * y) const; geometry_types type () const; private: linear_ring const& ring_; diff --git a/include/mapnik/vertex_cache.hpp b/include/mapnik/vertex_cache.hpp index a0a32e96b..9df786e62 100644 --- a/include/mapnik/vertex_cache.hpp +++ b/include/mapnik/vertex_cache.hpp @@ -28,8 +28,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index d9ec9d0f8..ba1829472 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -37,7 +37,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_math_stroke.h" #include "agg_trans_affine.h" #include "agg_conv_clip_polygon.h" @@ -46,6 +47,7 @@ #include "agg_conv_stroke.h" #include "agg_conv_dash.h" #include "agg_conv_transform.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/warning_ignore.hpp b/include/mapnik/warning_ignore.hpp index c67cd1f5a..ed3c2cceb 100644 --- a/include/mapnik/warning_ignore.hpp +++ b/include/mapnik/warning_ignore.hpp @@ -23,14 +23,34 @@ #pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc #pragma GCC diagnostic ignored "-Wpragmas" // gcc +#pragma GCC diagnostic ignored "-W#pragma-messages" #pragma GCC diagnostic ignored "-Wunsequenced" #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wredeclared-class-member" -#pragma GCC diagnostic ignored "-Wunused-local-typedef" +#pragma GCC diagnostic ignored "-Wunused-local-typedef" #pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wc++11-narrowing" #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" \ No newline at end of file +#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" +#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wdocumentation" +#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wdeprecated" +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wc++98-compat" +#pragma GCC diagnostic ignored "-Wreserved-id-macro" +#pragma GCC diagnostic ignored "-Wweak-vtables" +#pragma GCC diagnostic ignored "-Wextra-semi" +#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wheader-hygiene" +#pragma GCC diagnostic ignored "-Wexit-time-destructors" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wmissing-noreturn" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#pragma GCC diagnostic ignored "-Wfloat-equal" diff --git a/include/mapnik/warning_ignore_agg.hpp b/include/mapnik/warning_ignore_agg.hpp new file mode 100644 index 000000000..2f44c5c78 --- /dev/null +++ b/include/mapnik/warning_ignore_agg.hpp @@ -0,0 +1,32 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 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 + * + *****************************************************************************/ + + +#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc +#pragma GCC diagnostic ignored "-Wpragmas" // gcc +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wshadow" + diff --git a/include/mapnik/well_known_srs.hpp b/include/mapnik/well_known_srs.hpp index 246647813..235a90859 100644 --- a/include/mapnik/well_known_srs.hpp +++ b/include/mapnik/well_known_srs.hpp @@ -28,8 +28,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/wkb.hpp b/include/mapnik/wkb.hpp index 53f1e850d..98b3d30c9 100644 --- a/include/mapnik/wkb.hpp +++ b/include/mapnik/wkb.hpp @@ -60,9 +60,11 @@ class MAPNIK_DECL geometry_utils : private util::noncopyable { public: - static mapnik::geometry::geometry from_wkb(const char* wkb, - std::size_t size, - wkbFormat format = wkbGeneric); + static geometry::geometry from_wkb(char const* wkb, + std::size_t size, + wkbFormat format = wkbGeneric); + + static geometry::geometry from_twkb(char const* twkb, std::size_t size); }; } diff --git a/include/mapnik/wkt/wkt_generator_grammar.hpp b/include/mapnik/wkt/wkt_generator_grammar.hpp index 892e55137..f31fcc08e 100644 --- a/include/mapnik/wkt/wkt_generator_grammar.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar.hpp @@ -104,7 +104,7 @@ template struct wkt_generator_grammar : karma::grammar { - using coord_type = typename Geometry::value_type; + using coord_type = typename Geometry::coord_type; wkt_generator_grammar(); // rules karma::rule geometry; diff --git a/include/mapnik/wkt/wkt_generator_grammar_impl.hpp b/include/mapnik/wkt/wkt_generator_grammar_impl.hpp index fd56bedba..8d950edd0 100644 --- a/include/mapnik/wkt/wkt_generator_grammar_impl.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar_impl.hpp @@ -24,8 +24,11 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace wkt { diff --git a/include/mapnik/wkt/wkt_grammar_impl.hpp b/include/mapnik/wkt/wkt_grammar_impl.hpp index 432b19355..d2444130a 100644 --- a/include/mapnik/wkt/wkt_grammar_impl.hpp +++ b/include/mapnik/wkt/wkt_grammar_impl.hpp @@ -22,12 +22,16 @@ #include #include + +#pragma GCC diagnostic push +#include #include #include #include #include #include #include +#pragma GCC diagnostic pop namespace mapnik { namespace wkt { diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp index 1c3602134..bf7130c20 100644 --- a/include/mapnik/xml_node.hpp +++ b/include/mapnik/xml_node.hpp @@ -26,8 +26,10 @@ //mapnik #include // for MAPNIK_DECL -//boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop //stl #include diff --git a/localize.sh b/localize.sh index 4b69c2f6b..3d034f508 100755 --- a/localize.sh +++ b/localize.sh @@ -1,10 +1,12 @@ #!/bin/bash + # TODO - use rpath to avoid needing this to run tests locally + export CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ $(uname -s) = 'Darwin' ]; then - export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH} -else - export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH} +if [[ $(uname -s) == 'Darwin' ]]; then + export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH:-""} +elif [[ $(uname -s) == 'Linux' ]]; then + export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH:-""} fi export PATH=$(pwd)/utils/mapnik-render/:${PATH} diff --git a/mason_latest.sh b/mason_latest.sh index 62a0c94f0..d5db6963f 100755 --- a/mason_latest.sh +++ b/mason_latest.sh @@ -4,7 +4,11 @@ MASON_NAME=mapnik MASON_VERSION=latest MASON_LIB_FILE=lib/libmapnik-wkt.a -. ${MASON_DIR:-~/.mason}/mason.sh +# warning: may break when https://github.com/mapbox/mason/issues/141 lands +# hence we are pinned for now to older mason in bootstrap.sh +. ./.mason/mason.sh + +set -eu function mason_load_source { export MASON_BUILD_PATH=$(pwd) @@ -13,21 +17,38 @@ function mason_load_source { function mason_compile { HERE=$(pwd) make install - if [[ `uname` == 'Darwin' ]]; then - install_name_tool -id @loader_path/libmapnik.dylib ${MASON_PREFIX}"/lib/libmapnik.dylib"; + # this is to adapt to when mapnik is not installed in MASON_PREFIX + # originally (to make it easier to publish locally as a stopgap) + MAPNIK_PREFIX=$(mapnik-config --prefix) + if [[ ${MAPNIK_PREFIX} != ${MASON_PREFIX} ]]; then + mkdir -p ${MASON_PREFIX}/lib + mkdir -p ${MASON_PREFIX}/include + mkdir -p ${MASON_PREFIX}/bin + cp -r ${MAPNIK_PREFIX}/lib/*mapnik* ${MASON_PREFIX}/lib/ + cp -r ${MAPNIK_PREFIX}/include/mapnik ${MASON_PREFIX}/include/ + cp -r ${MAPNIK_PREFIX}/bin/mapnik* ${MASON_PREFIX}/bin/ + cp -r ${MAPNIK_PREFIX}/bin/shapeindex ${MASON_PREFIX}/bin/ + fi + if [[ $(uname -s) == 'Darwin' ]]; then + install_name_tool -id @loader_path/lib/libmapnik.dylib ${MASON_PREFIX}"/lib/libmapnik.dylib"; PLUGINDIR=${MASON_PREFIX}"/lib/mapnik/input/*.input"; for f in $PLUGINDIR; do echo $f; - echo `basename $f`; - install_name_tool -id plugins/input/`basename $f` $f; - install_name_tool -change ${MASON_PREFIX}"/lib/libmapnik.dylib" @loader_path/../../libmapnik.dylib $f; + echo $(basename $f); + install_name_tool -id plugins/input/$(basename $f) $f; + install_name_tool -change "${MAPNIK_PREFIX}/lib/libmapnik.dylib" @loader_path/../../lib/libmapnik.dylib $f; + done; + BINDIR=${MASON_PREFIX}"/bin/*"; + for f in $BINDIR; do + echo $f; + echo $(basename $f); + if [[ $(file $f) =~ 'Mach-O' ]]; then + install_name_tool -id bin/$(basename $f) $f; + install_name_tool -change "${MAPNIK_PREFIX}/lib/libmapnik.dylib" @loader_path/../lib/libmapnik.dylib $f; + fi done; fi; python -c "data=open('$MASON_PREFIX/bin/mapnik-config','r').read();open('$MASON_PREFIX/bin/mapnik-config','w').write(data.replace('$HERE','.'))" - mkdir -p ${MASON_PREFIX}/share/icu - cp -r $GDAL_DATA ${MASON_PREFIX}/share/ - cp -r $PROJ_LIB ${MASON_PREFIX}/share/ - cp -r $ICU_DATA/*dat ${MASON_PREFIX}/share/icu/ find ${MASON_PREFIX} -name "*.pyc" -exec rm {} \; } diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 1208c8b15..6c1ff1014 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -169,7 +169,7 @@ csv_datasource::~csv_datasource() {} void csv_datasource::parse_csv(std::istream & csv_file) { std::vector boxes; - csv_utils::csv_file_parser::parse_csv(csv_file, boxes); + csv_utils::csv_file_parser::parse_csv_and_boxes(csv_file, boxes); std::for_each(headers_.begin(), headers_.end(), [ & ](std::string const& header){ ctx_->push(header); }); diff --git a/plugins/input/csv/csv_utils.cpp b/plugins/input/csv/csv_utils.cpp index 2f8a84a7b..217276f6a 100644 --- a/plugins/input/csv/csv_utils.cpp +++ b/plugins/input/csv/csv_utils.cpp @@ -40,8 +40,157 @@ #include #include -namespace csv_utils +namespace csv_utils { +namespace detail { + +std::size_t file_length(std::istream & stream) { + stream.seekg(0, std::ios::end); + return stream.tellg(); +} + +std::tuple autodetect_csv_flavour(std::istream & stream, std::size_t file_length) +{ + // autodetect newlines/quotes/separators + char newline = '\n'; // default + bool has_newline = false; + bool has_single_quote = false; + char quote = '"'; // default + char separator = ','; // default + // local counters + int num_commas = 0; + int num_tabs = 0; + int num_pipes = 0; + int num_semicolons = 0; + + static std::size_t const max_size = 4000; + std::size_t size = std::min(file_length, max_size); + std::vector buffer; + buffer.resize(size); + stream.read(buffer.data(), size); + for (auto c : buffer) + { + switch (c) + { + case '\r': + newline = '\r'; + has_newline = true; + break; + case '\n': + has_newline = true; + break; + case '\'': + if (!has_single_quote) + { + quote = c; + has_single_quote = true; + } + break; + case ',': + if (!has_newline) ++num_commas; + break; + case '\t': + if (!has_newline) ++num_tabs; + break; + case '|': + if (!has_newline) ++num_pipes; + break; + case ';': + if (!has_newline) ++num_semicolons; + break; + } + } + // detect separator + if (num_tabs > 0 && num_tabs > num_commas) + { + separator = '\t'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected tab separator"; + } + else // pipes/semicolons + { + if (num_pipes > num_commas) + { + separator = '|'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected '|' separator"; + } + else if (num_semicolons > num_commas) + { + separator = ';'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected ';' separator"; + } + } + + if (has_newline && has_single_quote) + { + std::istringstream ss(std::string(buffer.begin(), buffer.end())); + std::size_t num_columns = 0; + for (std::string line; csv_utils::getline_csv(ss, line, newline, quote); ) + { + if (size < file_length && ss.eof()) + { + // we can't be sure that last line + // is not truncated so skip it + break; + } + if (line.size() == 0 || (line.size() == 1 && line[0] == char(0xa))) continue; // empty lines are not interesting + auto num_quotes = std::count(line.begin(), line.end(), quote); + if (num_quotes % 2 != 0) + { + quote = '"'; + break; + } + auto columns = csv_utils::parse_line(line, separator, quote); + if (num_columns > 0 && num_columns != columns.size()) + { + quote = '"'; + break; + } + num_columns = columns.size(); + } + } + return std::make_tuple(newline, has_newline, separator, quote); +} + +void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator) +{ + std::string lower_val(header); + std::transform(lower_val.begin(), lower_val.end(), lower_val.begin(), ::tolower); + if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) + { + locator.type = geometry_column_locator::WKT; + locator.index = index; + } + else if (lower_val == "geojson") + { + locator.type = geometry_column_locator::GEOJSON; + locator.index = index; + } + else if (lower_val == "x" || lower_val == "lon" + || lower_val == "lng" || lower_val == "long" + || (lower_val.find("longitude") != std::string::npos)) + { + locator.index = index; + locator.type = geometry_column_locator::LON_LAT; + } + + else if (lower_val == "y" + || lower_val == "lat" + || (lower_val.find("latitude") != std::string::npos)) + { + locator.index2 = index; + locator.type = geometry_column_locator::LON_LAT; + } +} + +bool valid(geometry_column_locator const& locator, std::size_t max_size) +{ + if (locator.type == geometry_column_locator::UNKNOWN) return false; + if (locator.index >= max_size) return false; + if (locator.type == geometry_column_locator::LON_LAT && locator.index2 >= max_size) return false; + return true; +} + +} // namespace detail static const mapnik::csv_line_grammar line_g; static const mapnik::csv_white_space_skipper skipper{}; @@ -89,8 +238,12 @@ void csv_file_parser::add_feature(mapnik::value_integer, mapnik::csv_line const // no-op by default } -void csv_file_parser::parse_csv(std::istream & csv_file, boxes_type & boxes) +template +void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, T & boxes) { + using boxes_type = T; + using box_type = typename boxes_type::value_type::first_type; + auto file_length = detail::file_length(csv_file); // set back to start csv_file.seekg(0, std::ios::beg); @@ -98,7 +251,7 @@ void csv_file_parser::parse_csv(std::istream & csv_file, boxes_type & boxes) bool has_newline; char detected_quote; char detected_separator; - std::tie(newline, has_newline, detected_separator, detected_quote) = detail::autodect_csv_flavour(csv_file, file_length); + std::tie(newline, has_newline, detected_separator, detected_quote) = detail::autodetect_csv_flavour(csv_file, file_length); if (quote_ == 0) quote_ = detected_quote; if (separator_ == 0) separator_ = detected_separator; @@ -117,6 +270,7 @@ void csv_file_parser::parse_csv(std::istream & csv_file, boxes_type & boxes) { std::size_t index = 0; auto headers = csv_utils::parse_line(manual_headers_, separator_, quote_); + headers_.reserve(headers.size()); for (auto const& header : headers) { detail::locate_geometry_column(header, index++, locator_); @@ -135,6 +289,7 @@ void csv_file_parser::parse_csv(std::istream & csv_file, boxes_type & boxes) else { std::size_t index = 0; + headers_.reserve(headers.size()); for (auto & header : headers) { mapnik::util::trim(header); @@ -261,7 +416,7 @@ void csv_file_parser::parse_csv(std::istream & csv_file, boxes_type & boxes) else extent_ = box; } - boxes.emplace_back(box, make_pair(record_offset, record_size)); + boxes.emplace_back(box_type(box), make_pair(record_offset, record_size)); add_feature(++feature_count, values); } else @@ -301,156 +456,6 @@ void csv_file_parser::parse_csv(std::istream & csv_file, boxes_type & boxes) } } -namespace detail { - -std::size_t file_length(std::istream & stream) -{ - stream.seekg(0, std::ios::end); - return stream.tellg(); -} - -std::tuple autodect_csv_flavour(std::istream & stream, std::size_t file_length) -{ - // autodetect newlines/quotes/separators - char newline = '\n'; // default - bool has_newline = false; - bool has_single_quote = false; - char quote = '"'; // default - char separator = ','; // default - // local counters - int num_commas = 0; - int num_tabs = 0; - int num_pipes = 0; - int num_semicolons = 0; - - static std::size_t const max_size = 4000; - std::size_t size = std::min(file_length, max_size); - std::vector buffer; - buffer.resize(size); - stream.read(buffer.data(), size); - for (auto c : buffer) - { - switch (c) - { - case '\r': - newline = '\r'; - has_newline = true; - break; - case '\n': - has_newline = true; - break; - case '\'': - if (!has_single_quote) - { - quote = c; - has_single_quote = true; - } - break; - case ',': - if (!has_newline) ++num_commas; - break; - case '\t': - if (!has_newline) ++num_tabs; - break; - case '|': - if (!has_newline) ++num_pipes; - break; - case ';': - if (!has_newline) ++num_semicolons; - break; - } - } - // detect separator - if (num_tabs > 0 && num_tabs > num_commas) - { - separator = '\t'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected tab separator"; - } - else // pipes/semicolons - { - if (num_pipes > num_commas) - { - separator = '|'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected '|' separator"; - } - else if (num_semicolons > num_commas) - { - separator = ';'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected ';' separator"; - } - } - - if (has_newline && has_single_quote) - { - std::istringstream ss(std::string(buffer.begin(), buffer.end())); - std::size_t num_columns = 0; - for (std::string line; csv_utils::getline_csv(ss, line, newline, quote); ) - { - if (size < file_length && ss.eof()) - { - // we can't be sure last line - // is not truncated so skip it - break; - } - if (line.size() == 0) continue; // empty lines are not interesting - auto num_quotes = std::count(line.begin(), line.end(), quote); - if (num_quotes % 2 != 0) - { - quote = '"'; - break; - } - auto columns = csv_utils::parse_line(line, separator, quote); - if (num_columns > 0 && num_columns != columns.size()) - { - quote = '"'; - break; - } - num_columns = columns.size(); - } - } - return std::make_tuple(newline, has_newline, separator, quote); -} - -void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator) -{ - std::string lower_val(header); - std::transform(lower_val.begin(), lower_val.end(), lower_val.begin(), ::tolower); - if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) - { - locator.type = geometry_column_locator::WKT; - locator.index = index; - } - else if (lower_val == "geojson") - { - locator.type = geometry_column_locator::GEOJSON; - locator.index = index; - } - else if (lower_val == "x" || lower_val == "lon" - || lower_val == "lng" || lower_val == "long" - || (lower_val.find("longitude") != std::string::npos)) - { - locator.index = index; - locator.type = geometry_column_locator::LON_LAT; - } - - else if (lower_val == "y" - || lower_val == "lat" - || (lower_val.find("latitude") != std::string::npos)) - { - locator.index2 = index; - locator.type = geometry_column_locator::LON_LAT; - } -} - -bool valid(geometry_column_locator const& locator, std::size_t max_size) -{ - if (locator.type == geometry_column_locator::UNKNOWN) return false; - if (locator.index >= max_size) return false; - if (locator.type == geometry_column_locator::LON_LAT && locator.index2 >= max_size) return false; - return true; -} - -} // namespace detail mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator) { @@ -495,4 +500,8 @@ mapnik::geometry::geometry extract_geometry(std::vector con return geom; } +template void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, std::vector, std::pair>> & boxes); + +template void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, std::vector, std::pair>> & boxes); + } // namespace csv_utils diff --git a/plugins/input/csv/csv_utils.hpp b/plugins/input/csv/csv_utils.hpp index f8538472d..df976e3a7 100644 --- a/plugins/input/csv/csv_utils.hpp +++ b/plugins/input/csv/csv_utils.hpp @@ -55,16 +55,6 @@ struct geometry_column_locator std::size_t index2; }; -namespace detail { - -std::size_t file_length(std::istream & stream); - -std::tuple autodect_csv_flavour(std::istream & stream, std::size_t file_length); - -void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator); -bool valid(geometry_column_locator const& locator, std::size_t max_size); - -} // namespace detail mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator); @@ -140,11 +130,8 @@ void process_properties(Feature & feature, Headers const& headers, Values const& struct csv_file_parser { - using box_type = mapnik::box2d; - using item_type = std::pair>; - using boxes_type = std::vector; - - void parse_csv(std::istream & csv_file, boxes_type & boxes); + template + void parse_csv_and_boxes(std::istream & csv_file, T & boxes); virtual void add_feature(mapnik::value_integer index, mapnik::csv_line const & values); diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index 07cec478a..2454ed65b 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -44,11 +44,14 @@ using mapnik::featureset_ptr; using mapnik::layer_descriptor; using mapnik::datasource_exception; +static std::once_flag once_flag; -static bool GDALAllRegister_once_() +extern "C" MAPNIK_EXP void on_plugin_load() { - static bool const quiet_unused = (GDALAllRegister(), true); - return quiet_unused; + // initialize gdal formats + std::call_once(once_flag,[](){ + GDALAllRegister(); + }); } gdal_datasource::gdal_datasource(parameters const& params) @@ -60,8 +63,6 @@ gdal_datasource::gdal_datasource(parameters const& params) { MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Initializing..."; - GDALAllRegister_once_(); - #ifdef MAPNIK_STATS mapnik::progress_timer __stats__(std::clog, "gdal_datasource::init"); #endif diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index fe1fe64a4..1377322e3 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -44,6 +44,41 @@ using mapnik::view_transform; using mapnik::datasource_exception; using mapnik::feature_factory; +#ifdef MAPNIK_LOG +namespace { + +void get_overview_meta(GDALRasterBand* band) +{ + int band_overviews = band->GetOverviewCount(); + if (band_overviews > 0) + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: " << band_overviews << " overviews found!"; + + for (int b = 0; b < band_overviews; b++) + { + GDALRasterBand * overview = band->GetOverview(b); + MAPNIK_LOG_DEBUG(gdal) << "Overview= " << b + << " Width=" << overview->GetXSize() + << " Height=" << overview->GetYSize(); + } + } + else + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No overviews found!"; + } + + int bsx,bsy; + double scale; + band->GetBlockSize(&bsx, &bsy); + scale = band->GetScale(); + + MAPNIK_LOG_DEBUG(gdal) << "Block=" << bsx << "x" << bsy + << " Scale=" << scale + << " Type=" << GDALGetDataTypeName(band->GetRasterDataType()) + << "Color=" << GDALGetColorInterpretationName(band->GetColorInterpretation()); +} +} // anonymous ns +#endif gdal_featureset::gdal_featureset(GDALDataset& dataset, int band, gdal_query q, @@ -403,15 +438,15 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) if( red->GetBand() == 1 && green->GetBand() == 2 && blue->GetBand() == 3 ) { int nBandsToRead = 3; - if( alpha != NULL && alpha->GetBand() == 4 && !raster_has_nodata ) + if( alpha != nullptr && alpha->GetBand() == 4 && !raster_has_nodata ) { nBandsToRead = 4; - alpha = NULL; // to avoid reading it again afterwards + alpha = nullptr; // to avoid reading it again afterwards } raster_io_error = dataset_.RasterIO(GF_Read, x_off, y_off, width, height, image.bytes(), image.width(), image.height(), GDT_Byte, - nBandsToRead, NULL, + nBandsToRead, nullptr, 4, 4 * image.width(), 1); if (raster_io_error == CE_Failure) { throw datasource_exception(CPLGetLastErrorMsg()); @@ -551,6 +586,32 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; } } + else if( dataset_.GetRasterCount() > 0 && dataset_.GetRasterBand(1) ) + { + // Check if we have a non-alpha mask band (for example a TIFF internal mask) + int flags = dataset_.GetRasterBand(1)->GetMaskFlags(); + GDALRasterBand* mask = 0; + if (flags == GMF_PER_DATASET) + { + mask = dataset_.GetRasterBand(1)->GetMaskBand(); + } + if (mask) + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: found and processing mask band..."; + if (!raster_has_nodata) + { + raster_io_error = mask->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + } + else + { + MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of mask band"; + } + } + } mapnik::raster_ptr raster = std::make_shared(intersect, image, filter_factor); // set nodata value to be used in raster colorizer if (nodata_value_) raster->set_nodata(*nodata_value_); @@ -620,36 +681,3 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) } return feature_ptr(); } - -#ifdef MAPNIK_LOG -void gdal_featureset::get_overview_meta(GDALRasterBand* band) -{ - int band_overviews = band->GetOverviewCount(); - if (band_overviews > 0) - { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: " << band_overviews << " overviews found!"; - - for (int b = 0; b < band_overviews; b++) - { - GDALRasterBand * overview = band->GetOverview(b); - MAPNIK_LOG_DEBUG(gdal) << "Overview= " << b - << " Width=" << overview->GetXSize() - << " Height=" << overview->GetYSize(); - } - } - else - { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No overviews found!"; - } - - int bsx,bsy; - double scale; - band->GetBlockSize(&bsx, &bsy); - scale = band->GetScale(); - - MAPNIK_LOG_DEBUG(gdal) << "Block=" << bsx << "x" << bsy - << " Scale=" << scale - << " Type=" << GDALGetDataTypeName(band->GetRasterDataType()) - << "Color=" << GDALGetColorInterpretationName(band->GetColorInterpretation()); -} -#endif diff --git a/plugins/input/gdal/gdal_featureset.hpp b/plugins/input/gdal/gdal_featureset.hpp index 639028b65..f2f66f796 100644 --- a/plugins/input/gdal/gdal_featureset.hpp +++ b/plugins/input/gdal/gdal_featureset.hpp @@ -73,11 +73,6 @@ public: private: mapnik::feature_ptr get_feature(mapnik::query const& q); mapnik::feature_ptr get_feature_at_point(mapnik::coord2d const& p); - -#ifdef MAPNIK_LOG - void get_overview_meta(GDALRasterBand * band); -#endif - GDALDataset & dataset_; mapnik::context_ptr ctx_; int band_; diff --git a/plugins/input/geojson/geojson_datasource.cpp b/plugins/input/geojson/geojson_datasource.cpp index d63e24316..e9456f8e1 100644 --- a/plugins/input/geojson/geojson_datasource.cpp +++ b/plugins/input/geojson/geojson_datasource.cpp @@ -151,7 +151,7 @@ geojson_datasource::geojson_datasource(parameters const& params) cache_features_ = *params.get("cache_features", true); #if !defined(MAPNIK_MEMORY_MAPPED_FILE) mapnik::util::file file(filename_); - if (!file.open()) + if (!file) { throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); } @@ -192,12 +192,14 @@ geojson_datasource::geojson_datasource(parameters const& params) } namespace { +using box_type = box2d; +using boxes_type = std::vector>>; using base_iterator_type = char const*; const mapnik::transcoder geojson_datasource_static_tr("utf8"); const mapnik::json::feature_collection_grammar geojson_datasource_static_fc_grammar(geojson_datasource_static_tr); const mapnik::json::feature_grammar_callback geojson_datasource_static_feature_callback_grammar(geojson_datasource_static_tr); const mapnik::json::feature_grammar geojson_datasource_static_feature_grammar(geojson_datasource_static_tr); -const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; +const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; } void geojson_datasource::initialise_descriptor(mapnik::feature_ptr const& feature) @@ -230,7 +232,7 @@ void geojson_datasource::initialise_disk_index(std::string const& filename) std::ifstream>::query_first_n(filter, index, positions, num_features_to_query_); mapnik::util::file file(filename_); - if (!file.open()) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); + if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); for (auto const& pos : positions) { @@ -257,7 +259,7 @@ void geojson_datasource::initialise_disk_index(std::string const& filename) template void geojson_datasource::initialise_index(Iterator start, Iterator end) { - mapnik::json::boxes_type boxes; + boxes_type boxes; boost::spirit::standard::space_type space; Iterator itr = start; if (!boost::spirit::qi::phrase_parse(itr, end, (geojson_datasource_static_bbox_grammar)(boost::phoenix::ref(boxes)) , space)) @@ -454,7 +456,7 @@ boost::optional geojson_datasource::get_geometry_ mapnik::util::file file(filename_); - if (!file.open()) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); + if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); for (auto const& pos : positions) { @@ -508,7 +510,7 @@ boost::optional geojson_datasource::get_geometry_ else { mapnik::util::file file(filename_); - if (!file.open()) + if (!file) { throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); } diff --git a/plugins/input/geojson/geojson_index_featureset.cpp b/plugins/input/geojson/geojson_index_featureset.cpp index bdf7f8a9c..4cd139899 100644 --- a/plugins/input/geojson/geojson_index_featureset.cpp +++ b/plugins/input/geojson/geojson_index_featureset.cpp @@ -24,7 +24,6 @@ #include "geojson_index_featureset.hpp" #include #include -#include #include #include #include diff --git a/plugins/input/geojson/geojson_memory_index_featureset.cpp b/plugins/input/geojson/geojson_memory_index_featureset.cpp index 61c5053b6..32b851373 100644 --- a/plugins/input/geojson/geojson_memory_index_featureset.cpp +++ b/plugins/input/geojson/geojson_memory_index_featureset.cpp @@ -23,7 +23,6 @@ // mapnik #include #include -#include #include #include #include diff --git a/plugins/input/ogr/ogr_datasource.cpp b/plugins/input/ogr/ogr_datasource.cpp index 41c0ebbe6..dc0fc9bec 100644 --- a/plugins/input/ogr/ogr_datasource.cpp +++ b/plugins/input/ogr/ogr_datasource.cpp @@ -59,6 +59,16 @@ using mapnik::datasource_exception; using mapnik::filter_in_box; using mapnik::filter_at_point; +static std::once_flag once_flag; + +extern "C" MAPNIK_EXP void on_plugin_load() +{ + // initialize ogr formats + // NOTE: in GDAL >= 2.0 this is the same as GDALAllRegister() + std::call_once(once_flag,[](){ + OGRRegisterAll(); + }); +} ogr_datasource::ogr_datasource(parameters const& params) : datasource(params), @@ -87,10 +97,6 @@ void ogr_datasource::init(mapnik::parameters const& params) mapnik::progress_timer __stats__(std::clog, "ogr_datasource::init"); #endif - // initialize ogr formats - // NOTE: in GDAL >= 2.0 this is the same as GDALAllRegister() - OGRRegisterAll(); - boost::optional file = params.get("file"); boost::optional string = params.get("string"); if (!string) string = params.get("inline"); @@ -371,7 +377,7 @@ void ogr_datasource::init(mapnik::parameters const& params) } mapnik::parameters & extra_params = desc_.get_extra_parameters(); OGRSpatialReference * srs_ref = layer->GetSpatialRef(); - char * srs_output = NULL; + char * srs_output = nullptr; if (srs_ref && srs_ref->exportToProj4( &srs_output ) == OGRERR_NONE ) { extra_params["proj4"] = mapnik::util::trim_copy(srs_output); } diff --git a/plugins/input/pgraster/pgraster_datasource.cpp b/plugins/input/pgraster/pgraster_datasource.cpp index 451c74e52..9390f3ace 100644 --- a/plugins/input/pgraster/pgraster_datasource.cpp +++ b/plugins/input/pgraster/pgraster_datasource.cpp @@ -257,7 +257,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params) if (srid_ == 0) { const char* srid_c = rs->getValue("srid"); - if (srid_c != NULL) + if (srid_c != nullptr) { int result = 0; const char * end = srid_c + std::strlen(srid_c); @@ -274,7 +274,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params) } else { - MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: no response from metadata query " << s.str(); + MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: no response from metadata query " << s.str(); } rs->close(); } @@ -297,7 +297,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params) if (rs->next()) { const char* srid_c = rs->getValue("srid"); - if (srid_c != NULL) + if (srid_c != nullptr) { int result = 0; const char * end = srid_c + std::strlen(srid_c); @@ -878,9 +878,10 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process std::string table_with_bbox; std::string col = geometryColumn_; - if ( use_overviews_ ) { - std::string sch = schema_; - std::string tab = mapnik::sql_utils::unquote_double(raster_table_); + if ( use_overviews_ && !overviews_.empty()) { + std::string sch = overviews_[0].schema; + std::string tab = overviews_[0].table; + col = overviews_[0].column; const double scale = std::min(px_gw, px_gh); std::vector::const_reverse_iterator i; for (i=overviews_.rbegin(); i!=overviews_.rend(); ++i) { diff --git a/plugins/input/pgraster/pgraster_wkb_reader.cpp b/plugins/input/pgraster/pgraster_wkb_reader.cpp index 87f71c093..4a9fd1c8f 100644 --- a/plugins/input/pgraster/pgraster_wkb_reader.cpp +++ b/plugins/input/pgraster/pgraster_wkb_reader.cpp @@ -66,7 +66,7 @@ read_uint16(const uint8_t** from, uint8_t littleEndian) { /* int16_t read_int16(const uint8_t** from, uint8_t littleEndian) { - assert(NULL != from); + assert(nullptr != from); return read_uint16(from, littleEndian); } @@ -183,17 +183,16 @@ mapnik::raster_ptr read_data_band(mapnik::box2d const& bbox, { mapnik::image_gray32f image(width, height); float* data = image.data(); - double val; - val = reader(); // nodata value, need to read anyway + double nodataval = reader(); for (int y=0; y(bbox, image, 1.0); - if ( hasnodata ) raster->set_nodata(val); + if ( hasnodata ) raster->set_nodata(nodataval); return raster; } @@ -270,15 +269,13 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d const& bbox, image.set(0xffffffff); - int val; - int nodataval; uint8_t * data = image.bytes(); int ps = 4; // sizeof(image::pixel_type) int off; - nodataval = reader(); // nodata value, need to read anyway + int nodataval = reader(); for (int y=0; y 255 ) val = 255; @@ -298,7 +295,7 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d const& bbox, } } mapnik::raster_ptr raster = std::make_shared(bbox, image, 1.0); - if ( hasnodata ) raster->set_nodata(val); + if ( hasnodata ) raster->set_nodata(nodataval); return raster; } diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index d95aa3392..909cd58ba 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -88,6 +88,17 @@ postgis_datasource::postgis_datasource(parameters const& params) extent_from_subquery_(*params.get("extent_from_subquery", false)), max_async_connections_(*params_.get("max_async_connection", 1)), asynchronous_request_(false), + twkb_encoding_(false), + twkb_rounding_adjustment_(*params_.get("twkb_rounding_adjustment", 0.0)), + simplify_snap_ratio_(*params_.get("simplify_snap_ratio", 1.0/40.0)), + // 1/20 of pixel seems to be a good compromise to avoid + // drop of collapsed polygons. + // See https://github.com/mapnik/mapnik/issues/1639 + // See http://trac.osgeo.org/postgis/ticket/2093 + simplify_dp_ratio_(*params_.get("simplify_dp_ratio", 1.0/20.0)), + simplify_prefilter_(*params_.get("simplify_prefilter", 0.0)), + simplify_dp_preserve_(false), + simplify_clip_resolution_(*params_.get("simplify_clip_resolution", 0.0)), // TODO - use for known tokens too: "(@\\w+|!\\w+!)" pattern_(boost::regex("(@\\w+)",boost::regex::normal | boost::regbase::icase)), // params below are for testing purposes only and may be removed at any time @@ -130,6 +141,12 @@ postgis_datasource::postgis_datasource(parameters const& params) boost::optional simplify_opt = params.get("simplify_geometries", false); simplify_geometries_ = simplify_opt && *simplify_opt; + boost::optional twkb_opt = params.get("twkb_encoding", false); + twkb_encoding_ = twkb_opt && *twkb_opt; + + boost::optional simplify_preserve_opt = params.get("simplify_dp_preserve", false); + simplify_dp_preserve_ = simplify_preserve_opt && *simplify_preserve_opt; + ConnectionManager::instance().registerPool(creator_, *initial_size, pool_max_size_); CnxPool_ptr pool = ConnectionManager::instance().getPool(creator_.id()); if (pool) @@ -794,25 +811,91 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo const double px_gw = 1.0 / std::get<0>(q.resolution()); const double px_gh = 1.0 / std::get<1>(q.resolution()); + const double px_sz = std::min(px_gw, px_gh); - s << "SELECT ST_AsBinary("; + if (twkb_encoding_) + { + // This will only work against PostGIS 2.2, or a back-patched version + // that has (a) a ST_Simplify with a "preserve collapsed" flag and + // (b) a ST_RemoveRepeatedPoints with a tolerance parameter and + // (c) a ST_AsTWKB implementation - if (simplify_geometries_) { - s << "ST_Simplify("; + // What number of decimals of rounding does the pixel size imply? + const int twkb_rounding = -1 * std::lround(log10(px_sz) + twkb_rounding_adjustment_) + 1; + // And what's that in map units? + const double twkb_tolerance = pow(10.0, -1.0 * twkb_rounding); + + s << "SELECT ST_AsTWKB("; + s << "ST_Simplify("; + s << "ST_RemoveRepeatedPoints("; + + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "ST_ClipByBox2D("; + } + s << "\"" << geometryColumn_ << "\""; + + // ! ST_ClipByBox2D() + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "," << sql_bbox(box) << ")"; + } + + // ! ST_RemoveRepeatedPoints() + s << "," << twkb_tolerance << ")"; + // ! ST_Simplify(), with parameter to keep collapsed geometries + s << "," << twkb_tolerance << ",true)"; + // ! ST_TWKB() + s << "," << twkb_rounding << ") AS geom"; } + else + { + s << "SELECT ST_AsBinary("; + if (simplify_geometries_) + { + s << "ST_Simplify("; + } + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "ST_ClipByBox2D("; + } + if (simplify_geometries_ && simplify_snap_ratio_ > 0.0) + { + s<< "ST_SnapToGrid("; + } - s << "\"" << geometryColumn_ << "\""; + // Geometry column! + s << "\"" << geometryColumn_ << "\""; - if (simplify_geometries_) { - // 1/20 of pixel seems to be a good compromise to avoid - // drop of collapsed polygons. - // See https://github.com/mapnik/mapnik/issues/1639 - const double tolerance = std::min(px_gw, px_gh) / 20.0; - s << ", " << tolerance << ")"; + // ! ST_SnapToGrid() + if (simplify_geometries_ && simplify_snap_ratio_ > 0.0) + { + const double tolerance = px_sz * simplify_snap_ratio_; + s << "," << tolerance << ")"; + } + + // ! ST_ClipByBox2D() + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "," << sql_bbox(box) << ")"; + } + + // ! ST_Simplify() + if (simplify_geometries_) + { + const double tolerance = px_sz * simplify_dp_ratio_; + s << ", " << tolerance; + // Add parameter to ST_Simplify to keep collapsed geometries + if (simplify_dp_preserve_) + { + s << ", true"; + } + s << ")"; + } + + // ! ST_AsBinary() + s << ") AS geom"; } - - s << ") AS geom"; - mapnik::context_ptr ctx = std::make_shared(); std::set const& props = q.property_names(); std::set::const_iterator pos = props.begin(); @@ -854,7 +937,8 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo } std::shared_ptr rs = get_resultset(conn, s.str(), pool, proc_ctx); - return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), key_field_as_attribute_); + return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), + key_field_as_attribute_, twkb_encoding_); } @@ -941,7 +1025,8 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t } std::shared_ptr rs = get_resultset(conn, s.str(), pool); - return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), key_field_as_attribute_); + return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), + key_field_as_attribute_, twkb_encoding_); } } diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index 2f5d24f47..80ba89495 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -119,6 +119,13 @@ private: bool estimate_extent_; int max_async_connections_; bool asynchronous_request_; + bool twkb_encoding_; + mapnik::value_double twkb_rounding_adjustment_; + mapnik::value_double simplify_snap_ratio_; + mapnik::value_double simplify_dp_ratio_; + mapnik::value_double simplify_prefilter_; + bool simplify_dp_preserve_; + mapnik::value_double simplify_clip_resolution_; boost::regex pattern_; int intersect_min_scale_; int intersect_max_scale_; diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 6d417bef1..25e2b6b4b 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -49,14 +49,16 @@ postgis_featureset::postgis_featureset(std::shared_ptr const& rs, context_ptr const& ctx, std::string const& encoding, bool key_field, - bool key_field_as_attribute) + bool key_field_as_attribute, + bool twkb_encoding) : rs_(rs), ctx_(ctx), tr_(new transcoder(encoding)), totalGeomSize_(0), feature_id_(1), key_field_(key_field), - key_field_as_attribute_(key_field_as_attribute) + key_field_as_attribute_(key_field_as_attribute), + twkb_encoding_(twkb_encoding) { } @@ -123,8 +125,14 @@ feature_ptr postgis_featureset::next() int size = rs_->getFieldLength(0); const char *data = rs_->getValue(0); - mapnik::geometry::geometry geometry = geometry_utils::from_wkb(data, size); - feature->set_geometry(std::move(geometry)); + if (twkb_encoding_ ) + { + feature->set_geometry(geometry_utils::from_twkb(data, size)); + } + else + { + feature->set_geometry(geometry_utils::from_wkb(data, size)); + } totalGeomSize_ += size; unsigned num_attrs = ctx_->size() + 1; diff --git a/plugins/input/postgis/postgis_featureset.hpp b/plugins/input/postgis/postgis_featureset.hpp index 4984ec968..9ef8cb392 100644 --- a/plugins/input/postgis/postgis_featureset.hpp +++ b/plugins/input/postgis/postgis_featureset.hpp @@ -44,7 +44,8 @@ public: context_ptr const& ctx, std::string const& encoding, bool key_field, - bool key_field_as_attribute); + bool key_field_as_attribute, + bool twkb_encoding); feature_ptr next(); ~postgis_featureset(); @@ -56,6 +57,7 @@ private: mapnik::value_integer feature_id_; bool key_field_; bool key_field_as_attribute_; + bool twkb_encoding_; }; #endif // POSTGIS_FEATURESET_HPP diff --git a/plugins/input/topojson/topojson_datasource.cpp b/plugins/input/topojson/topojson_datasource.cpp index f9ba8ecc9..502868562 100644 --- a/plugins/input/topojson/topojson_datasource.cpp +++ b/plugins/input/topojson/topojson_datasource.cpp @@ -66,18 +66,9 @@ struct attr_value_converter { return mapnik::Boolean; } - - mapnik::eAttributeType operator() (std::string const& /*val*/) const - { - return mapnik::String; - } - - mapnik::eAttributeType operator() (mapnik::value_unicode_string const& /*val*/) const - { - return mapnik::String; - } - - mapnik::eAttributeType operator() (mapnik::value_null const& /*val*/) const + // string, object, array + template + mapnik::eAttributeType operator() (T const& /*val*/) const { return mapnik::String; } @@ -109,6 +100,11 @@ struct geometry_type_visitor { return static_cast(mapnik::datasource_geometry_t::Polygon); } + template + int operator() (T const& ) const + { + return 0; + } }; struct collect_attributes_visitor @@ -117,6 +113,9 @@ struct collect_attributes_visitor collect_attributes_visitor(mapnik::layer_descriptor & desc): desc_(desc) {} + // no-op + void operator() (mapnik::topojson::empty) {} + // template void operator() (GeomType const& g) { @@ -166,7 +165,7 @@ topojson_datasource::topojson_datasource(parameters const& params) else { mapnik::util::file file(filename_); - if (!file.open()) + if (!file) { throw mapnik::datasource_exception("TopoJSON Plugin: could not open: '" + filename_ + "'"); } diff --git a/plugins/input/topojson/topojson_featureset.cpp b/plugins/input/topojson/topojson_featureset.cpp index 9e7c23ee4..36dbdf9db 100644 --- a/plugins/input/topojson/topojson_featureset.cpp +++ b/plugins/input/topojson/topojson_featureset.cpp @@ -21,13 +21,8 @@ *****************************************************************************/ // mapnik -#include -#include #include -#include -#include -#include - +#include // stl #include #include @@ -40,334 +35,6 @@ #include "topojson_featureset.hpp" -namespace mapnik { namespace topojson { - -struct attribute_value_visitor - -{ -public: - attribute_value_visitor(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value operator()(std::string const& val) const - { - return mapnik::value(tr_.transcode(val.c_str())); - } - - template - mapnik::value operator()(T const& val) const - { - return mapnik::value(val); - } - - mapnik::transcoder const& tr_; -}; - -template -void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::transcoder const& tr) -{ - if ( geom.props) - { - for (auto const& p : *geom.props) - { - feature.put_new(std::get<0>(p), mapnik::util::apply_visitor(attribute_value_visitor(tr),std::get<1>(p))); - } - } -} - -template -struct feature_generator -{ - feature_generator(Context & ctx, mapnik::transcoder const& tr, topology const& topo, std::size_t feature_id) - : ctx_(ctx), - tr_(tr), - topo_(topo), - num_arcs_(topo.arcs.size()), - feature_id_(feature_id) {} - - feature_ptr operator() (point const& pt) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - double x = pt.coord.x; - double y = pt.coord.y; - if (topo_.tr) - { - x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - mapnik::geometry::point point(x, y); - feature->set_geometry(std::move(point)); - assign_properties(*feature, pt, tr_); - return feature; - } - - feature_ptr operator() (multi_point const& multi_pt) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - mapnik::geometry::multi_point multi_point; - multi_point.reserve(multi_pt.points.size()); - for (auto const& pt : multi_pt.points) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - multi_point.add_coord(x, y); - } - feature->set_geometry(std::move(multi_point)); - assign_properties(*feature, multi_pt, tr_); - return feature; - } - - feature_ptr operator() (linestring const& line) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - index_type index = line.ring; - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - auto const& arcs = topo_.arcs[arc_index]; - double px = 0, py = 0; - mapnik::geometry::line_string line_string; - line_string.reserve(arcs.coordinates.size()); - - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - line_string.add_coord(x,y); - } - feature->set_geometry(std::move(line_string)); - assign_properties(*feature, line, tr_); - } - } - return feature; - } - - feature_ptr operator() (multi_linestring const& multi_line) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - mapnik::geometry::multi_line_string multi_line_string; - bool hit = false; - multi_line_string.reserve(multi_line.rings.size()); - for (auto const& index : multi_line.rings) - { - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - hit = true; - double px = 0, py = 0; - mapnik::geometry::line_string line_string; - auto const& arcs = topo_.arcs[arc_index]; - line_string.reserve(arcs.coordinates.size()); - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - line_string.add_coord(x, y); - } - multi_line_string.push_back(std::move(line_string)); - } - } - if (hit) - { - feature->set_geometry(std::move(multi_line_string)); - assign_properties(*feature, multi_line, tr_); - } - } - return feature; - } - - feature_ptr operator() (polygon const& poly) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - std::vector processed_coords; - mapnik::geometry::polygon polygon; - if (poly.rings.size() > 1) polygon.interior_rings.reserve(poly.rings.size() - 1); - bool first = true; - bool hit = false; - for (auto const& ring : poly.rings) - { - mapnik::geometry::linear_ring linear_ring; - for (auto const& index : ring) - { - double px = 0, py = 0; - bool reverse = index < 0; - index_type arc_index = reverse ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - hit = true; - auto const& arcs = topo_.arcs[arc_index]; - auto const& coords = arcs.coordinates; - processed_coords.clear(); - processed_coords.reserve(coords.size()); - for (auto const& pt : coords ) - { - double x = pt.x; - double y = pt.y; - - if (topo_.tr) - { - transform const& tr = *topo_.tr; - x = (px += x) * tr.scale_x + tr.translate_x; - y = (py += y) * tr.scale_y + tr.translate_y; - } - processed_coords.emplace_back(coordinate{x,y}); - } - - if (reverse) - { - for (auto const& c : processed_coords | boost::adaptors::reversed) - { - linear_ring.emplace_back(c.x, c.y); - } - } - else - { - for (auto const& c : processed_coords) - { - linear_ring.emplace_back(c.x, c.y); - } - } - } - } - if (first) - { - first = false; - polygon.set_exterior_ring(std::move(linear_ring)); - } - else - { - polygon.add_hole(std::move(linear_ring)); - } - } - if (hit) - { - mapnik::geometry::correct(polygon); - feature->set_geometry(std::move(polygon)); - assign_properties(*feature, poly, tr_); - } - } - return feature; - } - - feature_ptr operator() (multi_polygon const& multi_poly) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - std::vector processed_coords; - mapnik::geometry::multi_polygon multi_polygon; - multi_polygon.reserve(multi_poly.polygons.size()); - bool hit = false; - for (auto const& poly : multi_poly.polygons) - { - bool first = true; - mapnik::geometry::polygon polygon; - if (poly.size() > 1) polygon.interior_rings.reserve(poly.size() - 1); - - for (auto const& ring : poly) - { - mapnik::geometry::linear_ring linear_ring; - for (auto const& index : ring) - { - double px = 0, py = 0; - bool reverse = index < 0; - index_type arc_index = reverse ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - hit = true; - auto const& arcs = topo_.arcs[arc_index]; - auto const& coords = arcs.coordinates; - processed_coords.clear(); - processed_coords.reserve(coords.size()); - for (auto const& pt : coords ) - { - double x = pt.x; - double y = pt.y; - - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - processed_coords.emplace_back(coordinate{x,y}); - } - - using namespace boost::adaptors; - - if (reverse) - { - for (auto const& c : (processed_coords | reversed)) - { - linear_ring.add_coord(c.x, c.y); - } - } - else - { - for (auto const& c : processed_coords) - { - linear_ring.add_coord(c.x, c.y); - } - } - } - } - if (first) - { - first = false; - polygon.set_exterior_ring(std::move(linear_ring)); - } - else - { - polygon.add_hole(std::move(linear_ring)); - } - } - multi_polygon.push_back(std::move(polygon)); - } - if (hit) - { - mapnik::geometry::correct(multi_polygon); - feature->set_geometry(std::move(multi_polygon)); - assign_properties(*feature, multi_poly, tr_); - } - } - return feature; - } - - template - feature_ptr operator() (T const& ) const - { - return feature_ptr(); - } - - Context & ctx_; - mapnik::transcoder const& tr_; - topology const& topo_; - std::size_t num_arcs_; - std::size_t feature_id_; -}; - -}} - topojson_featureset::topojson_featureset(mapnik::topojson::topology const& topo, mapnik::transcoder const& tr, array_type && index_array) diff --git a/scripts/build-appveyor.bat b/scripts/build-appveyor.bat index 3fe8cd064..84088d4cb 100644 --- a/scripts/build-appveyor.bat +++ b/scripts/build-appveyor.bat @@ -30,8 +30,8 @@ ECHO ======== SET PATH=C:\Python27;%PATH% SET PATH=C:\Program Files\7-Zip;%PATH% -::update submodule variant -git submodule update --init deps/mapbox/variant +::update submodules (variant + test data) +git submodule update --init IF %ERRORLEVEL% NEQ 0 GOTO ERROR diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh index fc5cca4ad..40d18374e 100644 --- a/scripts/travis-common.sh +++ b/scripts/travis-common.sh @@ -81,18 +81,10 @@ config_override () { configure () { if enabled ${COVERAGE}; then - ./configure "$@" PGSQL2SQLITE=False SVG2PNG=False SVG_RENDERER=False \ - COVERAGE=True DEBUG=True - elif enabled ${MASON_PUBLISH}; then - export MASON_NAME=mapnik - export MASON_VERSION=latest - export MASON_LIB_FILE=lib/libmapnik-wkt.a - source ./.mason/mason.sh - ./configure "$@" PREFIX=${MASON_PREFIX} \ - PATH_REPLACE='' MAPNIK_BUNDLED_SHARE_DIRECTORY=True \ - RUNTIME_LINK='static' + ./configure "$@" PREFIX=${PREFIX} PGSQL2SQLITE=False SVG2PNG=False SVG_RENDERER=False \ + COVERAGE=True DEBUG=True WARNING_CXXFLAGS="-Wno-unknown-warning-option" else - ./configure "$@" + ./configure "$@" PREFIX=${PREFIX} WARNING_CXXFLAGS="-Wno-unknown-warning-option" fi # print final config values, sorted and indented sort -sk1,1 ./config.py | sed -e 's/^/ /' @@ -100,11 +92,28 @@ configure () { coverage () { ./mason_packages/.link/bin/cpp-coveralls \ - --gcov /usr/bin/llvm-cov-${LLVM_VERSION} \ - --build-root . --gcov-options '\-lp' \ + --gcov ${LLVM_COV} \ --exclude mason_packages \ --exclude .sconf_temp --exclude benchmark --exclude deps \ --exclude scons --exclude test --exclude demo --exclude docs \ --exclude fonts \ > /dev/null } + +trigger_downstream() { + body="{ + \"request\": { + \"message\": \"Triggered build: Mapnik core commit ${TRAVIS_COMMIT}\", + \"branch\":\"master\" + } + } + " + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Travis-API-Version: 3" \ + -H "Authorization: token ${TRAVIS_TRIGGER_TOKEN}" \ + -d "$body" \ + https://api.travis-ci.org/repo/mapnik%2Fpython-mapnik/requests +} diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index 9fbcdca4b..f144ceaad 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -43,7 +43,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_color_rgba.h" @@ -53,9 +55,12 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_span_image_filter_rgba.h" +#pragma GCC diagnostic pop -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index 9357b0ced..6bcee3457 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -38,7 +38,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_color_rgba.h" @@ -47,6 +48,7 @@ #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" #include "agg_conv_stroke.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_debug_symbolizer.cpp b/src/agg/process_debug_symbolizer.cpp index 2016c456d..3c3f898f8 100644 --- a/src/agg/process_debug_symbolizer.cpp +++ b/src/agg/process_debug_symbolizer.cpp @@ -33,7 +33,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_color_rgba.h" @@ -41,6 +42,7 @@ #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" #include "agg_conv_stroke.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_dot_symbolizer.cpp b/src/agg/process_dot_symbolizer.cpp index cc375862d..cfb58c6e9 100644 --- a/src/agg/process_dot_symbolizer.cpp +++ b/src/agg/process_dot_symbolizer.cpp @@ -33,7 +33,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_ellipse.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -41,6 +42,7 @@ #include "agg_renderer_scanline.h" #include "agg_color_rgba.h" #include "agg_renderer_base.h" +#pragma GCC diagnostic pop namespace mapnik { namespace detail { diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index 010d3f18a..6ba5605dc 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -35,8 +35,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index f5045c5a3..dbbb7f26d 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -37,7 +37,10 @@ #include #include #include -// agg + + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_pixfmt_rgba.h" #include "agg_color_rgba.h" @@ -50,6 +53,7 @@ #include "agg_span_allocator.h" #include "agg_span_pattern_rgba.h" #include "agg_renderer_outline_image.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -88,7 +92,7 @@ struct agg_renderer_process_visitor_l value_double opacity = get(sym_, feature_, common_.vars_); agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*ras_ptr_, marker, image_tr, 1.0, image); diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index b3a01c7e8..9bace2539 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -32,7 +32,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -45,6 +47,7 @@ #include "agg_conv_dash.h" #include "agg_renderer_outline_aa.h" #include "agg_rasterizer_outline_aa.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index b229f01af..3fc122dcb 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -33,7 +33,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_renderer_base.h" #include "agg_renderer_scanline.h" @@ -44,6 +45,7 @@ #include "agg_scanline_u.h" #include "agg_path_storage.h" #include "agg_conv_transform.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_point_symbolizer.cpp b/src/agg/process_point_symbolizer.cpp index 1da740fe6..bb54db51c 100644 --- a/src/agg/process_point_symbolizer.cpp +++ b/src/agg/process_point_symbolizer.cpp @@ -34,8 +34,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index 8e340a9a8..f2a0159d1 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -39,7 +39,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -52,6 +54,7 @@ #include "agg_span_pattern_rgba.h" #include "agg_image_accessors.h" #include "agg_conv_clip_polygon.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -81,7 +84,7 @@ struct agg_renderer_process_visitor_p { agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*ras_ptr_, marker, image_tr, 1.0, image); diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 9af6d4ac5..bd2d2bc15 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -32,7 +32,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -40,6 +42,7 @@ #include "agg_renderer_scanline.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index 0105e9bc3..746a5cc2b 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -38,9 +38,11 @@ // stl #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index b3794bcf5..685b66c95 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -63,7 +63,7 @@ void agg_renderer::process(text_symbolizer const& sym, if (halo_transform) { agg::trans_affine halo_affine_transform; - evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform); + evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform, common_.scale_factor_); ren.set_halo_transform(halo_affine_transform); } diff --git a/src/box2d.cpp b/src/box2d.cpp index ea7874269..407c054ba 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * Copyright (C) 2016 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,472 +21,12 @@ *****************************************************************************/ // mapnik -#include -#include +#include -// stl -#include -#include -#include - -#include - -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - -// agg -#include "agg_trans_affine.h" - -BOOST_FUSION_ADAPT_TPL_ADT( - (T), - (mapnik::box2d)(T), - (T, T, obj.minx(), obj.set_minx(mapnik::safe_cast(val))) - (T, T, obj.miny(), obj.set_miny(mapnik::safe_cast(val))) - (T, T, obj.maxx(), obj.set_maxx(mapnik::safe_cast(val))) - (T, T, obj.maxy(), obj.set_maxy(mapnik::safe_cast(val)))) - -namespace mapnik -{ -template -box2d::box2d() - :minx_( std::numeric_limits::max()), - miny_( std::numeric_limits::max()), - maxx_(-std::numeric_limits::max()), - maxy_(-std::numeric_limits::max()) {} - -template -box2d::box2d(T minx,T miny,T maxx,T maxy) -{ - init(minx,miny,maxx,maxy); -} - -template -box2d::box2d(coord const& c0, coord const& c1) -{ - init(c0.x,c0.y,c1.x,c1.y); -} - -template -box2d::box2d(box2d_type const& rhs) - : minx_(rhs.minx_), - miny_(rhs.miny_), - maxx_(rhs.maxx_), - maxy_(rhs.maxy_) {} - -template -box2d::box2d(box2d_type && rhs) - : minx_(std::move(rhs.minx_)), - miny_(std::move(rhs.miny_)), - maxx_(std::move(rhs.maxx_)), - maxy_(std::move(rhs.maxy_)) {} - -template -box2d& box2d::operator=(box2d_type other) -{ - swap(*this, other); - return *this; -} - -template -box2d::box2d(box2d_type const& rhs, agg::trans_affine const& tr) -{ - double x0 = rhs.minx_, y0 = rhs.miny_; - double x1 = rhs.maxx_, y1 = rhs.miny_; - double x2 = rhs.maxx_, y2 = rhs.maxy_; - double x3 = rhs.minx_, y3 = rhs.maxy_; - tr.transform(&x0, &y0); - tr.transform(&x1, &y1); - tr.transform(&x2, &y2); - tr.transform(&x3, &y3); - init(static_cast(x0), static_cast(y0), - static_cast(x2), static_cast(y2)); - expand_to_include(static_cast(x1), static_cast(y1)); - expand_to_include(static_cast(x3), static_cast(y3)); -} - -template -bool box2d::operator==(box2d const& other) const -{ - return minx_==other.minx_ && - miny_==other.miny_ && - maxx_==other.maxx_ && - maxy_==other.maxy_; -} - -template -T box2d::minx() const -{ - return minx_; -} - -template -T box2d::maxx() const -{ - return maxx_; -} - -template -T box2d::miny() const -{ - return miny_; -} - -template -T box2d::maxy() const -{ - return maxy_; -} - -template -void box2d::set_minx(T v) -{ - minx_ = v; -} - -template -void box2d::set_miny(T v) -{ - miny_ = v; -} - -template -void box2d::set_maxx(T v) -{ - maxx_ = v; -} - -template -void box2d::set_maxy(T v) -{ - maxy_ = v; -} - -template -T box2d::width() const -{ - return maxx_-minx_; -} - -template -T box2d::height() const -{ - return maxy_-miny_; -} - -template -void box2d::width(T w) -{ - T cx=center().x; - minx_=static_cast(cx-w*0.5); - maxx_=static_cast(cx+w*0.5); -} - -template -void box2d::height(T h) -{ - T cy=center().y; - miny_=static_cast(cy-h*0.5); - maxy_=static_cast(cy+h*0.5); -} - -template -coord box2d::center() const -{ - return coord(static_cast(0.5*(minx_+maxx_)), - static_cast(0.5*(miny_+maxy_))); -} - -template -void box2d::expand_to_include(coord const& c) -{ - expand_to_include(c.x,c.y); -} - -template -void box2d::expand_to_include(T x,T y) -{ - if (xmaxx_) maxx_=x; - if (ymaxy_) maxy_=y; -} - -template -void box2d::expand_to_include(box2d const& other) -{ - if (other.minx_maxx_) maxx_=other.maxx_; - if (other.miny_maxy_) maxy_=other.maxy_; -} - -template -bool box2d::contains(coord const& c) const -{ - return contains(c.x,c.y); -} - -template -bool box2d::contains(T x,T y) const -{ - return x>=minx_ && x<=maxx_ && y>=miny_ && y<=maxy_; -} - -template -bool box2d::contains(box2d const& other) const -{ - return other.minx_>=minx_ && - other.maxx_<=maxx_ && - other.miny_>=miny_ && - other.maxy_<=maxy_; -} - -template -bool box2d::intersects(coord const& c) const -{ - return intersects(c.x,c.y); -} - -template -bool box2d::intersects(T x,T y) const -{ - return !(x>maxx_ || xmaxy_ || y -bool box2d::intersects(box2d const& other) const -{ - return !(other.minx_>maxx_ || other.maxx_maxy_ || other.maxy_ -box2d box2d::intersect(box2d_type const& other) const -{ - if (intersects(other)) - { - T x0=std::max(minx_,other.minx_); - T y0=std::max(miny_,other.miny_); - T x1=std::min(maxx_,other.maxx_); - T y1=std::min(maxy_,other.maxy_); - return box2d(x0,y0,x1,y1); - } - else - { - return box2d(); - } -} - -template -void box2d::re_center(T cx,T cy) -{ - T dx=cx-center().x; - T dy=cy-center().y; - minx_+=dx; - miny_+=dy; - maxx_+=dx; - maxy_+=dy; -} - -template -void box2d::re_center(coord const& c) -{ - re_center(c.x,c.y); -} - -template -void box2d::init(T x0,T y0,T x1,T y1) -{ - if (x0 -void box2d::clip(box2d_type const& other) -{ - minx_ = std::max(minx_,other.minx()); - miny_ = std::max(miny_,other.miny()); - maxx_ = std::min(maxx_,other.maxx()); - maxy_ = std::min(maxy_,other.maxy()); -} - -template -void box2d::pad(T padding) -{ - minx_ -= padding; - miny_ -= padding; - maxx_ += padding; - maxy_ += padding; -} - - -template -bool box2d::from_string(std::string const& str) -{ - boost::spirit::qi::lit_type lit; - boost::spirit::qi::double_type double_; - boost::spirit::ascii::space_type space; - bool r = boost::spirit::qi::phrase_parse(str.begin(), - str.end(), - double_ >> -lit(',') >> double_ >> -lit(',') - >> double_ >> -lit(',') >> double_, - space, - *this); - return r; -} - -template -bool box2d::valid() const -{ - return (minx_ <= maxx_ && miny_ <= maxy_) ; -} - -template -void box2d::move(T x, T y) -{ - minx_ += x; - maxx_ += x; - miny_ += y; - maxy_ += y; -} - -template -std::string box2d::to_string() const -{ - std::ostringstream s; - if (valid()) - { - s << "box2d(" << std::fixed << std::setprecision(16) - << minx_ << ',' << miny_ << ',' - << maxx_ << ',' << maxy_ << ')'; - } - else - { - s << "box2d(INVALID)"; - } - return s.str(); -} - - -template -box2d& box2d::operator+=(box2d const& other) -{ - expand_to_include(other); - return *this; -} - -template -box2d box2d::operator+ (T other) const -{ - return box2d(minx_ - other, miny_ - other, maxx_ + other, maxy_ + other); -} - -template -box2d& box2d::operator+= (T other) -{ - minx_ -= other; - miny_ -= other; - maxx_ += other; - maxy_ += other; - return *this; -} - - -template -box2d& box2d::operator*=(T t) -{ - coord c = center(); - T sx = static_cast(0.5 * width() * t); - T sy = static_cast(0.5 * height() * t); - minx_ = c.x - sx; - maxx_ = c.x + sx; - miny_ = c.y - sy; - maxy_ = c.y + sy; - return *this; -} - -template -box2d& box2d::operator/=(T t) -{ - coord c = center(); - T sx = static_cast(0.5 * width() / t); - T sy = static_cast(0.5 * height() / t); - minx_ = c.x - sx; - maxx_ = c.x + sx; - miny_ = c.y - sy; - maxy_ = c.y + sy; - return *this; -} - -template -T box2d::operator[] (int index) const -{ - switch(index) - { - case 0: - return minx_; - case 1: - return miny_; - case 2: - return maxx_; - case 3: - return maxy_; - case -4: - return minx_; - case -3: - return miny_; - case -2: - return maxx_; - case -1: - return maxy_; - default: - throw std::out_of_range("index out of range, max value is 3, min value is -4 "); - } -} - -template -box2d box2d::operator*(agg::trans_affine const& tr) const -{ - return box2d(*this, tr); -} - -template -box2d& box2d::operator*=(agg::trans_affine const& tr) -{ - double x0 = minx_, y0 = miny_; - double x1 = maxx_, y1 = miny_; - double x2 = maxx_, y2 = maxy_; - double x3 = minx_, y3 = maxy_; - tr.transform(&x0, &y0); - tr.transform(&x1, &y1); - tr.transform(&x2, &y2); - tr.transform(&x3, &y3); - init(static_cast(x0), static_cast(y0), - static_cast(x2), static_cast(y2)); - expand_to_include(static_cast(x1), static_cast(y1)); - expand_to_include(static_cast(x3), static_cast(y3)); - return *this; -} +namespace mapnik { template class box2d; +template class box2d; template class box2d; } diff --git a/src/build.py b/src/build.py index b99248ba7..bfaaf4b93 100644 --- a/src/build.py +++ b/src/build.py @@ -206,6 +206,7 @@ source = Split( rule.cpp save_map.cpp wkb.cpp + twkb.cpp projection.cpp proj_transform.cpp scale_denominator.cpp diff --git a/src/cairo/process_line_pattern_symbolizer.cpp b/src/cairo/process_line_pattern_symbolizer.cpp index c6fc14e17..e4ae6f609 100644 --- a/src/cairo/process_line_pattern_symbolizer.cpp +++ b/src/cairo/process_line_pattern_symbolizer.cpp @@ -64,7 +64,7 @@ struct cairo_renderer_process_visitor_l mapnik::rasterizer ras; agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(ras, marker, image_tr, 1.0, image); diff --git a/src/cairo/process_polygon_pattern_symbolizer.cpp b/src/cairo/process_polygon_pattern_symbolizer.cpp index aa7b0ca12..4e21234b8 100644 --- a/src/cairo/process_polygon_pattern_symbolizer.cpp +++ b/src/cairo/process_polygon_pattern_symbolizer.cpp @@ -96,7 +96,7 @@ void cairo_renderer::process(polygon_pattern_symbolizer const& sym, value_double opacity = get(sym, feature, common_.vars_); agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform, common_.scale_factor_); cairo_save_restore guard(context_); context_.set_operator(comp_op); @@ -124,8 +124,7 @@ void cairo_renderer::process(polygon_pattern_symbolizer const& sym, agg::trans_affine tr; auto geom_transform = get_optional(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - using vertex_converter_type = vertex_converter< - clip_poly_tag, + using vertex_converter_type = vertex_converter type = params.get("type"); - if ( ! type) + if (!type) { throw config_error(std::string("Could not create datasource. Required ") + "parameter 'type' is missing"); diff --git a/src/debug.cpp b/src/debug.cpp index 169272f09..d1ae15fa4 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include // stl #include @@ -74,14 +75,7 @@ logger::severity_type logger::severity_level_ { logger::severity_map logger::object_severity_level_ = logger::severity_map(); - -// format - -#define __xstr__(s) __str__(s) -#define __str__(s) #s -std::string logger::format_ = __xstr__(MAPNIK_LOG_FORMAT); -#undef __xstr__ -#undef __str__ +std::string logger::format_ = MAPNIK_STRINGIFY(MAPNIK_LOG_FORMAT); std::string logger::str() { diff --git a/src/feature_kv_iterator.cpp b/src/feature_kv_iterator.cpp index 8fdba826b..4ae384254 100644 --- a/src/feature_kv_iterator.cpp +++ b/src/feature_kv_iterator.cpp @@ -22,7 +22,11 @@ #include #include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index cd2fcd813..293b18127 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -48,6 +48,11 @@ extern "C" #include FT_STROKER_H #include FT_MODULE_H } +#pragma GCC diagnostic pop + +// stl +#include +#include namespace mapnik @@ -76,7 +81,7 @@ unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char * if (count <= 0) return 0; FILE * file = static_cast(stream->descriptor.pointer); std::fseek (file , offset , SEEK_SET); - return std::fread ((char*)buffer, 1, count, file); + return std::fread(reinterpret_cast(buffer), 1, count, file); } bool freetype_engine::register_font(std::string const& file_name) @@ -94,7 +99,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, { MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name; mapnik::util::file file(file_name); - if (!file.open()) return false; + if (!file) return false; FT_Face face = 0; FT_Open_Args args; @@ -106,7 +111,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, streamRec.size = file.size(); streamRec.descriptor.pointer = file.get(); streamRec.read = ft_read_cb; - streamRec.close = NULL; + streamRec.close = nullptr; args.flags = FT_OPEN_STREAM; args.stream = &streamRec; int num_faces = 0; @@ -259,7 +264,7 @@ bool freetype_engine::can_open(std::string const& face_name, } if (!found_font_file) return false; mapnik::util::file file(itr->second.second); - if (!file.open()) return false; + if (!file) return false; FT_Face face = 0; FT_Open_Args args; FT_StreamRec streamRec; @@ -270,7 +275,7 @@ bool freetype_engine::can_open(std::string const& face_name, streamRec.size = file.size(); streamRec.descriptor.pointer = file.get(); streamRec.read = ft_read_cb; - streamRec.close = NULL; + streamRec.close = nullptr; args.flags = FT_OPEN_STREAM; args.stream = &streamRec; // -1 is used to quickly check if the font file appears valid without iterating each face @@ -333,7 +338,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name, if (found_font_file) { mapnik::util::file file(itr->second.second); - if (file.open()) + if (file) { #ifdef MAPNIK_THREADSAFE std::lock_guard lock(mutex_); diff --git a/src/fs.cpp b/src/fs.cpp index 9c87d97be..640345396 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -24,9 +24,12 @@ #include #include -// boost + +#pragma GCC diagnostic push +#include #include // for absolute, exists, etc #include // for path, operator/ +#pragma GCC diagnostic pop // stl #include diff --git a/src/geometry_envelope.cpp b/src/geometry_envelope.cpp index b8781d940..c253ca6cf 100644 --- a/src/geometry_envelope.cpp +++ b/src/geometry_envelope.cpp @@ -26,26 +26,17 @@ namespace mapnik { namespace geometry { template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); -template MAPNIK_DECL mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry_empty const& geom); +// single template MAPNIK_DECL mapnik::box2d envelope(point const& geom); template MAPNIK_DECL mapnik::box2d envelope(line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); template MAPNIK_DECL mapnik::box2d envelope(polygon const& geom); +template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); +// multi template MAPNIK_DECL mapnik::box2d envelope(multi_point const& geom); template MAPNIK_DECL mapnik::box2d envelope(multi_line_string const& geom); template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); +// collection template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); -template MAPNIK_DECL mapnik::box2d envelope(point const& geom); -template MAPNIK_DECL mapnik::box2d envelope(line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); -template MAPNIK_DECL mapnik::box2d envelope(polygon const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_point const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); - } // end ns geometry } // end ns mapnik diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index 33d10ee6a..fd970f580 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -47,11 +47,15 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index f878e0f68..f3fb0f76d 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -40,11 +40,13 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_conv_stroke.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_group_symbolizer.cpp b/src/grid/process_group_symbolizer.cpp index a93ea9d59..ba7f48ece 100644 --- a/src/grid/process_group_symbolizer.cpp +++ b/src/grid/process_group_symbolizer.cpp @@ -37,8 +37,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_line_pattern_symbolizer.cpp b/src/grid/process_line_pattern_symbolizer.cpp index dc370f73c..af54ac5b6 100644 --- a/src/grid/process_line_pattern_symbolizer.cpp +++ b/src/grid/process_line_pattern_symbolizer.cpp @@ -35,12 +35,15 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_conv_stroke.h" #include "agg_conv_dash.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_line_symbolizer.cpp b/src/grid/process_line_symbolizer.cpp index c569f6b2c..b65dd8502 100644 --- a/src/grid/process_line_symbolizer.cpp +++ b/src/grid/process_line_symbolizer.cpp @@ -32,12 +32,15 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_conv_stroke.h" #include "agg_conv_dash.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 2fa71c880..380923211 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -55,10 +55,12 @@ porting notes --> #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_rasterizer_scanline_aa.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_point_symbolizer.cpp b/src/grid/process_point_symbolizer.cpp index 130fc1fc2..60328009d 100644 --- a/src/grid/process_point_symbolizer.cpp +++ b/src/grid/process_point_symbolizer.cpp @@ -36,8 +36,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_polygon_pattern_symbolizer.cpp b/src/grid/process_polygon_pattern_symbolizer.cpp index 06408a801..03e27c65d 100644 --- a/src/grid/process_polygon_pattern_symbolizer.cpp +++ b/src/grid/process_polygon_pattern_symbolizer.cpp @@ -36,10 +36,12 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" +#pragma GCC diagnostic pop // stl #include @@ -76,7 +78,12 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); } - using vertex_converter_type = vertex_converter; + using vertex_converter_type = vertex_converter; + vertex_converter_type converter(common_.query_extent_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set(); diff --git a/src/grid/process_polygon_symbolizer.cpp b/src/grid/process_polygon_symbolizer.cpp index 3e1f08932..ab8526252 100644 --- a/src/grid/process_polygon_symbolizer.cpp +++ b/src/grid/process_polygon_symbolizer.cpp @@ -34,10 +34,12 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_shield_symbolizer.cpp b/src/grid/process_shield_symbolizer.cpp index 50bc8209f..0463bee8e 100644 --- a/src/grid/process_shield_symbolizer.cpp +++ b/src/grid/process_shield_symbolizer.cpp @@ -33,8 +33,11 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#include "agg_gamma_functions.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 7fe0ff377..d1b6a17b4 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -60,7 +60,7 @@ void grid_renderer::process(text_symbolizer const& sym, if (halo_transform) { agg::trans_affine halo_affine_transform; - evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform); + evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform, common_.scale_factor_); ren.set_halo_transform(halo_affine_transform); } diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index 925f56e64..a8f9bba3c 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -33,7 +33,8 @@ #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" @@ -41,7 +42,7 @@ #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" #include "agg_color_rgba.h" - +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/image_scaling.cpp b/src/image_scaling.cpp index f0cc450e6..413948c64 100644 --- a/src/image_scaling.cpp +++ b/src/image_scaling.cpp @@ -25,14 +25,14 @@ #include #include -// boost #pragma GCC diagnostic push #include #include #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_image_accessors.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" @@ -47,6 +47,7 @@ #include "agg_span_interpolator_linear.h" #include "agg_trans_affine.h" #include "agg_image_filters.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/image_util.cpp b/src/image_util.cpp index 43c599166..1fec8b130 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -38,13 +38,14 @@ #include #ifdef SSE_MATH #include - #endif -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_color_rgba.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/jpeg_reader.cpp b/src/jpeg_reader.cpp index 84c805ee8..6b6e1b127 100644 --- a/src/jpeg_reader.cpp +++ b/src/jpeg_reader.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include #include // jpeg @@ -30,16 +31,10 @@ extern "C" #include } -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - // std #include #include +#include namespace mapnik { @@ -49,7 +44,7 @@ class jpeg_reader : public image_reader { public: using source_type = T; - using input_stream = boost::iostreams::stream; + using input_stream = std::iostream; const static unsigned BUF_SIZE = 4096; private: struct jpeg_stream_wrapper @@ -77,7 +72,7 @@ private: unsigned width_; unsigned height_; public: - explicit jpeg_reader(std::string const& file_name); + explicit jpeg_reader(std::string const& filename); explicit jpeg_reader(char const* data, size_t size); ~jpeg_reader(); unsigned width() const final; @@ -99,14 +94,14 @@ private: namespace { -image_reader* create_jpeg_reader(std::string const& file) +image_reader* create_jpeg_reader(std::string const& filename) { - return new jpeg_reader(file); + return new jpeg_reader(filename); } image_reader* create_jpeg_reader2(char const* data, size_t size) { - return new jpeg_reader(data, size); + return new jpeg_reader(data, size); } const bool registered = register_image_reader("jpeg",create_jpeg_reader); @@ -115,20 +110,21 @@ const bool registered2 = register_image_reader("jpeg",create_jpeg_reader2); // ctors template -jpeg_reader::jpeg_reader(std::string const& file_name) - : source_(file_name,std::ios_base::in | std::ios_base::binary), - stream_(source_), +jpeg_reader::jpeg_reader(std::string const& filename) + : source_(), + stream_(&source_), width_(0), height_(0) { - if (!stream_) throw image_reader_exception("cannot open image file "+ file_name); + source_.open(filename, std::ios_base::in | std::ios_base::binary); + if (!stream_) throw image_reader_exception("cannot open image file "+ filename); init(); } template jpeg_reader::jpeg_reader(char const* data, size_t size) : source_(data, size), - stream_(source_), + stream_(&source_), width_(0), height_(0) { diff --git a/src/load_map.cpp b/src/load_map.cpp index 6e15ba2fb..f21708274 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -59,18 +59,22 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include #include #include #include #include +#pragma GCC diagnostic pop // stl #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop using boost::tokenizer; diff --git a/src/map.cpp b/src/map.cpp index 149d7b434..9feb21688 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -307,7 +307,7 @@ bool Map::load_fonts() continue; } mapnik::util::file file(file_path); - if (file.open()) + if (file) { auto item = font_memory_cache_.emplace(file_path, std::make_pair(file.data(),file.size())); if (item.second) result = true; diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 9e4062226..6fef8613e 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -39,9 +39,11 @@ #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/marker_helpers.cpp b/src/marker_helpers.cpp index 9baa546b8..eb0202169 100644 --- a/src/marker_helpers.cpp +++ b/src/marker_helpers.cpp @@ -24,8 +24,12 @@ #include #include #include + +#pragma GCC diagnostic push +#include #include "agg_ellipse.h" #include "agg_color_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -33,6 +37,7 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a { double width = 0.0; double height = 0.0; + double half_stroke_width = 0.0; if (has_key(sym,keys::width) && has_key(sym,keys::height)) { width = get(sym, keys::width, feature, vars, 0.0); @@ -46,6 +51,10 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a { width = height = get(sym, keys::height, feature, vars, 0.0); } + if (has_key(sym,keys::stroke_width)) + { + half_stroke_width = get(sym, keys::stroke_width, feature, vars, 0.0) / 2.0; + } svg::svg_converter_type styled_svg(svg_path, marker_ellipse.attributes()); styled_svg.push_attr(); styled_svg.begin_path(); @@ -55,6 +64,10 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a styled_svg.pop_attr(); double lox,loy,hix,hiy; styled_svg.bounding_rect(&lox, &loy, &hix, &hiy); + lox -= half_stroke_width; + loy -= half_stroke_width; + hix += half_stroke_width; + hiy += half_stroke_width; styled_svg.set_dimensions(width,height); marker_ellipse.set_dimensions(width,height); marker_ellipse.set_bounding_box(lox,loy,hix,hiy); diff --git a/src/palette.cpp b/src/palette.cpp index 54e4346b5..4c3807d1c 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -37,8 +37,8 @@ rgb::rgb(rgba const& c) // ordering by mean(a,r,g,b), a, r, g, b bool rgba::mean_sort_cmp::operator() (const rgba& x, const rgba& y) const { - int t1 = (int)x.a + x.r + x.g + x.b; - int t2 = (int)y.a + y.r + y.g + y.b; + int t1 = x.a + x.r + x.g + x.b; + int t2 = y.a + y.r + y.g + y.b; if (t1 != t2) return t1 < t2; // https://github.com/mapnik/mapnik/issues/1087 @@ -97,9 +97,9 @@ std::string rgba_palette::to_string() const str << std::hex << std::setfill('0'); for (unsigned i = 0; i < length; i++) { str << " #"; - str << std::setw(2) << (unsigned)rgb_pal_[i].r; - str << std::setw(2) << (unsigned)rgb_pal_[i].g; - str << std::setw(2) << (unsigned)rgb_pal_[i].b; + str << std::setw(2) << static_cast(rgb_pal_[i].r); + str << std::setw(2) << static_cast(rgb_pal_[i].g); + str << std::setw(2) << static_cast(rgb_pal_[i].b); if (i < alphaLength) str << std::setw(2) << alpha_pal_[i]; } str << "]"; diff --git a/src/plugin.cpp b/src/plugin.cpp index af9bef3fb..b2186304d 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -58,16 +58,24 @@ PluginInfo::PluginInfo(std::string const& filename, if (module_) module_->dl = LoadLibraryA(filename.c_str()); if (module_ && module_->dl) { - name_func name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); + callable_returning_string name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); if (name) name_ = name(); + callable_returning_void init_once = reinterpret_cast(dlsym(module_->dl, "on_plugin_load")); + if (init_once) { + init_once(); + } } #else #ifdef MAPNIK_HAS_DLCFN if (module_) module_->dl = dlopen(filename.c_str(),RTLD_LAZY); if (module_ && module_->dl) { - name_func name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); + callable_returning_string name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); if (name) name_ = name(); + callable_returning_void init_once = reinterpret_cast(dlsym(module_->dl, "on_plugin_load")); + if (init_once) { + init_once(); + } } #else throw std::runtime_error("no support for loading dynamic objects (Mapnik not compiled with -DMAPNIK_HAS_DLCFN)"); @@ -108,7 +116,7 @@ void * PluginInfo::get_symbol(std::string const& sym_name) const #ifdef MAPNIK_SUPPORTS_DLOPEN return static_cast(dlsym(module_->dl, sym_name.c_str())); #else - return NULL; + return nullptr; #endif } diff --git a/src/png_reader.cpp b/src/png_reader.cpp index 30b470fd6..8c58b2238 100644 --- a/src/png_reader.cpp +++ b/src/png_reader.cpp @@ -23,22 +23,17 @@ // mapnik #include #include +#include extern "C" { #include } -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - // stl #include #include +#include namespace mapnik { @@ -47,7 +42,7 @@ template class png_reader : public image_reader { using source_type = T; - using input_stream = boost::iostreams::stream; + using input_stream = std::istream; struct png_struct_guard { @@ -73,7 +68,7 @@ private: int color_type_; bool has_alpha_; public: - explicit png_reader(std::string const& file_name); + explicit png_reader(std::string const& filename); png_reader(char const* data, std::size_t size); ~png_reader(); unsigned width() const final; @@ -90,14 +85,14 @@ private: namespace { -image_reader* create_png_reader(std::string const& file) +image_reader* create_png_reader(std::string const& filename) { - return new png_reader(file); + return new png_reader(filename); } image_reader* create_png_reader2(char const * data, std::size_t size) { - return new png_reader(data, size); + return new png_reader(data, size); } const bool registered = register_image_reader("png",create_png_reader); @@ -128,31 +123,30 @@ void png_reader::png_read_data(png_structp png_ptr, png_bytep data, png_size_ } template -png_reader::png_reader(std::string const& file_name) - : source_(file_name,std::ios_base::in | std::ios_base::binary), - stream_(source_), +png_reader::png_reader(std::string const& filename) + : source_(), + stream_(&source_), width_(0), height_(0), bit_depth_(0), color_type_(0), has_alpha_(false) { - if (!source_.is_open()) throw image_reader_exception("PNG reader: cannot open file '"+ file_name + "'"); - if (!stream_) throw image_reader_exception("PNG reader: cannot open file '"+ file_name + "'"); + source_.open(filename, std::ios_base::in | std::ios_base::binary); + if (!source_.is_open()) throw image_reader_exception("PNG reader: cannot open file '"+ filename + "'"); init(); } template png_reader::png_reader(char const* data, std::size_t size) : source_(data,size), - stream_(source_), + stream_(&source_), width_(0), height_(0), bit_depth_(0), color_type_(0), has_alpha_(false) { - if (!stream_) throw image_reader_exception("PNG reader: cannot open image stream"); init(); } diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index a08b4d7dd..9c23d805a 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef MAPNIK_USE_PROJ4 // proj4 @@ -124,7 +125,7 @@ unsigned int proj_transform::forward (geometry::line_string & ls) const geometry::point * ptr = ls.data(); double * x = reinterpret_cast(ptr); double * y = x + 1; - double * z = NULL; + double * z = nullptr; if(!forward(x, y, z, size, 2)) { return size; @@ -199,20 +200,21 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co #ifdef MAPNIK_USE_PROJ4 if (is_dest_longlat_) { - int i; - for(i=0; i & ls) const geometry::point * ptr = ls.data(); double * x = reinterpret_cast(ptr); double * y = x + 1; - double * z = NULL; - if(!backward(x, y, z, size, 2)) + double * z = nullptr; + if (!backward(x, y, z, size, 2)) { return size; } @@ -311,31 +313,24 @@ bool proj_transform::backward (box2d & box) const if (is_source_equal_dest_) return true; - double llx = box.minx(); - double ulx = box.minx(); - double lly = box.miny(); - double lry = box.miny(); - double lrx = box.maxx(); - double urx = box.maxx(); - double uly = box.maxy(); - double ury = box.maxy(); - double z = 0.0; - if (!backward(llx,lly,z)) + double x[4], y[4]; + x[0] = box.minx(); // llx 0 + y[0] = box.miny(); // lly 1 + x[1] = box.maxx(); // lrx 2 + y[1] = box.miny(); // lry 3 + x[2] = box.minx(); // ulx 4 + y[2] = box.maxy(); // uly 5 + x[3] = box.maxx(); // urx 6 + y[3] = box.maxy(); // ury 7 + + if (!backward(x, y, nullptr, 4, 1)) return false; - if (!backward(lrx,lry,z)) - return false; - if (!backward(ulx,uly,z)) - return false; - if (!backward(urx,ury,z)) - return false; - double minx = std::min(ulx, llx); - double miny = std::min(lly, lry); - double maxx = std::max(urx, lrx); - double maxy = std::max(ury, uly); - box.init(minx, - miny, - maxx, - maxy); + + double minx = std::min(x[0], x[2]); + double miny = std::min(y[0], y[1]); + double maxx = std::max(x[1], x[3]); + double maxy = std::max(y[2], y[3]); + box.init(minx, miny, maxx, maxy); return true; } @@ -370,21 +365,6 @@ void envelope_points(std::vector< coord > & coords, box2d& env } } -// determine if an ordered sequence of coordinates is in clockwise order -bool is_clockwise(const std::vector< coord > & coords) -{ - int n = coords.size(); - coord c1, c2; - double a = 0.0; - - for (int i=0; i calculate_bbox(std::vector > & points) { std::vector >::iterator it = points.begin(); std::vector >::iterator it_end = points.end(); @@ -425,7 +405,7 @@ bool proj_transform::backward(box2d& env, int points) const } box2d result = calculate_bbox(coords); - if (is_source_longlat_ && !is_clockwise(coords)) + if (is_source_longlat_ && !util::is_clockwise(coords)) { // we've gone to a geographic CS, and our clockwise envelope has // changed into an anticlockwise one. This means we've crossed the antimeridian, and @@ -439,7 +419,6 @@ bool proj_transform::backward(box2d& env, int points) const env.re_center(result.center().x, result.center().y); env.height(result.height()); env.width(result.width()); - return true; } @@ -466,7 +445,7 @@ bool proj_transform::forward(box2d& env, int points) const box2d result = calculate_bbox(coords); - if (is_dest_longlat_ && !is_clockwise(coords)) + if (is_dest_longlat_ && !util::is_clockwise(coords)) { // we've gone to a geographic CS, and our clockwise envelope has // changed into an anticlockwise one. This means we've crossed the antimeridian, and diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp index c0a631f69..94e829405 100644 --- a/src/rapidxml_loader.cpp +++ b/src/rapidxml_loader.cpp @@ -28,12 +28,16 @@ #include #include #include -#include #include #include #include #include +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + // stl #include #include diff --git a/src/raster_colorizer.cpp b/src/raster_colorizer.cpp index 22d3ee88a..2c43df6b6 100644 --- a/src/raster_colorizer.cpp +++ b/src/raster_colorizer.cpp @@ -149,7 +149,7 @@ void raster_colorizer::colorize(image_rgba8 & out, T const& in, inline unsigned interpolate(unsigned start, unsigned end, float fraction) { - return static_cast(fraction * ((float)end - (float)start) + start); + return static_cast(fraction * (static_cast(end) - static_cast(start)) + static_cast(start)); } unsigned raster_colorizer::get_color(float value) const diff --git a/src/renderer_common/render_markers_symbolizer.cpp b/src/renderer_common/render_markers_symbolizer.cpp index 2ecc51bd8..6706cb1cd 100644 --- a/src/renderer_common/render_markers_symbolizer.cpp +++ b/src/renderer_common/render_markers_symbolizer.cpp @@ -159,7 +159,7 @@ struct render_marker_symbolizer_visitor if (auto image_transform = get_optional(sym_, keys::image_transform)) { - evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); } vector_dispatch_type rasterizer_dispatch(marker_ptr, @@ -183,7 +183,7 @@ struct render_marker_symbolizer_visitor setup_transform_scaling(image_tr, mark.width(), mark.height(), feature_, common_.vars_, sym_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); box2d const& bbox = mark.bounding_box(); mapnik::image_rgba8 const& marker = mark.get_data(); // - clamp sizes to > 4 pixels of interactivity diff --git a/src/renderer_common/render_pattern.cpp b/src/renderer_common/render_pattern.cpp index 06477d460..5e6f95820 100644 --- a/src/renderer_common/render_pattern.cpp +++ b/src/renderer_common/render_pattern.cpp @@ -28,12 +28,15 @@ #include #include +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" #include "agg_color_rgba.h" #include "agg_color_gray.h" #include "agg_scanline_u.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index 6613d5cde..2483bae56 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -30,10 +30,14 @@ #include #include #include + +#pragma GCC diagnostic push +#include #include "agg_ellipse.h" #include "agg_rounded_rect.h" #include "agg_span_gradient.h" #include "agg_color_rgba.h" +#pragma GCC diagnostic pop #pragma GCC diagnostic push #include @@ -150,7 +154,7 @@ double parse_svg_value(T & error_messages, const char* str, bool & percent) ("pc", DPI/6.0) ("mm", DPI/25.4) ("cm", DPI/2.54) - ("in", (double)DPI) + ("in", static_cast(DPI)) ; const char* cur = str; // phrase_parse modifies the first iterator const char* end = str + std::strlen(str); diff --git a/src/text/face.cpp b/src/text/face.cpp index 31538b672..b05f0d169 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -23,11 +23,16 @@ #include #include +#pragma GCC diagnostic push +#include + extern "C" { #include FT_GLYPH_H } +#pragma GCC diagnostic pop + namespace mapnik { @@ -36,7 +41,7 @@ font_face::font_face(FT_Face face) bool font_face::set_character_sizes(double size) { - return (FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0) == 0); + return (FT_Set_Char_Size(face_,0,static_cast(size * (1<<6)),0,0) == 0); } bool font_face::set_unscaled_character_sizes() @@ -108,7 +113,7 @@ void font_face_set::set_unscaled_character_sizes() void stroker::init(double radius) { - FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)), + FT_Stroker_Set(s_, static_cast(radius * (1<<6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); diff --git a/src/text/font_library.cpp b/src/text/font_library.cpp index 2bdb4ba48..37fd6a43b 100644 --- a/src/text/font_library.cpp +++ b/src/text/font_library.cpp @@ -28,6 +28,9 @@ #include #include +#pragma GCC diagnostic push +#include + // freetype2 extern "C" { @@ -36,6 +39,8 @@ extern "C" #include FT_MODULE_H } +#pragma GCC diagnostic pop + namespace { void* _Alloc_Func(FT_Memory, long size) diff --git a/src/text/formatting/format.cpp b/src/text/formatting/format.cpp index 8e0fef52d..8a6a8cc9d 100644 --- a/src/text/formatting/format.cpp +++ b/src/text/formatting/format.cpp @@ -30,9 +30,11 @@ #include #include -//boost +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop namespace mapnik { namespace formatting { diff --git a/src/text/formatting/layout.cpp b/src/text/formatting/layout.cpp index 19da033fc..ef908c569 100644 --- a/src/text/formatting/layout.cpp +++ b/src/text/formatting/layout.cpp @@ -35,8 +35,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace formatting { diff --git a/src/text/formatting/list.cpp b/src/text/formatting/list.cpp index 89e9d2373..4bf7c4d2d 100644 --- a/src/text/formatting/list.cpp +++ b/src/text/formatting/list.cpp @@ -25,8 +25,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { using boost::property_tree::ptree; diff --git a/src/text/formatting/text.cpp b/src/text/formatting/text.cpp index c24aab123..3158f20e2 100644 --- a/src/text/formatting/text.cpp +++ b/src/text/formatting/text.cpp @@ -30,8 +30,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index ac77d4f85..e6ae4d185 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -40,6 +40,41 @@ namespace mapnik { +namespace { +box2d get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot) +{ + /* + + (0/ymax) (width/ymax) + *************** + * * + (0/0)* * + * * + *************** + (0/ymin) (width/ymin) + Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)! + */ + double width = layout.cluster_width(glyph.char_index); + if (glyph.advance() <= 0) width = -width; + pixel_position tmp, tmp2; + tmp.set(0, glyph.ymax()); + tmp = tmp.rotate(rot); + tmp2.set(width, glyph.ymax()); + tmp2 = tmp2.rotate(rot); + box2d bbox(tmp.x, -tmp.y, + tmp2.x, -tmp2.y); + tmp.set(width, glyph.ymin()); + tmp = tmp.rotate(rot); + bbox.expand_to_include(tmp.x, -tmp.y); + tmp.set(0, glyph.ymin()); + tmp = tmp.rotate(rot); + bbox.expand_to_include(tmp.x, -tmp.y); + pixel_position pos2 = pos + pixel_position(0, glyph.offset.y).rotate(rot); + bbox.move(pos2.x , -pos2.y); + return bbox; +} +} // anonymous namespace + placement_finder::placement_finder(feature_impl const& feature, attributes const& attr, DetectorType &detector, @@ -433,37 +468,4 @@ bool placement_finder::add_marker(glyph_positions_ptr & glyphs, pixel_position c return true; } -box2d placement_finder::get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot) -{ - /* - - (0/ymax) (width/ymax) - *************** - * * - (0/0)* * - * * - *************** - (0/ymin) (width/ymin) - Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)! - */ - double width = layout.cluster_width(glyph.char_index); - if (glyph.advance() <= 0) width = -width; - pixel_position tmp, tmp2; - tmp.set(0, glyph.ymax()); - tmp = tmp.rotate(rot); - tmp2.set(width, glyph.ymax()); - tmp2 = tmp2.rotate(rot); - box2d bbox(tmp.x, -tmp.y, - tmp2.x, -tmp2.y); - tmp.set(width, glyph.ymin()); - tmp = tmp.rotate(rot); - bbox.expand_to_include(tmp.x, -tmp.y); - tmp.set(0, glyph.ymin()); - tmp = tmp.rotate(rot); - bbox.expand_to_include(tmp.x, -tmp.y); - pixel_position pos2 = pos + pixel_position(0, glyph.offset.y).rotate(rot); - bbox.move(pos2.x , -pos2.y); - return bbox; -} - }// ns mapnik diff --git a/src/text/placements/list.cpp b/src/text/placements/list.cpp index 65c729b84..7d609f2c4 100644 --- a/src/text/placements/list.cpp +++ b/src/text/placements/list.cpp @@ -24,8 +24,10 @@ #include #include -//boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/text/scrptrun.cpp b/src/text/scrptrun.cpp index 37a02e7c8..0cbb2c839 100644 --- a/src/text/scrptrun.cpp +++ b/src/text/scrptrun.cpp @@ -14,8 +14,11 @@ * http://source.icu-project.org/repos/icu/icu/trunk/license.html */ +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop #include diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index 1d0fe48d2..fe5568ad2 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -41,8 +41,39 @@ #include #include +namespace mapnik { +namespace geometry { -namespace mapnik { namespace detail { +struct envelope_impl +{ + template + box2d operator() (T const& ref) const + { + return envelope(ref); + } +}; + +mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom) +{ + return mapnik::util::apply_visitor(envelope_impl(), geom); +} + +struct geometry_type_impl +{ + template + auto operator() (T const& ref) const -> decltype(geometry_type(ref)) + { + return geometry_type(ref); + } +}; + +mapnik::geometry::geometry_types geometry_type(mapnik::base_symbolizer_helper::geometry_cref const& geom) +{ + return mapnik::util::apply_visitor(geometry_type_impl(), geom); +} + +} // geometry +namespace detail { template struct apply_vertex_placement @@ -389,7 +420,7 @@ bool text_symbolizer_helper::next_point_placement() const return true; } //No placement for this point. Keep it in points_ for next try. - point_itr_++; + ++point_itr_; } return false; } @@ -434,7 +465,7 @@ void text_symbolizer_helper::init_marker() const if (marker->is()) return; agg::trans_affine trans; auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform); + if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform, scale_factor_); double width = marker->width(); double height = marker->height(); double px0 = - 0.5 * width; @@ -460,7 +491,6 @@ void text_symbolizer_helper::init_marker() const finder_.set_marker(std::make_shared(marker, trans), bbox, unlock_image, marker_displacement); } - template text_symbolizer_helper::text_symbolizer_helper( text_symbolizer const& sym, feature_impl const& feature, diff --git a/src/text/text_layout.cpp b/src/text/text_layout.cpp index 36c925efd..0846ea8d7 100644 --- a/src/text/text_layout.cpp +++ b/src/text/text_layout.cpp @@ -29,7 +29,11 @@ #include #include +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + #include #include diff --git a/src/text/text_line.cpp b/src/text/text_line.cpp index f228e5b93..2d0516731 100644 --- a/src/text/text_line.cpp +++ b/src/text/text_line.cpp @@ -51,7 +51,7 @@ text_line::text_line(text_line && rhs) void text_line::add_glyph(glyph_info && glyph, double scale_factor_) { - line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing); + line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing * scale_factor_); double advance = glyph.advance(); if (glyphs_.empty()) { diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 71c52e992..4e3f1d10d 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -34,8 +34,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop #include diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index 1f885407e..157e4d0cb 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -23,21 +23,15 @@ // mapnik #include #include - +#include extern "C" { #include } -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - // stl #include +#include namespace mapnik { namespace impl { @@ -106,7 +100,7 @@ class tiff_reader : public image_reader { using tiff_ptr = std::shared_ptr; using source_type = T; - using input_stream = boost::iostreams::stream; + using input_stream = std::istream; struct tiff_closer { @@ -145,7 +139,7 @@ public: stripped, tiled }; - explicit tiff_reader(std::string const& file_name); + explicit tiff_reader(std::string const& filename); tiff_reader(char const* data, std::size_t size); virtual ~tiff_reader(); unsigned width() const final; @@ -183,14 +177,14 @@ private: namespace { -image_reader* create_tiff_reader(std::string const& file) +image_reader* create_tiff_reader(std::string const& filename) { - return new tiff_reader(file); + return new tiff_reader(filename); } image_reader* create_tiff_reader2(char const * data, std::size_t size) { - return new tiff_reader(data, size); + return new tiff_reader(data, size); } const bool registered = register_image_reader("tiff",create_tiff_reader); @@ -199,9 +193,9 @@ const bool registered2 = register_image_reader("tiff", create_tiff_reader2); } template -tiff_reader::tiff_reader(std::string const& file_name) - : source_(file_name, std::ios_base::in | std::ios_base::binary), - stream_(source_), +tiff_reader::tiff_reader(std::string const& filename) + : source_(), + stream_(&source_), tif_(nullptr), read_method_(generic), rows_per_strip_(0), @@ -218,14 +212,15 @@ tiff_reader::tiff_reader(std::string const& file_name) has_alpha_(false), is_tiled_(false) { - if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ file_name); + source_.open(filename, std::ios_base::in | std::ios_base::binary); + if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ filename); init(); } template tiff_reader::tiff_reader(char const* data, std::size_t size) : source_(data, size), - stream_(source_), + stream_(&source_), tif_(nullptr), read_method_(generic), rows_per_strip_(0), @@ -243,8 +238,6 @@ tiff_reader::tiff_reader(char const* data, std::size_t size) is_tiled_(false) { if (!stream_) throw image_reader_exception("TIFF reader: cannot open image stream "); - stream_.rdbuf()->pubsetbuf(0, 0); - stream_.seekg(0, std::ios::beg); init(); } diff --git a/src/twkb.cpp b/src/twkb.cpp new file mode 100644 index 000000000..f1928e5a6 --- /dev/null +++ b/src/twkb.cpp @@ -0,0 +1,387 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 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 + +namespace mapnik { namespace detail { + +struct twkb_reader : mapnik::util::noncopyable +{ +private: + const char *twkb_; + size_t size_; + unsigned int pos_; + // Metadata on the geometry we are parsing + uint8_t twkb_type_; + uint8_t has_bbox_; + uint8_t has_size_; + uint8_t has_idlist_; + uint8_t has_z_; + uint8_t has_m_; + uint8_t is_empty_; + // Precision factors to convert ints to double + double factor_xy_; + double factor_z_; + double factor_m_; + // An array to keep delta values from 4 dimensions + int64_t coord_x_; + int64_t coord_y_; + int64_t coord_z_; + int64_t coord_m_; + +public: + enum twkbGeometryType : std::uint8_t + { + twkbPoint = 1, + twkbLineString = 2, + twkbPolygon = 3, + twkbMultiPoint = 4, + twkbMultiLineString = 5, + twkbMultiPolygon = 6, + twkbGeometryCollection = 7 + }; + + twkb_reader(char const* twkb, size_t size) + : twkb_(twkb), size_(size), pos_(0), twkb_type_(0), // Geometry type + has_bbox_(0), // Bounding box? + has_size_(0), // Size attribute? + has_idlist_(0), // Presence of X/Y + has_z_(0), // Presence of Z + has_m_(0), // Presence of M + is_empty_(0), // Empty? + factor_xy_(0.0), // Expansion factor for X/Y + factor_z_(0.0), // Expansion factor for Z + factor_m_(0.0) // Expansion factor for M + {} + + mapnik::geometry::geometry read() + { + mapnik::geometry::geometry geom = mapnik::geometry::geometry_empty(); + // Read the metadata bytes, populating all the + // information about optional fields, extended (z/m) dimensions + // expansion factors and so on + read_header(); + + // Each new read call has to reset the coordinate accumulators + coord_x_ = 0; // Accumulation register (x) + coord_y_ = 0; // Accumulation register (y) + coord_z_ = 0; // Accumulation register (z) + coord_m_ = 0; // Accumulation register (m) + + // If the geometry is empty, add nothing to the paths array + if (is_empty_) + return geom; + + // Read the [optional] size information + if (has_size_) + size_ = read_unsigned_integer(); + + // Read the [optional] bounding box information + if (has_bbox_) read_bbox(); + + switch (twkb_type_) + { + case twkbPoint: + geom = read_point(); + break; + case twkbLineString: + geom = read_linestring(); + break; + case twkbPolygon: + geom = read_polygon(); + break; + case twkbMultiPoint: + geom = read_multipoint(); + break; + case twkbMultiLineString: + geom = read_multilinestring(); + break; + case twkbMultiPolygon: + geom = read_multipolygon(); + break; + case twkbGeometryCollection: + geom = read_collection(); + default: + break; + } + return geom; + } + +private: + int64_t unzigzag64(uint64_t val) + { + if (val & 0x01) + return -1 * (int64_t)((val + 1) >> 1); + else + return (int64_t)(val >> 1); + } + + int32_t unzigzag32(uint32_t val) + { + if (val & 0x01) return -1 * (int32_t)((val + 1) >> 1); + else return (int32_t)(val >> 1); + } + + int8_t unzigzag8(uint8_t val) + { + if (val & 0x01) return -1 * (int8_t)((val + 1) >> 1); + else return (int8_t)(val >> 1); + } + + // Read from signed 64bit varint + int64_t read_signed_integer() { return unzigzag64(read_unsigned_integer()); } + + // Read from unsigned 64bit varint + uint64_t read_unsigned_integer() + { + uint64_t nVal = 0; + int nShift = 0; + uint8_t nByte; + + // Check so we don't read beyond the twkb + while (pos_ < size_) + { + nByte = twkb_[pos_]; + // We get here when there is more to read in the input varInt + // Here we take the least significant 7 bits of the read + // byte and put it in the most significant place in the result variable. + nVal |= ((uint64_t)(nByte & 0x7f)) << nShift; + // move the "cursor" of the input buffer step (8 bits) + pos_++; + // move the cursor in the resulting variable (7 bits) + nShift += 7; + // Hibit isn't set, so this is the last byte + if (!(nByte & 0x80)) { + return nVal; + } + } + return 0; + } + + // Every TWKB geometry starts with a metadata header + // + // type_and_dims byte + // metadata_header byte + // [extended_dims] byte + // [size] uvarint + // [bounds] bbox + // + void read_header() + { + uint8_t type_precision = twkb_[pos_++]; + uint8_t metadata = twkb_[pos_++]; + twkb_type_ = type_precision & 0x0F; + int8_t precision = unzigzag8((type_precision & 0xF0) >> 4); + factor_xy_ = std::pow(10, static_cast(precision)); + has_bbox_ = metadata & 0x01; + has_size_ = (metadata & 0x02) >> 1; + has_idlist_ = (metadata & 0x04) >> 2; + uint8_t zm = (metadata & 0x08) >> 3; + is_empty_ = (metadata & 0x10) >> 4; + + // Flag for higher dimensions means read a third byte + // of extended dimension information + if (zm) + { + zm = twkb_[pos_++]; + // Strip Z/M presence and precision from ext byte + has_z_ = (zm & 0x01); + has_m_ = (zm & 0x02) >> 1; + // Convert the precision into factor + int8_t precision_z = (zm & 0x1C) >> 2; + int8_t precision_m = (zm & 0xE0) >> 5; + factor_z_ = pow(10, (double)precision_z); + factor_m_ = pow(10, (double)precision_m); + } + } + + void read_bbox() + { + // we have nowhere to store this box information + // for now, so we'll just move the read head forward + // an appropriate number of times + if (has_bbox_) + { + read_signed_integer(); // uint64_t xmin + read_signed_integer(); // uint64_t xdelta + read_signed_integer(); // uint64_t ymin + read_signed_integer(); // uint64_t ydelta + if (has_z_) + { + read_signed_integer(); // uint64_t zmin + read_signed_integer(); // uint64_t zdelta + } + if (has_m_) + { + read_signed_integer(); // uint64_t mmin + read_signed_integer(); // uint64_t mdelta + } + } + } + + void read_idlist(unsigned int num_ids) + { + // we have nowhere to store this id information + // for now, so we'll just move the read head + // forward an appropriate number of times + if (has_idlist_) + { + for (unsigned int i = 0; i < num_ids; ++i) + { + read_signed_integer(); // uint64_t id + } + } + } + + template + void read_coords(Ring & ring, std::size_t num_points) + { + for (std::size_t i = 0; i < num_points; ++i) + { + coord_x_ += read_signed_integer(); + coord_y_ += read_signed_integer(); + ring.emplace_back( coord_x_ / factor_xy_, coord_y_ / factor_xy_); + // Skip Z and M + if (has_z_) coord_z_ += read_signed_integer(); + if (has_m_) coord_m_ += read_signed_integer(); + } + } + + mapnik::geometry::point read_point() + { + coord_x_ += read_signed_integer(); + coord_y_ += read_signed_integer(); + double x = coord_x_ / factor_xy_; + double y = coord_y_ / factor_xy_; + return mapnik::geometry::point(x, y); + } + + mapnik::geometry::multi_point read_multipoint() + { + mapnik::geometry::multi_point multi_point; + unsigned int num_points = read_unsigned_integer(); + if (has_idlist_) read_idlist(num_points); + + if (num_points > 0) + { + multi_point.reserve(num_points); + for (unsigned int i = 0; i < num_points; ++i) + { + multi_point.emplace_back(read_point()); + } + } + return multi_point; + } + + mapnik::geometry::line_string read_linestring() + { + mapnik::geometry::line_string line; + unsigned int num_points = read_unsigned_integer(); + if (num_points > 0) + { + line.reserve(num_points); + read_coords>(line, num_points); + } + return line; + } + + mapnik::geometry::multi_line_string read_multilinestring() + { + mapnik::geometry::multi_line_string multi_line; + unsigned int num_lines = read_unsigned_integer(); + if (has_idlist_) read_idlist(num_lines); + multi_line.reserve(num_lines); + for (unsigned int i = 0; i < num_lines; ++i) + { + multi_line.push_back(read_linestring()); + } + return multi_line; + } + + mapnik::geometry::polygon read_polygon() + { + unsigned int num_rings = read_unsigned_integer(); + mapnik::geometry::polygon poly; + if (num_rings > 1) + { + poly.interior_rings.reserve(num_rings - 1); + } + + for (unsigned int i = 0; i < num_rings; ++i) + { + mapnik::geometry::linear_ring ring; + unsigned int num_points = read_unsigned_integer(); + if (num_points > 0) + { + ring.reserve(num_points); + read_coords>(ring, num_points); + } + if ( i == 0) poly.set_exterior_ring(std::move(ring)); + else poly.add_hole(std::move(ring)); + } + return poly; + } + + mapnik::geometry::multi_polygon read_multipolygon() + { + mapnik::geometry::multi_polygon multi_poly; + unsigned int num_polys = read_unsigned_integer(); + if (has_idlist_) read_idlist(num_polys); + for (unsigned int i = 0; i < num_polys; ++i) + { + multi_poly.push_back(read_polygon()); + } + return multi_poly; + } + + mapnik::geometry::geometry_collection read_collection() + { + unsigned int num_geometries = read_unsigned_integer(); + mapnik::geometry::geometry_collection collection; + if (has_idlist_) read_idlist(num_geometries); + for (unsigned int i = 0; i < num_geometries; ++i) + { + collection.push_back(read()); + } + return collection; + } +}; + +} // namespace detail + +mapnik::geometry::geometry geometry_utils::from_twkb(const char* wkb, std::size_t size) +{ + detail::twkb_reader reader(wkb, size); + mapnik::geometry::geometry geom(reader.read()); + // note: this will only be applied to polygons + mapnik::geometry::correct(geom); + return geom; +} + +} // namespace mapnik diff --git a/src/unicode.cpp b/src/unicode.cpp index abbf85df7..c96c58914 100644 --- a/src/unicode.cpp +++ b/src/unicode.cpp @@ -27,8 +27,10 @@ // std #include -// icu +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/value.cpp b/src/value.cpp index efcd15b5f..a3c8770cc 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -761,6 +761,13 @@ struct to_expression_string_impl std::string operator()(value_unicode_string const& val) const { + // toUTF8(sink) doesn't Flush() the sink if the source string + // is empty -- we must return a pair of quotes in that case + // https://github.com/mapnik/mapnik/issues/3362 + if (val.isEmpty()) + { + return std::string(2, quote_); + } EscapingByteSink sink(quote_); val.toUTF8(sink); return sink.dest_; diff --git a/src/vertex_adapters.cpp b/src/vertex_adapters.cpp index 06be6c2f4..e96a9e25e 100644 --- a/src/vertex_adapters.cpp +++ b/src/vertex_adapters.cpp @@ -34,7 +34,7 @@ point_vertex_adapter::point_vertex_adapter(point const& pt) first_(true) {} template -unsigned point_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned point_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (first_) { @@ -67,7 +67,7 @@ line_string_vertex_adapter::line_string_vertex_adapter(line_string const& {} template -unsigned line_string_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned line_string_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (current_index_ != end_index_) { @@ -117,7 +117,7 @@ void polygon_vertex_adapter::rewind(unsigned) const start_loop_ = true; } template -unsigned polygon_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned polygon_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (rings_itr_ == rings_end_) { @@ -177,7 +177,7 @@ void ring_vertex_adapter::rewind(unsigned) const } template -unsigned ring_vertex_adapter::vertex(value_type * x, value_type * y) const +unsigned ring_vertex_adapter::vertex(coord_type * x, coord_type * y) const { if (current_index_ < end_index_) { diff --git a/src/warp.cpp b/src/warp.cpp index 4a468a8b3..29cfa44cc 100644 --- a/src/warp.cpp +++ b/src/warp.cpp @@ -31,7 +31,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_image_filters.h" #include "agg_trans_bilinear.h" #include "agg_span_interpolator_linear.h" @@ -45,6 +46,7 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_renderer_scanline.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp index b3d4ea0e5..f5fec3416 100644 --- a/src/webp_reader.cpp +++ b/src/webp_reader.cpp @@ -33,9 +33,6 @@ extern "C" #include } -#include -#include -#include #pragma GCC diagnostic pop // stl diff --git a/src/well_known_srs.cpp b/src/well_known_srs.cpp index d3296effa..445d84aee 100644 --- a/src/well_known_srs.cpp +++ b/src/well_known_srs.cpp @@ -25,8 +25,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/wkb.cpp b/src/wkb.cpp index 0eeed5663..1d7e1f5f8 100644 --- a/src/wkb.cpp +++ b/src/wkb.cpp @@ -105,13 +105,13 @@ public: switch (format_) { case wkbSpatiaLite: - byteOrder_ = (wkbByteOrder) wkb_[1]; + byteOrder_ = static_cast(wkb_[1]); pos_ = 39; break; case wkbGeneric: default: - byteOrder_ = (wkbByteOrder) wkb_[0]; + byteOrder_ = static_cast(wkb_[0]); pos_ = 1; break; } @@ -126,8 +126,12 @@ public: switch (type) { case wkbPoint: - geom = read_point(); + { + auto pt = read_point(); + if (!std::isnan(pt.x) && !std::isnan(pt.y)) + geom = std::move(pt); break; + } case wkbLineString: geom = read_linestring(); break; @@ -148,11 +152,19 @@ public: break; case wkbPointZ: case wkbPointM: - geom = read_point(); + { + auto pt = read_point(); + if (!std::isnan(pt.x) && !std::isnan(pt.y)) + geom = std::move(pt); break; + } case wkbPointZM: - geom = read_point(); + { + auto pt = read_point(); + if (!std::isnan(pt.x) && !std::isnan(pt.y)) + geom = std::move(pt); break; + } case wkbLineStringZ: case wkbLineStringM: geom = read_linestring(); diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 55e32629c..2cc2c6adc 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -73,8 +73,6 @@ DEFINE_NAME_TRAIT( int, "int") DEFINE_NAME_TRAIT( boolean_type, "boolean_type") #ifdef BIGINT DEFINE_NAME_TRAIT( mapnik::value_integer, "long long" ) -#else -DEFINE_NAME_TRAIT( mapnik::value_integer, "int" ) #endif DEFINE_NAME_TRAIT( std::string, "string" ) DEFINE_NAME_TRAIT( color, "color" ) @@ -417,7 +415,9 @@ compile_get_opt_attr(boolean_type); compile_get_opt_attr(std::string); compile_get_opt_attr(int); compile_get_opt_attr(unsigned); +#ifdef BIGINT compile_get_opt_attr(mapnik::value_integer); +#endif compile_get_opt_attr(float); compile_get_opt_attr(double); compile_get_opt_attr(color); diff --git a/test/build.py b/test/build.py index c600d01bc..78fd9342a 100644 --- a/test/build.py +++ b/test/build.py @@ -9,6 +9,8 @@ test_env = env.Clone() if not env['CPP_TESTS']: for cpp_test_bin in glob.glob('./*/*-bin'): os.unlink(cpp_test_bin) + if os.path.exists('./unit/run'): os.unlink('./unit/run') + if os.path.exists('./visual/run'): os.unlink('./visual/run') else: test_env['LIBS'] = [env['MAPNIK_NAME']] test_env.AppendUnique(LIBS='mapnik-wkt') diff --git a/test/cleanup.hpp b/test/cleanup.hpp index f175e72b4..c775915b5 100644 --- a/test/cleanup.hpp +++ b/test/cleanup.hpp @@ -1,6 +1,9 @@ #ifndef TEST_MEMORY_CLEANUP #define TEST_MEMORY_CLEANUP +#pragma GCC diagnostic push +#include + #if defined(HAVE_LIBXML2) #include #include @@ -16,6 +19,8 @@ #include #endif +#pragma GCC diagnostic pop + namespace testing { inline void run_cleanup() diff --git a/test/data b/test/data index 2a8261be8..e74f1cef0 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 2a8261be8cca79a4b6fd62e8f4a93b2808613fef +Subproject commit e74f1cef09d579d6ff414cb56970adbe43b7a91b diff --git a/test/data-visual b/test/data-visual index cc17060aa..5f0e6f866 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit cc17060aaeb459fd5ed3f8c50ef66bfd461585ab +Subproject commit 5f0e6f86696a2a9a6733e42b1f400ba4ec2f8847 diff --git a/test/run b/test/run index cd45c681f..014b79861 100755 --- a/test/run +++ b/test/run @@ -1,5 +1,8 @@ #!/usr/bin/env bash +set -o pipefail +set -eu + failures=0 cd "$( dirname "${BASH_SOURCE[0]}" )" @@ -9,30 +12,45 @@ source ./localize.sh function run_step { >&2 echo -e "\033[1m\033[34m* $1\033[0m"; } function run_substep { >&2 echo -e "\033[1m\033[36m* $1\033[0m"; } function run_success { >&2 echo -e "\033[1m\033[32m* $1\033[0m"; } +function run_warn { >&2 echo -e "\033[1m\033[31m* $1\033[0m"; } run_step "Starting Mapnik tests" +ran_a_test=false if [ -d "test/data" ]; then run_substep "Running C++ Unit tests..." - ./test/unit/run - failures=$((failures+$?)) + if [[ -f ./test/unit/run ]]; then + ran_a_test=true + ./test/unit/run || failures=$((failures+$?)) + else + run_warn "Skipping unit tests since they were not built" + fi run_substep "Running standalone C++ tests..." + found_test=false if [ -n "$(find test/standalone/ -maxdepth 1 -name '*-bin' -print -quit)" ]; then for FILE in test/standalone/*-bin; do - ${FILE}; - failures=$((failures+$?)) + found_test=true + ran_a_test=true + ${FILE} || failures=$((failures+$?)) done fi + if [[ $found_test == false ]]; then + run_warn "Skipping standalone tests since they were not built" + fi if [ -d "test/data-visual/styles" ]; then run_substep "Running visual tests..." - if [ -z "$JOBS" ]; then + if [ -z "${JOBS:-}" ]; then JOBS=1 fi - ./test/visual/run -j $JOBS - failures=$((failures+$?)) + if [[ -f ./test/visual/run ]]; then + ran_a_test=true + ./test/visual/run -j $JOBS || failures=$((failures+$?)) + else + run_warn "Skipping visual tests since they were not built" + fi else echo "Notice: Skipping visual tests, the visual tests data are not present under the standard directory \"test/data-visual\"." fi @@ -41,4 +59,8 @@ else echo "Notice: Skipping all tests, the test data are not present under the standard directory \"test/data\"." fi +if [[ $ran_a_test == false ]]; then + run_warn "**** WARNING: no tests were run ****" +fi + exit $failures diff --git a/test/unit/core/expressions_test.cpp b/test/unit/core/expressions_test.cpp index 1b7d12faf..64cdd9ecf 100644 --- a/test/unit/core/expressions_test.cpp +++ b/test/unit/core/expressions_test.cpp @@ -88,6 +88,7 @@ TEST_CASE("expressions") // integer TRY_CHECK(parse_and_dump("123") == "123"); // unicode + TRY_CHECK(parse_and_dump("''") == "''"); TRY_CHECK(parse_and_dump("'single-quoted string'") == "'single-quoted string'"); TRY_CHECK(parse_and_dump("\"double-quoted string\"") == "'double-quoted string'"); TRY_CHECK(parse_and_dump("'escaped \\' apostrophe'") == "'escaped \\' apostrophe'"); @@ -181,4 +182,10 @@ TEST_CASE("expressions") // 'Québec' =~ m:^Q\S*$: TRY_CHECK(eval(" [name].match('^Q\\S*$') ") == true); TRY_CHECK(parse_and_dump(" [name].match('^Q\\S*$') ") == "[name].match('^Q\\S*$')"); + + // string & value concatenation + // this should evaluate as two strings concatenating, but currently fails + TRY_CHECK(eval("Hello + '!'") == eval("'Hello!'")); + // this should evaulate as a combination of an int value and string, but fails + TRY_CHECK(eval("[int]+m") == eval("'123m'")); } diff --git a/test/unit/data/well-known-geometries.test b/test/unit/data/well-known-geometries.test new file mode 100644 index 000000000..1c6273b29 --- /dev/null +++ b/test/unit/data/well-known-geometries.test @@ -0,0 +1,13 @@ +POINT (30 10);\x01010000000000000000003e400000000000002440;\x01003c14 +LINESTRING (30 10, 10 30, 40 40);\x0102000000030000000000000000003e40000000000000244000000000000024400000000000003e4000000000000044400000000000004440;\x0200033c1427283c14 +POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10));\x010300000001000000050000000000000000003e4000000000000024400000000000004440000000000000444000000000000034400000000000004440000000000000244000000000000034400000000000003e400000000000002440;\x030001053c14143c270013272813 +POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30));\x0103000000020000000500000000000000008041400000000000002440000000000080464000000000008046400000000000002e40000000000000444000000000000024400000000000003440000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40;\x03000205461414463b0909273213041d281e0a091d1314 +MULTIPOINT ((10 40), (40 30), (20 20), (30 10));\x010400000004000000010100000000000000000024400000000000004440010100000000000000000044400000000000003e4001010000000000000000003440000000000000344001010000000000000000003e400000000000002440;\x04000414503c1327131413 +MULTIPOINT (10 40, 40 30, 20 20, 30 10);\x010400000004000000010100000000000000000024400000000000004440010100000000000000000044400000000000003e4001010000000000000000003440000000000000344001010000000000000000003e400000000000002440;\x04000414503c1327131413 +MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10));\x010500000002000000010200000003000000000000000000244000000000000024400000000000003440000000000000344000000000000024400000000000004440010200000004000000000000000000444000000000000044400000000000003e400000000000003e40000000000000444000000000000034400000000000003e400000000000002440;\x05000203141414141328043c00131314131313 +MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)));\x010600000002000000010300000001000000040000000000000000003e40000000000000344000000000008046400000000000004440000000000000244000000000000044400000000000003e400000000000003440010300000001000000050000000000000000002e4000000000000014400000000000004440000000000000244000000000000024400000000000003440000000000000144000000000000024400000000000002e400000000000001440;\x06000201043c281e284500282701051d1d320a3b1409131409 +MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),(30 20, 20 15, 20 25, 30 20)));\x01060000000200000001030000000100000004000000000000000000444000000000000044400000000000003440000000000080464000000000008046400000000000003e4000000000000044400000000000004440010300000002000000060000000000000000003440000000000080414000000000000024400000000000003e40000000000000244000000000000024400000000000003e4000000000000014400000000000804640000000000000344000000000000034400000000000804140040000000000000000003e40000000000000344000000000000034400000000000002e40000000000000344000000000000039400000000000003e400000000000003440;\x06000201045050270a321d0914020627091309002728091e1e311e04141d130900141409 +GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10));\x010700000002000000010100000000000000000010400000000000001840010200000002000000000000000000104000000000000018400000000000001c400000000000002440;\x0700020100080c020002080c0608 +POINT EMPTY;\x0101000000000000000000f87f000000000000f87f;\x0110 +LINESTRING EMPTY;\x010200000000000000;\x0210 +POLYGON EMPTY;\x010300000000000000;\x0310 diff --git a/test/unit/datasource/csv.cpp b/test/unit/datasource/csv.cpp index f0df3b2d4..6142185ca 100644 --- a/test/unit/datasource/csv.cpp +++ b/test/unit/datasource/csv.cpp @@ -24,6 +24,7 @@ #include "ds_test_util.hpp" #include +#include #include #include #include @@ -141,7 +142,7 @@ TEST_CASE("csv") { int ret_posix = (ret >> 8) & 0x000000ff; INFO(ret); INFO(ret_posix); - require_fail = (path == "test/data/csv/warns/feature_id_counting.csv") ? false : true; + require_fail = (boost::iends_with(path,"feature_id_counting.csv")) ? false : true; if (!require_fail) { REQUIRE(mapnik::util::exists(path + ".index")); @@ -188,7 +189,7 @@ TEST_CASE("csv") { int ret_posix = (ret >> 8) & 0x000000ff; INFO(ret); INFO(ret_posix); - if (path != "test/data/csv/more_headers_than_column_values.csv") // mapnik-index won't create *.index for 0 features + if (!boost::iends_with(path,"more_headers_than_column_values.csv")) // mapnik-index won't create *.index for 0 features { CHECK(mapnik::util::exists(path + ".index")); } @@ -876,7 +877,15 @@ TEST_CASE("csv") { auto feature = all_features(ds)->next(); REQUIRE(bool(feature)); REQUIRE(feature->has_key("Name")); - CHECK(feature->get("Name") == ustring(name.c_str())); + std::string utf8; + mapnik::transcoder tr("utf-8"); + ustring expected_string = tr.transcode(name.c_str()); + mapnik::value val(expected_string); + mapnik::to_utf8(expected_string,utf8); + INFO(feature->get("Name")); + INFO(utf8); + INFO(val); + CHECK(feature->get("Name") == val); } } // END SECTION diff --git a/test/unit/datasource/ds_test_util.hpp b/test/unit/datasource/ds_test_util.hpp index 6e1c222b4..46868d4e5 100644 --- a/test/unit/datasource/ds_test_util.hpp +++ b/test/unit/datasource/ds_test_util.hpp @@ -106,13 +106,18 @@ inline std::size_t count_features(mapnik::featureset_ptr features) { } using attr = std::tuple; + +#define REQUIRE_ATTRIBUTES(feature, attrs) \ + REQUIRE(bool(feature)); \ + for (auto const &kv : attrs) { \ + REQUIRE(feature->has_key(std::get<0>(kv))); \ + CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); \ + } \ + + inline void require_attributes(mapnik::feature_ptr feature, std::initializer_list const &attrs) { - REQUIRE(bool(feature)); - for (auto const &kv : attrs) { - REQUIRE(feature->has_key(std::get<0>(kv))); - CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); - } + REQUIRE_ATTRIBUTES(feature, attrs); } namespace detail { diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index 0b0f2052a..1edeb4b55 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -23,6 +23,7 @@ #include "catch.hpp" #include "ds_test_util.hpp" +#include #include #include #include @@ -654,5 +655,72 @@ TEST_CASE("geojson") { } } } + + SECTION("GeoJSON properties are properly expressed") + { + mapnik::transcoder tr("utf8"); + mapnik::parameters params; + params["type"] = "geojson"; + + std::string filename("./test/data/json/escaped.geojson"); + params["file"] = filename; + + // cleanup in the case of a failed previous run + if (mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + + for (auto create_index : { true, false }) + { + if (create_index) + { + CHECK(!mapnik::util::exists(filename + ".index")); + int ret = create_disk_index(filename); + int ret_posix = (ret >> 8) & 0x000000ff; + INFO(ret); + INFO(ret_posix); + CHECK(mapnik::util::exists(filename + ".index")); + } + + for (auto cache_features : {true, false}) + { + params["cache_features"] = cache_features; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(bool(ds)); + auto fields = ds->get_descriptor().get_descriptors(); + std::initializer_list names = {"NOM_FR","array","boolean","description","double","empty_array", "empty_object","int","name","object","spaces"}; + REQUIRE_FIELD_NAMES(fields, names); + + auto fs = all_features(ds); + REQUIRE(bool(fs)); + std::initializer_list attrs = { + attr{"name", tr.transcode("Test")}, + attr{"NOM_FR", tr.transcode("Québec")}, + attr{"boolean", mapnik::value_bool("true")}, + attr{"description", tr.transcode("Test: \u005C")}, + attr{"double", mapnik::value_double(1.1)}, + attr{"int", mapnik::value_integer(1)}, + attr{"object", tr.transcode("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", tr.transcode("this has spaces")}, + attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{name:\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", tr.transcode("[]")}, + attr{"empty_object", tr.transcode("{}")}, + }; + auto feature = fs->next(); + REQUIRE(bool(feature)); + REQUIRE_ATTRIBUTES(feature, attrs); + } + // cleanup + if (create_index && mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + } + } } } diff --git a/test/unit/datasource/postgis.cpp b/test/unit/datasource/postgis.cpp index 268995216..95ee65851 100644 --- a/test/unit/datasource/postgis.cpp +++ b/test/unit/datasource/postgis.cpp @@ -29,13 +29,15 @@ #include /* -Compile and run just this test: -clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` && ./test-postgis -d yes + Compile and run just this test: + clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` && ./test-postgis -d yes */ #include -int run(std::string const& command, bool okay_to_fail = false) +namespace { + +bool run(std::string const& command, bool okay_to_fail = false) { std::string cmd; if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) @@ -61,251 +63,278 @@ int run(std::string const& command, bool okay_to_fail = false) return worked; } -std::string dbname("mapnik-tmp-postgis-test-db"); + +std::string const dbname("mapnik-tmp-postgis-test-db"); +bool status = false; + +bool ping_postmaster() +{ + return (run("psql --version") + && run("dropdb --if-exists " + dbname) + && run("createdb -T template_postgis " + dbname)); +} + +} TEST_CASE("postgis") { - SECTION("Postgis data initialization") + SECTION("Ping Postmaster (check if server is runnging and accessible") { - //don't add 'true' here, to get error message, when drop fails. If it works nothing is output - REQUIRE(run("dropdb --if-exists " + dbname)); - REQUIRE(run("createdb -T template_postgis " + dbname)); - //REQUIRE(run("createdb " + dbname)); - // Breaks when raster support is missing (unfortunately this is common) - //REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true)); - REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname)); + if (!ping_postmaster()) + { + WARN("Can't run postgis.input tests - check postmaster is running and accessible"); + return; + } + else + { + status = true; + } } - - mapnik::parameters base_params; - base_params["type"] = "postgis"; - base_params["dbname"] = dbname; - - SECTION("Postgis should throw without 'table' parameter") + if (status) { - mapnik::parameters params(base_params); - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'") - { - mapnik::parameters params(base_params); - params["table"] = "test"; - params["max_async_connection"] = "2"; - params["max_size"] = "1"; - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw with invalid metadata query") - { - mapnik::parameters params(base_params); - params["table"] = "does_not_exist"; - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw with invalid key field") - { - mapnik::parameters params(base_params); - params["table"] = "test_invalid_id"; - params["key_field"] = "id"; - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw with multicolumn primary key") - { - mapnik::parameters params(base_params); - params["table"] = "test_invalid_multi_col_pk"; - params["autodetect_key_field"] = "true"; - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis should throw without geom column") - { - mapnik::parameters params(base_params); - params["table"] = "test_no_geom_col"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - CHECK_THROWS(all_features(ds)); - } - - SECTION("Postgis should throw with invalid credentials") - { - mapnik::parameters params(base_params); - params["table"] = "test"; - params["user"] = "not_a_valid_user"; - params["password"] = "not_a_valid_pwd"; - CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); - } - - SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit") - { - mapnik::parameters params(base_params); - params["persist_connection"] = "false"; - params["table"] = "public.test"; - params["geometry_field"] = "geom"; - params["autodetect_key_field"] = "true"; - params["extent"] = "-1 -1, -1 2, 4 3, 3 -1, -1 -1"; - params["simplify_geometries"] = "true"; - params["row_limit"] = "1"; - auto ds = mapnik::datasource_cache::instance().create(params); - } - - SECTION("Postgis dataset geometry type") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM test WHERE gid=1) as data"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point); - } - - SECTION("Postgis query field names") - { - mapnik::parameters params(base_params); - params["table"] = "test"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector); - auto fields = ds->get_descriptor().get_descriptors(); - require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" }); - require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String }); - } - - SECTION("Postgis iterate features") - { - mapnik::parameters params(base_params); - params["table"] = "test"; - params["key_field"] = "gid"; - params["max_async_connection"] = "2"; - //params["cursor_size"] = "2"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - - auto featureset = ds->features_at_point(mapnik::coord2d(1, 1)); - mapnik::feature_ptr feature; - while ((bool(feature = featureset->next()))) { - REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string()); - REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool()); - REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double()); - REQUIRE(feature->get(5).to_string() == feature->get("colnumeric").to_string()); + SECTION("Postgis data initialization") + { + //don't add 'true' here, to get error message, when drop fails. If it works nothing is output + REQUIRE(run("dropdb --if-exists " + dbname)); + REQUIRE(run("createdb -T template_postgis " + dbname)); + //REQUIRE(run("createdb " + dbname)); + // Breaks when raster support is missing (unfortunately this is common) + //REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true)); + REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname)); } - featureset = all_features(ds); - feature = featureset->next(); - //deactivate char tests for now: not yet implemented. - //add at postgis_datasource.cpp:423 - //case 18: // char - //REQUIRE("A" == feature->get("col-char").to_string()); - feature = featureset->next(); - //REQUIRE("B" == feature->get("col-char").to_string()); - feature = featureset->next(); - REQUIRE(false == feature->get("col+bool").to_bool()); - } + mapnik::parameters base_params; + base_params["type"] = "postgis"; + base_params["dbname"] = dbname; - SECTION("Postgis cursorresultest") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM test) as data"; - params["cursor_size"] = "2"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - auto featureset = all_features(ds); - CHECK(count_features(featureset) == 8); - - featureset = all_features(ds); - mapnik::feature_ptr feature; - while (bool(feature = featureset->next())) { - CHECK(feature->size() == 10); + SECTION("Postgis should throw without 'table' parameter") + { + mapnik::parameters params(base_params); + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); } - featureset = all_features(ds); - require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point); - require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point); - require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPoint); - require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::LineString); - require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiLineString); - require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Polygon); - require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPolygon); - require_geometry(featureset->next(), 3, mapnik::geometry::geometry_types::GeometryCollection); - } + SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["max_async_connection"] = "2"; + params["max_size"] = "1"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } - SECTION("Postgis bbox query") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d ext = ds->envelope(); - CAPTURE(ext); - INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); - REQUIRE(ext.minx() == -2); - REQUIRE(ext.miny() == -2); - REQUIRE(ext.maxx() == 5); - REQUIRE(ext.maxy() == 4); - } + SECTION("Postgis should throw with invalid metadata query") + { + mapnik::parameters params(base_params); + params["table"] = "does_not_exist"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } - SECTION("Postgis query extent: full dataset") - { - //include schema to increase coverage - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM public.test) as data"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d ext = ds->envelope(); - CAPTURE(ext); - INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); - REQUIRE(ext.minx() == -2); - REQUIRE(ext.miny() == -2); - REQUIRE(ext.maxx() == 5); - REQUIRE(ext.maxy() == 4); - } + SECTION("Postgis should throw with invalid key field") + { + mapnik::parameters params(base_params); + params["table"] = "test_invalid_id"; + params["key_field"] = "id"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw with multicolumn primary key") + { + mapnik::parameters params(base_params); + params["table"] = "test_invalid_multi_col_pk"; + params["autodetect_key_field"] = "true"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw without geom column") + { + mapnik::parameters params(base_params); + params["table"] = "test_no_geom_col"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + CHECK_THROWS(all_features(ds)); + } + + SECTION("Postgis should throw with invalid credentials") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["user"] = "not_a_valid_user"; + params["password"] = "not_a_valid_pwd"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit") + { + mapnik::parameters params(base_params); + params["persist_connection"] = "false"; + params["table"] = "public.test"; + params["geometry_field"] = "geom"; + params["autodetect_key_field"] = "true"; + params["extent"] = "-1 -1, -1 2, 4 3, 3 -1, -1 -1"; + params["simplify_geometries"] = "true"; + params["row_limit"] = "1"; + auto ds = mapnik::datasource_cache::instance().create(params); + } + + SECTION("Postgis dataset geometry type") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test WHERE gid=1) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point); + } + + SECTION("Postgis query field names") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector); + auto fields = ds->get_descriptor().get_descriptors(); + require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" }); + require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String }); + } + + SECTION("Postgis iterate features") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["key_field"] = "gid"; + params["max_async_connection"] = "2"; + //params["cursor_size"] = "2"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + + auto featureset = ds->features_at_point(mapnik::coord2d(1, 1)); + mapnik::feature_ptr feature; + while ((bool(feature = featureset->next()))) { + REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string()); + REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool()); + REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double()); + REQUIRE(feature->get(5).to_string() == feature->get("colnumeric").to_string()); + } + + featureset = all_features(ds); + feature = featureset->next(); + //deactivate char tests for now: not yet implemented. + //add at postgis_datasource.cpp:423 + //case 18: // char + //REQUIRE("A" == feature->get("col-char").to_string()); + feature = featureset->next(); + //REQUIRE("B" == feature->get("col-char").to_string()); + feature = featureset->next(); + REQUIRE(false == feature->get("col+bool").to_bool()); + } + + SECTION("Postgis cursorresultest") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test) as data"; + params["cursor_size"] = "2"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + auto featureset = all_features(ds); + CHECK(count_features(featureset) == 8); + + featureset = all_features(ds); + mapnik::feature_ptr feature; + while (bool(feature = featureset->next())) { + CHECK(feature->size() == 10); + } + + featureset = all_features(ds); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point); + require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPoint); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::LineString); + require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiLineString); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Polygon); + require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPolygon); + require_geometry(featureset->next(), 3, mapnik::geometry::geometry_types::GeometryCollection); + } + + SECTION("Postgis bbox query") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == -2); + REQUIRE(ext.miny() == -2); + REQUIRE(ext.maxx() == 5); + REQUIRE(ext.maxy() == 4); + } + + SECTION("Postgis query extent: full dataset") + { + //include schema to increase coverage + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM public.test) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == -2); + REQUIRE(ext.miny() == -2); + REQUIRE(ext.maxx() == 5); + REQUIRE(ext.maxy() == 4); + } /* deactivated for merging: still investigating a proper fix - SECTION("Postgis query extent from subquery") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM test where gid=4) as data"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d ext = ds->envelope(); - CAPTURE(ext); - INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); - REQUIRE(ext.minx() == 0); - REQUIRE(ext.miny() == 0); - REQUIRE(ext.maxx() == 1); - REQUIRE(ext.maxy() == 2); - } + SECTION("Postgis query extent from subquery") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test where gid=4) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == 0); + REQUIRE(ext.miny() == 0); + REQUIRE(ext.maxx() == 1); + REQUIRE(ext.maxy() == 2); + } */ - SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'") - { - mapnik::parameters params(base_params); - params["table"] = "(SELECT * FROM test where gid=4) as data"; - params["extent_from_subquery"] = "true"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d ext = ds->envelope(); - CAPTURE(ext); - INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); - REQUIRE(ext.minx() == 0); - REQUIRE(ext.miny() == 0); - REQUIRE(ext.maxx() == 1); - REQUIRE(ext.maxy() == 2); - } + SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test where gid=4) as data"; + params["extent_from_subquery"] = "true"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == 0); + REQUIRE(ext.miny() == 0); + REQUIRE(ext.maxx() == 1); + REQUIRE(ext.maxy() == 2); + } /* deactivated for merging: still investigating a proper fix - SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'") - { - mapnik::parameters params(base_params); - // !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000' - // https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617 - params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data"; - params["extent_from_subquery"] = "true"; - auto ds = mapnik::datasource_cache::instance().create(params); - REQUIRE(ds != nullptr); - mapnik::box2d ext = ds->envelope(); - CAPTURE(ext); - INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); - REQUIRE(ext.minx() == 0); - REQUIRE(ext.miny() == 0); - REQUIRE(ext.maxx() == 1); - REQUIRE(ext.maxy() == 2); - } + SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'") + { + mapnik::parameters params(base_params); + // !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000' + // https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617 + params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data"; + params["extent_from_subquery"] = "true"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == 0); + REQUIRE(ext.miny() == 0); + REQUIRE(ext.maxx() == 1); + REQUIRE(ext.maxy() == 2); + } */ -} \ No newline at end of file + + } +} diff --git a/test/unit/datasource/topojson.cpp b/test/unit/datasource/topojson.cpp new file mode 100644 index 000000000..6b1a2e1b1 --- /dev/null +++ b/test/unit/datasource/topojson.cpp @@ -0,0 +1,114 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include "catch.hpp" +#include "ds_test_util.hpp" + +#include +#include +#include +#include +#include + +namespace { + +using iterator_type = std::string::const_iterator; +const mapnik::topojson::topojson_grammar grammar; + +bool parse_topology(std::string const& filename, mapnik::topojson::topology & topo) +{ + mapnik::util::file file(filename); + std::string buffer; + buffer.resize(file.size()); + std::fread(&buffer[0], buffer.size(), 1, file.get()); + if (!file) return false; + boost::spirit::standard::space_type space; + iterator_type itr = buffer.begin(); + iterator_type end = buffer.end(); + bool result = boost::spirit::qi::phrase_parse(itr, end, grammar, space, topo); + return (result && (itr == end)); +} + + +} + +TEST_CASE("topojson") +{ + SECTION("geometry parsing") + { + mapnik::value_integer feature_id = 0; + mapnik::context_ptr ctx = std::make_shared(); + mapnik::transcoder tr("utf8"); + for (auto const& path : mapnik::util::list_directory("test/data/topojson/")) + { + mapnik::topojson::topology topo; + REQUIRE(parse_topology(path, topo)); + for (auto const& geom : topo.geometries) + { + mapnik::box2d bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom); + CHECK(bbox.valid()); + mapnik::topojson::feature_generator visitor(ctx, tr, topo, feature_id++); + mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom); + CHECK(feature); + CHECK(feature->envelope() == bbox); + } + } + } + + SECTION("TopoJSON properties are properly expressed") + { + std::string filename("./test/data/topojson/escaped.topojson"); + mapnik::context_ptr ctx = std::make_shared(); + mapnik::transcoder tr("utf8"); + mapnik::topojson::topology topo; + REQUIRE(parse_topology(filename, topo)); + mapnik::value_integer feature_id = 0; + for (auto const& geom : topo.geometries) + { + mapnik::box2d bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom); + CHECK(bbox.valid()); + mapnik::topojson::feature_generator visitor(ctx, tr, topo, feature_id); + mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom); + CHECK(feature); + CHECK(feature->envelope() == bbox); + std::initializer_list attrs = { + attr{"name", tr.transcode("Test")}, + attr{"NOM_FR", tr.transcode("Québec")}, + attr{"boolean", mapnik::value_bool("true")}, + attr{"description", tr.transcode("Test: \u005C")}, + attr{"double", mapnik::value_double(1.1)}, + attr{"int", mapnik::value_integer(1)}, + attr{"object", tr.transcode("{name:\"waka\",spaces:\"value with spaces\",int:1,double:1.1,boolean:false" + ",NOM_FR:\"Québec\",array:[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],another_object:{name:\"nested object\"}}")}, + attr{"spaces", tr.transcode("this has spaces")}, + attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{name:\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", tr.transcode("[]")}, + attr{"empty_object", tr.transcode("{}")}, + }; + REQUIRE_ATTRIBUTES(feature, attrs); + } + } + +} diff --git a/test/unit/geometry/geometry.cpp b/test/unit/geometry/geometry.cpp index 60f9c0b95..53c1e2e57 100644 --- a/test/unit/geometry/geometry.cpp +++ b/test/unit/geometry/geometry.cpp @@ -1,4 +1,3 @@ - #include "catch.hpp" #include @@ -10,7 +9,7 @@ TEST_CASE("geometry") { SECTION("json point") { mapnik::util::file input("./test/data/json/point1.json"); - REQUIRE( input.open() ); + REQUIRE( input ); mapnik::geometry::geometry geom; REQUIRE( input.data() ); std::string json_string(input.data().get(), input.size()); @@ -25,7 +24,7 @@ SECTION("json point") { SECTION("json point reversed") { mapnik::util::file input("./test/data/json/point2.json"); - REQUIRE( input.open() ); + REQUIRE( input ); mapnik::geometry::geometry geom; REQUIRE( input.data() ); std::string json_string(input.data().get(), input.size()); @@ -38,7 +37,7 @@ SECTION("json point reversed") { SECTION("json point reversed + extra attributes") { mapnik::util::file input("./test/data/json/point3.json"); - REQUIRE( input.open() ); + REQUIRE( input ); mapnik::geometry::geometry geom; REQUIRE( input.data() ); std::string json_string(input.data().get(), input.size()); diff --git a/test/unit/geometry/geometry_envelope_test.cpp b/test/unit/geometry/geometry_envelope_test.cpp index fd5d78fbd..75049820a 100644 --- a/test/unit/geometry/geometry_envelope_test.cpp +++ b/test/unit/geometry/geometry_envelope_test.cpp @@ -1,17 +1,19 @@ - #include "catch.hpp" #include #include -#include -TEST_CASE("geometry ops - envelope") { +namespace { -SECTION("envelope_test - double") { +template +void envelope_test() +{ using namespace mapnik::geometry; + using coord_type = T; + { - geometry geom(point(1,2)); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(point(1,2)); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == 1 ); REQUIRE( bbox.miny() == 2 ); REQUIRE( bbox.maxx() == 1 ); @@ -19,80 +21,67 @@ SECTION("envelope_test - double") { } { // Test empty geom - geometry geom = mapnik::geometry::geometry_empty(); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom = mapnik::geometry::geometry_empty(); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE_FALSE( bbox.valid() ); } { - line_string line; + line_string line; line.add_coord(0,0); line.add_coord(1,1); line.add_coord(2,2); - geometry geom(line); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(line); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == 0 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 2 ); REQUIRE( bbox.maxy() == 2 ); } { - line_string line; + line_string line; line.add_coord(0,0); line.add_coord(1,1); line.add_coord(2,2); - line_string line2; + line_string line2; line2.add_coord(0,0); line2.add_coord(-1,-1); line2.add_coord(-2,-2); - multi_line_string multi_line; + multi_line_string multi_line; multi_line.emplace_back(std::move(line)); multi_line.emplace_back(std::move(line2)); - geometry geom(multi_line); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(multi_line); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == -2 ); REQUIRE( bbox.miny() == -2 ); REQUIRE( bbox.maxx() == 2 ); REQUIRE( bbox.maxy() == 2 ); } { - polygon poly; - linear_ring ring; + polygon poly; + linear_ring ring; ring.add_coord(0,0); ring.add_coord(-10,0); ring.add_coord(-10,10); ring.add_coord(0,10); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); - geometry geom(poly); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(poly); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - multi_polygon mp; + multi_polygon mp; mp.push_back(poly); - geometry geom_mp(mp); + geometry geom_mp(mp); bbox = mapnik::geometry::envelope(geom_mp); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - correct(geom); - bbox = mapnik::geometry::envelope(geom); - REQUIRE( bbox.minx() == -10 ); - REQUIRE( bbox.miny() == 0 ); - REQUIRE( bbox.maxx() == 0 ); - REQUIRE( bbox.maxy() == 10 ); - correct(geom_mp); - bbox = mapnik::geometry::envelope(geom_mp); - REQUIRE( bbox.minx() == -10 ); - REQUIRE( bbox.miny() == 0 ); - REQUIRE( bbox.maxx() == 0 ); - REQUIRE( bbox.maxy() == 10 ); - - geometry_collection gc; + geometry_collection gc; bbox = mapnik::geometry::envelope(gc); REQUIRE_FALSE( bbox.valid() ); gc.push_back(geom_mp); @@ -101,7 +90,7 @@ SECTION("envelope_test - double") { REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - gc.emplace_back(point(-50,-50)); + gc.emplace_back(point(-50,-50)); bbox = mapnik::geometry::envelope(gc); REQUIRE( bbox.minx() == -50 ); REQUIRE( bbox.miny() == -50 ); @@ -111,30 +100,30 @@ SECTION("envelope_test - double") { { // polygon with hole - polygon poly; - linear_ring ring; + polygon poly; + linear_ring ring; ring.add_coord(0,0); ring.add_coord(-10,0); ring.add_coord(-10,10); ring.add_coord(0,10); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); - linear_ring hole; + linear_ring hole; hole.add_coord(-7,7); hole.add_coord(-7,3); hole.add_coord(-3,3); hole.add_coord(-3,7); hole.add_coord(-7,7); poly.add_hole(std::move(hole)); - geometry geom(poly); - mapnik::box2d bbox = mapnik::geometry::envelope(poly); + geometry geom(poly); + mapnik::box2d bbox = mapnik::geometry::envelope(poly); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); // add another hole inside the first hole // which should be considered a hit - linear_ring fill; + linear_ring fill; fill.add_coord(-6,4); fill.add_coord(-6,6); fill.add_coord(-4,6); @@ -150,3 +139,14 @@ SECTION("envelope_test - double") { } } + +TEST_CASE("geometry ops - envelope") { + +SECTION("envelope_test") +{ + envelope_test(); + envelope_test(); + envelope_test(); +} + +} diff --git a/test/unit/geometry/geometry_equal.hpp b/test/unit/geometry/geometry_equal.hpp index f8ebc4d25..4ff80abab 100644 --- a/test/unit/geometry/geometry_equal.hpp +++ b/test/unit/geometry/geometry_equal.hpp @@ -1,4 +1,3 @@ - #ifndef MAPNIK_UNIT_GEOMETRY_EQUAL #define MAPNIK_UNIT_GEOMETRY_EQUAL @@ -85,7 +84,15 @@ auto zip_crange(Conts&... conts) #include #include -using namespace mapnik::geometry; +using mapnik::geometry::geometry; +using mapnik::geometry::geometry_empty; +using mapnik::geometry::point; +using mapnik::geometry::line_string; +using mapnik::geometry::polygon; +using mapnik::geometry::multi_point; +using mapnik::geometry::multi_line_string; +using mapnik::geometry::multi_polygon; +using mapnik::geometry::geometry_collection; template void assert_g_equal(geometry const& g1, geometry const& g2); diff --git a/test/unit/geometry/geometry_test_helper.cpp b/test/unit/geometry/geometry_test_helper.cpp new file mode 100644 index 000000000..44bcce596 --- /dev/null +++ b/test/unit/geometry/geometry_test_helper.cpp @@ -0,0 +1,15 @@ +#include +#include +#include + + +namespace mapnik { namespace geometry { +// instantiate types required by geometry_envelope_test +template mapnik::box2d envelope(geometry const& geom); +template mapnik::box2d envelope(geometry const& geom); +template mapnik::box2d envelope(polygon const& geom); +template mapnik::box2d envelope(polygon const& geom); +template mapnik::box2d envelope(geometry_collection const& geom); +template mapnik::box2d envelope(geometry_collection const& geom); + +}} diff --git a/test/unit/geometry/is_clockwise.cpp b/test/unit/geometry/is_clockwise.cpp new file mode 100644 index 000000000..42aebf6cf --- /dev/null +++ b/test/unit/geometry/is_clockwise.cpp @@ -0,0 +1,27 @@ +#include "catch.hpp" + +#include +#include + +TEST_CASE("Ring is_clockwise") { + + // Input is rather thin triangle to test precision issues aren't getting in the way. + SECTION("Clockwise") + { + mapnik::geometry::linear_ring ring; + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + ring.emplace_back(-13499697.1113113686, 4698431.85179749783); + ring.emplace_back(-13499697.0366658326, 4698431.92644303292); + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + REQUIRE(mapnik::util::is_clockwise(ring) == true); + } + SECTION("Anti-Clockwise") + { + mapnik::geometry::linear_ring ring; + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + ring.emplace_back(-13499697.0366658326, 4698431.92644303292); + ring.emplace_back(-13499697.1113113686, 4698431.85179749783); + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + REQUIRE(mapnik::util::is_clockwise(ring) == false); + } +} diff --git a/test/unit/imaging/image_io_test.cpp b/test/unit/imaging/image_io_test.cpp index 7591d487a..c562148dc 100644 --- a/test/unit/imaging/image_io_test.cpp +++ b/test/unit/imaging/image_io_test.cpp @@ -14,7 +14,15 @@ #include #endif +#pragma GCC diagnostic push +#include #include +#include +#pragma GCC diagnostic pop + +inline void make_directory(std::string const& dir) { + boost::filesystem::create_directories(dir); +} TEST_CASE("image io") { @@ -144,25 +152,33 @@ SECTION("image_util : save_to_file/save_to_stream/save_to_string") supported_types.push_back(std::make_tuple("webp","webp")); #endif + std::string directory_name("/tmp/mapnik-tests/"); + make_directory(directory_name); + REQUIRE(mapnik::util::exists(directory_name)); + for (auto const& info : supported_types) { std::string extension; std::string format; std::tie(extension, format) = info; - std::string filename = (boost::format("/tmp/mapnik-%1%.%2%") % named_color % extension).str(); + std::string filename = (boost::format(directory_name + "mapnik-%1%.%2%") % named_color % extension).str(); mapnik::save_to_file(im, filename); std::string str = mapnik::save_to_string(im, format); std::ostringstream ss; mapnik::save_to_stream(im, ss, format); CHECK(str.length() == ss.str().length()); - std::unique_ptr reader(mapnik::get_image_reader(filename, extension)); - unsigned w = reader->width(); - unsigned h = reader->height(); - auto im2 = reader->read(0, 0, w, h); - CHECK(im2.size() == im.size()); - if (extension == "png" || extension == "tiff") + // wrap reader in scope to ensure the file handle is + // released before we try to remove the file { - CHECK(0 == std::memcmp(im2.bytes(), im.bytes(), im.width() * im.height())); + std::unique_ptr reader(mapnik::get_image_reader(filename, extension)); + unsigned w = reader->width(); + unsigned h = reader->height(); + auto im2 = reader->read(0, 0, w, h); + CHECK(im2.size() == im.size()); + if (extension == "png" || extension == "tiff") + { + CHECK(0 == std::memcmp(im2.bytes(), im.bytes(), im.width() * im.height())); + } } if (mapnik::util::exists(filename)) { diff --git a/test/unit/imaging/tiff_io.cpp b/test/unit/imaging/tiff_io.cpp index 1ace38fa1..14f9e5f29 100644 --- a/test/unit/imaging/tiff_io.cpp +++ b/test/unit/imaging/tiff_io.cpp @@ -1,4 +1,3 @@ - // disabled on windows due to https://github.com/mapnik/mapnik/issues/2838 // TODO - get to the bottom of why including `tiff_reader.cpp` breaks windows // or re-write image_readers to allow `#include tiff_reader.hpp` @@ -12,7 +11,7 @@ #include "../../../src/tiff_reader.cpp" #define TIFF_ASSERT(filename) \ - mapnik::tiff_reader tiff_reader(filename); \ + mapnik::tiff_reader tiff_reader(filename); \ REQUIRE( tiff_reader.width() == 256 ); \ REQUIRE( tiff_reader.height() == 256 ); \ REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \ @@ -20,7 +19,7 @@ REQUIRE( reader->width() == 256 ); \ REQUIRE( reader->height() == 256 ); \ mapnik::util::file file(filename); \ - mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); \ + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); \ REQUIRE( tiff_reader2.width() == 256 ); \ REQUIRE( tiff_reader2.height() == 256 ); \ std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); \ @@ -57,11 +56,13 @@ REQUIRE( subimage.width() == 1 ); \ REQUIRE( subimage.height() == 1 ); \ -TEST_CASE("tiff io") { +TEST_CASE("tiff io") +{ -SECTION("scan rgb8 striped") { +SECTION("scan rgb8 striped") +{ std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif"); - mapnik::tiff_reader tiff_reader(filename); + mapnik::tiff_reader tiff_reader(filename); REQUIRE( tiff_reader.width() == 512 ); REQUIRE( tiff_reader.height() == 512 ); REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); @@ -76,7 +77,7 @@ SECTION("scan rgb8 striped") { REQUIRE( reader->width() == 512 ); REQUIRE( reader->height() == 512 ); mapnik::util::file file(filename); - mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); REQUIRE( tiff_reader2.width() == 512 ); REQUIRE( tiff_reader2.height() == 512 ); std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); @@ -91,7 +92,7 @@ SECTION("scan rgb8 striped") { SECTION("scan rgb8 tiled") { std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif"); - mapnik::tiff_reader tiff_reader(filename); + mapnik::tiff_reader tiff_reader(filename); REQUIRE( tiff_reader.width() == 512 ); REQUIRE( tiff_reader.height() == 512 ); REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); @@ -106,7 +107,7 @@ SECTION("scan rgb8 tiled") { REQUIRE( reader->width() == 512 ); REQUIRE( reader->height() == 512 ); mapnik::util::file file(filename); - mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); REQUIRE( tiff_reader2.width() == 512 ); REQUIRE( tiff_reader2.height() == 512 ); std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); diff --git a/test/unit/serialization/parse_hex.hpp b/test/unit/serialization/parse_hex.hpp new file mode 100644 index 000000000..48c70a5d4 --- /dev/null +++ b/test/unit/serialization/parse_hex.hpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_PARSE_HEX_HPP +#define MAPNIK_PARSE_HEX_HPP + +#include +#include + +namespace mapnik { namespace util { + +template +bool parse_hex(std::string const& input, Out & output) +{ + boost::spirit::qi::lit_type lit; + auto itr = input.begin(); + auto end = input.end(); + using hex2 = boost::spirit::qi::uint_parser< unsigned, 16, 2, 2 >; + return boost::spirit::qi::parse(itr, end, -(lit("\\x") | lit("0x")) > *hex2(), output); +} + +}} + + +#endif // MAPNIK_PARSE_HEX_HPP diff --git a/test/unit/serialization/wkb_formats_test.cpp b/test/unit/serialization/wkb_formats_test.cpp index 698645266..bc0c17198 100644 --- a/test/unit/serialization/wkb_formats_test.cpp +++ b/test/unit/serialization/wkb_formats_test.cpp @@ -1,13 +1,10 @@ - #include "catch.hpp" #include #include -#include #include #include #include -#include #include TEST_CASE("geometry formats") { @@ -56,9 +53,6 @@ SECTION("wkb") { unsigned char sq_invalid_blob[] = { 0x23, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x23 }; - mapnik::context_ptr ctx(new mapnik::context_type); - mapnik::feature_ptr feature = mapnik::feature_factory::create(ctx, 1); - // test of parsing wkb geometries try { diff --git a/test/unit/serialization/wkb_test.cpp b/test/unit/serialization/wkb_test.cpp new file mode 100644 index 000000000..8a617df26 --- /dev/null +++ b/test/unit/serialization/wkb_test.cpp @@ -0,0 +1,117 @@ +#include "catch.hpp" +// mapnik +#include +#include +#include +#include +#include +// bool +#include +#include +#include +// stl +#include "parse_hex.hpp" +#include +#include +#include +#include + +#if BOOST_VERSION >= 105800 +namespace { + +struct spatially_equal_visitor +{ + using result_type = bool; + + result_type operator() (mapnik::geometry::geometry_empty, mapnik::geometry::geometry_empty) const + { + return true; + } + + result_type operator() (mapnik::geometry::geometry_collection const& lhs, mapnik::geometry::geometry_collection const& rhs) const + { + std::size_t size0 = lhs.size(); + std::size_t size1 = rhs.size(); + if (size0 != size1) return false; + for (std::size_t index = 0; index < size0 ; ++index) + { + if (!mapnik::util::apply_visitor(*this, lhs[index], rhs[index])) + return false; + } + return true; + } + + result_type operator() (mapnik::geometry::multi_point const& lhs, mapnik::geometry::multi_point const& rhs) const + { + std::size_t size0 = lhs.size(); + std::size_t size1 = rhs.size(); + if (size0 != size1) return false; + auto tmp0 = lhs; + auto tmp1 = rhs; + std::sort(tmp0.begin(), tmp0.end(), boost::geometry::less>()); + std::sort(tmp1.begin(), tmp1.end(), boost::geometry::less>()); + for (std::size_t index = 0; index < size0 ; ++index) + { + if (!boost::geometry::equals(tmp0[index], tmp1[index])) return false; + } + return true; + } + + template + result_type operator() (T const& lhs, T const& rhs) const + { + if (mapnik::geometry::is_empty(lhs) && mapnik::geometry::is_empty(rhs)) + return true; //Empty geometries of the same type are considered to be spatially equal + return boost::geometry::equals(lhs, rhs); + } + + template + result_type operator() (T0 const& lhs, T1 const& rhs) const + { + return false; + } + +}; + +template +bool spatially_equal(mapnik::geometry::geometry const& g0, mapnik::geometry::geometry const& g1) +{ + return mapnik::util::apply_visitor(spatially_equal_visitor(), g0, g1); +} + +} +#endif + +TEST_CASE("Well-known-geometries") +{ + SECTION("wkb") + { + std::string filename("test/unit/data/well-known-geometries.test"); + std::ifstream is(filename.c_str(),std::ios_base::in | std::ios_base::binary); + if (!is) throw std::runtime_error("could not open: '" + filename + "'"); + + for (std::string line; std::getline(is, line,'\n');) + { + std::vector columns; + boost::split(columns, line, boost::is_any_of(";")); + REQUIRE(columns.size() == 3); + std::vector wkb, twkb; + REQUIRE(mapnik::util::parse_hex(columns[1], wkb)); + REQUIRE(mapnik::util::parse_hex(columns[2], twkb)); + mapnik::geometry::geometry geom_0 = mapnik::geometry_utils::from_wkb(wkb.data(), wkb.size(), mapnik::wkbAuto); + mapnik::geometry::geometry geom_1 = mapnik::geometry_utils::from_twkb(twkb.data(), twkb.size()); + // compare WKTs + std::string wkt0, wkt1; + REQUIRE(mapnik::util::to_wkt(wkt0, geom_0)); + REQUIRE(mapnik::util::to_wkt(wkt1, geom_1)); + if (!mapnik::geometry::is_empty(geom_0) && !mapnik::geometry::is_empty(geom_1)) + { + REQUIRE(wkt0 == wkt1); + // compare spatially (NOTE: GeometryCollection comparison also enforces strict order) +#if BOOST_VERSION >= 105800 + REQUIRE(spatially_equal(geom_0, geom_1)); +#endif + } + } + } +} diff --git a/test/visual/renderer.hpp b/test/visual/renderer.hpp index 6b033f99c..7ea9198df 100644 --- a/test/visual/renderer.hpp +++ b/test/visual/renderer.hpp @@ -38,10 +38,21 @@ #if defined(GRID_RENDERER) #include #endif + #if defined(HAVE_CAIRO) #include #include +#ifdef CAIRO_HAS_SVG_SURFACE +#include #endif +#ifdef CAIRO_HAS_PS_SURFACE +#include +#endif +#ifdef CAIRO_HAS_PDF_SURFACE +#include +#endif +#endif + #if defined(SVG_RENDERER) #include #endif @@ -53,7 +64,7 @@ namespace visual_tests { template -struct renderer_base +struct raster_renderer_base { using image_type = ImageType; @@ -80,7 +91,35 @@ struct renderer_base } }; -struct agg_renderer : renderer_base +struct vector_renderer_base +{ + using image_type = std::string; + + static constexpr const bool support_tiles = false; + + unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const + { + std::ifstream stream(reference.string().c_str(), std::ios_base::in | std::ios_base::binary); + if (!stream) + { + throw std::runtime_error("Could not open: " + reference.string()); + } + std::string expected(std::istreambuf_iterator(stream.rdbuf()), std::istreambuf_iterator()); + return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); + } + + void save(image_type const & image, boost::filesystem::path const& path) const + { + std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); + if (!file) + { + throw std::runtime_error("Cannot open file for writing: " + path.string()); + } + file << image; + } +}; + +struct agg_renderer : raster_renderer_base { static constexpr const char * name = "agg"; @@ -94,7 +133,7 @@ struct agg_renderer : renderer_base }; #if defined(HAVE_CAIRO) -struct cairo_renderer : renderer_base +struct cairo_renderer : raster_renderer_base { static constexpr const char * name = "cairo"; @@ -111,14 +150,65 @@ struct cairo_renderer : renderer_base return image; } }; + +using surface_create_type = cairo_surface_t *(&)(cairo_write_func_t, void *, double, double); + +template +struct cairo_vector_renderer : vector_renderer_base +{ + static cairo_status_t write(void *closure, + const unsigned char *data, + unsigned int length) + { + std::ostringstream & ss = *reinterpret_cast(closure); + ss.write(reinterpret_cast(data), length); + return ss ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR; + } + + image_type render(mapnik::Map const & map, double scale_factor) const + { + std::ostringstream ss(std::stringstream::binary); + mapnik::cairo_surface_ptr image_surface( + SurfaceCreateFunction(write, &ss, map.width(), map.height()), + mapnik::cairo_surface_closer()); + mapnik::cairo_ptr image_context(mapnik::create_context(image_surface)); + mapnik::cairo_renderer ren(map, image_context, scale_factor); + ren.apply(); + cairo_surface_finish(&*image_surface); + return ss.str(); + } +}; + +#ifdef CAIRO_HAS_SVG_SURFACE +struct cairo_svg_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-svg"; + static constexpr const char * ext = ".svg"; +}; +#endif + +#ifdef CAIRO_HAS_PS_SURFACE +struct cairo_ps_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-ps"; + static constexpr const char * ext = ".ps"; +}; +#endif + +#ifdef CAIRO_HAS_PDF_SURFACE +struct cairo_pdf_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-pdf"; + static constexpr const char * ext = ".pdf"; +}; +#endif #endif #if defined(SVG_RENDERER) -struct svg_renderer : renderer_base +struct svg_renderer : vector_renderer_base { static constexpr const char * name = "svg"; static constexpr const char * ext = ".svg"; - static constexpr const bool support_tiles = false; image_type render(mapnik::Map const & map, double scale_factor) const { @@ -128,35 +218,11 @@ struct svg_renderer : renderer_base ren.apply(); return ss.str(); } - - unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const - { - std::ifstream stream(reference.string().c_str(),std::ios_base::in|std::ios_base::binary); - if (!stream.is_open()) - { - throw std::runtime_error("could not open: '" + reference.string() + "'"); - } - std::string expected(std::istreambuf_iterator(stream.rdbuf()),(std::istreambuf_iterator())); - stream.close(); - return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); - } - - void save(image_type const & image, boost::filesystem::path const& path) const - { - std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); - if (!file) { - throw std::runtime_error((std::string("cannot open file for writing file ") + path.string()).c_str()); - } else { - file << image; - file.close(); - } - } - }; #endif #if defined(GRID_RENDERER) -struct grid_renderer : renderer_base +struct grid_renderer : raster_renderer_base { static constexpr const char * name = "grid"; @@ -335,6 +401,15 @@ private: using renderer_type = mapnik::util::variant #if defined(HAVE_CAIRO) ,renderer +#ifdef CAIRO_HAS_SVG_SURFACE + ,renderer +#endif +#ifdef CAIRO_HAS_PS_SURFACE + ,renderer +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + ,renderer +#endif #endif #if defined(SVG_RENDERER) ,renderer diff --git a/test/visual/run.cpp b/test/visual/run.cpp index 70284bc3e..587727906 100644 --- a/test/visual/run.cpp +++ b/test/visual/run.cpp @@ -48,30 +48,48 @@ namespace po = boost::program_options; runner::renderer_container create_renderers(po::variables_map const & args, boost::filesystem::path const & output_dir, - bool append_all = false) + bool force_append = false) { boost::filesystem::path reference_dir(args["images-dir"].as()); bool overwrite = args.count("overwrite"); runner::renderer_container renderers; - if (append_all || args.count(agg_renderer::name)) + if (force_append || args.count(agg_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } #if defined(HAVE_CAIRO) - if (append_all || args.count(cairo_renderer::name)) + if (force_append || args.count(cairo_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } +#ifdef CAIRO_HAS_SVG_SURFACE + if (args.count(cairo_svg_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif +#ifdef CAIRO_HAS_PS_SURFACE + if (args.count(cairo_ps_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + if (args.count(cairo_pdf_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif #endif #if defined(SVG_RENDERER) - if (append_all || args.count(svg_renderer::name)) + if (force_append || args.count(svg_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } #endif #if defined(GRID_RENDERER) - if (append_all || args.count(grid_renderer::name)) + if (force_append || args.count(grid_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } @@ -112,6 +130,15 @@ int main(int argc, char** argv) (agg_renderer::name, "render with AGG renderer") #if defined(HAVE_CAIRO) (cairo_renderer::name, "render with Cairo renderer") +#ifdef CAIRO_HAS_SVG_SURFACE + (cairo_svg_renderer::name, "render with Cairo SVG renderer") +#endif +#ifdef CAIRO_HAS_PS_SURFACE + (cairo_ps_renderer::name, "render with Cairo PS renderer") +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + (cairo_pdf_renderer::name, "render with Cairo PDF renderer") +#endif #endif #if defined(SVG_RENDERER) (svg_renderer::name, "render with SVG renderer") @@ -183,7 +210,7 @@ int main(int argc, char** argv) } catch (std::exception & e) { - std::cerr << "Error runnig tests: " << e.what() << std::endl; + std::cerr << "Error running tests: " << e.what() << std::endl; return 1; } diff --git a/utils/mapnik-config/build.py b/utils/mapnik-config/build.py index bf3e5b304..e4178ba41 100644 --- a/utils/mapnik-config/build.py +++ b/utils/mapnik-config/build.py @@ -131,11 +131,6 @@ mapnik_bundled_gdal_data = '' mapnik_bundled_proj_data = '' mapnik_bundled_icu_data = '' -if config_env.get('MAPNIK_BUNDLED_SHARE_DIRECTORY'): - mapnik_bundled_gdal_data = 'lib/mapnik/share/gdal' - mapnik_bundled_proj_data = 'lib/mapnik/share/proj' - mapnik_bundled_icu_data = 'lib/mapnik/share/icu' - configuration = { "git_revision": git_revision, "git_describe": git_describe, diff --git a/utils/mapnik-index/mapnik-index.cpp b/utils/mapnik-index/mapnik-index.cpp index f6f72be1d..9b1859bf2 100644 --- a/utils/mapnik-index/mapnik-index.cpp +++ b/utils/mapnik-index/mapnik-index.cpp @@ -163,7 +163,7 @@ int main (int argc, char** argv) std::clog << "max tree depth:" << depth << std::endl; std::clog << "split ratio:" << ratio << std::endl; - using box_type = mapnik::box2d; + using box_type = mapnik::box2d; using item_type = std::pair>; for (auto const& filename : files_to_process) @@ -175,12 +175,16 @@ int main (int argc, char** argv) } std::vector boxes; - mapnik::box2d extent; + box_type extent; if (mapnik::detail::is_csv(filename)) { std::clog << "processing '" << filename << "' as CSV\n"; auto result = mapnik::detail::process_csv_file(boxes, filename, manual_headers, separator, quote); - if (!result.first) continue; + if (!result.first) + { + std::clog << "Error: failed to process " << filename << std::endl; + return EXIT_FAILURE; + } extent = result.second; } else if (mapnik::detail::is_geojson(filename)) @@ -190,7 +194,7 @@ int main (int argc, char** argv) if (!result.first) { std::clog << "Error: failed to process " << filename << std::endl; - continue; + return EXIT_FAILURE; } extent = result.second; } @@ -198,10 +202,12 @@ int main (int argc, char** argv) if (extent.valid()) { std::clog << extent << std::endl; - mapnik::quad_tree> tree(extent, depth, ratio); + mapnik::box2d extent_d(extent.minx(), extent.miny(), extent.maxx(), extent.maxy()); + mapnik::quad_tree> tree(extent_d, depth, ratio); for (auto const& item : boxes) { - tree.insert(std::get<1>(item), std::get<0>(item)); + auto ext_f = std::get<0>(item); + tree.insert(std::get<1>(item), mapnik::box2d(ext_f.minx(), ext_f.miny(), ext_f.maxx(), ext_f.maxy())); } std::fstream file((filename + ".index").c_str(), @@ -222,6 +228,11 @@ int main (int argc, char** argv) file.close(); } } + else + { + std::clog << "Invalid extent " << extent << std::endl; + return EXIT_FAILURE; + } } std::clog << "done!" << std::endl; return EXIT_SUCCESS; diff --git a/utils/mapnik-index/process_csv_file.cpp b/utils/mapnik-index/process_csv_file.cpp index fa3b68264..a0342cff5 100644 --- a/utils/mapnik-index/process_csv_file.cpp +++ b/utils/mapnik-index/process_csv_file.cpp @@ -44,8 +44,9 @@ namespace mapnik { namespace detail { template -std::pair> process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote) +std::pair process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote) { + using box_type = typename T::value_type::first_type; csv_utils::csv_file_parser p; p.manual_headers_ = manual_headers; p.separator_ = separator; @@ -65,7 +66,7 @@ std::pair> process_csv_file(T & boxes, std::string const& fil else { std::clog << "Error : cannot mmap " << filename << std::endl; - return std::make_pair(false, p.extent_); + return std::make_pair(false, box_type(p.extent_)); } #else #if defined(_WINDOWS) @@ -76,24 +77,24 @@ std::pair> process_csv_file(T & boxes, std::string const& fil if (!csv_file.is_open()) { std::clog << "Error : cannot open " << filename << std::endl; - return std::make_pair(false, p.extent_); + return std::make_pair(false, box_type(p.extent_)); } #endif try { - p.parse_csv(csv_file, boxes); - return std::make_pair(true, p.extent_); + p.parse_csv_and_boxes(csv_file, boxes); + return std::make_pair(true, box_type(p.extent_)); } catch (std::exception const& ex) { std::clog << ex.what() << std::endl; - return std::make_pair(false, p.extent_); + return std::make_pair(false, box_type(p.extent_)); } } -using box_type = mapnik::box2d; +using box_type = mapnik::box2d; using item_type = std::pair>; using boxes_type = std::vector; -template std::pair> process_csv_file(boxes_type&, std::string const&, std::string const&, char, char); +template std::pair process_csv_file(boxes_type&, std::string const&, std::string const&, char, char); }} diff --git a/utils/mapnik-index/process_csv_file.hpp b/utils/mapnik-index/process_csv_file.hpp index f84393d7c..395bf55c7 100644 --- a/utils/mapnik-index/process_csv_file.hpp +++ b/utils/mapnik-index/process_csv_file.hpp @@ -29,7 +29,7 @@ namespace mapnik { namespace detail { template -std::pair> process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote); +std::pair process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote); }} diff --git a/utils/mapnik-index/process_geojson_file.cpp b/utils/mapnik-index/process_geojson_file.cpp index fb393a938..44553185f 100644 --- a/utils/mapnik-index/process_geojson_file.cpp +++ b/utils/mapnik-index/process_geojson_file.cpp @@ -38,33 +38,38 @@ #include namespace { + +template struct feature_validate_callback { - feature_validate_callback(mapnik::box2d const& box) + feature_validate_callback(mapnik::box2d const& box) : box_(box) {} void operator() (mapnik::feature_ptr const& f) const { - if (box_ != f->envelope()) + if (box_ != box_) { throw std::runtime_error("Bounding boxes mismatch validation feature"); } } - mapnik::box2d const& box_; + mapnik::box2d const& box_; }; +using box_type = mapnik::box2d; +using boxes_type = std::vector>>; using base_iterator_type = char const*; -const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; +const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; const mapnik::transcoder tr("utf8"); -const mapnik::json::feature_grammar_callback fc_grammar(tr); +const mapnik::json::feature_grammar_callback> fc_grammar(tr); } namespace mapnik { namespace detail { template -std::pair> process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose) +std::pair process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose) { - mapnik::box2d extent; + using box_type = typename T::value_type::first_type; + box_type extent; #if defined(MAPNIK_MEMORY_MAPPED_FILE) mapnik::mapped_region_ptr mapped_region; boost::optional memory = @@ -82,7 +87,7 @@ std::pair> process_geojson_file(T & boxes, std::string const& char const* end = start + mapped_region->get_size(); #else mapnik::util::file file(filename); - if (!file.open()) + if (!file) { std::clog << "Error : cannot open " << filename << std::endl; return std::make_pair(false, extent); @@ -121,7 +126,7 @@ std::pair> process_geojson_file(T & boxes, std::string const& { base_iterator_type feat_itr = start + item.second.first; base_iterator_type feat_end = feat_itr + item.second.second; - feature_validate_callback callback(item.first); + feature_validate_callback callback(item.first); bool result = boost::spirit::qi::phrase_parse(feat_itr, feat_end, (fc_grammar) (boost::phoenix::ref(ctx), boost::phoenix::ref(start_id), boost::phoenix::ref(callback)), space); @@ -136,9 +141,6 @@ std::pair> process_geojson_file(T & boxes, std::string const& return std::make_pair(true, extent); } -using box_type = mapnik::box2d; -using item_type = std::pair>; -using boxes_type = std::vector; -template std::pair> process_geojson_file(boxes_type&, std::string const&, bool, bool); +template std::pair process_geojson_file(boxes_type&, std::string const&, bool, bool); }} diff --git a/utils/mapnik-index/process_geojson_file.hpp b/utils/mapnik-index/process_geojson_file.hpp index aba49114a..a377d23e3 100644 --- a/utils/mapnik-index/process_geojson_file.hpp +++ b/utils/mapnik-index/process_geojson_file.hpp @@ -29,7 +29,7 @@ namespace mapnik { namespace detail { template -std::pair> process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose); +std::pair process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose); }} diff --git a/utils/mapnik-render/mapnik-render.cpp b/utils/mapnik-render/mapnik-render.cpp index c39922639..c172995c7 100644 --- a/utils/mapnik-render/mapnik-render.cpp +++ b/utils/mapnik-render/mapnik-render.cpp @@ -21,7 +21,7 @@ int main (int argc,char** argv) namespace po = boost::program_options; bool verbose = false; - bool auto_open = true; + bool auto_open = false; int return_value = 0; std::string xml_file; std::string img_file; @@ -37,7 +37,7 @@ int main (int argc,char** argv) ("help,h", "produce usage message") ("version,V","print version string") ("verbose,v","verbose output") - ("open","automatically open the file after rendering (os x only)") + ("open","automatically open the file after rendering") ("xml",po::value(),"xml map to read") ("img",po::value(),"image to render") ("scale-factor",po::value(),"scale factor for rendering") diff --git a/utils/pgsql2sqlite/main.cpp b/utils/pgsql2sqlite/main.cpp index 39ced62be..81eff635e 100644 --- a/utils/pgsql2sqlite/main.cpp +++ b/utils/pgsql2sqlite/main.cpp @@ -26,10 +26,13 @@ #include #include "connection_manager.hpp" -// boost +#pragma GCC diagnostic push +#include #include -#include #include +#pragma GCC diagnostic pop + +#include //stl #include diff --git a/utils/pgsql2sqlite/sqlite.hpp b/utils/pgsql2sqlite/sqlite.hpp index 07d2128a3..be4e4a384 100644 --- a/utils/pgsql2sqlite/sqlite.hpp +++ b/utils/pgsql2sqlite/sqlite.hpp @@ -24,8 +24,11 @@ #include // boost #include -//sqlite3 + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop //stl #ifdef MAPNIK_DEBUG diff --git a/utils/svg2png/svg2png.cpp b/utils/svg2png/svg2png.cpp index c7fe79735..b78f53b16 100644 --- a/utils/svg2png/svg2png.cpp +++ b/utils/svg2png/svg2png.cpp @@ -40,12 +40,16 @@ #include #pragma GCC diagnostic pop +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_renderer_base.h" #include "agg_pixfmt_rgba.h" #include "agg_scanline_u.h" +#pragma GCC diagnostic pop + struct main_marker_visitor {