Compare commits

...

109 commits

Author SHA1 Message Date
Dane Springmeyer
44e8b6d51f try appveyor installed via mapnik-gyp/build.bat like before 2017-05-31 10:43:17 -07:00
Dane Springmeyer
ce47610677 update font path in test file 2017-05-31 10:41:34 -07:00
Dane Springmeyer
e6173385ca use latest version of mason 2017-05-25 11:31:16 -07:00
artemp
09933916d6 fix spelling 2017-05-19 14:40:47 +02:00
artemp
185d788ea4 Backport TIFF I/O fixes from master (ref #3669 #3670) 2017-05-19 13:47:11 +02:00
artemp
99a7fa5044 Revert "update visual data one more time." : wrong branch
This reverts commit de533ab712.
2017-05-17 21:21:02 +02:00
artemp
de533ab712 update visual data one more time. 2017-05-17 21:17:11 +02:00
Blake Thompson
125cd694b8 Updated changelog 2017-05-12 12:16:25 -05:00
Blake Thompson
5911fe6374 Merge pull request #3668 from mapnik/raster_overzoom_quest
Raster Overzoom Quest
2017-05-12 11:48:34 -05:00
Blake Thompson
b29e56051c Merge branch 'v3.0.x' into raster_overzoom_quest 2017-05-12 10:59:32 -05:00
Blake Thompson
7222129e6c Update visual test data to 3.0.x branch 2017-05-12 10:55:48 -05:00
artemp
ab783cbec4 Merge branch 'raster_overzoom_quest' of https://github.com/mapnik/mapnik into raster_overzoom_quest 2017-05-12 15:25:44 +02:00
Blake Thompson
baf6c9f321 Updated tests, changed boostrap to use latest released mason 2017-05-11 09:57:18 -05:00
Blake Thompson
e945eb74fe Merge pull request #3672 from mapnik/filter_factor_removal
Removed filter factor
2017-05-10 16:02:17 -05:00
Blake Thompson
bc9dcdc584 Updated visual test data 2017-05-10 13:31:11 -05:00
Dane Springmeyer
2fd1f098f5 update to latest 3.0.x test-data-visual branch 2017-05-10 10:06:31 -07:00
Blake Thompson
318be793f9 Removed filter factor 2017-05-10 09:04:29 -05:00
Blake Thompson
adacb16a2c Removed 0.5 limit on width and height in gdal plugin, added new visual tests 2017-05-09 12:15:03 -05:00
artemp
85d7f28610 remove QMAKE_MAC_SDK requirement - just use what is available 2017-05-09 09:54:51 +02:00
Blake Thompson
170e20e864 First attempt at making raster overzooming and scaling work correctly and handle offsets properly. 2017-05-08 22:37:35 -05:00
Dane Springmeyer
b53db334af link -ldl last 2017-04-19 18:30:34 -07:00
Dane Springmeyer
1632018a14 pgsql2sqlite:also link -ldl on linux 2017-04-19 18:10:03 -07:00
artemp
9f4a138b8b fix formatting 2017-04-06 10:43:12 +01:00
artemp
149d2ca0a1 Avoid using c++14 extensions as v3.0.x should only require c++11 compliant compiler (fixes #3645). 2017-03-29 10:09:48 +01:00
Dane Springmeyer
635af3f4a3 point at 3.0.x branch of visual test data - refs mapnik/test-data-visual#46 2017-03-28 15:47:12 -07:00
Dane Springmeyer
9c4613f934 remove explicit instantiation of 'image_view<mapnik::image<mapnik::null_t> >' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] (clang 4.x) 2017-03-28 15:25:17 -07:00
Dane Springmeyer
520f3fd0a0 improve check padding script to see deps via submodules 2017-03-28 15:18:48 -07:00
artemp
15fb2debb0 fix compilation - auto args in lambda is c++14 oops 2017-03-23 16:21:38 +00:00
artemp
fa549b380a GeoJSON IO test - ensure geometries round-trip. 2017-03-23 15:01:50 +00:00
artemp
60d891f094 add "invalid" empty geometry tests 2017-03-22 15:07:07 +00:00
artemp
7caa0cffd4 from_geojson - catch all exceptions. 2017-03-22 15:06:34 +00:00
artemp
dbbf18c752 GeoJSON test - add empty geometries tests. 2017-03-22 14:41:08 +00:00
artemp
a1084e0c09 port GeoJSON parser/generator logic from master 2017-03-22 14:40:07 +00:00
Dane Springmeyer
c2fd522d0f remove mason latest publishing and triggered builds - refs #3639 2017-03-19 17:57:10 -07:00
Dane Springmeyer
dfccc5f6bb Merge pull request #3640 from mapnik/build-fixes
v3.0.x build fixes
2017-03-19 13:07:42 -07:00
Dane Springmeyer
284842a9d3 Merge pull request #3641 from mapnik/v3.0.x-more-dep-updates
Update mason deps
2017-03-19 12:39:30 -07:00
Dane Springmeyer
40753edadc Merge branch 'v3.0.x-more-dep-updates' into build-fixes 2017-03-19 12:38:57 -07:00
Dane Springmeyer
e0db6b9a47 consistently use pkg-config in both postgis plugin and pgsql2sqlite + use GDAL_CONFIG var in plugins 2017-03-18 19:40:18 -07:00
Dane Springmeyer
91515cad69 update sqlite, icu, ccache, and libpq 2017-03-18 19:39:09 -07:00
Dane Springmeyer
0c232313d6 update visual test down now that mapnik/test-data-visual#44 is merged 2017-03-10 16:51:46 -08:00
Dane Springmeyer
8665fc7313 Merge pull request #3614 from mapnik/3.0.x-mason-upgrades
3.0.x mason upgrades
2017-03-10 14:58:14 -08:00
Dane Springmeyer
08822729cc use zlib 1.2.8 package 2017-03-09 17:26:17 -08:00
Dane Springmeyer
f8e5f146ec update mason version 2017-03-09 17:20:31 -08:00
Dane Springmeyer
07de7155f1 upgrade to latest harfbuzz 2017-03-09 17:10:34 -08:00
Mickey Rose
3fbe7f61a6 load_map: avoid segfault when ShieldSymbolizer has invalid placements 2017-02-22 03:21:48 +01:00
Dane Springmeyer
3706fcf587 use mason v0.7.0 2017-02-09 18:00:01 -08:00
Dane Springmeyer
947ac81ee4 point at mason master until mason is tagged 2017-02-08 19:24:33 -08:00
Dane Springmeyer
163af7a40f update test-data - refs mapnik/test-data-visual#44 2017-02-08 17:31:46 -08:00
Dane Springmeyer
55e3e14f4d more code coverage adjustments 2017-02-08 15:05:48 -08:00
Dane Springmeyer
7483f6328c Add codecov.yml ignores 2017-02-08 15:02:47 -08:00
Dane Springmeyer
941a7eaf69 try codecov 2017-02-08 15:02:16 -08:00
artemp
489b7f2aca fix typo 2017-02-08 14:04:59 -08:00
artemp
4c22e631a7 remove remaining usage of deprecated dymamic exceptions: dtors are implicitely noexcept + qualify what methods with noexcept 2017-02-08 13:47:02 -08:00
artemp
2845cdc121 remove bogus throw() specifier from 'add_attribute' 2017-02-08 13:46:51 -08:00
artemp
0cd3bd8737 dynamic exceptions deprecated in c++11 and removed in c++17 (http://en.cppreference.com/w/cpp/language/except_spec) 2017-02-08 13:46:40 -08:00
Dane Springmeyer
85da8ef128 port fix for std::fread from master - a220bda05d 2017-02-08 13:33:41 -08:00
Dane Springmeyer
7affd674fd remove unused var [skip ci] 2017-02-08 13:31:13 -08:00
Dane Springmeyer
1f2de83531 also upgrade libpq 2017-02-08 13:04:35 -08:00
Dane Springmeyer
887964ae97 upgrade mason deps 2017-02-08 10:57:27 -08:00
artemp
c1267ebcd5 update CHANGELOG for mapnik v3.0.13 release [skip ci] 2017-02-08 14:06:42 +01:00
Dane Springmeyer
2a153c0d1f fix linking of postgis to boost_regex (when boost regex is statically linked to icu libs) 2017-02-07 12:54:12 -08:00
artemp
4f3e6f4846 update CHANGELOG 2017-02-06 16:00:00 +01:00
Artem Pavlenko
391a9f835b Merge pull request #3612 from mapnik/v3.0.x-3611
V3.0.x ref #3611
2017-02-06 14:26:01 +01:00
artemp
74e66bac58 test - update malformed featurecollection test (ref #3611) 2017-02-03 17:36:28 +01:00
artemp
d2d62bc95c Return failure on invalid bounding box when --validate-features option is used. (ref #3611) 2017-02-03 17:23:48 +01:00
artemp
8cc7060ef1 remove bounding box validity check (ref #3611) 2017-02-03 17:20:25 +01:00
Artem Pavlenko
e35bca7381 Merge pull request #3610 from mapnik/v3.0.x-3609
GeoJSON - backport positions grammar changes from master, fixes #3609
2017-02-03 11:28:22 +01:00
artemp
6cb3bce2d7 GeoJSON - backport positions grammar changes from master, fixes #3609 2017-02-03 11:22:24 +01:00
lightmare
17dcffaf78 Merge pull request #3583 from mapnik/v3.0.x-cherry-pr3566
v3.0.x cherry-pick #3566
2017-02-02 15:32:29 +01:00
Dane Springmeyer
1a268343a9 fix clang++ package name 2017-02-01 21:57:34 -08:00
Dane Springmeyer
7578534dc8 pass std::string to std::out_of_range 2017-02-01 21:54:27 -08:00
Dane Springmeyer
adcf611fab upgrad clang++ on circle too 2017-01-31 16:34:50 -08:00
Dane Springmeyer
8f06db6ac0 ensure mason check works via tag 2017-01-31 16:32:50 -08:00
Dane Springmeyer
401aade813 use clang++ 3.9.1 / pin mason to v0.5.0 2017-01-31 16:18:55 -08:00
artemp
ab206321b5 update version to 3.0.13 2017-01-20 14:40:35 +01:00
artemp
5db03aeb03 update test-data 2017-01-19 11:14:20 +01:00
artemp
2db538c470 update in prep for v3.0.13 release 2017-01-18 14:27:49 +01:00
artemp
8a3a380b3b fix blank line test for require headers.size() == 1 + reduce stderr verbosity. 2017-01-18 10:16:44 +01:00
artemp
ff4a1c1e9b use variant v1.1.5 2017-01-18 10:09:52 +01:00
Dane Springmeyer
7ce68e2c08 fix variant_io include 2017-01-04 15:22:36 -08:00
Dane Springmeyer
5b1c5f83cb Avoid -Winstantiation-after-specialization warnings 2017-01-04 15:08:08 -08:00
Dane Springmeyer
5d28a25ad3 Point as latest mason rather than branch 2017-01-04 11:45:55 -08:00
Artem Pavlenko
c71c1bc0a8 Merge pull request #3586 from lightmare/v3.0.x-groupsym-thunk-list
backport render_thunk_list change #3585 to v3.0.x branch
2017-01-04 10:30:05 +01:00
Mickey Rose
63128fdba1 can't store noncopyable list in std::vector
std::list can have a throwing move constructor.
std::vector of such lists makes copies when growing its storage array,
it doesn't move them.
render_thunk_list is noncopyable (because render_thunk is noncopyable),
and so can't be stored in std::vector in some STL implementations.
2017-01-03 22:53:39 +01:00
Mickey Rose
0a5495e442 change render_thunk_list to std::list<render_thunk>
Wrapping render_thunk in std::unique_ptr is one extra allocation per
element, with no purpose. The somewhat costly xyz_render_thunk move
constructor is only called once upon insertion, regardless of whether
we're emplacing render_thunk or unique_ptr.
2017-01-03 22:53:39 +01:00
Jiri Drbalek
b5c04cc132 find max element instead of std::sort 2017-01-02 03:53:53 +01:00
Jiri Drbalek
cdefee3524 remove redundant code 2017-01-02 03:53:53 +01:00
Dane Springmeyer
47443526a0 Merge pull request #3580 from mapnik/v3.0.x-cherry
Cherry pick stable commits from master into v3.0.x branch
2016-12-21 11:44:34 -08:00
Dane Springmeyer
a3b4e1f575 remove duplicate sudo:false from travis 2016-12-15 13:33:29 -08:00
Dane Springmeyer
283481b347 backport warnings fix from master for enumeration 2016-12-15 11:33:23 -08:00
Mickey Rose
fdd542a3c4 make mapnik_value_type_t C++11-friendly 2016-12-15 12:13:42 +01:00
Mickey Rose
06201e3842 bring C++14 type traits aliases for C++11 support 2016-12-15 12:12:12 +01:00
Dane Springmeyer
96ce2d8b3b update to latest variant 2016-12-14 18:25:41 -08:00
Mickey Rose
f00470dc02 simplify mapnik::value conversion rules
- fixes #3570

- avoids recursive exception-specification on value constructor
  by only constructing a temporary for arithmetic types (everything
  else passes a reference to the base variant constructor)

- also removes `is_same<decay_t<T>, value>` SFINAE check -- because
  we're only passing a reference down, explicitly forcing the compiler
  to use the implicitly-defined copy/move instead is pointless
2016-12-14 18:24:32 -08:00
artemp
dd5c134f01 update test to use std::unordered_map<mapnik::value, mapnik::value> 2016-12-14 18:24:29 -08:00
artemp
7c41b835ca use latest mapbox::variant 2016-12-14 18:24:26 -08:00
artemp
641cd6555e expand std::hash<mapnik::value> and operator== test for all types in mapnik::value 2016-12-14 18:24:22 -08:00
artemp
fa2d63c601 remove hash_combine (unused) 2016-12-14 18:24:19 -08:00
artemp
204d30e58d simplify hash calculation (we don't need combine with which(), using hash<T> is sufficient) 2016-12-14 18:24:15 -08:00
artemp
8dee1a9088 use mapbox namespace to fix name resolution 2016-12-14 18:23:02 -08:00
Mickey Rose
2b3fdf1bc9 fix #3526 GroupSymbolizer PairLayout with 3+ items 2016-12-14 18:21:52 -08:00
Jiri Drbalek
701a459427 duplicate code elimination 2016-12-14 18:21:30 -08:00
Dane Springmeyer
335c3e4265 allow visual test failures with g++ https://github.com/mapnik/mapnik/issues/3567 2016-12-14 18:21:18 -08:00
Dane Springmeyer
4cd55330dd avoid -Wshadow and 'unrecognized command line option' with gcc 2016-12-14 18:21:03 -08:00
Dane Springmeyer
b2f7bea7b5 try g++6 on precise 2016-12-14 18:20:52 -08:00
Dane Springmeyer
d5a9322a11 use clang 3.9, g++-6 2016-12-14 18:20:43 -08:00
Dane Springmeyer
d378ddbf66 mason packages are currently built with -D_GLIBCXX_USE_CXX11_ABI=0 2016-12-14 18:20:10 -08:00
Jiri Drbalek
27a0f3562d remove methods that are not referenced anywhere 2016-12-14 18:19:54 -08:00
artemp
4d4ea3a576 Fix clang >= 3.9.0 compilation by using mapbox::util::variant as alias (via deps/mapbox/variant => "types" branch) 2016-12-14 18:18:50 -08:00
79 changed files with 1472 additions and 1381 deletions

2
.gitmodules vendored
View file

@ -5,7 +5,7 @@
[submodule "test/data-visual"] [submodule "test/data-visual"]
path = test/data-visual path = test/data-visual
url = https://github.com/mapnik/test-data-visual.git url = https://github.com/mapnik/test-data-visual.git
branch = master branch = 3.0.x
[submodule "deps/mapbox/variant"] [submodule "deps/mapbox/variant"]
path = deps/mapbox/variant path = deps/mapbox/variant
url = https://github.com/mapbox/variant.git url = https://github.com/mapbox/variant.git

View file

@ -10,8 +10,6 @@ env:
- CCACHE_COMPRESS=1 - CCACHE_COMPRESS=1
- HEAVY_JOBS="2" - HEAVY_JOBS="2"
- PREFIX=/tmp/mapnik - PREFIX=/tmp/mapnik
- secure: "D5CLP5lbyFru788iZO8RqDenY/YsHPREvr34zCEi93xMqOTxPmME/zyuEZSyjP5ZLyf8g/fxOuPYSDbOQ1QLwNDBWxB0JomWOahyimHKrMCrMcGHCjl//2W2mE+p9VwF5VLGgfy7CskGkS49Mye37FDK0ejwuq6MDI45DsH4Fkk="
- secure: "ZPHyAVL3ID5g3KEmwcnzG9z2tAQwSx526Qd3Y6tsZ3Yj+aSagVBiZQjZGKWgNX74lymtmYKnb2Md46apWLeImt6tjB3MWTu7WwWoZRnqUligz/8Nmg4Lgo7EOCkQcjN/gpA1i+cM5b+ZKDTZYOaHO6/+DAaunQzA7/p99hw/XYg="
- secure: "F6ivqDNMBQQnrDGA9+7IX+GDswuIqQQd7YPJdQqa2Ked9jddAQDeJClb05ig3JlwfOlYLGZOd43ZX0pKuMtI2Gbkwz211agGP9S3YunwlRg8iWtJlO5kYFUdKCmJNhjg4icfkGELCgwXn+zuEWFSLpkPcjqAFKFlQrIJeAJJgKM=" - secure: "F6ivqDNMBQQnrDGA9+7IX+GDswuIqQQd7YPJdQqa2Ked9jddAQDeJClb05ig3JlwfOlYLGZOd43ZX0pKuMtI2Gbkwz211agGP9S3YunwlRg8iWtJlO5kYFUdKCmJNhjg4icfkGELCgwXn+zuEWFSLpkPcjqAFKFlQrIJeAJJgKM="
addons: addons:
postgresql: "9.4" postgresql: "9.4"
@ -25,24 +23,32 @@ matrix:
- os: linux - os: linux
sudo: false sudo: false
compiler: ": clang" compiler: ": clang"
env: JOBS=8 MASON_PUBLISH=true CXX="ccache clang++-3.8 -Qunused-arguments" CC="clang-3.8" TRIGGER=true env: JOBS=4 CXX="ccache g++-6" CC="gcc-6"
addons: addons:
apt: apt:
sources: [ 'ubuntu-toolchain-r-test'] sources: [ 'ubuntu-toolchain-r-test']
packages: [ 'libstdc++-5-dev', 'xutils-dev'] packages: [ 'libstdc++-6-dev', 'g++-6', 'xutils-dev']
- os: linux
sudo: false
compiler: ": clang"
env: JOBS=8 CXX="ccache clang++-3.9 -Qunused-arguments" CC="clang-3.9" TRIGGER=true
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test']
packages: [ 'libstdc++-4.9-dev', 'xutils-dev']
- os: linux - os: linux
sudo: false sudo: false
compiler: ": clang-coverage" compiler: ": clang-coverage"
env: JOBS=8 COVERAGE=true CXX="ccache clang++-3.8 -Qunused-arguments" CC="clang-3.8" env: JOBS=8 COVERAGE=true CXX="ccache clang++-3.9 -Qunused-arguments" CC="clang-3.9"
addons: addons:
apt: apt:
sources: [ 'ubuntu-toolchain-r-test'] sources: [ 'ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'xutils-dev' ] packages: ['libstdc++-4.9-dev', 'xutils-dev' ]
- os: osx - os: osx
compiler: ": clang-osx" compiler: ": clang-osx"
# https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions
osx_image: xcode7.3 # upgrades clang from 6 -> 7 osx_image: xcode7.3 # upgrades clang from 6 -> 7
env: JOBS=4 MASON_PUBLISH=true CXX="ccache clang++ -Qunused-arguments" env: JOBS=4 CXX="ccache clang++ -Qunused-arguments"
before_install: before_install:
# workaround travis rvm bug # workaround travis rvm bug
@ -52,18 +58,12 @@ before_install:
rvm get head || true rvm get head || true
fi fi
- source scripts/travis-common.sh - source scripts/travis-common.sh
- export PYTHONUSERBASE=$(pwd)/mason_packages/.link - export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PATH}
- export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PYTHONUSERBASE}/bin:${PATH}
- export COVERAGE=${COVERAGE:-false} - export COVERAGE=${COVERAGE:-false}
- export MASON_PUBLISH=${MASON_PUBLISH:-false}
- export BENCH=${BENCH:-false} - export BENCH=${BENCH:-false}
- if [[ ${TRAVIS_BRANCH} != 'master' ]]; then export MASON_PUBLISH=false; fi
- if [[ ${TRAVIS_PULL_REQUEST} != 'false' ]]; then export MASON_PUBLISH=false; fi
- git_submodule_update --init --depth=10 - git_submodule_update --init --depth=10
install: install:
- on 'linux' export PYTHONPATH=${PYTHONUSERBASE}/lib/python2.7/site-packages
- on 'osx' export PYTHONPATH=${PYTHONUSERBASE}/lib/python/site-packages
- on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres - on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres
- on 'osx' rm -rf ${DATA_PATH} - on 'osx' rm -rf ${DATA_PATH}
- on 'osx' initdb ${DATA_PATH} -E utf8 - on 'osx' initdb ${DATA_PATH} -E utf8
@ -72,16 +72,19 @@ install:
- on 'osx' createuser -s postgres - on 'osx' createuser -s postgres
- psql -c 'create database template_postgis;' -U postgres - psql -c 'create database template_postgis;' -U postgres
- psql -c 'create extension postgis;' -d template_postgis -U postgres - psql -c 'create extension postgis;' -d template_postgis -U postgres
- enabled ${COVERAGE} pip install --user cpp-coveralls - enabled ${COVERAGE} curl -S -f https://codecov.io/bash -o codecov
- enabled ${COVERAGE} chmod +x codecov
before_script: before_script:
- source bootstrap.sh - source bootstrap.sh
- | - |
if [[ $(uname -s) == 'Linux' ]]; then if [[ $(uname -s) == 'Linux' ]]; then
mason install clang 3.8.0 mason install clang++ 3.9.1
export PATH=$(mason prefix clang 3.8.0)/bin:${PATH} export PATH=$(mason prefix clang++ 3.9.1)/bin:${PATH}
which clang++ mason install llvm-cov 3.9.1
export LLVM_COV="$(mason prefix clang 3.8.0)/bin/llvm-cov" export PATH=$(mason prefix llvm-cov 3.9.1)/bin:${PATH}
which llvm-cov
export LLVM_COV="$(mason prefix llvm-cov 3.9.1)/bin/llvm-cov"
fi fi
- ccache --version - ccache --version
- ccache -p || true - ccache -p || true
@ -98,14 +101,9 @@ script:
# (and might work) for the next build # (and might work) for the next build
- DURATION=2400 - DURATION=2400
- scripts/travis-command-wrapper.py -s "date" -i 120 --deadline=$(( $(date +%s) + ${DURATION} )) make - scripts/travis-command-wrapper.py -s "date" -i 120 --deadline=$(( $(date +%s) + ${DURATION} )) make
- make test - RESULT=0
- make test || RESULT=$?
# we allow visual failures with g++ for now: https://github.com/mapnik/mapnik/issues/3567
- if [[ ${RESULT} != 0 ]] && [[ ${CXX} =~ 'clang++' ]]; then false; fi;
- enabled ${COVERAGE} coverage - enabled ${COVERAGE} coverage
- enabled ${BENCH} make bench - 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 publish;
fi

View file

@ -6,6 +6,36 @@ Developers: Please commit along with changes.
For a complete change history, see the git log. For a complete change history, see the git log.
## 3.0.x
#### Summary
- Fixed problems with high levels of overzooming in the GDAL and raster plugin where data would be slightly offset
- High levels of overzooming on raster data no longer results in the return of a transparent image.
## 3.0.13
Released: February 8, 2017
(Packaged from 2a153c0)
#### Summary
- Unbundle `unifont` font from distribution
- GeoJSON: improved parsing grammar avoiding temp synthesised attribute (#3507)
- GeoJSON: expose `num_features_to_query` datasource parameter + unit test (#3515)
- Fixed intersecting extents in different projections (PR #3525 )
- Fixed `blur` implementation by taking into account `scale_factor`
- postgis.input - use 2D box for pgraster bounding box (PR #3551)
- Fixed GroupSymbolizer PairLayout with 3+ items (#3526)
- Simplified `hash` implementation (204d30e58d3553278ab6bcda2d4122b0f13f6392)
- Simplified `mapnik::value` conversion rules (#3570)
- Changed `render_thunk_list` to `std::list<render_thunk>` (PR #3585)
- Upgraded to variant `v1.1.5`
- CSV.input - fixed `blank` line test (8a3a380b3b5c64681f2478b4f0d06f6a907f5eed)
- GeoJSON - handle empty elements in position grammar (ref #3609)
- mapnik-index - return failure on invalid bounding box (ref #3611)
## 3.0.12 ## 3.0.12
Released: September 8, 2016 Released: September 8, 2016

View file

@ -11,14 +11,6 @@ os: Visual Studio 2015
# limit clone to latest 5 commits # limit clone to latest 5 commits
clone_depth: 5 clone_depth: 5
services:
- postgresql94 #if changing this, also change PATH below
install:
- SET PGUSER=postgres
- SET PGPASSWORD=Password12!
- SET PATH=C:\Program Files\PostgreSQL\9.4\bin\;%PATH%
build_script: build_script:
- scripts\build-appveyor.bat - scripts\build-appveyor.bat

View file

@ -2,7 +2,7 @@
<!DOCTYPE Map[]> <!DOCTYPE Map[]>
<Map <Map
srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
font-directory="../../fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf" font-directory="../../fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf"
background-color="#dfd8c9"> background-color="#dfd8c9">
<Style name="marking" filter-mode="first"> <Style name="marking" filter-mode="first">

View file

@ -11,7 +11,7 @@ todo
- shrink icu data - shrink icu data
' '
MASON_VERSION="new-pkgs" MASON_VERSION="v0.11.1"
function setup_mason() { function setup_mason() {
if [[ ! -d ./.mason ]]; then if [[ ! -d ./.mason ]]; then
@ -19,7 +19,7 @@ function setup_mason() {
(cd ./.mason && git checkout ${MASON_VERSION}) (cd ./.mason && git checkout ${MASON_VERSION})
else else
echo "Updating to latest mason" echo "Updating to latest mason"
(cd ./.mason && git fetch && git checkout ${MASON_VERSION} && git pull) (cd ./.mason && git fetch && git checkout ${MASON_VERSION} && git pull origin ${MASON_VERSION})
fi fi
export PATH=$(pwd)/.mason:$PATH export PATH=$(pwd)/.mason:$PATH
export CXX=${CXX:-clang++} export CXX=${CXX:-clang++}
@ -44,45 +44,37 @@ function install() {
mason link $1 $2 mason link $1 $2
} }
ICU_VERSION="55.1" ICU_VERSION="57.1"
function install_mason_deps() { function install_mason_deps() {
FAIL=0 install ccache 3.3.1
install ccache 3.3.0 & install zlib 1.2.8
install zlib system & install jpeg_turbo 1.5.1 libjpeg
install jpeg_turbo 1.5.0 libjpeg & install libpng 1.6.28 libpng
install libpng 1.6.24 libpng & install libtiff 4.0.7 libtiff
install libtiff 4.0.6 libtiff & install libpq 9.6.2
install libpq 9.5.2 & install sqlite 3.17.0 libsqlite3
install sqlite 3.14.1 libsqlite3 & install expat 2.2.0 libexpat
install expat 2.2.0 libexpat & install icu ${ICU_VERSION}
install icu ${ICU_VERSION} & install proj 4.9.3 libproj
install proj 4.9.2 libproj & install pixman 0.34.0 libpixman-1
install pixman 0.34.0 libpixman-1 & install cairo 1.14.8 libcairo
install cairo 1.14.6 libcairo & install protobuf 3.2.0
install protobuf 2.6.1 &
# technically protobuf is not a mapnik core dep, but installing # technically protobuf is not a mapnik core dep, but installing
# here by default helps make mapnik-vector-tile builds easier # here by default helps make mapnik-vector-tile builds easier
install webp 0.5.1 libwebp & install webp 0.6.0 libwebp
install gdal 2.1.1 libgdal & install libgdal 2.1.3 libgdal
install boost 1.61.0 & install boost 1.63.0
install boost_libsystem 1.61.0 & install boost_libsystem 1.63.0
install boost_libfilesystem 1.61.0 & install boost_libfilesystem 1.63.0
install boost_libprogram_options 1.61.0 & install boost_libprogram_options 1.63.0
install boost_libregex_icu 1.61.0 & install boost_libregex_icu57 1.63.0
# technically boost thread and python are not a core dep, but installing # technically boost thread and python are not a core dep, but installing
# here by default helps make python-mapnik builds easier # here by default helps make python-mapnik builds easier
install boost_libthread 1.61.0 & install boost_libthread 1.63.0
install boost_libpython 1.61.0 & install boost_libpython 1.63.0
install freetype 2.6.5 libfreetype & install freetype 2.7.1 libfreetype
install harfbuzz 1.3.0 libharfbuzz & install harfbuzz 1.4.4-ft libharfbuzz
for job in $(jobs -p)
do
wait $job || let "FAIL+=1"
done
if [[ "$FAIL" != "0" ]]; then
exit ${FAIL}
fi
} }
MASON_LINKED_ABS=$(pwd)/mason_packages/.link MASON_LINKED_ABS=$(pwd)/mason_packages/.link
@ -95,6 +87,7 @@ function make_config() {
echo " echo "
CXX = '$CXX' CXX = '$CXX'
CC = '$CC' CC = '$CC'
CUSTOM_CXXFLAGS = '-D_GLIBCXX_USE_CXX11_ABI=0'
RUNTIME_LINK = 'static' RUNTIME_LINK = 'static'
INPUT_PLUGINS = 'all' INPUT_PLUGINS = 'all'
PATH = '${MASON_LINKED_REL}/bin' PATH = '${MASON_LINKED_REL}/bin'

View file

@ -7,11 +7,7 @@ machine:
JOBS: 8 JOBS: 8
CCACHE_TEMPDIR: /tmp/.ccache-temp CCACHE_TEMPDIR: /tmp/.ccache-temp
CCACHE_COMPRESS: 1 CCACHE_COMPRESS: 1
LLVM_VERSION: 3.8 LLVM_VERSION: 3.9.1
pre:
- echo "here"
post:
- echo "there"
checkout: checkout:
post: post:
@ -32,9 +28,9 @@ dependencies:
database: database:
pre: pre:
- ./bootstrap.sh - ./bootstrap.sh
- ./.mason/mason install clang ${LLVM_VERSION}.0 - ./.mason/mason install clang++ ${LLVM_VERSION}
- ./.mason/mason link clang ${LLVM_VERSION}.0 - ./.mason/mason link clang++ ${LLVM_VERSION}
- ./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" - ./configure CC="$(pwd)/mason_packages/.link/bin/clang" CXX="$(pwd)/mason_packages/.link/bin/ccache $(pwd)/mason_packages/.link/bin/clang++ -Qunused-arguments"
- make - make
override: override:
- psql -c 'create database template_postgis;' - psql -c 'create database template_postgis;'

10
codecov.yml Normal file
View file

@ -0,0 +1,10 @@
ignore:
- "mason_packages"
- "benchmark"
- "deps"
- ".sconf_temp"
- "scons"
- "test"
- "demo"
- "docs"
- "fonts"

View file

@ -1,7 +1,6 @@
###################################################################### ######################################################################
# Mapnik viewer - Copyright (C) 2007 Artem Pavlenko # Mapnik viewer - Copyright (C) 2007 Artem Pavlenko
###################################################################### ######################################################################
QMAKE_MAC_SDK = macosx10.11
TEMPLATE = app TEMPLATE = app
QT += core gui widgets QT += core gui widgets
QMAKE_CXX = $$system(mapnik-config --cxx) QMAKE_CXX = $$system(mapnik-config --cxx)

2
deps/mapbox/variant vendored

@ -1 +1 @@
Subproject commit 9a115c5eb3c09509c70a57b25b283b6e1cbba919 Subproject commit d2588a8f1d6b5d480d228e6d8a906ce634bdea9a

View file

@ -116,6 +116,7 @@ public:
bool valid() const; bool valid() const;
void move(T x, T y); void move(T x, T y);
std::string to_string() const; std::string to_string() const;
T area() const;
// define some operators // define some operators
box2d_type& operator+=(box2d_type const& other); box2d_type& operator+=(box2d_type const& other);

View file

@ -393,6 +393,11 @@ std::string box2d<T>::to_string() const
return s.str(); return s.str();
} }
template <typename T>
T box2d<T>::area() const
{
return width() * height();
}
template <typename T> template <typename T>
box2d<T>& box2d<T>::operator+=(box2d<T> const& other) box2d<T>& box2d<T>::operator+=(box2d<T> const& other)
@ -466,7 +471,7 @@ T box2d<T>::operator[] (int index) const
case -1: case -1:
return maxy_; return maxy_;
default: default:
throw std::out_of_range("index out of range, max value is 3, min value is -4 "); throw std::out_of_range(std::string("index out of range, max value is 3, min value is -4 "));
} }
} }

View file

@ -41,10 +41,8 @@ public:
config_error(std::string const& what, config_error(std::string const& what,
unsigned line_number, unsigned line_number,
std::string const& filename); std::string const& filename);
virtual ~config_error() throw() {} virtual ~config_error() {}
virtual const char * what() const noexcept;
virtual const char * what() const throw();
void append_context(std::string const& ctx) const; void append_context(std::string const& ctx) const;
void append_context(std::string const& ctx, xml_node const& node) const; void append_context(std::string const& ctx, xml_node const& node) const;
void append_context(xml_node const& node) const; void append_context(xml_node const& node) const;

View file

@ -0,0 +1,43 @@
/*****************************************************************************
*
* 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_CXX11_SUPPORT_HPP
#define MAPNIK_CXX11_SUPPORT_HPP
#include <type_traits>
namespace mapnik {
namespace detail {
template <bool B, typename T, typename F>
using conditional_t = typename std::conditional<B, T, F>::type;
template <typename T>
using decay_t = typename std::decay<T>::type;
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
} // namespace detail
} // namespace mapnik
#endif // MAPNIK_CXX11_SUPPORT_HPP

View file

@ -46,14 +46,11 @@ class MAPNIK_DECL datasource_exception : public std::exception
public: public:
datasource_exception(std::string const& message) datasource_exception(std::string const& message)
: message_(message) : message_(message)
{ {}
}
~datasource_exception() throw() ~datasource_exception() {}
{
}
virtual const char* what() const throw() virtual const char* what() const noexcept
{ {
return message_.c_str(); return message_.c_str();
} }

View file

@ -28,7 +28,6 @@
#include <mapnik/debug.hpp> #include <mapnik/debug.hpp>
// stl // stl
#include <bitset>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <algorithm> #include <algorithm>
@ -45,9 +44,9 @@ public:
what_( _what ) what_( _what )
{ {
} }
virtual ~illegal_enum_value() throw() {} virtual ~illegal_enum_value() {}
virtual const char * what() const throw() virtual const char * what() const noexcept
{ {
return what_.c_str(); return what_.c_str();
} }
@ -190,6 +189,8 @@ public:
for (unsigned i = 0; i < THE_MAX; ++i) for (unsigned i = 0; i < THE_MAX; ++i)
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template" #pragma GCC diagnostic ignored "-Wundefined-var-template"
if (str_copy == our_strings_[i]) if (str_copy == our_strings_[i])
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -203,6 +204,8 @@ public:
} }
} }
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template" #pragma GCC diagnostic ignored "-Wundefined-var-template"
throw illegal_enum_value(std::string("Illegal enumeration value '") + throw illegal_enum_value(std::string("Illegal enumeration value '") +
str + "' for enum " + our_name_); str + "' for enum " + our_name_);
@ -213,6 +216,8 @@ public:
std::string as_string() const std::string as_string() const
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc
#pragma GCC diagnostic ignored "-Wpragmas" // gcc
#pragma GCC diagnostic ignored "-Wundefined-var-template" #pragma GCC diagnostic ignored "-Wundefined-var-template"
return our_strings_[value_]; return our_strings_[value_];
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View file

@ -96,7 +96,7 @@ public:
void get_control_points(double &x1, double &y1, double &x2, double &y2) const; void get_control_points(double &x1, double &y1, double &x2, double &y2) const;
private: private:
void swap(gradient& other) throw(); void swap(gradient& other) noexcept;
}; };
} }

View file

@ -68,16 +68,6 @@ public:
box_elements_.push_back(box_element(box, repeat_key)); box_elements_.push_back(box_element(box, repeat_key));
} }
inline void clear_box_elements()
{
box_elements_.clear();
}
inline text_symbolizer_properties const& get_properties() const
{
return info_ptr_->properties;
}
pixel_position_list const& get(); pixel_position_list const& get();
// Iterate over the given path, placing line-following labels or point labels with respect to label_spacing. // Iterate over the given path, placing line-following labels or point labels with respect to label_spacing.

View file

@ -50,9 +50,9 @@ public:
image_reader_exception(std::string const& message) image_reader_exception(std::string const& message)
: message_(message) {} : message_(message) {}
~image_reader_exception() throw() {} ~image_reader_exception() {}
virtual const char* what() const throw() virtual const char* what() const noexcept
{ {
return message_.c_str(); return message_.c_str();
} }

View file

@ -56,9 +56,9 @@ public:
image_writer_exception(std::string const& message) image_writer_exception(std::string const& message)
: message_(message) {} : message_(message) {}
~image_writer_exception() throw() {} ~image_writer_exception(){}
virtual const char* what() const throw() virtual const char* what() const noexcept
{ {
return message_.c_str(); return message_.c_str();
} }

View file

@ -51,7 +51,7 @@ struct extract_bounding_box_grammar :
qi::rule<Iterator, qi::locals<Iterator>, void(boxes_type&), space_type> features; qi::rule<Iterator, qi::locals<Iterator>, void(boxes_type&), space_type> features;
qi::rule<Iterator, qi::locals<int, box_type>, void(boxes_type&, Iterator const&), space_type> feature; qi::rule<Iterator, qi::locals<int, box_type>, void(boxes_type&, Iterator const&), space_type> feature;
qi::rule<Iterator, qi::locals<box_type>, box_type(), space_type> coords; qi::rule<Iterator, qi::locals<box_type>, box_type(), space_type> coords;
qi::rule<Iterator, boost::optional<position_type>(), space_type> pos; qi::rule<Iterator, position_type(), space_type> pos;
qi::rule<Iterator, void(box_type&), space_type> ring; qi::rule<Iterator, void(box_type&), space_type> ring;
qi::rule<Iterator, void(box_type&), space_type> rings; qi::rule<Iterator, void(box_type&), space_type> rings;
qi::rule<Iterator, void(box_type&), space_type> rings_array; qi::rule<Iterator, void(box_type&), space_type> rings_array;

View file

@ -42,18 +42,15 @@ struct calculate_bounding_box_impl
template <typename T0, typename T1> template <typename T0, typename T1>
result_type operator() (T0 & bbox, T1 const& pos) const 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())
{ {
typename T0::value_type x = pos->x; bbox.init(x, y);
typename T0::value_type y = pos->y; }
if (!bbox.valid()) else
{ {
bbox.init(x, y); bbox.expand_to_include(x, y);
}
else
{
bbox.expand_to_include(x, y);
}
} }
} }
}; };
@ -64,10 +61,10 @@ struct push_box_impl
template <typename T0, typename T1, typename T2, typename T3> template <typename T0, typename T1, typename T2, typename T3>
void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const
{ {
if (box.valid()) boxes.emplace_back(box, boxes.emplace_back(box,
std::make_pair(std::distance(begin, std::make_pair(std::distance(begin,
range.begin()), range.begin()),
std::distance(range.begin(), range.end()))); std::distance(range.begin(), range.end())));
} }
}; };
@ -132,16 +129,16 @@ extract_bounding_box_grammar<Iterator, Boxes, ErrorHandler>::extract_bounding_bo
>> lit(':') >> (rings_array(_a) | rings (_a) | ring(_a) | pos[calculate_bounding_box(_a,_1)])[_val = _a] >> lit(':') >> (rings_array(_a) | rings (_a) | ring(_a) | pos[calculate_bounding_box(_a,_1)])[_val = _a]
; ;
pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']') pos = lit('[') > double_ > lit(',') > double_ > omit[*(lit(',') > double_)] > lit(']')
; ;
ring = lit('[') >> pos[calculate_bounding_box(_r1,_1)] % lit(',') > lit(']') ring = lit('[') >> -(pos[calculate_bounding_box(_r1,_1)] % lit(',')) >> lit(']')
; ;
rings = lit('[') >> ring(_r1) % lit(',') > lit(']') rings = lit('[') >> (ring(_r1) % lit(',') > lit(']'))
; ;
rings_array = lit('[') >> rings(_r1) % lit(',') > lit(']') rings_array = lit('[') >> (rings(_r1) % lit(',') > lit(']'))
; ;
coords.name("Coordinates"); coords.name("Coordinates");

View file

@ -56,26 +56,24 @@ geometry_generator_grammar<OutputIterator, Geometry>::geometry_generator_grammar
; ;
geometry_dispatch = eps[_a = geometry_type(_val)] << geometry_dispatch = eps[_a = geometry_type(_val)] <<
(&uint_(geometry::geometry_types::Point)[_1 = _a] (&uint_(geometry::geometry_types::Point)[_1 = _a] << point)
<< (point | lit("null")))
| |
(&uint_(geometry::geometry_types::LineString)[_1 = _a] (&uint_(geometry::geometry_types::LineString)[_1 = _a]
<< (linestring | lit("null"))) << (linestring | "{\"type\":\"LineString\",\"coordinates\":[]}"))
| |
(&uint_(geometry::geometry_types::Polygon)[_1 = _a] (&uint_(geometry::geometry_types::Polygon)[_1 = _a]
<< (polygon | lit("null"))) << (polygon | "{\"type\":\"Polygon\",\"coordinates\":[[]]}"))
| |
(&uint_(geometry::geometry_types::MultiPoint)[_1 = _a] (&uint_(geometry::geometry_types::MultiPoint)[_1 = _a]
<< (multi_point | lit("null"))) << (multi_point | "{\"type\":\"MultiPoint\",\"coordinates\":[]}"))
| |
(&uint_(geometry::geometry_types::MultiLineString)[_1 = _a] (&uint_(geometry::geometry_types::MultiLineString)[_1 = _a]
<< (multi_linestring | lit("null"))) << (multi_linestring | "{\"type\":\"MultiLineString\",\"coordinates\":[[]]}"))
| |
(&uint_(geometry::geometry_types::MultiPolygon)[_1 = _a] (&uint_(geometry::geometry_types::MultiPolygon)[_1 = _a]
<< (multi_polygon | lit("null"))) << (multi_polygon | "{\"type\":\"MultiPolygon\",\"coordinates\":[[[]]]}"))
| |
(&uint_(geometry::geometry_types::GeometryCollection)[_1 = _a] (&uint_(geometry::geometry_types::GeometryCollection)[_1 = _a] << geometry_collection)
<< (geometry_collection | lit("null")))
| |
lit("null") lit("null")
; ;
@ -96,7 +94,7 @@ geometry_generator_grammar<OutputIterator, Geometry>::geometry_generator_grammar
; ;
point_coord = lit('[') << coordinate << lit(',') << coordinate << lit(']') point_coord = lit('[') << coordinate << lit(',') << coordinate << lit(']')
; ;
linestring_coord = point_coord % lit(',') linestring_coord = (point_coord % lit(','))
; ;
polygon_coord = lit('[') << exterior_ring_coord << lit(']') << interior_ring_coord polygon_coord = lit('[') << exterior_ring_coord << lit(']') << interior_ring_coord
; ;

View file

@ -43,7 +43,10 @@ struct create_point
} }
template <typename T> template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here void operator()(T const&) const
{
throw std::runtime_error("Failed to parse geojson geometry");
}
Geometry & geom_; Geometry & geom_;
}; };
@ -55,21 +58,21 @@ struct create_linestring
void operator() (positions const& ring) const void operator() (positions const& ring) const
{ {
mapnik::geometry::line_string<double> line;
std::size_t size = ring.size(); std::size_t size = ring.size();
if (size > 1) line.reserve(size);
for (auto && pt : ring)
{ {
mapnik::geometry::line_string<double> line; line.emplace_back(std::move(pt));
line.reserve(size);
for (auto && pt : ring)
{
line.emplace_back(std::move(pt));
}
geom_ = std::move(line);
} }
geom_ = std::move(line);
} }
template <typename T> template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here void operator()(T const&) const
{
throw std::runtime_error("Failed to parse geojson geometry");
}
Geometry & geom_; Geometry & geom_;
}; };
@ -106,7 +109,10 @@ struct create_polygon
} }
template <typename T> template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here void operator()(T const&) const
{
throw std::runtime_error("Failed to parse geojson geometry");
}
Geometry & geom_; Geometry & geom_;
}; };
@ -130,7 +136,10 @@ struct create_multipoint
} }
template <typename T> template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here void operator()(T const&) const
{
throw std::runtime_error("Failed to parse geojson geometry");
}
Geometry & geom_; Geometry & geom_;
}; };
@ -160,7 +169,10 @@ struct create_multilinestring
} }
template <typename T> template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here void operator()(T const&) const
{
throw std::runtime_error("Failed to parse geojson geometry");
}
Geometry & geom_; Geometry & geom_;
}; };
@ -201,7 +213,10 @@ struct create_multipolygon
} }
template <typename T> template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here void operator()(T const&) const
{
throw std::runtime_error("Failed to parse geojson geometry");
}
Geometry & geom_; Geometry & geom_;
}; };

View file

@ -44,7 +44,7 @@ struct positions_grammar :
{ {
positions_grammar(ErrorHandler & error_handler); positions_grammar(ErrorHandler & error_handler);
qi::rule<Iterator, coordinates(),space_type> coords; qi::rule<Iterator, coordinates(),space_type> coords;
qi::rule<Iterator, boost::optional<position>(), space_type> pos; qi::rule<Iterator, position(), space_type> pos;
qi::rule<Iterator, positions(), space_type> ring; qi::rule<Iterator, positions(), space_type> ring;
qi::rule<Iterator, std::vector<positions>(), space_type> rings; qi::rule<Iterator, std::vector<positions>(), space_type> rings;
qi::rule<Iterator, std::vector<std::vector<positions> >(), space_type> rings_array; qi::rule<Iterator, std::vector<std::vector<positions> >(), space_type> rings_array;

View file

@ -41,7 +41,7 @@ struct set_position_impl
template <typename T0,typename T1> template <typename T0,typename T1>
result_type operator() (T0 & coords, T1 const& pos) const result_type operator() (T0 & coords, T1 const& pos) const
{ {
if (pos) coords = *pos; coords = pos;
} }
}; };
@ -51,7 +51,7 @@ struct push_position_impl
template <typename T0, typename T1> template <typename T0, typename T1>
result_type operator() (T0 & coords, T1 const& pos) const result_type operator() (T0 & coords, T1 const& pos) const
{ {
if (pos) coords.emplace_back(*pos); coords.emplace_back(pos);
} }
}; };
@ -75,13 +75,13 @@ positions_grammar<Iterator, ErrorHandler>::positions_grammar(ErrorHandler & erro
coords = rings_array[_val = _1] | rings [_val = _1] | ring[_val = _1] | pos[set_position(_val,_1)] 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(']') pos = lit('[') > double_ > lit(',') > double_ > omit[*(lit(',') > double_)] > lit(']')
; ;
ring = lit('[') >> pos[push_position(_val,_1)] % lit(',') > lit(']') ring = lit('[') >> -(pos[push_position(_val,_1)] % lit(',')) >> lit(']')
; ;
rings = lit('[') >> ring % lit(',') > lit(']') rings = lit('[') >> (ring % lit(',') > lit(']'))
; ;
rings_array = lit('[') >> rings % lit(',') > lit(']') rings_array = lit('[') >> (rings % lit(',') > lit(']'))
; ;
coords.name("Coordinates"); coords.name("Coordinates");
pos.name("Position"); pos.name("Position");

View file

@ -77,18 +77,18 @@ struct offset_converter
return threshold_; return threshold_;
} }
void set_offset(double value) void set_offset(double val)
{ {
if (offset_ != value) if (offset_ != val)
{ {
offset_ = value; offset_ = val;
reset(); reset();
} }
} }
void set_threshold(double value) void set_threshold(double val)
{ {
threshold_ = value; threshold_ = val;
// no need to reset(), since threshold doesn't affect // no need to reset(), since threshold doesn't affect
// offset vertices' computation, it only controls how // offset vertices' computation, it only controls how
// far will we be looking for self-intersections // far will we be looking for self-intersections

View file

@ -40,15 +40,27 @@ class raster : private util::noncopyable
{ {
public: public:
box2d<double> ext_; box2d<double> ext_;
box2d<double> query_ext_;
image_any data_; image_any data_;
double filter_factor_; double filter_factor_;
boost::optional<double> nodata_; boost::optional<double> nodata_;
template <typename ImageData> template <typename ImageData>
raster(box2d<double> const& ext, raster(box2d<double> const& ext,
box2d<double> const& query_ext,
ImageData && data, ImageData && data,
double filter_factor) double filter_factor)
: ext_(ext), : ext_(ext),
query_ext_(query_ext),
data_(std::move(data)),
filter_factor_(filter_factor) {}
template <typename ImageData>
raster(box2d<double> const& ext,
ImageData && data,
double filter_factor)
: ext_(ext),
query_ext_(ext),
data_(std::move(data)), data_(std::move(data)),
filter_factor_(filter_factor) {} filter_factor_(filter_factor) {}
@ -71,7 +83,6 @@ public:
{ {
filter_factor_ = factor; filter_factor_ = factor;
} }
}; };
} }

View file

@ -53,6 +53,7 @@ struct image_dispatcher
image_dispatcher(int start_x, int start_y, image_dispatcher(int start_x, int start_y,
int width, int height, int width, int height,
double scale_x, double scale_y, double scale_x, double scale_y,
double offset_x, double offset_y,
scaling_method_e method, double filter_factor, scaling_method_e method, double filter_factor,
double opacity, composite_mode_e comp_op, double opacity, composite_mode_e comp_op,
raster_symbolizer const& sym, feature_impl const& feature, raster_symbolizer const& sym, feature_impl const& feature,
@ -63,15 +64,17 @@ struct image_dispatcher
height_(height), height_(height),
scale_x_(scale_x), scale_x_(scale_x),
scale_y_(scale_y), scale_y_(scale_y),
offset_x_(offset_x),
offset_y_(offset_y),
method_(method), method_(method),
filter_factor_(filter_factor), filter_factor_(filter_factor),
opacity_(opacity), opacity_(opacity),
comp_op_(comp_op), comp_op_(comp_op),
sym_(sym), sym_(sym),
feature_(feature), feature_(feature),
composite_(composite), composite_(composite),
nodata_(nodata), nodata_(nodata),
need_scaling_(need_scaling) {} need_scaling_(need_scaling) {}
void operator() (image_null const&) const {} //no-op void operator() (image_null const&) const {} //no-op
void operator() (image_rgba8 const& data_in) const void operator() (image_rgba8 const& data_in) const
@ -79,7 +82,7 @@ struct image_dispatcher
if (need_scaling_) if (need_scaling_)
{ {
image_rgba8 data_out(width_, height_, true, true); image_rgba8 data_out(width_, height_, true, true);
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_, nodata_); scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, offset_x_, offset_y_, filter_factor_, nodata_);
composite_(data_out, comp_op_, opacity_, start_x_, start_y_); composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
} }
else else
@ -97,7 +100,7 @@ struct image_dispatcher
if (need_scaling_) if (need_scaling_)
{ {
image_type data_out(width_, height_); image_type data_out(width_, height_);
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_, nodata_); scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, offset_x_, offset_y_, filter_factor_, nodata_);
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_); if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
} }
else else
@ -114,6 +117,8 @@ private:
int height_; int height_;
double scale_x_; double scale_x_;
double scale_y_; double scale_y_;
double offset_x_;
double offset_y_;
scaling_method_e method_; scaling_method_e method_;
double filter_factor_; double filter_factor_;
double opacity_; double opacity_;
@ -210,12 +215,18 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
if (source) if (source)
{ {
box2d<double> target_ext = box2d<double>(source->ext_); box2d<double> target_ext = box2d<double>(source->ext_);
prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS); box2d<double> target_query_ext = box2d<double>(source->query_ext_);
if (!prj_trans.equal())
{
prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
prj_trans.backward(target_query_ext, PROJ_ENVELOPE_POINTS);
}
box2d<double> ext = common.t_.forward(target_ext); box2d<double> ext = common.t_.forward(target_ext);
int start_x = static_cast<int>(std::floor(ext.minx()+.5)); box2d<double> query_ext = common.t_.forward(target_query_ext);
int start_y = static_cast<int>(std::floor(ext.miny()+.5)); int start_x = static_cast<int>(std::floor(query_ext.minx()+.5));
int end_x = static_cast<int>(std::floor(ext.maxx()+.5)); int start_y = static_cast<int>(std::floor(query_ext.miny()+.5));
int end_y = static_cast<int>(std::floor(ext.maxy()+.5)); int end_x = static_cast<int>(std::floor(query_ext.maxx()+.5));
int end_y = static_cast<int>(std::floor(query_ext.maxy()+.5));
int raster_width = end_x - start_x; int raster_width = end_x - start_x;
int raster_height = end_y - start_y; int raster_height = end_y - start_y;
if (raster_width > 0 && raster_height > 0) if (raster_width > 0 && raster_height > 0)
@ -236,17 +247,20 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
if (!prj_trans.equal()) if (!prj_trans.equal())
{ {
double offset_x = ext.minx() - start_x; // This path does not currently work and is still being figured out.
double offset_y = ext.miny() - start_y; double offset_x = query_ext.minx() - start_x;
double offset_y = query_ext.miny() - start_y;
unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, common.vars_, 16)); unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, common.vars_, 16));
detail::image_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height, detail::image_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height,
target_ext, source->ext_, offset_x, offset_y, mesh_size, target_query_ext, source->ext_, offset_x, offset_y, mesh_size,
scaling_method, source->get_filter_factor(), scaling_method, source->get_filter_factor(),
opacity, comp_op, sym, feature, composite, source->nodata()); opacity, comp_op, sym, feature, composite, source->nodata());
util::apply_visitor(dispatcher, source->data_); util::apply_visitor(dispatcher, source->data_);
} }
else else
{ {
double offset_x = query_ext.minx() - ext.minx();
double offset_y = query_ext.miny() - ext.miny();
double image_ratio_x = ext.width() / source->data_.width(); double image_ratio_x = ext.width() / source->data_.width();
double image_ratio_y = ext.height() / source->data_.height(); double image_ratio_y = ext.height() / source->data_.height();
double eps = 1e-5; double eps = 1e-5;
@ -256,6 +270,7 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
(std::abs(start_y) > eps); (std::abs(start_y) > eps);
detail::image_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height, detail::image_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height,
image_ratio_x, image_ratio_y, image_ratio_x, image_ratio_y,
offset_x, offset_y,
scaling_method, source->get_filter_factor(), scaling_method, source->get_filter_factor(),
opacity, comp_op, sym, feature, composite, source->nodata(), scale); opacity, comp_op, sym, feature, composite, source->nodata(), scale);
util::apply_visitor(dispatcher, source->data_); util::apply_visitor(dispatcher, source->data_);

View file

@ -42,9 +42,9 @@ struct render_thunk_list_dispatch
{ {
offset_ = offset; offset_ = offset;
for (render_thunk_ptr const& thunk : thunks) for (render_thunk const& thunk : thunks)
{ {
util::apply_visitor(std::ref(*this), *thunk); util::apply_visitor(std::ref(*this), thunk);
} }
} }

View file

@ -107,8 +107,7 @@ struct text_render_thunk : util::movable
using render_thunk = util::variant<vector_marker_render_thunk, using render_thunk = util::variant<vector_marker_render_thunk,
raster_marker_render_thunk, raster_marker_render_thunk,
text_render_thunk>; text_render_thunk>;
using render_thunk_ptr = std::unique_ptr<render_thunk>; using render_thunk_list = std::list<render_thunk>;
using render_thunk_list = std::list<render_thunk_ptr>;
} // namespace mapnik } // namespace mapnik

View file

@ -120,11 +120,11 @@ public:
return algorithm_; return algorithm_;
} }
void set_simplify_algorithm(simplify_algorithm_e value) void set_simplify_algorithm(simplify_algorithm_e val)
{ {
if (algorithm_ != value) if (algorithm_ != val)
{ {
algorithm_ = value; algorithm_ = val;
reset(); reset();
} }
} }
@ -134,11 +134,11 @@ public:
return tolerance_; return tolerance_;
} }
void set_simplify_tolerance(double value) void set_simplify_tolerance(double val)
{ {
if (tolerance_ != value) if (tolerance_ != val)
{ {
tolerance_ = value; tolerance_ = val;
reset(); reset();
} }
} }

View file

@ -38,9 +38,9 @@ public:
svg_parser_exception(std::string const& message) svg_parser_exception(std::string const& message)
: message_(message) {} : message_(message) {}
~svg_parser_exception() throw() {} ~svg_parser_exception() {}
virtual const char* what() const throw() virtual const char* what() const noexcept
{ {
return message_.c_str(); return message_.c_str();
} }

View file

@ -100,18 +100,13 @@ struct strict_value : value_base_type
{ {
strict_value() = default; strict_value() = default;
strict_value(const char* val) strict_value(const char* val) noexcept(false)
: value_base_type(std::string(val)) {} : value_base_type(std::string(val)) {}
template <typename T> template <typename T, typename U = detail::mapnik_value_type_t<T>>
strict_value(T const& obj)
: value_base_type(typename detail::mapnik_value_type<T>::type(obj))
{}
template <typename T>
strict_value(T && obj) strict_value(T && obj)
noexcept(std::is_nothrow_constructible<value_base_type, T && >::value) noexcept(std::is_nothrow_constructible<value_base_type, U>::value)
: value_base_type(std::forward<T>(obj)) : value_base_type(U(std::forward<T>(obj)))
{} {}
}; };

View file

@ -83,7 +83,8 @@ public:
if (!size_) return nullptr; if (!size_) return nullptr;
std::fseek(file_.get(), 0, SEEK_SET); std::fseek(file_.get(), 0, SEEK_SET);
data_type buffer(new char[size_]); data_type buffer(new char[size_]);
std::fread(buffer.get(), size_, 1, file_.get()); auto count = std::fread(buffer.get(), size_, 1, file_.get());
if (count != 1) return nullptr;
return buffer; return buffer;
} }
private: private:

View file

@ -32,15 +32,7 @@ template <typename T>
using recursive_wrapper = typename mapbox::util::recursive_wrapper<T>; using recursive_wrapper = typename mapbox::util::recursive_wrapper<T>;
template<typename... Types> template<typename... Types>
class variant : public mapbox::util::variant<Types...> using variant = typename mapbox::util::variant<Types...>;
{
public:
// tell spirit that this is an adapted variant
struct adapted_variant_tag;
using types = std::tuple<Types...>;
// inherit ctor's
using mapbox::util::variant<Types...>::variant;
};
// unary visitor interface // unary visitor interface
// const // const

View file

@ -24,7 +24,7 @@
#define MAPNIK_UTIL_VARIANT_IO_HPP #define MAPNIK_UTIL_VARIANT_IO_HPP
namespace mapnik { namespace util { namespace mapbox { namespace util {
namespace detail { namespace detail {

View file

@ -47,30 +47,20 @@ class MAPNIK_DECL value : public value_base
public: public:
value() = default; value() = default;
// conversion from type T is done via a temporary of type U, which // Conversion from type T is done via a temporary value or reference
// is determined by mapnik_value_type; // of type U, which is determined by mapnik_value_type_t.
// enable_if< decay<T> != value > is necessary to avoid ill-formed //
// recursion in noexcept specifier; and it also prevents using this // CAVEAT: We don't check `noexcept(conversion from T to U)`.
// constructor where implicitly-declared copy/move should be used // But since the type U is either value_bool, value_integer,
// (e.g. value(value&)) // value_double or T &&, this conversion SHOULD NEVER throw.
template <typename T, template <typename T, typename U = detail::mapnik_value_type_t<T>>
typename U = typename std::enable_if<
!detail::is_same_decay<T, value>::value,
detail::mapnik_value_type_decay<T>
>::type::type>
value(T && val) value(T && val)
noexcept(noexcept(U(std::forward<T>(val))) && noexcept(std::is_nothrow_constructible<value_base, U>::value)
std::is_nothrow_constructible<value_base, U && >::value)
: value_base(U(std::forward<T>(val))) {} : value_base(U(std::forward<T>(val))) {}
template <typename T, template <typename T, typename U = detail::mapnik_value_type_t<T>>
typename U = typename std::enable_if<
!detail::is_same_decay<T, value>::value,
detail::mapnik_value_type_decay<T>
>::type::type>
value& operator=(T && val) value& operator=(T && val)
noexcept(noexcept(U(std::forward<T>(val))) && noexcept(std::is_nothrow_assignable<value_base, U>::value)
std::is_nothrow_assignable<value_base, U && >::value)
{ {
value_base::operator=(U(std::forward<T>(val))); value_base::operator=(U(std::forward<T>(val)));
return *this; return *this;

View file

@ -41,9 +41,9 @@ public:
{ {
} }
virtual ~value_error() throw() {} virtual ~value_error() {}
virtual const char * what() const throw() virtual const char * what() const noexcept
{ {
return what_.c_str(); return what_.c_str();
} }

View file

@ -37,11 +37,6 @@
namespace mapnik { namespace detail { namespace mapnik { namespace detail {
inline void hash_combine(std::size_t & seed, std::size_t val)
{
seed ^= val + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
struct value_hasher struct value_hasher
{ {
std::size_t operator() (value_null val) const std::size_t operator() (value_null val) const
@ -54,11 +49,6 @@ struct value_hasher
return static_cast<std::size_t>(val.hashCode()); return static_cast<std::size_t>(val.hashCode());
} }
std::size_t operator()(value_integer val) const
{
return static_cast<std::size_t>(val);
}
template <class T> template <class T>
std::size_t operator()(T const& val) const std::size_t operator()(T const& val) const
{ {
@ -72,10 +62,7 @@ struct value_hasher
template <typename T> template <typename T>
std::size_t mapnik_hash_value(T const& val) std::size_t mapnik_hash_value(T const& val)
{ {
std::size_t seed = 0; return util::apply_visitor(detail::value_hasher(), val);
detail::hash_combine(seed, util::apply_visitor(detail::value_hasher(), val));
detail::hash_combine(seed, val.which());
return seed;
} }
} // namespace mapnik } // namespace mapnik

View file

@ -25,6 +25,7 @@
// mapnik // mapnik
#include <mapnik/config.hpp> #include <mapnik/config.hpp>
#include <mapnik/cxx11_support.hpp>
#include <mapnik/pixel_types.hpp> #include <mapnik/pixel_types.hpp>
@ -34,7 +35,6 @@
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
// stl // stl
#include <type_traits>
#include <iosfwd> #include <iosfwd>
#include <cstddef> #include <cstddef>
@ -152,90 +152,23 @@ inline std::istream& operator>> ( std::istream & s, value_null & )
namespace detail { namespace detail {
// to mapnik::value_type conversions traits
template <typename T>
struct is_value_bool
{
constexpr static bool value = std::is_same<T, bool>::value;
};
template <typename T> // Helper metafunction for mapnik::value construction and assignment.
struct is_value_integer // Returns:
{ // value_bool if T is bool
constexpr static bool value = std::is_integral<T>::value && !std::is_same<T, bool>::value; // value_integer if T is an integral type (except bool)
}; // value_double if T is a floating-point type
// T && otherwise
template <typename T> template <typename T, typename dT = decay_t<T>>
struct is_value_double using mapnik_value_type_t =
{ conditional_t<
constexpr static bool value = std::is_floating_point<T>::value; std::is_same<dT, bool>::value, value_bool,
}; conditional_t<
std::is_integral<dT>::value, value_integer,
template <typename T> conditional_t<
struct is_value_unicode_string std::is_floating_point<dT>::value, value_double,
{ T && >>>;
constexpr static bool value = std::is_same<T, typename mapnik::value_unicode_string>::value;
};
template <typename T>
struct is_value_string
{
constexpr static bool value = std::is_same<T, typename std::string>::value;
};
template <typename T>
struct is_value_null
{
constexpr static bool value = std::is_same<T, typename mapnik::value_null>::value;
};
template <typename T, class Enable = void>
struct mapnik_value_type
{
using type = T;
};
// value_null
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_null<T>::value>::type>
{
using type = mapnik::value_null;
};
// value_bool
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_bool<T>::value>::type>
{
using type = mapnik::value_bool;
};
// value_integer
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_integer<T>::value>::type>
{
using type = mapnik::value_integer;
};
// value_double
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_double<T>::value>::type>
{
using type = mapnik::value_double;
};
// value_unicode_string
template <typename T>
struct mapnik_value_type<T, typename std::enable_if<detail::is_value_unicode_string<T>::value>::type>
{
using type = mapnik::value_unicode_string const&;
};
template <typename T>
using mapnik_value_type_decay = mapnik_value_type<typename std::decay<T>::type>;
template <typename T, typename U>
using is_same_decay = std::is_same<typename std::decay<T>::type,
typename std::decay<U>::type>;
} // namespace detail } // namespace detail

View file

@ -27,7 +27,7 @@
#define MAPNIK_MAJOR_VERSION 3 #define MAPNIK_MAJOR_VERSION 3
#define MAPNIK_MINOR_VERSION 0 #define MAPNIK_MINOR_VERSION 0
#define MAPNIK_PATCH_VERSION 12 #define MAPNIK_PATCH_VERSION 13
#define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION) #define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)

View file

@ -53,8 +53,8 @@ class MAPNIK_DECL node_not_found: public std::exception
{ {
public: public:
node_not_found(std::string const& node_name); node_not_found(std::string const& node_name);
virtual const char* what() const throw(); virtual const char* what() const noexcept;
~node_not_found() throw (); ~node_not_found();
private: private:
std::string node_name_; std::string node_name_;
protected: protected:
@ -65,8 +65,8 @@ class MAPNIK_DECL attribute_not_found: public std::exception
{ {
public: public:
attribute_not_found(std::string const& node_name, std::string const& attribute_name); attribute_not_found(std::string const& node_name, std::string const& attribute_name);
virtual const char* what() const throw(); virtual const char* what() const noexcept;
~attribute_not_found() throw (); ~attribute_not_found();
private: private:
std::string node_name_; std::string node_name_;
std::string attribute_name_; std::string attribute_name_;
@ -78,8 +78,8 @@ class MAPNIK_DECL more_than_one_child: public std::exception
{ {
public: public:
more_than_one_child(std::string const& node_name); more_than_one_child(std::string const& node_name);
virtual const char* what() const throw(); virtual const char* what() const noexcept;
~more_than_one_child() throw (); ~more_than_one_child();
private: private:
std::string node_name_; std::string node_name_;
protected: protected:

View file

@ -285,7 +285,10 @@ void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, T & boxes)
{ {
auto headers = csv_utils::parse_line(csv_line, separator_, quote_); auto headers = csv_utils::parse_line(csv_line, separator_, quote_);
// skip blank lines // skip blank lines
if (headers.size() > 0 && headers[0].empty()) ++line_number; if (headers.size() == 1 && headers[0].empty())
{
++line_number;
}
else else
{ {
std::size_t index = 0; std::size_t index = 0;
@ -300,7 +303,7 @@ void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, T & boxes)
std::ostringstream s; std::ostringstream s;
s << "CSV Plugin: expected a column header at line "; s << "CSV Plugin: expected a column header at line ";
s << line_number << ", column " << index; s << line_number << ", column " << index;
s << " - ensure this row contains valid header fields: '"; s << " - expected fields: '";
s << csv_line; s << csv_line;
throw mapnik::datasource_exception(s.str()); throw mapnik::datasource_exception(s.str());
} }
@ -338,7 +341,6 @@ void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, T & boxes)
std::string str("CSV Plugin: could not detect column(s) with the name(s) of wkt, geojson, x/y, or "); std::string str("CSV Plugin: could not detect column(s) with the name(s) of wkt, geojson, x/y, or ");
str += "latitude/longitude in:\n"; str += "latitude/longitude in:\n";
str += csv_line; str += csv_line;
str += "\n - this is required for reading geometry data";
throw mapnik::datasource_exception(str); throw mapnik::datasource_exception(str);
} }

View file

@ -38,7 +38,7 @@ plugin_env['LIBS'] = []
plugin_env.Append(LIBS=env['PLUGINS']['gdal']['lib']) plugin_env.Append(LIBS=env['PLUGINS']['gdal']['lib'])
if env['RUNTIME_LINK'] == 'static': if env['RUNTIME_LINK'] == 'static':
cmd = 'gdal-config --dep-libs' cmd = '%s --dep-libs' % plugin_env['GDAL_CONFIG']
plugin_env.ParseConfig(cmd) plugin_env.ParseConfig(cmd)
# Link Library to Dependencies # Link Library to Dependencies

View file

@ -187,19 +187,9 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
int width = end_x - x_off; int width = end_x - x_off;
int height = end_y - y_off; int height = end_y - y_off;
// don't process almost invisible data
if (box.width() < 0.5)
{
width = 0;
}
if (box.height() < 0.5)
{
height = 0;
}
//calculate actual box2d of returned raster //calculate actual box2d of returned raster
box2d<double> feature_raster_extent(x_off, y_off, x_off + width, y_off + height); box2d<double> feature_raster_extent(x_off, y_off, x_off + width, y_off + height);
intersect = t.backward(feature_raster_extent); feature_raster_extent = t.backward(feature_raster_extent);
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Raster extent=" << raster_extent_; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Raster extent=" << raster_extent_;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: View extent=" << intersect; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: View extent=" << intersect;
@ -208,374 +198,380 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
if (width > 0 && height > 0) if (width > 0 && height > 0)
{ {
double width_res = std::get<0>(q.resolution()); MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << width << "," << height << ")";
double height_res = std::get<1>(q.resolution()); MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;
int im_width = int(width_res * intersect.width() + 0.5); if (band_ > 0) // we are querying a single band
int im_height = int(height_res * intersect.height() + 0.5);
double filter_factor = q.get_filter_factor();
im_width = int(im_width * filter_factor + 0.5);
im_height = int(im_height * filter_factor + 0.5);
// case where we need to avoid upsampling so that the
// image can be later scaled within raster_symbolizer
if (im_width >= width || im_height >= height)
{ {
im_width = width; GDALRasterBand * band = dataset_.GetRasterBand(band_);
im_height = height; if (band_ > nbands_)
}
if (im_width > 0 && im_height > 0)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << im_width << "," << im_height << ")";
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;
if (band_ > 0) // we are querying a single band
{ {
GDALRasterBand * band = dataset_.GetRasterBand(band_); std::ostringstream s;
if (band_ > nbands_) s << "GDAL Plugin: " << band_ << " is an invalid band, dataset only has " << nbands_ << "bands";
throw datasource_exception(s.str());
}
GDALDataType band_type = band->GetRasterDataType();
switch (band_type)
{
case GDT_Byte:
{
mapnik::image_gray8 image(width, height);
image.set(std::numeric_limits<std::uint8_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.data(), image.width(), image.height(),
GDT_Byte, 0, 0);
if (raster_io_error == CE_Failure)
{ {
std::ostringstream s; throw datasource_exception(CPLGetLastErrorMsg());
s << "GDAL Plugin: " << band_ << " is an invalid band, dataset only has " << nbands_ << "bands";
throw datasource_exception(s.str());
} }
GDALDataType band_type = band->GetRasterDataType(); mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
switch (band_type) // set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
case GDT_Float64:
case GDT_Float32:
{
mapnik::image_gray32f image(width, height);
image.set(std::numeric_limits<float>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.data(), image.width(), image.height(),
GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure)
{ {
case GDT_Byte: throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
case GDT_UInt16:
{
mapnik::image_gray16 image(width, height);
image.set(std::numeric_limits<std::uint16_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.data(), image.width(), image.height(),
GDT_UInt16, 0, 0);
if (raster_io_error == CE_Failure)
{ {
mapnik::image_gray8 image(im_width, im_height); throw datasource_exception(CPLGetLastErrorMsg());
image.set(std::numeric_limits<std::uint8_t>::max()); }
raster_nodata = band->GetNoDataValue(&raster_has_nodata); mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height, // set nodata value to be used in raster colorizer
image.data(), image.width(), image.height(), if (nodata_value_) raster->set_nodata(*nodata_value_);
GDT_Byte, 0, 0); else raster->set_nodata(raster_nodata);
if (raster_io_error == CE_Failure) feature->set_raster(raster);
break;
}
default:
case GDT_Int16:
{
mapnik::image_gray16s image(width, height);
image.set(std::numeric_limits<std::int16_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.data(), image.width(), image.height(),
GDT_Int16, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
}
}
else // working with all bands
{
mapnik::image_rgba8 image(width, height);
image.set(std::numeric_limits<std::uint32_t>::max());
for (int i = 0; i < nbands_; ++i)
{
GDALRasterBand * band = dataset_.GetRasterBand(i + 1);
#ifdef MAPNIK_LOG
get_overview_meta(band);
#endif
GDALColorInterp color_interp = band->GetColorInterpretation();
switch (color_interp)
{
case GCI_RedBand:
red = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found red band";
break;
case GCI_GreenBand:
green = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found green band";
break;
case GCI_BlueBand:
blue = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found blue band";
break;
case GCI_AlphaBand:
alpha = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found alpha band";
break;
case GCI_GrayIndex:
grey = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band";
break;
case GCI_PaletteIndex:
{
grey = band;
#ifdef MAPNIK_LOG
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band, and colortable...";
GDALColorTable *color_table = band->GetColorTable();
if (color_table)
{ {
throw datasource_exception(CPLGetLastErrorMsg()); int count = color_table->GetColorEntryCount();
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color Table count=" << count;
for (int j = 0; j < count; j++)
{
const GDALColorEntry *ce = color_table->GetColorEntry (j);
if (! ce) continue;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color entry RGB=" << ce->c1 << "," <<ce->c2 << "," << ce->c3;
}
} }
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor); #endif
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break; break;
} }
case GDT_Float64: case GCI_Undefined:
case GDT_Float32: #if GDAL_VERSION_NUM <= 1730
if (nbands_ == 4)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming alpha band)";
alpha = band;
}
else
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";
grey = band;
}
#else
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";
grey = band;
#endif
break;
default:
MAPNIK_LOG_WARN(gdal) << "gdal_featureset: Band type unknown!";
break;
}
}
if (red && green && blue)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing rgb bands...";
raster_nodata = red->GetNoDataValue(&raster_has_nodata);
GDALColorTable *color_table = red->GetColorTable();
bool has_nodata = nodata_value_ || raster_has_nodata;
// we can deduce the alpha channel from nodata in the Byte case
// by reusing the reading of R,G,B bands directly
if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
{ {
mapnik::image_gray32f image(im_width, im_height); double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
image.set(std::numeric_limits<float>::max()); // read the data in and create an alpha channel from the nodata values
raster_nodata = band->GetNoDataValue(&raster_has_nodata); // TODO - we assume here the nodata value for the red band applies to all bands
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height, // more details about this at http://trac.osgeo.org/gdal/ticket/2734
image.data(), image.width(), image.height(), float* imageData = (float*)image.bytes();
raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height,
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
int len = image.width() * image.height();
for (int i = 0; i < len; ++i)
{
if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0;
}
else
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
}
}
}
/* Use dataset RasterIO in priority in 99.9% of the cases */
if( red->GetBand() == 1 && green->GetBand() == 2 && blue->GetBand() == 3 )
{
int nBandsToRead = 3;
if( alpha != nullptr && alpha->GetBand() == 4 && !raster_has_nodata )
{
nBandsToRead = 4;
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, nullptr,
4, 4 * image.width(), 1);
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
}
else
{
raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = green->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 1,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = blue->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 2,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
}
// In the case we skipped initializing the alpha channel
if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
{
double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
if( apply_nodata >= 0 && apply_nodata <= 255 )
{
int len = image.width() * image.height();
GByte* pabyBytes = (GByte*) image.bytes();
for (int i = 0; i < len; ++i)
{
// TODO - we assume here the nodata value for the red band applies to all bands
// more details about this at http://trac.osgeo.org/gdal/ticket/2734
if (std::fabs(apply_nodata - pabyBytes[4*i]) < nodata_tolerance_)
pabyBytes[4*i + 3] = 0;
else
pabyBytes[4*i + 3] = 255;
}
}
}
}
else if (grey)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing gray band...";
raster_nodata = grey->GetNoDataValue(&raster_has_nodata);
GDALColorTable* color_table = grey->GetColorTable();
bool has_nodata = nodata_value_ || raster_has_nodata;
if (!color_table && has_nodata)
{
double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: applying nodata value for layer=" << apply_nodata;
// first read the data in and create an alpha channel from the nodata values
float* imageData = (float*)image.bytes();
raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height,
imageData, image.width(), image.height(),
GDT_Float32, 0, 0); GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure) if (raster_io_error == CE_Failure)
{ {
throw datasource_exception(CPLGetLastErrorMsg()); throw datasource_exception(CPLGetLastErrorMsg());
} }
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor); int len = image.width() * image.height();
// set nodata value to be used in raster colorizer for (int i = 0; i < len; ++i)
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
case GDT_UInt16:
{
mapnik::image_gray16 image(im_width, im_height);
image.set(std::numeric_limits<std::uint16_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.data(), image.width(), image.height(),
GDT_UInt16, 0, 0);
if (raster_io_error == CE_Failure)
{ {
throw datasource_exception(CPLGetLastErrorMsg()); if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
default:
case GDT_Int16:
{
mapnik::image_gray16s image(im_width, im_height);
image.set(std::numeric_limits<std::int16_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.data(), image.width(), image.height(),
GDT_Int16, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
}
}
else // working with all bands
{
mapnik::image_rgba8 image(im_width, im_height);
image.set(std::numeric_limits<std::uint32_t>::max());
for (int i = 0; i < nbands_; ++i)
{
GDALRasterBand * band = dataset_.GetRasterBand(i + 1);
#ifdef MAPNIK_LOG
get_overview_meta(band);
#endif
GDALColorInterp color_interp = band->GetColorInterpretation();
switch (color_interp)
{
case GCI_RedBand:
red = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found red band";
break;
case GCI_GreenBand:
green = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found green band";
break;
case GCI_BlueBand:
blue = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found blue band";
break;
case GCI_AlphaBand:
alpha = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found alpha band";
break;
case GCI_GrayIndex:
grey = band;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band";
break;
case GCI_PaletteIndex:
{
grey = band;
#ifdef MAPNIK_LOG
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band, and colortable...";
GDALColorTable *color_table = band->GetColorTable();
if (color_table)
{ {
int count = color_table->GetColorEntryCount(); *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color Table count=" << count;
for (int j = 0; j < count; j++)
{
const GDALColorEntry *ce = color_table->GetColorEntry (j);
if (! ce) continue;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color entry RGB=" << ce->c1 << "," <<ce->c2 << "," << ce->c3;
}
}
#endif
break;
}
case GCI_Undefined:
#if GDAL_VERSION_NUM <= 1730
if (nbands_ == 4)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming alpha band)";
alpha = band;
} }
else else
{ {
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)"; *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
grey = band;
} }
#else
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";
grey = band;
#endif
break;
default:
MAPNIK_LOG_WARN(gdal) << "gdal_featureset: Band type unknown!";
break;
} }
} }
if (red && green && blue)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing rgb bands...";
raster_nodata = red->GetNoDataValue(&raster_has_nodata);
GDALColorTable *color_table = red->GetColorTable();
bool has_nodata = nodata_value_ || raster_has_nodata;
// we can deduce the alpha channel from nodata in the Byte case raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
// by reusing the reading of R,G,B bands directly image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte) if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 1,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 2,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
if (color_table)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Loading color table...";
for (unsigned y = 0; y < image.height(); ++y)
{ {
double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata; unsigned int* row = image.get_row(y);
// read the data in and create an alpha channel from the nodata values for (unsigned x = 0; x < image.width(); ++x)
// TODO - we assume here the nodata value for the red band applies to all bands
// more details about this at http://trac.osgeo.org/gdal/ticket/2734
float* imageData = (float*)image.bytes();
raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height,
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
int len = image.width() * image.height();
for (int i = 0; i < len; ++i)
{ {
if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_) unsigned value = row[x] & 0xff;
const GDALColorEntry *ce = color_table->GetColorEntry(value);
if (ce)
{ {
*reinterpret_cast<unsigned *>(&imageData[i]) = 0; row[x] = (ce->c4 << 24)| (ce->c3 << 16) | (ce->c2 << 8) | (ce->c1) ;
} }
else else
{ {
*reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF; // make lacking color entry fully alpha
} // note - gdal_translate makes black
} row[x] = 0;
}
/* Use dataset RasterIO in priority in 99.9% of the cases */
if( red->GetBand() == 1 && green->GetBand() == 2 && blue->GetBand() == 3 )
{
int nBandsToRead = 3;
if( alpha != nullptr && alpha->GetBand() == 4 && !raster_has_nodata )
{
nBandsToRead = 4;
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, nullptr,
4, 4 * image.width(), 1);
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
}
else
{
raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = green->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 1,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = blue->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 2,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg());
}
}
// In the case we skipped initializing the alpha channel
if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
{
double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
if( apply_nodata >= 0 && apply_nodata <= 255 )
{
int len = image.width() * image.height();
GByte* pabyBytes = (GByte*) image.bytes();
for (int i = 0; i < len; ++i)
{
// TODO - we assume here the nodata value for the red band applies to all bands
// more details about this at http://trac.osgeo.org/gdal/ticket/2734
if (std::fabs(apply_nodata - pabyBytes[4*i]) < nodata_tolerance_)
pabyBytes[4*i + 3] = 0;
else
pabyBytes[4*i + 3] = 255;
} }
} }
} }
} }
else if (grey) }
if (alpha)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band...";
if (!raster_has_nodata)
{ {
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing gray band..."; raster_io_error = alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3,
raster_nodata = grey->GetNoDataValue(&raster_has_nodata); image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
GDALColorTable* color_table = grey->GetColorTable(); if (raster_io_error == CE_Failure) {
bool has_nodata = nodata_value_ || raster_has_nodata;
if (!color_table && has_nodata)
{
double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: applying nodata value for layer=" << apply_nodata;
// first read the data in and create an alpha channel from the nodata values
float* imageData = (float*)image.bytes();
raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height,
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
int len = image.width() * image.height();
for (int i = 0; i < len; ++i)
{
if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0;
}
else
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
}
}
}
raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg()); throw datasource_exception(CPLGetLastErrorMsg());
} }
raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 1,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 2,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
if (color_table)
{
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Loading color table...";
for (unsigned y = 0; y < image.height(); ++y)
{
unsigned int* row = image.get_row(y);
for (unsigned x = 0; x < image.width(); ++x)
{
unsigned value = row[x] & 0xff;
const GDALColorEntry *ce = color_table->GetColorEntry(value);
if (ce)
{
row[x] = (ce->c4 << 24)| (ce->c3 << 16) | (ce->c2 << 8) | (ce->c1) ;
}
else
{
// make lacking color entry fully alpha
// note - gdal_translate makes black
row[x] = 0;
}
}
}
}
} }
if (alpha) else
{ {
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band..."; 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) if (!raster_has_nodata)
{ {
raster_io_error = alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3, 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()); image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (raster_io_error == CE_Failure) { if (raster_io_error == CE_Failure) {
throw datasource_exception(CPLGetLastErrorMsg()); throw datasource_exception(CPLGetLastErrorMsg());
@ -583,48 +579,22 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
} }
else else
{ {
MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of mask 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<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
} }
// report actual/original source nodata in feature attributes mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
if (raster_has_nodata) // set nodata value to be used in raster colorizer
{ if (nodata_value_) raster->set_nodata(*nodata_value_);
feature->put("nodata",raster_nodata); else raster->set_nodata(raster_nodata);
} feature->set_raster(raster);
return feature;
} }
// report actual/original source nodata in feature attributes
if (raster_has_nodata)
{
feature->put("nodata",raster_nodata);
}
return feature;
} }
return feature_ptr(); return feature_ptr();
} }

View file

@ -42,7 +42,7 @@ plugin_env['LIBS'] = []
plugin_env.Append(LIBS=env['PLUGINS']['ogr']['lib']) plugin_env.Append(LIBS=env['PLUGINS']['ogr']['lib'])
if env['RUNTIME_LINK'] == 'static': if env['RUNTIME_LINK'] == 'static':
cmd = 'gdal-config --dep-libs' cmd = '%s --dep-libs' % plugin_env['GDAL_CONFIG']
plugin_env.ParseConfig(cmd) plugin_env.ParseConfig(cmd)
# Link Library to Dependencies # Link Library to Dependencies

View file

@ -54,7 +54,9 @@ if env['PLUGIN_LINKING'] == 'shared':
libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_system%s' % env['BOOST_APPEND'])
libraries.append('boost_regex%s' % env['BOOST_APPEND']) libraries.append('boost_regex%s' % env['BOOST_APPEND'])
libraries.insert(0,env['MAPNIK_NAME']) libraries.insert(0,env['MAPNIK_NAME'])
libraries.append('icui18n')
libraries.append(env['ICU_LIB_NAME']) libraries.append(env['ICU_LIB_NAME'])
libraries.append('icudata')
TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME,
SHLIBPREFIX='', SHLIBPREFIX='',

View file

@ -89,33 +89,34 @@ feature_ptr raster_featureset<LookupPolicy>::next()
box2d<double> intersect = bbox_.intersect(curIter_->envelope()); box2d<double> intersect = bbox_.intersect(curIter_->envelope());
box2d<double> ext = t.forward(intersect); box2d<double> ext = t.forward(intersect);
box2d<double> rem = policy_.transform(ext); box2d<double> rem = policy_.transform(ext);
if (ext.width() > 0.5 && ext.height() > 0.5 ) // select minimum raster containing whole ext
{ int x_off = static_cast<int>(std::floor(ext.minx()));
// select minimum raster containing whole ext int y_off = static_cast<int>(std::floor(ext.miny()));
int x_off = static_cast<int>(std::floor(ext.minx())); int end_x = static_cast<int>(std::ceil(ext.maxx()));
int y_off = static_cast<int>(std::floor(ext.miny())); int end_y = static_cast<int>(std::ceil(ext.maxy()));
int end_x = static_cast<int>(std::ceil(ext.maxx()));
int end_y = static_cast<int>(std::ceil(ext.maxy()));
// clip to available data // clip to available data
if (x_off < 0) x_off = 0; if (x_off >= image_width) x_off = image_width - 1;
if (y_off < 0) y_off = 0; if (y_off >= image_width) y_off = image_width - 1;
if (end_x > image_width) end_x = image_width; if (x_off < 0) x_off = 0;
if (end_y > image_height) end_y = image_height; if (y_off < 0) y_off = 0;
if (end_x > image_width) end_x = image_width;
if (end_y > image_height) end_y = image_height;
int width = end_x - x_off; int width = end_x - x_off;
int height = end_y - y_off; int height = end_y - y_off;
if (width < 1) width = 1;
if (height < 1) height = 1;
// calculate actual box2d of returned raster // calculate actual box2d of returned raster
box2d<double> feature_raster_extent(rem.minx() + x_off, box2d<double> feature_raster_extent(rem.minx() + x_off,
rem.miny() + y_off, rem.miny() + y_off,
rem.maxx() + x_off + width, rem.maxx() + x_off + width,
rem.maxy() + y_off + height); rem.maxy() + y_off + height);
intersect = t.backward(feature_raster_extent); feature_raster_extent = t.backward(feature_raster_extent);
mapnik::image_any data = reader->read(x_off, y_off, width, height); mapnik::image_any data = reader->read(x_off, y_off, width, height);
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, std::move(data), 1.0); mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, std::move(data), 1.0);
feature->set_raster(raster); feature->set_raster(raster);
}
} }
} }
} }

View file

@ -44,7 +44,7 @@ raster_info::raster_info(const raster_info& rhs)
{ {
} }
void raster_info::swap(raster_info& other) //throw() void raster_info::swap(raster_info& other)
{ {
std::swap(file_,other.file_); std::swap(file_,other.file_);
std::swap(format_,other.format_); std::swap(format_,other.format_);

View file

@ -137,7 +137,7 @@ const field_descriptor& dbf_file::descriptor(int col) const
} }
void dbf_file::add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const throw() void dbf_file::add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const
{ {
using namespace boost::spirit; using namespace boost::spirit;

View file

@ -77,7 +77,7 @@ public:
field_descriptor const& descriptor(int col) const; field_descriptor const& descriptor(int col) const;
void move_to(int index); void move_to(int index);
std::string string_value(int col) const; std::string string_value(int col) const;
void add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const throw(); void add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const;
private: private:
void read_header(); void read_header();
int read_short(); int read_short();

View file

@ -26,7 +26,7 @@ function add() {
CXX=${CXX:-clang++} CXX=${CXX:-clang++}
function compile() { function compile() {
${CXX} -o ${app} ${cpp} -Wpadded -I./ -isystem ./mason_packages/.link/include `mapnik-config --all-flags` -Ideps -Lsrc -Ideps/agg/include -Iinclude ${CXX} -o ${app} ${cpp} -Wpadded -I./ -I./deps/mapbox/variant/include -isystem ./mason_packages/.link/include -std=c++11 -Ideps -Lsrc -Ideps/agg/include -Iinclude
} }
if [[ ${1:-unset} == "unset" ]] || [[ ${2:-unset} == "unset" ]] || [[ $@ == '-h' ]] || [[ $@ == '--help' ]]; then if [[ ${1:-unset} == "unset" ]] || [[ ${2:-unset} == "unset" ]] || [[ $@ == '-h' ]] || [[ $@ == '--help' ]]; then

View file

@ -46,15 +46,6 @@ git_submodule_update () {
git submodule update "$@" git submodule update "$@"
} }
# install and call pip
pip () {
if ! which pip >/dev/null; then
easy_install --user pip && \
export PATH="$HOME/Library/Python/2.7/bin:$PATH"
fi
command pip "$@"
}
# commit_message_contains TEXT # commit_message_contains TEXT
# - returns 0 (true) if TEXT is found in commit message # - returns 0 (true) if TEXT is found in commit message
# - case-insensitive, plain-text search, not regex # - case-insensitive, plain-text search, not regex
@ -83,22 +74,16 @@ config_override () {
configure () { configure () {
if enabled ${COVERAGE}; then if enabled ${COVERAGE}; then
./configure "$@" PREFIX=${PREFIX} PGSQL2SQLITE=False SVG2PNG=False SVG_RENDERER=False \ ./configure "$@" PREFIX=${PREFIX} PGSQL2SQLITE=False SVG2PNG=False SVG_RENDERER=False \
COVERAGE=True DEBUG=True WARNING_CXXFLAGS="-Wno-unknown-warning-option" COVERAGE=True DEBUG=True
else else
./configure "$@" PREFIX=${PREFIX} WARNING_CXXFLAGS="-Wno-unknown-warning-option" ./configure "$@" PREFIX=${PREFIX}
fi fi
# print final config values, sorted and indented # print final config values, sorted and indented
sort -sk1,1 ./config.py | sed -e 's/^/ /' sort -sk1,1 ./config.py | sed -e 's/^/ /'
} }
coverage () { coverage () {
./mason_packages/.link/bin/cpp-coveralls \ ./codecov -x "llvm-cov gcov" -Z
--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() { trigger_downstream() {

View file

@ -79,79 +79,22 @@ struct agg_renderer_process_visitor_l
void operator() (marker_svg const& marker) const void operator() (marker_svg const& marker) const
{ {
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
using pattern_type = agg::line_image_pattern<pattern_filter_type>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform); auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_);
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
image_rgba8 image(bbox_image.width(), bbox_image.height()); image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image); render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
render(image, marker.width(), marker.height());
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
agg::rendering_buffer buf(current_buffer_->bytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->row_size());
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(image, opacity);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
double half_stroke = std::max(marker.width()/2.0,marker.height()/2.0);
int rast_clip_padding = static_cast<int>(std::round(half_stroke));
ren.clip_box(-rast_clip_padding,-rast_clip_padding,common_.width_+rast_clip_padding,common_.height_+rast_clip_padding);
rasterizer_type ras(ren);
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
box2d<double> clip_box = clipping_extent(common_);
if (clip)
{
double padding = (double)(common_.query_extent_.width()/pixmap_.width());
if (half_stroke > 1)
padding *= half_stroke;
if (std::fabs(offset) > 0)
padding *= std::fabs(offset) * 1.2;
padding *= common_.scale_factor_;
clip_box.pad(padding);
}
using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag,
affine_transform_tag,
simplify_tag,smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (clip) converter.set<clip_line_tag>();
converter.set<transform_tag>(); //always transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
converter.set<affine_transform_tag>(); // optional affine transform
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer_type>;
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
apply_vertex_converter_type apply(converter, ras);
mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
} }
void operator() (marker_rgba8 const& marker) const void operator() (marker_rgba8 const& marker) const
{
render(marker.get_data(), marker.width(), marker.height());
}
private:
void render(mapnik::image_rgba8 const& marker, double width, double height) const
{ {
using color = agg::rgba8; using color = agg::rgba8;
using order = agg::order_rgba; using order = agg::order_rgba;
@ -164,8 +107,6 @@ struct agg_renderer_process_visitor_l
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>; using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_); value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
mapnik::image_rgba8 const& image = marker.get_data();
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_); value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_); value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_); value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
@ -178,10 +119,10 @@ struct agg_renderer_process_visitor_l
renderer_base ren_base(pixf); renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter; agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(image, opacity); pattern_source source(marker, opacity);
pattern_type pattern (filter,source); pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern); renderer_type ren(ren_base, pattern);
double half_stroke = std::max(marker.width()/2.0,marker.height()/2.0); double half_stroke = std::max(width / 2.0, height / 2.0);
int rast_clip_padding = static_cast<int>(std::round(half_stroke)); int rast_clip_padding = static_cast<int>(std::round(half_stroke));
ren.clip_box(-rast_clip_padding,-rast_clip_padding,common_.width_+rast_clip_padding,common_.height_+rast_clip_padding); ren.clip_box(-rast_clip_padding,-rast_clip_padding,common_.width_+rast_clip_padding,common_.height_+rast_clip_padding);
rasterizer_type ras(ren); rasterizer_type ras(ren);
@ -221,7 +162,6 @@ struct agg_renderer_process_visitor_l
mapnik::util::apply_visitor(vertex_processor_type(apply), feature_.get_geometry()); mapnik::util::apply_visitor(vertex_processor_type(apply), feature_.get_geometry());
} }
private:
renderer_common & common_; renderer_common & common_;
buffer_type & pixmap_; buffer_type & pixmap_;
buffer_type * current_buffer_; buffer_type * current_buffer_;

View file

@ -88,123 +88,17 @@ struct agg_renderer_process_visitor_p
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image); render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
render(image);
agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->row_size());
ras_ptr_->reset();
value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
if (gamma != gamma_ || gamma_method != gamma_method_)
{
set_gamma_method(ras_ptr_, gamma, gamma_method);
gamma_method_ = gamma_method;
gamma_ = gamma;
}
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
box2d<double> clip_box = clipping_extent(common_);
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
ren_base renb(pixf);
unsigned w = image.width();
unsigned h = image.height();
agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
unsigned offset_x=0;
unsigned offset_y=0;
if (alignment == LOCAL_ALIGNMENT)
{
double x0 = 0;
double y0 = 0;
using apply_local_alignment = detail::apply_local_alignment;
apply_local_alignment apply(common_.t_,prj_trans_, clip_box, x0, y0);
util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature_.get_geometry());
offset_x = unsigned(current_buffer_->width() - x0);
offset_y = unsigned(current_buffer_->height() - y0);
}
span_gen_type sg(img_src, offset_x, offset_y);
agg::span_allocator<agg::rgba8> sa;
renderer_type rp(renb,sa, sg, unsigned(opacity * 255));
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
using vertex_converter_type = vertex_converter<clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag,
smooth_tag>;
vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (prj_trans_.equal() && clip) converter.set<clip_poly_tag>();
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer>;
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
apply_vertex_converter_type apply(converter, *ras_ptr_);
mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
agg::scanline_u8 sl;
ras_ptr_->filling_rule(agg::fill_even_odd);
agg::render_scanlines(*ras_ptr_, sl, rp);
} }
void operator() (marker_rgba8 const& marker) const void operator() (marker_rgba8 const& marker) const
{ {
using color = agg::rgba8; render(marker.get_data());
using order = agg::order_rgba; }
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
mapnik::image_rgba8 const& image = marker.get_data();
private:
void render(mapnik::image_rgba8 const& image) const
{
agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(), agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->row_size()); current_buffer_->height(), current_buffer_->row_size());
ras_ptr_->reset(); ras_ptr_->reset();
@ -224,6 +118,23 @@ struct agg_renderer_process_visitor_p
box2d<double> clip_box = clipping_extent(common_); box2d<double> clip_box = clipping_extent(common_);
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
pixfmt_type pixf(buf); pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_))); pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
@ -282,7 +193,6 @@ struct agg_renderer_process_visitor_p
agg::render_scanlines(*ras_ptr_, sl, rp); agg::render_scanlines(*ras_ptr_, sl, rp);
} }
private:
renderer_common & common_; renderer_common & common_;
buffer_type * current_buffer_; buffer_type * current_buffer_;
std::unique_ptr<rasterizer> const& ras_ptr_; std::unique_ptr<rasterizer> const& ras_ptr_;

View file

@ -37,7 +37,7 @@ config_error::config_error(std::string const& what,
{ {
} }
char const* config_error::what() const throw() char const* config_error::what() const noexcept
{ {
msg_ = what_; msg_ = what_;
if (!node_name_.empty()) if (!node_name_.empty())

View file

@ -121,7 +121,7 @@ stop_array const& gradient::get_stop_array() const
return stops_; return stops_;
} }
void gradient::swap(gradient& other) throw() void gradient::swap(gradient& other) noexcept
{ {
std::swap(gradient_type_, other.gradient_type_); std::swap(gradient_type_, other.gradient_type_);
std::swap(stops_, other.stops_); std::swap(stops_, other.stops_);

View file

@ -90,30 +90,26 @@ struct process_layout
return; return;
} }
bound_box layout_box; auto max_diff = layout.get_max_difference();
int middle_ifirst = safe_cast<int>((member_boxes_.size() - 1) >> 1); auto layout_box = make_horiz_pair(0, 0.0, 0, x_margin, max_diff);
int top_i = 0; auto y_shift = 0.5 * layout_box.height();
int bottom_i = 0;
if (middle_ifirst % 2 == 0) for (size_t i = 2; i < member_boxes_.size(); i += 2)
{ {
layout_box = make_horiz_pair(0, 0.0, 0, x_margin, layout.get_max_difference()); auto y = layout_box.maxy() + y_margin;
top_i = middle_ifirst - 2; auto pair_box = make_horiz_pair(i, y, 1, x_margin, max_diff);
bottom_i = middle_ifirst + 2; layout_box.expand_to_include(pair_box);
}
else
{
top_i = middle_ifirst - 1;
bottom_i = middle_ifirst + 1;
} }
while (bottom_i >= 0 && top_i >= 0 && top_i < static_cast<int>(member_offsets_.size())) // layout_box.center corresponds to the center of the first row;
{ // shift offsets so that the whole group is centered vertically
layout_box.expand_to_include(make_horiz_pair(static_cast<std::size_t>(top_i), layout_box.miny() - y_margin, -1, x_margin, layout.get_max_difference()));
layout_box.expand_to_include(make_horiz_pair(static_cast<std::size_t>(bottom_i), layout_box.maxy() + y_margin, 1, x_margin, layout.get_max_difference()));
top_i -= 2;
bottom_i += 2;
}
y_shift -= 0.5 * layout_box.height();
for (auto & offset : member_offsets_)
{
offset.y += y_shift;
}
} }
private: private:
@ -146,12 +142,12 @@ private:
// stores corresponding offset, and returns modified bounding box // stores corresponding offset, and returns modified bounding box
bound_box box_offset_align(size_t i, double x, double y, int x_dir, int y_dir) const bound_box box_offset_align(size_t i, double x, double y, int x_dir, int y_dir) const
{ {
bound_box const& box = member_boxes_[i]; auto box = member_boxes_[i];
pixel_position offset((x_dir == 0 ? x - input_origin_.x : x - (x_dir < 0 ? box.maxx() : box.minx())), auto & offset = member_offsets_[i];
(y_dir == 0 ? y - input_origin_.y : y - (y_dir < 0 ? box.maxy() : box.miny()))); offset.x = x - (x_dir == 0 ? input_origin_.x : (x_dir < 0 ? box.maxx() : box.minx()));
offset.y = y - (y_dir == 0 ? input_origin_.y : (y_dir < 0 ? box.maxy() : box.miny()));
member_offsets_[i] = offset; box.move(offset.x, offset.y);
return bound_box(box.minx() + offset.x, box.miny() + offset.y, box.maxx() + offset.x, box.maxy() + offset.y); return box;
} }
}; };

View file

@ -88,7 +88,6 @@ template struct MAPNIK_DECL image_dimensions<65535>;
} // end ns detail } // end ns detail
template class MAPNIK_DECL image<null_t>;
template class MAPNIK_DECL image<rgba8_t>; template class MAPNIK_DECL image<rgba8_t>;
template class MAPNIK_DECL image<gray8_t>; template class MAPNIK_DECL image<gray8_t>;
template class MAPNIK_DECL image<gray8s_t>; template class MAPNIK_DECL image<gray8s_t>;

View file

@ -133,6 +133,7 @@ void scale_image_agg(T & target, T const& source, scaling_method_e scaling_metho
// create a scaling matrix // create a scaling matrix
agg::trans_affine img_mtx; agg::trans_affine img_mtx;
img_mtx *= agg::trans_affine_translation(x_off_f, y_off_f);
img_mtx /= agg::trans_affine_scaling(image_ratio_x, image_ratio_y); img_mtx /= agg::trans_affine_scaling(image_ratio_x, image_ratio_y);
// create a linear interpolator for our scaling matrix // create a linear interpolator for our scaling matrix
@ -141,11 +142,10 @@ void scale_image_agg(T & target, T const& source, scaling_method_e scaling_metho
double scaled_width = target.width(); double scaled_width = target.width();
double scaled_height = target.height(); double scaled_height = target.height();
ras.reset(); ras.reset();
ras.move_to_d(x_off_f, y_off_f); ras.move_to_d(0.0, 0.0);
ras.line_to_d(x_off_f + scaled_width, y_off_f); ras.line_to_d(scaled_width, 0.0);
ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height); ras.line_to_d(scaled_width, scaled_height);
ras.line_to_d(x_off_f, y_off_f + scaled_height); ras.line_to_d(0.0, scaled_height);
if (scaling_method == SCALING_NEAR) if (scaling_method == SCALING_NEAR)
{ {
using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_filter; using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_filter;

View file

@ -119,7 +119,6 @@ void jpeg_saver::operator() (T const& image) const
throw image_writer_exception("Mapnik does not support jpeg grayscale images"); throw image_writer_exception("Mapnik does not support jpeg grayscale images");
} }
template void jpeg_saver::operator()<image_rgba8> (image_rgba8 const& image) const;
template void jpeg_saver::operator()<image_gray8> (image_gray8 const& image) const; template void jpeg_saver::operator()<image_gray8> (image_gray8 const& image) const;
template void jpeg_saver::operator()<image_gray8s> (image_gray8s const& image) const; template void jpeg_saver::operator()<image_gray8s> (image_gray8s const& image) const;
template void jpeg_saver::operator()<image_gray16> (image_gray16 const& image) const; template void jpeg_saver::operator()<image_gray16> (image_gray16 const& image) const;
@ -130,7 +129,6 @@ template void jpeg_saver::operator()<image_gray32f> (image_gray32f const& image)
template void jpeg_saver::operator()<image_gray64> (image_gray64 const& image) const; template void jpeg_saver::operator()<image_gray64> (image_gray64 const& image) const;
template void jpeg_saver::operator()<image_gray64s> (image_gray64s const& image) const; template void jpeg_saver::operator()<image_gray64s> (image_gray64s const& image) const;
template void jpeg_saver::operator()<image_gray64f> (image_gray64f const& image) const; template void jpeg_saver::operator()<image_gray64f> (image_gray64f const& image) const;
template void jpeg_saver::operator()<image_view_rgba8> (image_view_rgba8 const& image) const;
template void jpeg_saver::operator()<image_view_gray8> (image_view_gray8 const& image) const; template void jpeg_saver::operator()<image_view_gray8> (image_view_gray8 const& image) const;
template void jpeg_saver::operator()<image_view_gray8s> (image_view_gray8s const& image) const; template void jpeg_saver::operator()<image_view_gray8s> (image_view_gray8s const& image) const;
template void jpeg_saver::operator()<image_view_gray16> (image_view_gray16 const& image) const; template void jpeg_saver::operator()<image_view_gray16> (image_view_gray16 const& image) const;

View file

@ -316,7 +316,6 @@ void png_saver_pal::operator() (T const& image) const
#endif #endif
} }
template void png_saver::operator()<image_rgba8> (image_rgba8 const& image) const;
template void png_saver::operator()<image_gray8> (image_gray8 const& image) const; template void png_saver::operator()<image_gray8> (image_gray8 const& image) const;
template void png_saver::operator()<image_gray8s> (image_gray8s const& image) const; template void png_saver::operator()<image_gray8s> (image_gray8s const& image) const;
template void png_saver::operator()<image_gray16> (image_gray16 const& image) const; template void png_saver::operator()<image_gray16> (image_gray16 const& image) const;
@ -327,7 +326,6 @@ template void png_saver::operator()<image_gray32f> (image_gray32f const& image)
template void png_saver::operator()<image_gray64> (image_gray64 const& image) const; template void png_saver::operator()<image_gray64> (image_gray64 const& image) const;
template void png_saver::operator()<image_gray64s> (image_gray64s const& image) const; template void png_saver::operator()<image_gray64s> (image_gray64s const& image) const;
template void png_saver::operator()<image_gray64f> (image_gray64f const& image) const; template void png_saver::operator()<image_gray64f> (image_gray64f const& image) const;
template void png_saver::operator()<image_view_rgba8> (image_view_rgba8 const& image) const;
template void png_saver::operator()<image_view_gray8> (image_view_gray8 const& image) const; template void png_saver::operator()<image_view_gray8> (image_view_gray8 const& image) const;
template void png_saver::operator()<image_view_gray8s> (image_view_gray8s const& image) const; template void png_saver::operator()<image_view_gray8s> (image_view_gray8s const& image) const;
template void png_saver::operator()<image_view_gray16> (image_view_gray16 const& image) const; template void png_saver::operator()<image_view_gray16> (image_view_gray16 const& image) const;
@ -338,7 +336,6 @@ template void png_saver::operator()<image_view_gray32f> (image_view_gray32f cons
template void png_saver::operator()<image_view_gray64> (image_view_gray64 const& image) const; template void png_saver::operator()<image_view_gray64> (image_view_gray64 const& image) const;
template void png_saver::operator()<image_view_gray64s> (image_view_gray64s const& image) const; template void png_saver::operator()<image_view_gray64s> (image_view_gray64s const& image) const;
template void png_saver::operator()<image_view_gray64f> (image_view_gray64f const& image) const; template void png_saver::operator()<image_view_gray64f> (image_view_gray64f const& image) const;
template void png_saver_pal::operator()<image_rgba8> (image_rgba8 const& image) const;
template void png_saver_pal::operator()<image_gray8> (image_gray8 const& image) const; template void png_saver_pal::operator()<image_gray8> (image_gray8 const& image) const;
template void png_saver_pal::operator()<image_gray8s> (image_gray8s const& image) const; template void png_saver_pal::operator()<image_gray8s> (image_gray8s const& image) const;
template void png_saver_pal::operator()<image_gray16> (image_gray16 const& image) const; template void png_saver_pal::operator()<image_gray16> (image_gray16 const& image) const;
@ -349,7 +346,6 @@ template void png_saver_pal::operator()<image_gray32f> (image_gray32f const& ima
template void png_saver_pal::operator()<image_gray64> (image_gray64 const& image) const; template void png_saver_pal::operator()<image_gray64> (image_gray64 const& image) const;
template void png_saver_pal::operator()<image_gray64s> (image_gray64s const& image) const; template void png_saver_pal::operator()<image_gray64s> (image_gray64s const& image) const;
template void png_saver_pal::operator()<image_gray64f> (image_gray64f const& image) const; template void png_saver_pal::operator()<image_gray64f> (image_gray64f const& image) const;
template void png_saver_pal::operator()<image_view_rgba8> (image_view_rgba8 const& image) const;
template void png_saver_pal::operator()<image_view_gray8> (image_view_gray8 const& image) const; template void png_saver_pal::operator()<image_view_gray8> (image_view_gray8 const& image) const;
template void png_saver_pal::operator()<image_view_gray8s> (image_view_gray8s const& image) const; template void png_saver_pal::operator()<image_view_gray8s> (image_view_gray8s const& image) const;
template void png_saver_pal::operator()<image_view_gray16> (image_view_gray16 const& image) const; template void png_saver_pal::operator()<image_view_gray16> (image_view_gray16 const& image) const;

View file

@ -360,7 +360,6 @@ void webp_saver::operator() (T const& image) const
throw image_writer_exception("Mapnik does not support webp grayscale images"); throw image_writer_exception("Mapnik does not support webp grayscale images");
} }
template void webp_saver::operator()<image_rgba8> (image_rgba8 const& image) const;
template void webp_saver::operator()<image_gray8> (image_gray8 const& image) const; template void webp_saver::operator()<image_gray8> (image_gray8 const& image) const;
template void webp_saver::operator()<image_gray8s> (image_gray8s const& image) const; template void webp_saver::operator()<image_gray8s> (image_gray8s const& image) const;
template void webp_saver::operator()<image_gray16> (image_gray16 const& image) const; template void webp_saver::operator()<image_gray16> (image_gray16 const& image) const;
@ -371,7 +370,6 @@ template void webp_saver::operator()<image_gray32f> (image_gray32f const& image)
template void webp_saver::operator()<image_gray64> (image_gray64 const& image) const; template void webp_saver::operator()<image_gray64> (image_gray64 const& image) const;
template void webp_saver::operator()<image_gray64s> (image_gray64s const& image) const; template void webp_saver::operator()<image_gray64s> (image_gray64s const& image) const;
template void webp_saver::operator()<image_gray64f> (image_gray64f const& image) const; template void webp_saver::operator()<image_gray64f> (image_gray64f const& image) const;
template void webp_saver::operator()<image_view_rgba8> (image_view_rgba8 const& image) const;
template void webp_saver::operator()<image_view_gray8> (image_view_gray8 const& image) const; template void webp_saver::operator()<image_view_gray8> (image_view_gray8 const& image) const;
template void webp_saver::operator()<image_view_gray8s> (image_view_gray8s const& image) const; template void webp_saver::operator()<image_view_gray8s> (image_view_gray8s const& image) const;
template void webp_saver::operator()<image_view_gray16> (image_view_gray16 const& image) const; template void webp_saver::operator()<image_view_gray16> (image_view_gray16 const& image) const;

View file

@ -29,7 +29,6 @@
namespace mapnik namespace mapnik
{ {
template class MAPNIK_DECL image_view<image_null>;
template class MAPNIK_DECL image_view<image_rgba8>; template class MAPNIK_DECL image_view<image_rgba8>;
template class MAPNIK_DECL image_view<image_gray8>; template class MAPNIK_DECL image_view<image_gray8>;
template class MAPNIK_DECL image_view<image_gray8s>; template class MAPNIK_DECL image_view<image_gray8s>;

View file

@ -37,7 +37,15 @@ bool from_geojson(std::string const& json, mapnik::geometry::geometry<double> &
standard::space_type space; standard::space_type space;
char const* start = json.c_str(); char const* start = json.c_str();
char const* end = start + json.length(); char const* end = start + json.length();
return qi::phrase_parse(start, end, g, space, geom); try
{
if (!qi::phrase_parse(start, end, g, space, geom))
{
throw std::runtime_error("Can't parser GeoJSON Geometry");
}
}
catch (...) { return false; }
return true;
} }
}} }}

View file

@ -133,7 +133,7 @@ private:
void find_unused_nodes_recursive(xml_node const& node, std::string & error_text); void find_unused_nodes_recursive(xml_node const& node, std::string & error_text);
std::string ensure_relative_to_xml(boost::optional<std::string> const& opt_path); std::string ensure_relative_to_xml(boost::optional<std::string> const& opt_path);
void ensure_exists(std::string const& file_path); void ensure_exists(std::string const& file_path);
void check_styles(Map const & map) const throw (config_error); void check_styles(Map const & map);
boost::optional<color> get_opt_color_attr(boost::property_tree::ptree const& node, boost::optional<color> get_opt_color_attr(boost::property_tree::ptree const& node,
std::string const& name); std::string const& name);
@ -1155,10 +1155,14 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& node)
if (placement_type) if (placement_type)
{ {
placements = placements::registry::instance().from_xml(*placement_type, node, fontsets_, true); placements = placements::registry::instance().from_xml(*placement_type, node, fontsets_, true);
} else { if (!placements)
placements = std::make_shared<text_placements_dummy>(); return;
}
else
{
placements = std::make_shared<text_placements_dummy>();
placements->defaults.from_xml(node, fontsets_, true);
} }
placements->defaults.from_xml(node, fontsets_, true);
if (strict_ && if (strict_ &&
!placements->defaults.format_defaults.fontset) !placements->defaults.format_defaults.fontset)
{ {
@ -1691,7 +1695,7 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::string &
} }
} }
void map_parser::check_styles(Map const & map) const throw (config_error) void map_parser::check_styles(Map const & map)
{ {
for (auto const & layer : map.layers()) for (auto const & layer : map.layers())
{ {

View file

@ -66,7 +66,7 @@ void render_group_symbolizer(group_symbolizer const& sym,
// keep track of which lists of render thunks correspond to // keep track of which lists of render thunks correspond to
// entries in the group_layout_manager. // entries in the group_layout_manager.
std::vector<render_thunk_list> layout_thunks; std::list<render_thunk_list> layout_thunks;
// layout manager to store and arrange bboxes of matched features // layout manager to store and arrange bboxes of matched features
group_layout_manager layout_manager(props->get_layout()); group_layout_manager layout_manager(props->get_layout());
@ -182,11 +182,13 @@ void render_group_symbolizer(group_symbolizer const& sym,
pixel_position_list const& positions = helper.get(); pixel_position_list const& positions = helper.get();
for (pixel_position const& pos : positions) for (pixel_position const& pos : positions)
{ {
for (size_t layout_i = 0; layout_i < layout_thunks.size(); ++layout_i) size_t layout_i = 0;
for (auto const& thunks : layout_thunks)
{ {
pixel_position const& offset = layout_manager.offset_at(layout_i); pixel_position const& offset = layout_manager.offset_at(layout_i);
pixel_position render_offset = pos + offset; pixel_position render_offset = pos + offset;
render_thunks.render_list(layout_thunks[layout_i], render_offset); render_thunks.render_list(thunks, render_offset);
++layout_i;
} }
} }
} }

View file

@ -55,7 +55,7 @@ struct thunk_markers_renderer_context : markers_renderer_context
{ {
vector_marker_render_thunk thunk(src, attrs, marker_tr, params.opacity, vector_marker_render_thunk thunk(src, attrs, marker_tr, params.opacity,
comp_op_, params.snap_to_pixels); comp_op_, params.snap_to_pixels);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk))); thunks_.emplace_back(std::move(thunk));
} }
virtual void render_marker(image_rgba8 const& src, virtual void render_marker(image_rgba8 const& src,
@ -64,7 +64,7 @@ struct thunk_markers_renderer_context : markers_renderer_context
{ {
raster_marker_render_thunk thunk(src, marker_tr, params.opacity, raster_marker_render_thunk thunk(src, marker_tr, params.opacity,
comp_op_, params.snap_to_pixels); comp_op_, params.snap_to_pixels);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk))); thunks_.emplace_back(std::move(thunk));
} }
private: private:
@ -128,7 +128,7 @@ void render_thunk_extractor::extract_text_thunk(text_render_thunk::helper_ptr &&
halo_rasterizer_enum halo_rasterizer = get<halo_rasterizer_enum>(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL); halo_rasterizer_enum halo_rasterizer = get<halo_rasterizer_enum>(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL);
text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer); text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer);
thunks_.push_back(std::make_unique<render_thunk>(std::move(thunk))); thunks_.emplace_back(std::move(thunk));
update_box(); update_box();
} }

View file

@ -187,23 +187,26 @@ base_symbolizer_helper::base_symbolizer_helper(
initialize_points(); initialize_points();
} }
struct largest_bbox_first template <typename It>
static It largest_bbox(It begin, It end)
{ {
bool operator() (geometry::geometry<double> const* g0, geometry::geometry<double> const* g1) const if (begin == end)
{ {
box2d<double> b0 = geometry::envelope(*g0); return end;
box2d<double> b1 = geometry::envelope(*g1);
return b0.width() * b0.height() > b1.width() * b1.height();
} }
bool operator() (base_symbolizer_helper::geometry_cref const& g0, It largest_geom = begin;
base_symbolizer_helper::geometry_cref const& g1) const double largest_bbox = geometry::envelope(*largest_geom).area();
for (++begin; begin != end; ++begin)
{ {
// TODO - this has got to be expensive! Can we cache bbox's if there are repeated calls to same geom? double bbox = geometry::envelope(*begin).area();
box2d<double> b0 = geometry::envelope(g0); if (bbox > largest_bbox)
box2d<double> b1 = geometry::envelope(g1); {
return b0.width() * b0.height() > b1.width() * b1.height(); largest_bbox = bbox;
largest_geom = begin;
}
} }
}; return largest_geom;
}
void base_symbolizer_helper::initialize_geometries() const void base_symbolizer_helper::initialize_geometries() const
{ {
@ -216,10 +219,16 @@ void base_symbolizer_helper::initialize_geometries() const
type == geometry::geometry_types::MultiPolygon) type == geometry::geometry_types::MultiPolygon)
{ {
bool largest_box_only = text_props_->largest_bbox_only; bool largest_box_only = text_props_->largest_bbox_only;
if (largest_box_only) if (largest_box_only && geometries_to_process_.size() > 1)
{ {
geometries_to_process_.sort(largest_bbox_first()); auto largest_geom = largest_bbox(
geometries_to_process_.begin(),
geometries_to_process_.end());
geo_itr_ = geometries_to_process_.begin(); geo_itr_ = geometries_to_process_.begin();
if (geo_itr_ != largest_geom)
{
std::swap(*geo_itr_, *largest_geom);
}
geometries_to_process_.erase(++geo_itr_, geometries_to_process_.end()); geometries_to_process_.erase(++geo_itr_, geometries_to_process_.end());
} }
} }

View file

@ -2,7 +2,7 @@
* *
* This file is part of Mapnik (c++ mapping toolkit) * This file is part of Mapnik (c++ mapping toolkit)
* *
* Copyright (C) 2015 Artem Pavlenko * Copyright (C) 2017 Artem Pavlenko
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -162,8 +162,12 @@ private:
tiff_reader(const tiff_reader&); tiff_reader(const tiff_reader&);
tiff_reader& operator=(const tiff_reader&); tiff_reader& operator=(const tiff_reader&);
void init(); void init();
void read_generic(std::size_t x,std::size_t y,image_rgba8& image);
void read_stripped(std::size_t x,std::size_t y,image_rgba8& image); template <typename ImageData>
void read_generic(std::size_t x,std::size_t y, ImageData & image);
template <typename ImageData>
void read_stripped(std::size_t x,std::size_t y, ImageData & image);
template <typename ImageData> template <typename ImageData>
void read_tiled(std::size_t x,std::size_t y, ImageData & image); void read_tiled(std::size_t x,std::size_t y, ImageData & image);
@ -257,25 +261,24 @@ void tiff_reader<T>::init()
TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photometric_); TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photometric_);
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &bands_); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &bands_);
MAPNIK_LOG_DEBUG(tiff_reader) << "bits per sample: " << bps_; MAPNIK_LOG_DEBUG(tiff_reader) << "bits per sample: " << bps_ ;
MAPNIK_LOG_DEBUG(tiff_reader) << "sample format: " << sample_format_; MAPNIK_LOG_DEBUG(tiff_reader) << "sample format: " << sample_format_ ;
MAPNIK_LOG_DEBUG(tiff_reader) << "photometric: " << photometric_; MAPNIK_LOG_DEBUG(tiff_reader) << "photometric: " << photometric_ ;
MAPNIK_LOG_DEBUG(tiff_reader) << "bands: " << bands_; MAPNIK_LOG_DEBUG(tiff_reader) << "bands: " << bands_ ;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_);
TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config_); TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config_);
TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression_ ); TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression_ );
TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip_);
std::uint16_t orientation; std::uint16_t orientation;
if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation) == 0) if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation) == 0)
{ {
orientation = 1; orientation = 1;
} }
MAPNIK_LOG_DEBUG(tiff_reader) << "orientation: " << orientation; MAPNIK_LOG_DEBUG(tiff_reader) << "orientation: " << orientation ;
MAPNIK_LOG_DEBUG(tiff_reader) << "planar-config: " << planar_config_ ;
is_tiled_ = TIFFIsTiled(tif); is_tiled_ = TIFFIsTiled(tif);
if (is_tiled_) if (is_tiled_)
@ -285,7 +288,7 @@ void tiff_reader<T>::init()
MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is tiled"; MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is tiled";
read_method_ = tiled; read_method_ = tiled;
} }
else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0) else if (TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip_) != 0)
{ {
MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is stripped"; MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is stripped";
read_method_ = stripped; read_method_ = stripped;
@ -311,9 +314,9 @@ void tiff_reader<T>::init()
if (TIFFGetField(tif, 33550, &count, &pixelscale) == 1 && count == 3 if (TIFFGetField(tif, 33550, &count, &pixelscale) == 1 && count == 3
&& TIFFGetField(tif, 33922 , &count, &tilepoint) == 1 && count == 6) && TIFFGetField(tif, 33922 , &count, &tilepoint) == 1 && count == 6)
{ {
MAPNIK_LOG_DEBUG(tiff_reader) << "PixelScale:" << pixelscale[0] << "," << pixelscale[1] << "," << pixelscale[2]; MAPNIK_LOG_DEBUG(tiff_reader) << "PixelScale:" << pixelscale[0] << "," << pixelscale[1] << "," << pixelscale[2] ;
MAPNIK_LOG_DEBUG(tiff_reader) << "TilePoint:" << tilepoint[0] << "," << tilepoint[1] << "," << tilepoint[2]; MAPNIK_LOG_DEBUG(tiff_reader) << "TilePoint:" << tilepoint[0] << "," << tilepoint[1] << "," << tilepoint[2] ;
MAPNIK_LOG_DEBUG(tiff_reader) << " " << tilepoint[3] << "," << tilepoint[4] << "," << tilepoint[5]; MAPNIK_LOG_DEBUG(tiff_reader) << " " << tilepoint[3] << "," << tilepoint[4] << "," << tilepoint[5] ;
// assuming upper-left // assuming upper-left
double lox = tilepoint[3]; double lox = tilepoint[3];
@ -321,7 +324,7 @@ void tiff_reader<T>::init()
double hix = lox + pixelscale[0] * width_; double hix = lox + pixelscale[0] * width_;
double hiy = loy - pixelscale[1] * height_; double hiy = loy - pixelscale[1] * height_;
bbox_.reset(box2d<double>(lox, loy, hix, hiy)); bbox_.reset(box2d<double>(lox, loy, hix, hiy));
MAPNIK_LOG_DEBUG(tiff_reader) << "Bounding Box:" << *bbox_; MAPNIK_LOG_DEBUG(tiff_reader) << "Bounding Box:" << *bbox_ ;
} }
} }
@ -391,10 +394,17 @@ image_any tiff_reader<T>::read_any_gray(std::size_t x0, std::size_t y0, std::siz
using pixel_type = typename image_type::pixel_type; using pixel_type = typename image_type::pixel_type;
if (read_method_ == tiled) if (read_method_ == tiled)
{ {
image_type data(width,height); image_type data(width, height);
read_tiled<image_type>(x0, y0, data); read_tiled<image_type>(x0, y0, data);
return image_any(std::move(data)); return image_any(std::move(data));
} }
// TODO: temp disable and default to `scanline` method for stripped images.
else if (read_method_ == stripped)
{
image_type data(width, height);
read_stripped<image_type>(x0, y0, data);
return image_any(std::move(data));
}
else else
{ {
TIFF* tif = open(stream_); TIFF* tif = open(stream_);
@ -407,14 +417,52 @@ image_any tiff_reader<T>::read_any_gray(std::size_t x0, std::size_t y0, std::siz
std::size_t start_x = x0; std::size_t start_x = x0;
std::size_t end_x = std::min(x0 + width, width_); std::size_t end_x = std::min(x0 + width, width_);
std::size_t element_size = sizeof(pixel_type); std::size_t element_size = sizeof(pixel_type);
MAPNIK_LOG_DEBUG(tiff_reader) << "SCANLINE SIZE=" << TIFFScanlineSize(tif);
std::size_t size_to_allocate = (TIFFScanlineSize(tif) + element_size - 1)/element_size; std::size_t size_to_allocate = (TIFFScanlineSize(tif) + element_size - 1)/element_size;
const std::unique_ptr<pixel_type[]> scanline(new pixel_type[size_to_allocate]); std::unique_ptr<pixel_type[]> const scanline(new pixel_type[size_to_allocate]);
for (std::size_t y = start_y; y < end_y; ++y) if (planar_config_ == PLANARCONFIG_CONTIG)
{ {
if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0)) for (std::size_t y = start_y; y < end_y; ++y)
{ {
pixel_type * row = data.get_row(y - y0); // we have to read all scanlines sequentially from start_y
std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;}); // to be able to use scanline interface with compressed blocks.
if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0))
{
pixel_type * row = data.get_row(y - y0);
if (bands_ == 1)
{
std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;});
}
else if (size_to_allocate == bands_ * width_)
{
// bands_ > 1 => packed bands in grayscale image e.g an extra alpha channel.
// Just pick first one for now.
pixel_type * buf = scanline.get() + start_x * bands_;
std::size_t x_index = 0;
for (std::size_t j = 0; j < end_x * bands_; ++j)
{
if (x_index >= width) break;
if (j % bands_ == 0)
{
row[x_index++] = buf[j];
}
}
}
}
}
}
else if (planar_config_ == PLANARCONFIG_SEPARATE)
{
for (std::size_t s = 0 ; s < bands_ ; ++s)
{
for (std::size_t y = start_y; y < end_y; ++y)
{
if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0))
{
pixel_type * row = data.get_row(y - y0);
std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;});
}
}
} }
} }
return image_any(std::move(data)); return image_any(std::move(data));
@ -446,9 +494,17 @@ struct tiff_reader_traits
{ {
using image_type = T; using image_type = T;
using pixel_type = typename image_type::pixel_type; using pixel_type = typename image_type::pixel_type;
constexpr static bool reverse = false;
static bool read_tile(TIFF * tif, std::size_t x, std::size_t y, pixel_type* buf, std::size_t tile_width, std::size_t tile_height) static bool read_tile(TIFF * tif, std::size_t x, std::size_t y, pixel_type* buf, std::size_t tile_width, std::size_t tile_height)
{ {
return (TIFFReadEncodedTile(tif, TIFFComputeTile(tif, x,y,0,0), buf, tile_width * tile_height * sizeof(pixel_type)) != -1); std::uint32_t tile_size = TIFFTileSize(tif);
return (TIFFReadEncodedTile(tif, TIFFComputeTile(tif, x, y, 0, 0), buf, tile_size) != -1);
}
static bool read_strip(TIFF * tif, std::size_t y, std::size_t rows_per_strip, std::size_t strip_width, pixel_type * buf)
{
return (TIFFReadEncodedStrip(tif, y/rows_per_strip, buf, -1) != -1);
} }
}; };
@ -456,18 +512,17 @@ struct tiff_reader_traits
template <> template <>
struct tiff_reader_traits<image_rgba8> struct tiff_reader_traits<image_rgba8>
{ {
using image_type = image_rgba8;
using pixel_type = std::uint32_t; using pixel_type = std::uint32_t;
constexpr static bool reverse = true;
static bool read_tile(TIFF * tif, std::size_t x0, std::size_t y0, pixel_type* buf, std::size_t tile_width, std::size_t tile_height) static bool read_tile(TIFF * tif, std::size_t x0, std::size_t y0, pixel_type* buf, std::size_t tile_width, std::size_t tile_height)
{ {
if (TIFFReadRGBATile(tif, x0, y0, buf) != -1) return (TIFFReadRGBATile(tif, x0, y0, buf) != 0);
{ }
for (std::size_t y = 0; y < tile_height/2; ++y)
{ static bool read_strip(TIFF * tif, std::size_t y, std::size_t rows_per_strip, std::size_t strip_width, pixel_type * buf)
std::swap_ranges(buf + y * tile_width, buf + (y + 1) * tile_width, buf + (tile_height - y - 1) * tile_width); {
} return (TIFFReadRGBAStrip(tif, y, buf) != 0);
return true;
}
return false;
} }
}; };
@ -591,7 +646,8 @@ image_any tiff_reader<T>::read(unsigned x, unsigned y, unsigned width, unsigned
} }
template <typename T> template <typename T>
void tiff_reader<T>::read_generic(std::size_t, std::size_t, image_rgba8&) template <typename ImageData>
void tiff_reader<T>::read_generic(std::size_t, std::size_t, ImageData &)
{ {
throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled"); throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled");
} }
@ -605,7 +661,8 @@ void tiff_reader<T>::read_tiled(std::size_t x0,std::size_t y0, ImageData & image
TIFF* tif = open(stream_); TIFF* tif = open(stream_);
if (tif) if (tif)
{ {
std::unique_ptr<pixel_type[]> buf(new pixel_type[tile_width_*tile_height_]); std::uint32_t tile_size = TIFFTileSize(tif);
std::unique_ptr<pixel_type[]> tile(new pixel_type[tile_size]);
std::size_t width = image.width(); std::size_t width = image.width();
std::size_t height = image.height(); std::size_t height = image.height();
std::size_t start_y = (y0 / tile_height_) * tile_height_; std::size_t start_y = (y0 / tile_height_) * tile_height_;
@ -614,7 +671,7 @@ void tiff_reader<T>::read_tiled(std::size_t x0,std::size_t y0, ImageData & image
std::size_t end_x = ((x0 + width) / tile_width_ + 1) * tile_width_; std::size_t end_x = ((x0 + width) / tile_width_ + 1) * tile_width_;
end_y = std::min(end_y, height_); end_y = std::min(end_y, height_);
end_x = std::min(end_x, width_); end_x = std::min(end_x, width_);
bool pick_first_band = (bands_ > 1) && (tile_size / (tile_width_ * tile_height_ * sizeof(pixel_type)) == bands_);
for (std::size_t y = start_y; y < end_y; y += tile_height_) for (std::size_t y = start_y; y < end_y; y += tile_height_)
{ {
std::size_t ty0 = std::max(y0, y) - y; std::size_t ty0 = std::max(y0, y) - y;
@ -622,56 +679,98 @@ void tiff_reader<T>::read_tiled(std::size_t x0,std::size_t y0, ImageData & image
for (std::size_t x = start_x; x < end_x; x += tile_width_) for (std::size_t x = start_x; x < end_x; x += tile_width_)
{ {
if (!detail::tiff_reader_traits<ImageData>::read_tile(tif, x, y, buf.get(), tile_width_, tile_height_)) if (!detail::tiff_reader_traits<ImageData>::read_tile(tif, x, y, tile.get(), tile_width_, tile_height_))
{ {
MAPNIK_LOG_DEBUG(tiff_reader) << "read_tile(...) failed at " << x << "/" << y << " for " << width_ << "/" << height_ << "\n"; MAPNIK_LOG_DEBUG(tiff_reader) << "read_tile(...) failed at " << x << "/" << y << " for " << width_ << "/" << height_ << "\n";
break; break;
} }
if (pick_first_band)
{
std::uint32_t size = tile_width_ * tile_height_ * sizeof(pixel_type);
for (std::uint32_t n = 0; n < size; ++n)
{
tile[n] = tile[n * bands_];
}
}
std::size_t tx0 = std::max(x0, x); std::size_t tx0 = std::max(x0, x);
std::size_t tx1 = std::min(width + x0, x + tile_width_); std::size_t tx1 = std::min(width + x0, x + tile_width_);
std::size_t row = y + ty0 - y0; std::size_t row_index = y + ty0 - y0;
for (std::size_t ty = ty0; ty < ty1; ++ty, ++row)
if (detail::tiff_reader_traits<ImageData>::reverse)
{ {
image.set_row(row, tx0 - x0, tx1 - x0, &buf[ty * tile_width_ + tx0 - x]); for (std::size_t ty = ty0; ty < ty1; ++ty, ++row_index)
{
// This is in reverse because the TIFFReadRGBATile reads are inverted
image.set_row(row_index, tx0 - x0, tx1 - x0, &tile[(tile_height_ - ty - 1) * tile_width_ + tx0 - x]);
}
}
else
{
for (std::size_t ty = ty0; ty < ty1; ++ty, ++row_index)
{
image.set_row(row_index, tx0 - x0, tx1 - x0, &tile[ty * tile_width_ + tx0 - x]);
}
} }
} }
} }
} }
} }
template <typename T> template <typename T>
void tiff_reader<T>::read_stripped(std::size_t x0,std::size_t y0,image_rgba8& image) template <typename ImageData>
void tiff_reader<T>::read_stripped(std::size_t x0, std::size_t y0, ImageData & image)
{ {
using pixel_type = typename detail::tiff_reader_traits<ImageData>::pixel_type;
TIFF* tif = open(stream_); TIFF* tif = open(stream_);
if (tif) if (tif)
{ {
image_rgba8 strip(width_,rows_per_strip_,false); std::uint32_t strip_size = TIFFStripSize(tif);
std::size_t width=image.width(); std::unique_ptr<pixel_type[]> strip(new pixel_type[strip_size]);
std::size_t height=image.height(); std::size_t width = image.width();
std::size_t height = image.height();
std::size_t start_y=(y0/rows_per_strip_)*rows_per_strip_; std::size_t start_y = (y0 / rows_per_strip_) * rows_per_strip_;
std::size_t end_y=std::min(y0+height, height_); std::size_t end_y = std::min(y0 + height, height_);
std::size_t tx0,tx1,ty0,ty1; std::size_t tx0, tx1, ty0, ty1;
tx0=x0; tx0 = x0;
tx1=std::min(width+x0,width_); tx1 = std::min(width + x0, width_);
std::size_t row = 0; std::size_t row = 0;
for (std::size_t y=start_y; y < end_y; y+=rows_per_strip_) bool pick_first_band = (bands_ > 1) && (strip_size / (width_ * rows_per_strip_ * sizeof(pixel_type)) == bands_);
for (std::size_t y = start_y; y < end_y; y += rows_per_strip_)
{ {
ty0 = std::max(y0,y)-y; ty0 = std::max(y0, y) - y;
ty1 = std::min(end_y,y+rows_per_strip_)-y; ty1 = std::min(end_y, y + rows_per_strip_) - y;
if (!TIFFReadRGBAStrip(tif,y,strip.data())) if (!detail::tiff_reader_traits<ImageData>::read_strip(tif, y, rows_per_strip_, width_, strip.get()))
{ {
MAPNIK_LOG_DEBUG(tiff_reader) << "TIFFReadRGBAStrip failed at " << y << " for " << width_ << "/" << height_ << "\n"; MAPNIK_LOG_DEBUG(tiff_reader) << "TIFFRead(Encoded|RGBA)Strip failed at " << y << " for " << width_ << "/" << height_ << "\n";
break; break;
} }
// This is in reverse because the TIFFReadRGBAStrip reads inverted if (pick_first_band)
for (std::size_t ty = ty1; ty > ty0; --ty)
{ {
image.set_row(row,tx0-x0,tx1-x0,&strip.data()[(ty-1)*width_+tx0]); std::uint32_t size = width_ * rows_per_strip_ * sizeof(pixel_type);
++row; for (std::uint32_t n = 0; n < size; ++n)
{
strip[n] = strip[bands_ * n];
}
}
if (detail::tiff_reader_traits<ImageData>::reverse)
{
std::size_t num_rows = std::min(end_y - y, static_cast<std::size_t>(rows_per_strip_));
for (std::size_t ty = ty0; ty < ty1; ++ty)
{
// This is in reverse because the TIFFReadRGBAStrip reads are inverted
image.set_row(row++, tx0 - x0, tx1 - x0, &strip[(num_rows - ty - 1) * width_ + tx0]);
}
}
else
{
for (std::size_t ty = ty0; ty < ty1; ++ty)
{
image.set_row(row++, tx0 - x0, tx1 - x0, &strip[ty * width_ + tx0]);
}
} }
} }
} }

View file

@ -133,13 +133,13 @@ node_not_found::node_not_found(std::string const& node_name)
: node_name_(node_name), : node_name_(node_name),
msg_() {} msg_() {}
const char* node_not_found::what() const throw() const char* node_not_found::what() const noexcept
{ {
msg_ = std::string("Node "+node_name_+ "not found"); msg_ = std::string("Node "+node_name_+ "not found");
return msg_.c_str(); return msg_.c_str();
} }
node_not_found::~node_not_found() throw() {} node_not_found::~node_not_found() {}
attribute_not_found::attribute_not_found(std::string const& node_name, attribute_not_found::attribute_not_found(std::string const& node_name,
@ -148,25 +148,25 @@ attribute_not_found::attribute_not_found(std::string const& node_name,
attribute_name_(attribute_name), attribute_name_(attribute_name),
msg_() {} msg_() {}
const char* attribute_not_found::what() const throw() const char* attribute_not_found::what() const noexcept
{ {
msg_ = std::string("Attribute '" + attribute_name_ +"' not found in node '"+node_name_+ "'"); msg_ = std::string("Attribute '" + attribute_name_ +"' not found in node '"+node_name_+ "'");
return msg_.c_str(); return msg_.c_str();
} }
attribute_not_found::~attribute_not_found() throw() {} attribute_not_found::~attribute_not_found() {}
more_than_one_child::more_than_one_child(std::string const& node_name) more_than_one_child::more_than_one_child(std::string const& node_name)
: node_name_(node_name), : node_name_(node_name),
msg_() {} msg_() {}
const char* more_than_one_child::what() const throw() const char* more_than_one_child::what() const noexcept
{ {
msg_ = std::string("More than one child node in node '" + node_name_ +"'"); msg_ = std::string("More than one child node in node '" + node_name_ +"'");
return msg_.c_str(); return msg_.c_str();
} }
more_than_one_child::~more_than_one_child() throw() {} more_than_one_child::~more_than_one_child() {}
xml_node::xml_node(xml_tree &tree, std::string && name, unsigned line, bool is_text) xml_node::xml_node(xml_tree &tree, std::string && name, unsigned line, bool is_text)
: tree_(tree), : tree_(tree),

@ -1 +1 @@
Subproject commit 6ce59adfc4f11b16a5dc0e2020c36dc614850989 Subproject commit da43561d111b3539c09dbb9622fb0743e2d99973

@ -1 +1 @@
Subproject commit 941db3d00920dc7aceaa6797096a7228bc7bac14 Subproject commit c3879224d25d01571e8e803180ae15c31bbf6b24

View file

@ -284,16 +284,19 @@ SECTION("to string") {
REQUIRE( string2bool("true",val) ); REQUIRE( string2bool("true",val) );
REQUIRE( val == true ); REQUIRE( val == true );
// mapnik::value hashability // mapnik::value hash() and operator== works for all T in value<Types...>
using values_container = std::unordered_map<mapnik::value, unsigned>; mapnik::transcoder tr("utf8");
using values_container = std::unordered_map<mapnik::value, mapnik::value>;
values_container vc; values_container vc;
mapnik::value val2(1); mapnik::value keys[5] = {true, 123456789, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()} ;
vc[val2] = 1; for (auto const& k : keys)
REQUIRE( vc[1] == static_cast<int>(1) ); {
vc.insert({k, k});
REQUIRE( vc[k] == k );
}
// mapnik::value << to ostream // mapnik::value << to ostream
std::stringstream s; std::stringstream s;
mapnik::transcoder tr("utf-8");
mapnik::value_unicode_string ustr = tr.transcode("hello world!"); mapnik::value_unicode_string ustr = tr.transcode("hello world!");
mapnik::value streamable(ustr); mapnik::value streamable(ustr);
s << streamable; s << streamable;

View file

@ -28,9 +28,11 @@
#include <mapnik/datasource_cache.hpp> #include <mapnik/datasource_cache.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/geometry_type.hpp> #include <mapnik/geometry_type.hpp>
#include <mapnik/json/geometry_parser.hpp> // from_geojson
#include <mapnik/util/geometry_to_geojson.hpp>
#include <mapnik/util/fs.hpp> #include <mapnik/util/fs.hpp>
#include <cstdlib> #include <cstdlib>
#include <algorithm>
#include <boost/optional/optional_io.hpp> #include <boost/optional/optional_io.hpp>
/* /*
@ -115,6 +117,50 @@ TEST_CASE("geojson") {
} }
} }
SECTION("GeoJSON empty Geometries handling")
{
auto valid_empty_geometries =
{
"null", // Point can't be empty
"{ \"type\": \"LineString\", \"coordinates\": [] }",
"{ \"type\": \"Polygon\", \"coordinates\": [ [ ] ] } ",
"{ \"type\": \"MultiPoint\", \"coordinates\": [ ] }",
"{ \"type\": \"MultiLineString\", \"coordinates\": [ [] ] }",
"{ \"type\": \"MultiPolygon\", \"coordinates\": [[ []] ] }"
};
for (auto const& in : valid_empty_geometries)
{
std::string json(in);
mapnik::geometry::geometry<double> geom;
CHECK(mapnik::json::from_geojson(json, geom));
// round trip
std::string json_out;
CHECK(mapnik::util::to_geojson(json_out, geom));
json.erase(std::remove_if(
std::begin(json), std::end(json),
[](char ch) { return std::isspace(ch, std::locale{}); }
), std::end(json));
REQUIRE(json == json_out);
}
auto invalid_empty_geometries =
{
"{ \"type\": \"Point\", \"coordinates\": [] }",
"{ \"type\": \"LineString\", \"coordinates\": [[]] }"
"{ \"type\": \"Polygon\", \"coordinates\": [[[]]] }",
"{ \"type\": \"MultiPoint\", \"coordinates\": [[]] }",
"{ \"type\": \"MultiLineString\", \"coordinates\": [[[]]] }",
"{ \"type\": \"MultiPolygon\", \"coordinates\": [[[[]]]] }"
};
for (auto const& json : invalid_empty_geometries)
{
mapnik::geometry::geometry<double> geom;
CHECK(!mapnik::json::from_geojson(json, geom));
}
}
SECTION("GeoJSON num_features_to_query") SECTION("GeoJSON num_features_to_query")
{ {
std::string filename = "./test/data/json/featurecollection-multipleprops.geojson"; std::string filename = "./test/data/json/featurecollection-multipleprops.geojson";
@ -514,7 +560,8 @@ TEST_CASE("geojson") {
for (auto const& c_str : {"./test/data/json/feature-malformed-1.geojson", for (auto const& c_str : {"./test/data/json/feature-malformed-1.geojson",
"./test/data/json/feature-malformed-2.geojson", "./test/data/json/feature-malformed-2.geojson",
"./test/data/json/feature-malformed-3.geojson"}) "./test/data/json/feature-malformed-3.geojson",
"./test/data/json/feature-malformed-4.geojson"})
{ {
std::string filename(c_str); std::string filename(c_str);
params["file"] = filename; params["file"] = filename;
@ -554,43 +601,45 @@ TEST_CASE("geojson") {
SECTION("GeoJSON ensure mapnik::featureset::next() throws on malformed input") SECTION("GeoJSON ensure mapnik::featureset::next() throws on malformed input")
{ {
std::string filename{"./test/data/json/featurecollection-malformed.json"};
mapnik::parameters params; mapnik::parameters params;
params["type"] = "geojson"; params["type"] = "geojson";
params["file"] = filename; for (auto const& c_str : {"./test/data/json/featurecollection-malformed.json"})
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
{ {
mapnik::util::remove(filename + ".index"); std::string filename(c_str);
} params["file"] = filename;
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
}
CHECK(!mapnik::util::exists(filename + ".index")); CHECK(!mapnik::util::exists(filename + ".index"));
int ret = create_disk_index(filename); int ret = create_disk_index(filename);
int ret_posix = (ret >> 8) & 0x000000ff; int ret_posix = (ret >> 8) & 0x000000ff;
INFO(ret); INFO(ret);
INFO(ret_posix); INFO(ret_posix);
CHECK(mapnik::util::exists(filename + ".index")); CHECK(mapnik::util::exists(filename + ".index"));
for (auto cache_features : {true,false}) for (auto cache_features : {true,false})
{ {
params["cache_features"] = cache_features; params["cache_features"] = cache_features;
auto ds = mapnik::datasource_cache::instance().create(params); auto ds = mapnik::datasource_cache::instance().create(params);
auto fields = ds->get_descriptor().get_descriptors(); auto fields = ds->get_descriptor().get_descriptors();
mapnik::query query(ds->envelope()); mapnik::query query(ds->envelope());
auto features = ds->features(query); auto features = ds->features(query);
REQUIRE_THROWS( REQUIRE_THROWS(
auto feature = features->next(); auto feature = features->next();
while (feature != nullptr) while (feature != nullptr)
{ {
feature = features->next(); feature = features->next();
}); });
} }
// cleanup // cleanup
if (mapnik::util::exists(filename + ".index")) if (mapnik::util::exists(filename + ".index"))
{ {
mapnik::util::remove(filename + ".index"); mapnik::util::remove(filename + ".index");
}
} }
} }

View file

@ -5,280 +5,398 @@
#include "catch.hpp" #include "catch.hpp"
#include <mapnik/color.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_reader.hpp> #include <mapnik/image_reader.hpp>
#include <mapnik/util/file_io.hpp> #include <mapnik/util/file_io.hpp>
#include <mapnik/util/fs.hpp>
#include "../../../src/tiff_reader.cpp" #include "../../../src/tiff_reader.cpp"
#define TIFF_ASSERT(filename) \ #define TIFF_ASSERT(filename) \
mapnik::tiff_reader<std::filebuf> tiff_reader(filename); \ mapnik::tiff_reader<std::filebuf> tiff_reader(filename); \
REQUIRE( tiff_reader.width() == 256 ); \ REQUIRE( tiff_reader.width() == 256 ); \
REQUIRE( tiff_reader.height() == 256 ); \ REQUIRE( tiff_reader.height() == 256 ); \
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \ REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff")); \ std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff")); \
REQUIRE( reader->width() == 256 ); \ REQUIRE( reader->width() == 256 ); \
REQUIRE( reader->height() == 256 ); \ REQUIRE( reader->height() == 256 ); \
mapnik::util::file file(filename); \ mapnik::util::file file(filename); \
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size()); \ mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size()); \
REQUIRE( tiff_reader2.width() == 256 ); \ REQUIRE( tiff_reader2.width() == 256 ); \
REQUIRE( tiff_reader2.height() == 256 ); \ REQUIRE( tiff_reader2.height() == 256 ); \
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size())); \ std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size())); \
REQUIRE( reader2->width() == 256 ); \ REQUIRE( reader2->width() == 256 ); \
REQUIRE( reader2->height() == 256 ); \ REQUIRE( reader2->height() == 256 ); \
#define TIFF_ASSERT_ALPHA( data ) \ #define TIFF_ASSERT_ALPHA( data ) \
REQUIRE( tiff_reader.has_alpha() == true ); \ REQUIRE( tiff_reader.has_alpha() == true ); \
REQUIRE( reader->has_alpha() == true ); \ REQUIRE( reader->has_alpha() == true ); \
REQUIRE( tiff_reader2.has_alpha() == true ); \ REQUIRE( tiff_reader2.has_alpha() == true ); \
REQUIRE( reader2->has_alpha() == true ); \ REQUIRE( reader2->has_alpha() == true ); \
REQUIRE( data.get_premultiplied() == true ); \ REQUIRE( data.get_premultiplied() == true ); \
#define TIFF_ASSERT_NO_ALPHA_RGB( data ) \ #define TIFF_ASSERT_NO_ALPHA_RGB( data ) \
REQUIRE( tiff_reader.has_alpha() == false ); \ REQUIRE( tiff_reader.has_alpha() == false ); \
REQUIRE( reader->has_alpha() == false ); \ REQUIRE( reader->has_alpha() == false ); \
REQUIRE( tiff_reader2.has_alpha() == false ); \ REQUIRE( tiff_reader2.has_alpha() == false ); \
REQUIRE( reader2->has_alpha() == false ); \ REQUIRE( reader2->has_alpha() == false ); \
REQUIRE( data.get_premultiplied() == true ); \ REQUIRE( data.get_premultiplied() == true ); \
#define TIFF_ASSERT_NO_ALPHA_GRAY( data ) \ #define TIFF_ASSERT_NO_ALPHA_GRAY( data ) \
REQUIRE( tiff_reader.has_alpha() == false ); \ REQUIRE( tiff_reader.has_alpha() == false ); \
REQUIRE( reader->has_alpha() == false ); \ REQUIRE( reader->has_alpha() == false ); \
REQUIRE( tiff_reader2.has_alpha() == false ); \ REQUIRE( tiff_reader2.has_alpha() == false ); \
REQUIRE( reader2->has_alpha() == false ); \ REQUIRE( reader2->has_alpha() == false ); \
REQUIRE( data.get_premultiplied() == false ); \ REQUIRE( data.get_premultiplied() == false ); \
#define TIFF_ASSERT_SIZE( data,reader ) \ #define TIFF_ASSERT_SIZE( data,reader ) \
REQUIRE( data.width() == reader->width() ); \ REQUIRE( data.width() == reader->width() ); \
REQUIRE( data.height() == reader->height() ); \ REQUIRE( data.height() == reader->height() ); \
#define TIFF_READ_ONE_PIXEL \ #define TIFF_READ_ONE_PIXEL \
mapnik::image_any subimage = reader->read(1, 1, 1, 1); \ mapnik::image_any subimage = reader->read(1, 1, 1, 1); \
REQUIRE( subimage.width() == 1 ); \ REQUIRE( subimage.width() == 1 ); \
REQUIRE( subimage.height() == 1 ); \ REQUIRE( subimage.height() == 1 ); \
namespace {
template <typename Image>
struct test_image_traits
{
using value_type = mapnik::color;
static value_type const& get_value(mapnik::color const& c)
{
return c;
}
};
template <>
struct test_image_traits<mapnik::image_gray8>
{
using value_type = std::uint8_t;
static value_type get_value(mapnik::color const& c)
{
return c.green(); // use green channel for gray scale images
}
};
template <typename Image>
Image generate_test_image()
{
std::size_t tile_size = 16;
Image im(64, 64);
mapnik::color colors[] = {{mapnik::color("red")},
{mapnik::color("blue")},
{mapnik::color("green")},
{mapnik::color("yellow")}};
std::size_t index = 0;
for (std::size_t j = 0; j < im.height()/tile_size; ++j)
{
++index;
for (std::size_t i = 0; i < im.width()/tile_size; ++i)
{
++index;
for (std::size_t x = 0; x < tile_size; ++x)
{
for (std::size_t y = 0; y < tile_size; ++y)
{
auto value = test_image_traits<Image>::get_value(colors[index % 4]);
mapnik::set_pixel(im, i * tile_size + x, j * tile_size + y, value );
}
}
}
}
return im;
}
template <typename Image1, typename Image2>
bool identical(Image1 const& im1, Image2 const& im2)
{
if ((im1.width() != im2.width()) || (im1.height() != im2.height()))
return false;
for (std::size_t i = 0; i < im1.width(); ++i)
{
for (std::size_t j = 0; j < im1.height(); ++j)
{
if (im1(i,j) != im2(i,j)) return false;
}
}
return true;
}
template <typename Image>
void test_tiff_reader(std::string const& pattern)
{
// generate expected image (rgba8 or gray8)
auto im = generate_test_image<Image>();
for (auto const& path : mapnik::util::list_directory("test/data/tiff/"))
{
if (boost::iends_with(path,".tif")
&& boost::istarts_with(mapnik::util::basename(path), pattern))
{
mapnik::tiff_reader<std::filebuf> tiff_reader(path);
auto width = tiff_reader.width();
auto height = tiff_reader.height();
{
// whole image
auto tiff = tiff_reader.read(0, 0, width, height);
CHECK(tiff.is<Image>());
auto im2 = tiff.get<Image>();
REQUIRE(identical(im, im2));
}
{
// portion
auto tiff = tiff_reader.read(11, 13, width - 11, height - 13);
CHECK(tiff.is<Image>());
auto im2 = tiff.get<Image>();
auto view = mapnik::image_view<Image>(11, 13, width, height, im);
REQUIRE(identical(view, im2));
}
}
}
}
}
TEST_CASE("tiff io") TEST_CASE("tiff io")
{ {
SECTION("tiff-reader rgb8+rgba8")
{
test_tiff_reader<mapnik::image_rgba8>("tiff_rgb");
}
SECTION("scan rgb8 striped") SECTION("tiff-reader gray8")
{ {
std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif"); test_tiff_reader<mapnik::image_gray8>("tiff_gray");
mapnik::tiff_reader<std::filebuf> tiff_reader(filename); }
REQUIRE( tiff_reader.width() == 512 );
REQUIRE( tiff_reader.height() == 512 );
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
REQUIRE( tiff_reader.rows_per_strip() == 16 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
REQUIRE( reader->width() == 512 );
REQUIRE( reader->height() == 512 );
mapnik::util::file file(filename);
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
REQUIRE( tiff_reader2.width() == 512 );
REQUIRE( tiff_reader2.height() == 512 );
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
REQUIRE( reader2->width() == 512 );
REQUIRE( reader2->height() == 512 );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data );
TIFF_READ_ONE_PIXEL
}
SECTION("scan rgb8 tiled") { SECTION("scan rgb8 striped")
std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif"); {
mapnik::tiff_reader<std::filebuf> tiff_reader(filename); std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif");
REQUIRE( tiff_reader.width() == 512 ); mapnik::tiff_reader<std::filebuf> tiff_reader(filename);
REQUIRE( tiff_reader.height() == 512 ); REQUIRE( tiff_reader.width() == 512 );
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); REQUIRE( tiff_reader.height() == 512 );
REQUIRE( tiff_reader.rows_per_strip() == 0 ); REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.rows_per_strip() == 16 );
REQUIRE( tiff_reader.is_tiled() == true ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.tile_width() == 256 ); REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_height() == 256 ); REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE ); REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff")); REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
REQUIRE( reader->width() == 512 ); std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
REQUIRE( reader->height() == 512 ); REQUIRE( reader->width() == 512 );
mapnik::util::file file(filename); REQUIRE( reader->height() == 512 );
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size()); mapnik::util::file file(filename);
REQUIRE( tiff_reader2.width() == 512 ); mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
REQUIRE( tiff_reader2.height() == 512 ); REQUIRE( tiff_reader2.width() == 512 );
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size())); REQUIRE( tiff_reader2.height() == 512 );
REQUIRE( reader2->width() == 512 ); std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
REQUIRE( reader2->height() == 512 ); REQUIRE( reader2->width() == 512 );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); REQUIRE( reader2->height() == 512 );
REQUIRE( data.is<mapnik::image_rgba8>() == true ); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
TIFF_ASSERT_SIZE( data,reader ); REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_NO_ALPHA_RGB( data ); TIFF_ASSERT_SIZE( data,reader );
TIFF_READ_ONE_PIXEL TIFF_ASSERT_NO_ALPHA_RGB( data );
} TIFF_READ_ONE_PIXEL
}
SECTION("rgba8 striped") { SECTION("scan rgb8 tiled") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_striped.tif") std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif");
REQUIRE( tiff_reader.rows_per_strip() == 1 ); mapnik::tiff_reader<std::filebuf> tiff_reader(filename);
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.width() == 512 );
REQUIRE( tiff_reader.is_tiled() == false ); REQUIRE( tiff_reader.height() == 512 );
REQUIRE( tiff_reader.tile_width() == 0 ); REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
REQUIRE( tiff_reader.tile_height() == 0 ); REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE ); REQUIRE( tiff_reader.is_tiled() == true );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( data.is<mapnik::image_rgba8>() == true ); REQUIRE( tiff_reader.tile_height() == 256 );
TIFF_ASSERT_SIZE( data,reader ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
TIFF_ASSERT_ALPHA( data ); REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
TIFF_READ_ONE_PIXEL std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
} REQUIRE( reader->width() == 512 );
REQUIRE( reader->height() == 512 );
mapnik::util::file file(filename);
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
REQUIRE( tiff_reader2.width() == 512 );
REQUIRE( tiff_reader2.height() == 512 );
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
REQUIRE( reader2->width() == 512 );
REQUIRE( reader2->height() == 512 );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data );
TIFF_READ_ONE_PIXEL
}
SECTION("rgba8 tiled") { SECTION("rgba8 striped") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_tiled.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 ); REQUIRE( tiff_reader.rows_per_strip() == 1 );
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true ); REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 256 ); REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 256 ); REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true ); REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_ALPHA( data ); TIFF_ASSERT_ALPHA( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("rgb8 striped") { SECTION("rgba8 tiled") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_striped.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 10 ); REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false ); REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 0 ); REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 0 ); REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true ); REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data ); TIFF_ASSERT_ALPHA( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("rgb8 tiled") { SECTION("rgb8 striped") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_tiled.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 ); REQUIRE( tiff_reader.rows_per_strip() == 10 );
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true ); REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 256 ); REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 256 ); REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true ); REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data ); TIFF_ASSERT_NO_ALPHA_RGB( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray8 striped") { SECTION("rgb8 tiled") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_striped.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 32 ); REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false ); REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 0 ); REQUIRE( tiff_reader.tile_width() == 32 );
REQUIRE( tiff_reader.tile_height() == 0 ); REQUIRE( tiff_reader.tile_height() == 32 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray8>() == true ); REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data ); TIFF_ASSERT_NO_ALPHA_RGB( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray8 tiled") { SECTION("gray8 striped") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_tiled.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 ); REQUIRE( tiff_reader.rows_per_strip() == 32 );
REQUIRE( tiff_reader.bits_per_sample() == 8 ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true ); REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 256 ); REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 256 ); REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray8>() == true ); REQUIRE( data.is<mapnik::image_gray8>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data ); TIFF_ASSERT_NO_ALPHA_GRAY( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray16 striped") { SECTION("gray8 tiled") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_striped.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 16 ); REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 16 ); REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false ); REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 0 ); REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 0 ); REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray16>() == true ); REQUIRE( data.is<mapnik::image_gray8>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data ); TIFF_ASSERT_NO_ALPHA_GRAY( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray16 tiled") { SECTION("gray16 striped") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_tiled.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 ); REQUIRE( tiff_reader.rows_per_strip() == 16 );
REQUIRE( tiff_reader.bits_per_sample() == 16 ); REQUIRE( tiff_reader.bits_per_sample() == 16 );
REQUIRE( tiff_reader.is_tiled() == true ); REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 256 ); REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 256 ); REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray16>() == true ); REQUIRE( data.is<mapnik::image_gray16>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data ); TIFF_ASSERT_NO_ALPHA_GRAY( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray32f striped") { SECTION("gray16 tiled") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_striped.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 8 ); REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 32 ); REQUIRE( tiff_reader.bits_per_sample() == 16 );
REQUIRE( tiff_reader.is_tiled() == false ); REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 0 ); REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 0 ); REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray32f>() == true ); REQUIRE( data.is<mapnik::image_gray16>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data ); TIFF_ASSERT_NO_ALPHA_GRAY( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray32f tiled") { SECTION("gray32f striped") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_tiled.tif") TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 ); REQUIRE( tiff_reader.rows_per_strip() == 8 );
REQUIRE( tiff_reader.bits_per_sample() == 32 ); REQUIRE( tiff_reader.bits_per_sample() == 32 );
REQUIRE( tiff_reader.is_tiled() == true ); REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 256 ); REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 256 ); REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height()); mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray32f>() == true ); REQUIRE( data.is<mapnik::image_gray32f>() == true );
TIFF_ASSERT_SIZE( data,reader ); TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data ); TIFF_ASSERT_NO_ALPHA_GRAY( data );
TIFF_READ_ONE_PIXEL TIFF_READ_ONE_PIXEL
} }
SECTION("gray32f tiled") {
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 32 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray32f>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
TIFF_READ_ONE_PIXEL
}
} }

View file

@ -137,6 +137,11 @@ std::pair<bool,typename T::value_type::first_type> process_geojson_file(T & boxe
} }
} }
} }
else if (validate_features)
{
if (verbose) std::clog << "Invalid bbox encountered " << item.first << std::endl;
return std::make_pair(false, extent);
}
} }
return std::make_pair(true, extent); return std::make_pair(true, extent);
} }

View file

@ -39,6 +39,20 @@ source = Split(
program_env['CXXFLAGS'] = copy(env['LIBMAPNIK_CXXFLAGS']) program_env['CXXFLAGS'] = copy(env['LIBMAPNIK_CXXFLAGS'])
program_env['LINKFLAGS'] = copy(env['LIBMAPNIK_LINKFLAGS']) program_env['LINKFLAGS'] = copy(env['LIBMAPNIK_LINKFLAGS'])
program_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES']) program_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
program_env['LIBS'] = []
if env['RUNTIME_LINK'] == 'static':
# pkg-config is more reliable than pg_config across platforms
cmd = 'pkg-config libpq --libs --static'
try:
program_env.ParseConfig(cmd)
except OSError, e:
program_env.Append(LIBS='pq')
else:
program_env.Append(LIBS='pq')
# Link Library to Dependencies
libraries = copy(program_env['LIBS'])
if env['HAS_CAIRO']: if env['HAS_CAIRO']:
program_env.PrependUnique(CPPPATH=env['CAIRO_CPPPATHS']) program_env.PrependUnique(CPPPATH=env['CAIRO_CPPPATHS'])
@ -46,9 +60,8 @@ if env['HAS_CAIRO']:
program_env.PrependUnique(CPPPATH=['#plugins/input/postgis']) program_env.PrependUnique(CPPPATH=['#plugins/input/postgis'])
libraries = []
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND'] boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
libraries.extend([boost_program_options,'sqlite3','pq',env['MAPNIK_NAME'],'icuuc']) libraries.extend([boost_program_options,'sqlite3',env['MAPNIK_NAME'],'icuuc'])
if env.get('BOOST_LIB_VERSION_FROM_HEADER'): if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
@ -59,13 +72,8 @@ if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
if env['SQLITE_LINKFLAGS']: if env['SQLITE_LINKFLAGS']:
program_env.Append(LINKFLAGS=env['SQLITE_LINKFLAGS']) program_env.Append(LINKFLAGS=env['SQLITE_LINKFLAGS'])
if env['RUNTIME_LINK'] == 'static': if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
if env['PLATFORM'] == 'Darwin': libraries.append('dl')
libraries.extend(['ldap', 'pam', 'ssl', 'crypto', 'krb5'])
else:
# TODO - parse back into libraries variable
program_env.ParseConfig('pg_config --libs')
libraries.append('dl')
pgsql2sqlite = program_env.Program('pgsql2sqlite', source, LIBS=libraries) pgsql2sqlite = program_env.Program('pgsql2sqlite', source, LIBS=libraries)
Depends(pgsql2sqlite, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME'])) Depends(pgsql2sqlite, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))