Compare commits

..

197 commits

Author SHA1 Message Date
lightmare
81eff1025d Merge pull request #3478 from estadtherr/bypass_unconfigured_plugins_2.3.x
Bypass unavailable plugins in Python tests (2.3.x)
2016-08-05 17:44:36 +02:00
Eric Stadtherr
264407b259 refined the unit test data source logic 2016-08-03 09:11:27 -06:00
Eric Stadtherr
ed39efcfcb reworked python tests to skip maps that rely on unavailable input plugins 2016-08-02 11:53:24 -06:00
Dane Springmeyer
1b0f4d663c backport nik2img command from master 2015-07-02 15:56:07 -07:00
Dane Springmeyer
718a8b3b5a update expected cairo outputs 2015-02-02 22:44:33 -08:00
Dane Springmeyer
0df0872f79 update expected images 2015-02-02 21:51:47 -08:00
Dane Springmeyer
186d62006b scons: collect pycairo flags at configure time 2015-02-02 21:41:32 -08:00
Dane Springmeyer
fb35d1815f travis: build against pycairo 2015-02-02 21:41:11 -08:00
Dane Springmeyer
92d6e79a75 fix invalid use of gamma in tests/python_tests/image_encoding_speed_test.py 2015-02-02 14:28:40 -08:00
Dane Springmeyer
e2990ac3b1 Merge pull request #2672 from sarametz/2.3.x-png8-encoding-bug
2.3.x png8 encoding bug
2015-02-02 14:25:28 -08:00
Dane Springmeyer
10daf73f56 drop # of JOBS 2015-02-02 13:38:09 -08:00
Dane Springmeyer
abd1c441de add missing test shim 2015-02-02 13:26:07 -08:00
Dane Springmeyer
8408b56623 pull in Makefile/bootstrap fixes from master 2015-02-02 12:27:14 -08:00
Sara Metz
22ab62f16d Fixes bugs that cause tests in PR #2599 to fail 2015-02-02 10:51:12 +13:00
Robert Coup
25fe253f12 Test for 2px png8 encoding bug (hextree & octree) 2015-02-02 10:50:30 +13:00
Dane Springmeyer
0025225e44 isolate crashing python plugin test 2015-01-28 15:12:53 -08:00
Dane Springmeyer
40cb3595a5 debug segfaulting python tests 2015-01-28 14:54:32 -08:00
Dane Springmeyer
def040a42d try again to fix pgsql2sqlite linking on linux 2015-01-28 13:40:58 -08:00
Dane Springmeyer
f0936f2672 always link pthread on linux 2015-01-28 13:33:15 -08:00
Dane Springmeyer
d8358ffdd5 fix linking of pgsql2sqlite on linux 2015-01-28 13:31:41 -08:00
Dane Springmeyer
c28aa7272b fix benchmark linking on linux 2015-01-28 13:16:55 -08:00
Dane Springmeyer
0a6beede62 scons: fix sqlite_rtree check + support configuring freetype and xml2 without config scripts 2015-01-28 11:35:57 -08:00
Dane Springmeyer
1c3a958205 scons: remove obsolete -finline-functions flag (clang does not support) 2015-01-28 11:10:45 -08:00
Dane Springmeyer
b4f018a676 update a few more expected images 2015-01-28 09:26:31 -08:00
Dane Springmeyer
73487cdaae bootstrap: cleanup options 2015-01-28 01:20:22 -08:00
Dane Springmeyer
9efb67bf9e no need for harfbuzz 2015-01-28 01:18:21 -08:00
Dane Springmeyer
e8628b2e21 switch to mason for deps - refs #2662 2015-01-28 01:17:50 -08:00
Dane Springmeyer
9cbf97f124 update a few visual test images 2015-01-28 00:58:43 -08:00
Robert Coup
f75d3e7b2f Update reference images for failing cairo tests after opacity fix 2015-01-28 14:01:13 +13:00
Dane Springmeyer
e957a75d8d respect alpha in cairo comparisons (reasons for ignoring it once no longer apply - refs #2662) 2015-01-28 13:23:28 +13:00
Robert Coup
a27b886e19 Handle bounds reprojections which cross the anti-meridian.
When doing an envelope-points reprojection to a geographic CS, check
the points stay in clockwise order. Otherwise expand the resulting bounds
to include the world.

Backport of #2657 from master to 2.3.x. Fixes #2648.
2015-01-28 13:20:33 +13:00
Dane Springmeyer
7c4325fd76 fix rasterlite linking in the case of static libs 2015-01-09 18:11:21 -08:00
Dane Springmeyer
2ce8900cf1 quick fix for #2451 2014-12-17 11:36:02 -08:00
Dane Springmeyer
a35acd2a41 support building without dlopen support 2014-12-16 16:03:51 -05:00
Dane Springmeyer
82df66e9c3 Merge pull request #2589 from CartoDB/fix-pgraster-datasource-null-scale
Ignore overviews with 0 scale in pgraster
2014-12-04 11:06:51 -05:00
Rafa de la Torre
c4684e09cd Ignore overviews with 0 scale in pgraster
refs #2551

Postgis raster_columns view is returning NULL values for raster
overviews with large scale factors. That issue in postgis is described
in http://trac.osgeo.org/postgis/ticket/3006

This causes two main problems:

  - The first overview with scale = NULL is wrongly chosen for rendering
    always

  - The messed up scaling factor causes the render symbolizer to spent
    an insane amount of CPU and memory to render a messed up tiles.

The patch in postgis is expected to be released with the new version, a
few months from now.
2014-12-04 15:26:30 +00:00
Robert Coup
ea61c5728d Merge pull request #2555 from stephend/2.3.x
Throw datasource_exception on GDAL RasterIO() failures
2014-11-05 18:21:26 +13:00
Stephen Davis
5a770d6a96 throw datasource_exception on GDAL RasterIO failures 2014-10-31 17:06:09 +13:00
Artem Pavlenko
ad768389ab Merge pull request #2529 from mapycz/2.3.x
2.3.x: sqlite plugin - disable shared cache for sqlite prior to 3.7.15
2014-10-13 14:57:23 +01:00
Jiri Drbalek
f5398e16de sqlite plugin - disable shared cache for sqlite prior to 3.7.15 2014-10-13 13:48:28 +00:00
Dane Springmeyer
779c5c2376 Merge pull request #2473 from strk/2.3.x-faster-pgraster-test
Use a smaller input file for testing dataraster 16bsi
2014-10-01 10:47:01 -07:00
Sandro Santilli
6c936f1ede Further speedup dataraster test by importing only tiled 2014-10-01 10:54:25 +02:00
Sandro Santilli
420e9bbbf6 Use a smaller input file for testing dataraster 16bsi
Also test a minor number of overviews.
The aim is to make the test faster (#2470)
2014-10-01 10:50:54 +02:00
Dane Springmeyer
bad6aa9d43 disable failing test in 2.3.x branch - refs #2438 2014-09-30 17:59:57 -07:00
Dane Springmeyer
40a0326130 match fix from #2466 in 2.3.x branch (although no obvious benefit) 2014-09-30 15:54:25 -07:00
Dane Springmeyer
6e8f02c343 drop auto-parallelization of build to stay consistent with master 2014-09-26 13:08:21 -07:00
Dane Springmeyer
bb569bae3b sync text rendering style between master and 2.3.x branch - refs #2326 2014-09-26 12:55:07 -07:00
Dane Springmeyer
a54f621d98 fix make clean - refs #2112 2014-09-24 16:01:32 -07:00
Dane Springmeyer
e2ea6e487d fix return of painted in grid_renderer 2014-09-19 14:34:17 -07:00
Dane Springmeyer
b8d497844a enable painted for svg_renderer 2014-09-19 14:15:59 -07:00
Dane Springmeyer
c2385437f1 apply fix from #2418 to 2.3.x branch 2014-09-19 14:15:21 -07:00
Dane Springmeyer
faa87d42e5 unmask now fixed raster warping test - amends db39528231 - refs #1913 2014-09-11 10:26:12 -07:00
artemp
b0cfbdf2b7 disable AA when warping images #1913
Conflicts:
	src/warp.cpp
2014-09-11 10:26:12 -07:00
Sean Gillies
648dea63ac Fix install doc formatting. 2014-09-04 10:21:12 -06:00
Dane Springmeyer
afe770a708 Merge pull request #2406 from mapnik/user-specified-python
Allow user to specify a python executable.
2014-09-03 15:53:52 -07:00
Sean Gillies
c1e47cc5df Allow user to specify a python executable.¬
¬
Fall back on `python`. Unlike the solution in PR #2395 this¬
puts all the responsibility for selecting the right python in the¬
case that "python" is Python 3 on the user. I've followed the lead¬
of the Python documentation Makefile. See

http://hg.python.org/cpython/file/340d48347295/Doc/README.txt
http://hg.python.org/cpython/file/340d48347295/Doc/Makefile

Intent is that if your `python` is Python 2 everything works as
before and that is your `python` is Python 3 but you have a
`python2` you can specify that instead.¬
2014-09-03 16:00:12 -06:00
Dane Springmeyer
9c548771ce remove useless svg renderer tests 2014-09-02 22:41:24 -07:00
Dane Springmeyer
5ae55a07e2 Merge pull request #2393 from strk/2.3.x-pgis-simplify-20th
Bring postgis simplification factor back to 1/20 of a pixel
2014-08-26 21:25:14 -07:00
Sandro Santilli
22a8946f62 Bring postgis simplification factor back to 1/20 of a pixel
This was the value in 2.2.x and was accidentally changed as part
of a completely unrelated commit, see:
http://github.com/mapnik/mapnik/issues/1639#issuecomment-53388951
2014-08-26 13:00:32 +02:00
Dane Springmeyer
5e96d5d54b fix gdal compile with msvs 2013 - closes #2257 2014-08-25 17:51:11 -07:00
Dane Springmeyer
c0e8fba619 add support for windows unicode paths in rapidxml loader 2014-08-25 14:50:58 -07:00
Dane Springmeyer
b221d571c5 avoid warning from boost geometry 2014-08-24 15:58:44 -07:00
Dane Springmeyer
5103e84ade fix compile with boost 1.56 - refs #2368 2014-08-24 15:58:28 -07:00
Dane Springmeyer
c7cca17494 fix avoid-edges support for shields - closes #983 2014-08-21 23:51:03 -07:00
Dane Springmeyer
3d5655f7e5 update expected visual images after fix for #2381 2014-08-21 23:46:41 -07:00
Dane Springmeyer
bfedde3cc6 visual tests: don't exit without reporting 2014-08-21 23:36:51 -07:00
Dane Springmeyer
5651a8b9db fix collsion box for shields when scale_factor is used #2381 2014-08-21 23:36:27 -07:00
Dane Springmeyer
3db8d34117 testcase for #983 against 2.3.x 2014-08-21 23:11:14 -07:00
Dane Springmeyer
7e725e59e1 Merge pull request #2380 from mapnik/travis-gdal
Travis gdal
2014-08-21 16:34:00 -07:00
Dane Springmeyer
a2ee09646e travis: re-enable devel for proj + image libs 2014-08-21 16:16:46 -07:00
Dane Springmeyer
ef6cabfa8a backport geojson plugin fixes from master - refs #2319 and 2367 2014-08-21 15:56:46 -07:00
Dane Springmeyer
df205e9b34 travis: another attempt at getting both gdal+postgis going - refs #2353 2014-08-21 15:28:18 -07:00
Dane Springmeyer
36bd809361 Merge pull request #2372 from strk/2.3.x-pgraster-credit
Add mention of CartoDB support in pgraster input plugin code
2014-08-20 08:42:26 -07:00
Sandro Santilli
743404d88c Add mention of CartoDB support in pgraster input plugin code 2014-08-20 17:22:44 +02:00
Dane Springmeyer
14b6ba951e tests: fix postgis/pgraster tests if lack of connection 2014-08-19 13:52:03 -07:00
Dane Springmeyer
f939a8f8e7 adapt to new rtree interface in boost geometry >= 1.56 - refs #2367 2014-08-19 13:51:32 -07:00
Dane Springmeyer
d62365cd64 adapt to ptree change in boost 1.56 - closes #2365 2014-08-19 09:07:30 -07:00
Dane Springmeyer
f3495c3e67 fix css_grammar compile error with boost 1.56 - close #2366 2014-08-19 09:06:40 -07:00
Dane Springmeyer
542deba997 fix compile with older OGR 2014-08-18 21:33:18 -07:00
Dane Springmeyer
0be6c2d7e1 don't throw for OGR layers with no features - refs #2260 #2352 #2354 2014-08-15 19:48:27 -07:00
Dane Springmeyer
422f3bd8b0 add RESPECT mode to make 'fixing' of bbox aspect a no-op on map 2014-08-14 20:25:53 -07:00
Dane Springmeyer
a616e9d7e7 postgis: disable NOTICES by default - refs #2296 2014-08-12 20:27:01 -07:00
Dane Springmeyer
a968f972e0 quiet pgraster tests by default 2014-08-12 20:27:01 -07:00
Dane Springmeyer
b302929fb4 make sure pgraster is rebuilt if headers change inside the postgis plugin dir 2014-08-12 20:27:01 -07:00
Dane Springmeyer
e458959ea3 remove unused function 2014-08-12 20:27:01 -07:00
Dane Springmeyer
f566df3fca Merge pull request #2352 from kernelsanders/2.3.x
ogr plugin extent error handling
2014-08-12 17:32:08 -07:00
Dane Springmeyer
cb3281e3a4 travis: disable gdal 2014-08-12 16:41:14 -07:00
Dane Springmeyer
9f2ceb71f1 travis: try upgrading postgis from ubuntugis repo 2014-08-12 16:36:22 -07:00
Dane Springmeyer
df8aa14f9a travis: try by declaring libgdal1h=1.10.0-1~precise1 2014-08-12 16:06:44 -07:00
Dane Springmeyer
60974742e7 travis: try without ubuntugis-unstable 2014-08-12 16:02:41 -07:00
Dane Springmeyer
3032c836a8 travis: see if postgis works with default postgres 2014-08-12 15:56:41 -07:00
Dane Springmeyer
435ebbad91 travis: create and init template_postgis 2014-08-12 15:26:57 -07:00
Dane Springmeyer
ce5d5e4b4c Merge pull request #2329 from strk/2.3.x-pgraster2
Implement input plugin for PostGIS Rasters
2014-08-12 14:53:56 -07:00
Joel Brown
e8c3c0bad9 ogr plugin extent error handling 2014-08-12 15:10:25 -06:00
Dane Springmeyer
35f7314e92 rollback png8 default in 2.3.x - closes #2110 2014-08-12 13:50:32 -07:00
Dane Springmeyer
6c3301d8eb deprecate bilinear8 in 2.3.x - refs #2076 2014-08-12 13:26:35 -07:00
Dane Springmeyer
9d74adb871 Merge pull request #2350 from kernelsanders/2.3.x
Add optional extent parameter to OGR datasource plugin
2014-08-12 11:40:19 -07:00
Joel Brown
b28ca1ff08 Undo stupid windows file permissions change on rundemo.py 2014-08-12 12:03:58 -06:00
Joel Brown
8553514f23 formatting 2014-08-12 11:59:36 -06:00
Joel Brown
480a8f3d48 formatting 2014-08-12 11:58:46 -06:00
Joel Brown
106ecb2b9c formatting 2014-08-12 11:54:46 -06:00
Joel Brown
e9d1ea8032 OGR plugin extent test 2014-08-12 11:39:24 -06:00
Dane Springmeyer
5a481fcf2d fix support for ttc/dfont font formats
- both formats likely will contain multiple valid faces
  - ttc should work on across platforms - dfont is likely osx only
  - fixes #2274 and 2341

Thanks @strk for helping uncover the problem and providing a testcase
2014-08-11 19:13:20 -07:00
Dane Springmeyer
60b72524c1 font_registration test: only modify severity temporarily 2014-08-11 18:51:38 -07:00
Dane Springmeyer
9253ce10f8 multiface font tests 2014-08-11 17:30:48 -07:00
Dane Springmeyer
6bfd920c6c travis: only test with clang 2014-08-11 17:27:54 -07:00
Joel Brown
d75fb237b1 Add optional extent paramater to ogr plugin 2014-08-11 16:06:21 -06:00
Dane Springmeyer
fdf86c7411 Merge pull request #2343 from strk/2.3.x-false-negatives
Fix false negative responses from python tests
2014-08-10 19:53:40 -07:00
Sandro Santilli
7afc2754cb Fix false negative responses from python tests
Closes #2298
2014-08-08 13:01:02 +02:00
Dane Springmeyer
ca2c0d028d travis: attempt to fix gdal install 2014-08-07 19:24:03 -07:00
Dane Springmeyer
bf276591eb scons: no need to link to fontconfig in static cairo build 2014-08-07 19:17:16 -07:00
Dane Springmeyer
dd02192932 remove deprecation warnings in 2.3.x - refs #1340 2014-08-04 19:23:38 -07:00
Sandro Santilli
fa4d1e4ada Implement input plugin for PostGIS Rasters
Closes #1660.
Includes python bindings and testcases.
2014-08-01 10:25:41 +02:00
Dane Springmeyer
798dd3124b Merge branch '2.3.x' of github.com:mapnik/mapnik into 2.3.x 2014-07-30 09:59:46 -07:00
Dane Springmeyer
6eea010c6a scons: fix first-run clean problem #2112 2014-07-29 17:55:29 -07:00
Dane Springmeyer
916a30124b Merge pull request #2304 from strk/2.3.x-readonly
Ensure read-only transactions
2014-07-28 18:00:53 -07:00
Dane Springmeyer
417f1c7c3f fix -Wsign-compare warnings in several grammars 2014-07-28 11:56:33 -07:00
Dane Springmeyer
861f2677e0 Revert "return code 0 to gracefully exit if python bindings are not available"
This reverts commit 540f70a1f4.
2014-07-25 11:49:59 -07:00
Dane Springmeyer
dc61b2ac12 scons: fix 'make clean' so it actually runs completely 2014-07-24 19:06:26 -07:00
Dane Springmeyer
540f70a1f4 return code 0 to gracefully exit if python bindings are not available 2014-07-24 18:59:53 -07:00
Dane Springmeyer
7957c05df0 update expected tests after 136e97edd4 - closes #2311 2014-07-24 18:24:41 -07:00
Dane Springmeyer
48f920ab95 workaround old GDAL bug regarding rgba images and alpha reporting - closes #2310 2014-07-22 15:01:36 -07:00
artemp
5fe68f6d1b Merge branch 'mojodna-color-comp-op' into 2.3.x 2014-07-22 10:57:33 +01:00
Seth Fitzsimmons
136e97edd4 Work in HSL so luma can be preserved 2014-07-21 18:08:43 -07:00
Sandro Santilli
f131040dff Ensure read-only transactions
Closes #2142
2014-07-16 10:59:11 +02:00
Dane Springmeyer
c07aeac4c2 repair visual tests to be able to round trip (undo bits that require 3.x support) 2014-06-27 12:44:47 -07:00
Artem Pavlenko
f06c089067 Merge pull request #2285 from mapnik/faster-font-io2
Faster font i/o backported to 2.3.x - refs #2282
2014-06-25 08:48:18 +01:00
Dane Springmeyer
bdd800b6fc Faster font i/o backported to 2.3.x - refs #2282 2014-06-24 19:46:46 -07:00
Dane Springmeyer
a1cab08d77 fix #2283 2014-06-24 17:50:35 -07:00
Dane Springmeyer
7c7da1a2fd backport image-filters/alpha fix to 2.3.x branch - refs #1313 2014-06-19 10:27:34 -07:00
Dane Springmeyer
4b90c96600 windows build fixes in palette and miniz_png headers 2014-06-18 17:53:33 -07:00
Dane Springmeyer
cda6238325 windows fix: declar miniz PNGWriter 2014-06-18 17:14:07 -07:00
Dane Springmeyer
42698d76b8 register_font: return false instead of throwing 2014-06-18 16:19:35 -07:00
Dane Springmeyer
474b3c0d6d fix typo 2014-06-18 16:13:52 -07:00
Dane Springmeyer
b70997fe73 fix boost directory iterator to use wide paths - closes #2273 2014-06-18 16:11:36 -07:00
Dane Springmeyer
4007104bf1 use FT_Open_Face instead of FT_New_Face - refs #1897 2014-06-18 15:42:32 -07:00
Dane Springmeyer
90396b4359 travis: run valgrind 2014-06-18 15:37:26 -07:00
Dane Springmeyer
a96fc9e9cc fix unicode handling in is_regular_file check - refs #2273 2014-06-18 12:55:59 -07:00
artemp
19bd20f8a6 + add eq/neq operators value_null <--> T 2014-06-17 22:45:38 -07:00
Dane Springmeyer
1f81ee09d4 add test for #2240 2014-06-17 22:20:24 -07:00
artemp
8b97c8a7d1 return default constructed ``value_type->value_null` instead of `std::numeric_limits<value_type>::infinity()`` 2014-06-17 22:20:02 -07:00
artemp
8c03ea3d68 mapnik::value - return 'infinity' if rhs == 0 to avoid division by zero 2014-06-17 22:19:52 -07:00
Dane Springmeyer
911993512a Merge pull request #2271 from strk/2.3.x-helloworld-makefile
2.3.x helloworld makefile tweaks
2014-06-13 08:34:59 -07:00
Sandro Santilli
018e33cda8 Makefile tweaks for helloworld template plugin
- Do not force use of clang++ to build the plugin (broken on recent debian
   and derivates: https://bugs.debian.org/643959)
 - Do not force clean on install
 - Use -fPIC to build objects (or g++ complains)
2014-06-13 12:57:35 +02:00
Dane Springmeyer
49c01f8449 webp reader: initialize WebPDecoderConfig 2014-06-12 20:54:50 -07:00
Dane Springmeyer
7960be55fe remove libcurl dependency 2014-06-12 18:29:26 -07:00
Sean Gillies
803f8591e3 Remove config example. 2014-06-12 16:37:10 -07:00
Sean Gillies
5856822455 Add an example config file for cpp03-libstdcpp-x86_64-macosx. 2014-06-12 09:08:07 -07:00
Dane Springmeyer
fa3971b99f fix miniz inlining 2014-06-12 06:52:13 -07:00
Dane Springmeyer
ce948e20e7 improve png comparison tests 2014-06-11 22:43:36 -07:00
Dane Springmeyer
a56389a093 fix miniz encoder - closes #1560 2014-06-11 22:43:05 -07:00
Dane Springmeyer
8c5049e0f8 image readers: ability to check if image has alpha before full read 2014-06-11 18:50:58 -07:00
Dane Springmeyer
96a93c4b14 allow external image data - refs #2002 2014-06-11 16:58:58 -07:00
Dane Springmeyer
8457f8a852 benchmark: also need -lrt on linux 2014-06-10 12:01:35 -07:00
Dane Springmeyer
8a0760aaaf fixup benchmark build flags 2014-06-10 11:58:58 -07:00
Dane Springmeyer
a7e6f3a24b scons: support MAPNIK_NAME option to customize libmapnik name for custom packaging 2014-06-09 13:32:48 -07:00
Dane Springmeyer
49feda9b13 update travis script 2014-06-04 09:32:09 -07:00
Dane Springmeyer
4903689cf7 improvements to GDAL 2.x handling - refs #2259 amends cbdd112223 2014-06-02 20:25:32 -07:00
Dane Springmeyer
cbdd112223 support for GDAL >= 2.0 in ogr plugin - refs #2259 2014-06-02 19:33:49 -07:00
Dane Springmeyer
d0a509ccf4 speed up xml map loading 2014-05-28 14:32:39 -07:00
Dane Springmeyer
5f3e11c33a fixup xml_node::get_text() to avoid returning temporary 2014-05-28 14:14:14 -07:00
Dane Springmeyer
9be034e753 more tests for handling of empty Parameters 2014-05-28 14:13:38 -07:00
Dane Springmeyer
93e1b74c82 use math functions from std:: 2014-05-28 07:52:55 -07:00
Dane Springmeyer
c87cf109a6 return const& string from xml_node::get_text()
Conflicts:
	src/load_map.cpp
2014-05-27 18:23:21 -07:00
Dane Springmeyer
dc7fc35446 don't report the line number unless its > 0 (its not meaningful) 2014-05-23 14:29:24 -07:00
Dane Springmeyer
68f4906088 Revert "rapidxml: don't report the line number (its not meaningful)"
This reverts commit f56121377e.
2014-05-23 14:26:37 -07:00
Dane Springmeyer
f56121377e rapidxml: don't report the line number (its not meaningful) 2014-05-23 14:18:05 -07:00
Dane Springmeyer
30c6bc53fb travis: add matrix switch on XML parser 2014-05-23 10:33:45 -07:00
Dane Springmeyer
ab85fb4705 fix skipping of empty text nodes in rapidxml parser (matches libxml2) - closes #2253 2014-05-23 10:27:37 -07:00
Dane Springmeyer
6612567fd3 fix typo 2014-05-22 21:49:24 -07:00
Dane Springmeyer
e915521015 yet another try to please msvs 2010 2014-05-22 21:33:07 -07:00
Dane Springmeyer
d5ecf81ce2 no default args for template declaration 2014-05-22 21:30:25 -07:00
Dane Springmeyer
5a1995e051 fix msvs 2010 linking - refs #260 2014-05-22 21:27:28 -07:00
Dane Springmeyer
468ead3370 fix ambiguous std::fabs and the compile on windows 2014-05-22 19:57:34 -07:00
Dane Springmeyer
bb67ae0fb7 expose various image symbols for windows - refs mapnik/node-mapnik#260 2014-05-22 19:18:43 -07:00
Dane Springmeyer
ed3afe5b86 try to get gdal/ogr plugins building 2014-05-22 17:12:57 -07:00
Dane Springmeyer
bb27a4282b travis: try removing postgres-server-dev 2014-05-22 17:04:01 -07:00
Dane Springmeyer
050b51bf7d add localize script 2014-05-22 17:00:43 -07:00
Dane Springmeyer
2b49af9627 pass string by const& 2014-05-22 16:55:48 -07:00
Dane Springmeyer
5b7a9b9b2d rapidxml: validate closing tags like libxml2 parser (no overhead measurable seen) 2014-05-22 16:54:28 -07:00
Dane Springmeyer
5bfd260859 benchmark: use halo-rasterizer='fast' (doubles perf) 2014-05-16 19:30:26 -07:00
Dane Springmeyer
104e40c376 backport benchmark framework from master 2014-05-16 19:09:41 -07:00
Dane Springmeyer
63bff33f35 minor benchmark build tweaks to be consistent with master 2014-05-16 19:00:37 -07:00
Dane Springmeyer
0ca9c5c0aa fix variable shadowing 2014-05-16 18:59:54 -07:00
Dane Springmeyer
b128de321b remove unused variables 2014-05-16 18:59:26 -07:00
Dane Springmeyer
87e69a20c3 tests for #2245 2014-05-16 12:21:36 -07:00
artemp
461c3dab18 relax FeatureCollection grammar to allow arbitary key:value's 2014-05-16 10:07:48 -07:00
Dane Springmeyer
e31411bd21 travis: apt-get verbose to see problems 2014-05-16 01:12:35 -07:00
Dane Springmeyer
3684db211c optimize raster rendering when not resizing 2014-05-15 23:23:31 -07:00
Dane Springmeyer
a7ab1eeb66 don't allow marker-spacing less than 1 - fixes #2218 2014-05-12 21:24:51 -07:00
Dane Springmeyer
94e78f2ae4 stop testing bogus wkb since it will crash wkb reader - refs #2236 2014-05-05 17:05:23 -07:00
Dane Springmeyer
91f57bda73 alt boost install method 2014-05-02 22:17:52 -07:00
Dane Springmeyer
f71d1c0abc use ppa:boost-latest 2014-05-02 22:11:01 -07:00
Dane Springmeyer
a4985b3b79 add support for halo-rasterizer for shields - closes #2226 2014-04-25 16:01:35 -07:00
artemp
4ad7b13799 re-use evaluator object
Conflicts:
	include/mapnik/expression_evaluator.hpp
2014-04-24 22:56:50 -07:00
Dane Springmeyer
3bcf54a693 update tests 2014-04-24 21:30:54 -07:00
Dane Springmeyer
3339255b18 remove force_odd_labels - refs #2120 2014-04-24 20:22:01 -07:00
5006 changed files with 179085 additions and 607101 deletions

View file

@ -1,94 +0,0 @@
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: Consecutive
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Inline
# AlwaysBreakAfterReturnType:
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BitFieldColonSpacing: After
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Always
AfterEnum: false # see AllowShortEnumsOnASingleLine
AfterFunction: true # see AllowShortFunctionsOnASingleLine
AfterNamespace: false
AfterStruct: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: AfterComma
BreakStringLiterals: true
ColumnLimit: 120
CompactNamespaces: false
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DeriveLineEnding: true
EmptyLineAfterAccessModifier: Leave
EmptyLineBeforeAccessModifier: LogicalBlock
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: NoIndent
IndentPPDirectives: None
IndentRequires: true
IndentWidth: 4
IndentWrappedFunctionNames: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
# PackConstructorInitializers: CurrentLine # only clang-format > 14
PointerAlignment: Left
#QualifierAlignment: Left # only clang-format > 14
ReferenceAlignment: Left
ReflowComments: true
SortIncludes: Never
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeInheritanceColon: true
Standard: c++14
BinPackParameters: false
BreakBeforeInheritanceComma: false
IncludeCategories:
# Headers in <> without extension.
- Regex: '<([A-Za-z0-9\Q/-_\E])+>'
Priority: 1
# Headers in <> from specific external libraries.
- Regex: '<(boost)\/'
Priority: 2
# Headers in <> from specific external libraries.
- Regex: '<(mapnik)\/'
Priority: 3
# Headers in <> with extension.
- Regex: '<([A-Za-z0-9.\Q/-_\E])+>'
Priority: 4
# Headers in "" with extension.
- Regex: '"([A-Za-z0-9.\Q/-_\E])+"'
Priority: 5

2
.gitattributes vendored
View file

@ -1,2 +0,0 @@
*.svg text eol=lf
scons/** linguist-vendored

View file

@ -1,85 +0,0 @@
name: Run tests with coverage
description: Runs all mapnik tests with coverage
inputs:
cmake-preset:
description: The used CMake preset
required: true
runs:
using: composite
steps:
- name: Set PROJ_LIB
shell: bash
run: |
cmake --preset ${{ inputs.cmake-preset }} -N -L | grep -o "PROJ_LIB=.*" >> ${GITHUB_ENV}
- name: Set TEST_WRAPPER (Windows)
if: runner.os == 'Windows'
shell: bash
run: |-
echo "TEST_WRAPPER=OpenCppCoverage \
--cover_children \
--export_type binary \
--modules '*.input' \
--modules '*libmapnik*' \
--modules 'mapnik*.exe' \
--quiet \
--sources '${{ github.workspace }}' \
--" >> ${GITHUB_ENV}
- name: Test
shell: bash
env:
UPDATE: 1
run: |
${TEST_WRAPPER:-} ctest --preset ${{ inputs.cmake-preset }}
- name: Test visuals
continue-on-error: true
working-directory: build/out
shell: bash
run: |
${TEST_WRAPPER:-} ./mapnik-test-visual -j ${CTEST_PARALLEL_LEVEL} --output-dir visual-test-result
- name: Pack visual test results
working-directory: build/out
shell: bash
run: |
tar -vzcf visual-test-results.tar.gz visual-test-result
- name: Upload visual test results
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.cmake-preset }}-visual-tests-${{ github.sha }}
path: build/out/visual-test-results.tar.gz
- name: Run Benchmarks (Linux & macOS)
working-directory: build/out
if: runner.os != 'Windows'
shell: bash
run: |
./run_benchmarks
- name: Collect coverage (Linux & macOS)
working-directory: build
if: runner.os != 'Windows'
shell: bash
run: |
if [ "${RUNNER_OS}" == "macOS" ]; then
LCOV_EXTRA_OPTIONS="--ignore-errors count,gcov,inconsistent,range,unused --keep-going"
fi
lcov ${LCOV_EXTRA_OPTIONS:-} --directory . --capture --output-file coverage.info
lcov ${LCOV_EXTRA_OPTIONS:-} --remove coverage.info '/usr/*' '*/vcpkg_installed/*' '/.cache/*' '*/test/*' --output-file coverage.info
lcov ${LCOV_EXTRA_OPTIONS:-} --list coverage.info
- name: Upload coverage to Codecov (Linux & macOS)
if: runner.os != 'Windows'
uses: codecov/codecov-action@v4
with:
files: build/coverage.info
- name: Upload coverage to Codecov (Windows)
if: runner.os == 'Windows'
uses: codecov/codecov-action@v4
with:
files: ctest.cov,build/out/mapnik-test-visual.cov

View file

@ -1,136 +0,0 @@
name: Build and Test
on:
push:
branches:
- "*"
pull_request:
branches-ignore:
- "no-ci-*"
env:
VCPKG_BINARY_SOURCES: clear;x-gha,readwrite
VCPKG_RELEASE: 2024.06.15
jobs:
checkSource:
name: Check Source Code
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
- uses: pre-commit/action@v3.0.1
buildAndTest:
name: >-
Build & Test
(${{ matrix.os }})
(C++ ${{ matrix.cxx-standard }})
${{ startsWith(matrix.os, 'macos-') && (matrix.os == 'macos-14' && '(ARM64)' || '(AMD64)') || '' }}
needs: checkSource
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- macos-14
- ubuntu-22.04
- windows-2022
cxx-standard:
- 17
steps:
- name: Checkout Mapnik
uses: actions/checkout@v4
with:
submodules: recursive
- name: Checkout vcpkg
uses: actions/checkout@v4
with:
path: vcpkg
ref: ${{ env.VCPKG_RELEASE }}
repository: microsoft/vcpkg
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Install required system packages
shell: bash
run: |
if [ "${RUNNER_OS}" == "Linux" ]; then
sudo apt-get update
sudo apt-get -y install \
autoconf \
autoconf-archive \
automake \
gperf \
lcov \
libxxf86vm-dev \
ninja-build \
postgresql-client
elif [ "${RUNNER_OS}" == "macOS" ]; then
brew install \
autoconf \
autoconf-archive \
automake \
lcov \
libtool \
ninja \
vcpkg
elif [ "${RUNNER_OS}" == "Windows" ]; then
choco install \
ninja \
OpenCppCoverage
echo "C:\Program Files\OpenCppCoverage" >> ${GITHUB_PATH}
fi
- name: Enable Developer Command Prompt (Windows)
uses: ilammy/msvc-dev-cmd@v1
if: runner.os == 'Windows'
- name: Set CMAKE_BUILD_PARALLEL_LEVEL, CTEST_PARALLEL_LEVEL & PRESET
shell: bash
run: |
PRESET=$(echo "${RUNNER_OS}" | perl -ne "print lc")-ci
if [ "${RUNNER_OS}" == "Linux" ]; then
echo "CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)" >> ${GITHUB_ENV}
echo "CTEST_PARALLEL_LEVEL=$(nproc)" >> ${GITHUB_ENV}
elif [ "${RUNNER_OS}" == "macOS" ]; then
echo "CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu)" >> ${GITHUB_ENV}
echo "CTEST_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu)" >> ${GITHUB_ENV}
PRESET=${PRESET}-${{ matrix.os == 'macos-14' && 'arm64' || 'x64' }}
elif [ "${RUNNER_OS}" == "Windows" ]; then
echo "CMAKE_BUILD_PARALLEL_LEVEL=$(pwsh -Command '(Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfLogicalProcessors')" >> ${GITHUB_ENV}
echo "CTEST_PARALLEL_LEVEL=$(pwsh -Command '(Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfLogicalProcessors')" >> ${GITHUB_ENV}
fi
echo "PRESET=${PRESET}" >> ${GITHUB_ENV}
- name: Configure CMake
shell: bash
run: |
cmake \
-DBUILD_SHARED_LIBS:BOOL=ON \
-DCMAKE_CXX_STANDARD:STRING=${{ matrix.cxx-standard }} \
-DUSE_MEMORY_MAPPED_FILE:BOOL=ON \
-LA \
--preset ${PRESET}
- name: Build
shell: bash
run: |
cmake \
--build \
--preset ${PRESET}
- name: Run Tests
uses: ./.github/actions/run_tests
with:
cmake-preset: ${{ env.PRESET }}

View file

@ -1,55 +0,0 @@
name: Release Linux
on:
push:
branches:
- "*"
pull_request:
branches-ignore:
- "no-ci-*"
env:
PRESET: linux-ci-release
jobs:
build:
runs-on: "ubuntu-22.04"
steps:
- name: checkout mapnik
uses: actions/checkout@v4
with:
submodules: "recursive"
- name: "Install required system packages"
shell: bash
run: |
sudo apt update
sudo apt install -y ninja-build\
libicu-dev \
libfreetype6-dev \
libharfbuzz-dev \
libxml2-dev \
libjpeg-dev \
libtiff-dev \
libwebp-dev \
libcairo2-dev \
libproj-dev \
libgdal-dev \
libboost-filesystem-dev \
libboost-program-options-dev \
libboost-regex-dev
- name: Configure CMake
run: cmake -LA --preset ${{ env.PRESET }}
- name: Build
run: cmake --build --preset ${{ env.PRESET }}
- name: Package
run: cmake --build --preset ${{ env.PRESET }} --target package
- name: Upload mapnik debian package
uses: actions/upload-artifact@v4
with:
name: ${{ env.PRESET }}-deb
path: build/mapnik-*.deb

31
.gitignore vendored
View file

@ -1,19 +1,11 @@
.DS_Store
.vscode
.cache
*.gcov
*.gcda
*.gcno
*~
*.o
*.pyc
*.os
*.so
*.so.*
*.a
*.swp
*.dylib
mapnik-gyp
plugins/input/*.input
plugins/input/templates/*.input
demo/c++/rundemo
@ -21,9 +13,6 @@ bindings/python/mapnik/paths.py
config.cache
config.log
config.py
mapnik-settings.env
mason_packages/
.mason/
.sconf_temp/
.sconsign.dblite
demo/viewer/viewer.ini
@ -31,14 +20,21 @@ tests/cpp_tests/font_registration_test
tests/python_tests/raster_colorizer_test.png
tests/python_tests/raster_colorizer_test_save.xml
utils/mapnik-config/mapnik-config
utils/mapnik-config/mapnik2.pc
utils/shapeindex/shapeindex
utils/mapnik-index/mapnik-index
utils/ogrindex/ogrindex
utils/pgsql2sqlite/pgsql2sqlite
utils/svg2png/svg2png
utils/mapnik-render/mapnik-render
demo/python/demo*
demo/python/map.xml
tests/cpp_tests/svg_renderer_tests/background_color_test
tests/cpp_tests/svg_renderer_tests/combined_test
tests/cpp_tests/svg_renderer_tests/compilation_test
tests/cpp_tests/svg_renderer_tests/file_output_test
tests/cpp_tests/svg_renderer_tests/file_output_test_case.svg
tests/cpp_tests/svg_renderer_tests/path_element_test
tests/cpp_tests/svg_renderer_tests/path_element_test_case_1.svg
tests/cpp_tests/svg_renderer_tests/root_element_test
tests/data/sqlite/*index
demo/c++/cairo-demo.pdf
demo/c++/cairo-demo.png
@ -55,11 +51,4 @@ demo/viewer/release/
demo/viewer/ui_about.h
demo/viewer/ui_info.h
demo/viewer/ui_layer_info.h
test/standalone/*-bin
test/unit/run
test/visual/run
# cmake
build
.vs
CMakeUserPresets.json
tests/cpp_tests/*-bin

23
.gitmodules vendored
View file

@ -1,23 +0,0 @@
[submodule "test/data"]
path = test/data
url = https://github.com/mapnik/test-data.git
branch = master
[submodule "test/data-visual"]
path = test/data-visual
url = https://github.com/mapnik/test-data-visual.git
branch = master
[submodule "deps/mapbox/variant"]
path = deps/mapbox/variant
url = https://github.com/mapbox/variant.git
branch = master
[submodule "deps/mapbox/geometry"]
path = deps/mapbox/geometry
url = https://github.com/mapbox/geometry.hpp.git
branch = master
[submodule "deps/mapbox/protozero"]
path = deps/mapbox/protozero
url = https://github.com/mapbox/protozero.git
branch = master
[submodule "deps/mapbox/polylabel"]
path = deps/mapbox/polylabel
url = https://github.com/mapbox/polylabel.git

View file

@ -1,16 +0,0 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
files: ^.*\.cmake|CMakeLists\.txt$
- id: end-of-file-fixer
files: ^.*\.cmake|CMakeLists\.txt$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v18.1.3
hooks:
- id: clang-format
types_or: [c++, c]

34
.travis.yml Normal file
View file

@ -0,0 +1,34 @@
language: cpp
sudo: false
addons:
postgresql: "9.3"
matrix:
include:
- os: osx
compiler: clang
env: JOBS=4
- os: linux
compiler: clang
env: JOBS=4
- os: linux
compiler: gcc
env: JOBS=2
install:
- if [[ $(uname -s) == 'Linux' ]]; then psql -U postgres -c 'create database template_postgis;' -U postgres; psql -U postgres -c 'create extension postgis;' -d template_postgis -U postgres; fi;
- if [[ $(uname -s) == 'Darwin' ]]; then brew install bash; export PATH="$(brew --prefix)/bin":${PATH}; fi;
- echo `which bash`
script:
- source bootstrap.sh
# also install pycairo
- wget https://gist.githubusercontent.com/springmeyer/0833fa43794838889139/raw/build_pycairo.sh && chmod +x build_pycairo.sh && ./build_pycairo.sh
- export PYTHONPATH=$(pwd)/mason_packages/.link/lib/python2.7/site-packages:${PYTHONPATH}
- ./configure
- cat config.log
- make
- make test
- make bench

View file

@ -6,55 +6,39 @@ Mapnik is written by Artem Pavlenko with contributions from:
* AJ Ashton
* Matt Amos
* Lucio Asnaghi
* Alexandre Bonnasseau
* Justin Bronn
* Joel Brown
* Christopher Brown
* Jon Burgess
* Stephan Bösch-Plepelits
* Manel Clos
* Toby Collet
* Robert Coup
* Berteun Damman
* Petr Dlouhy
* Jiri Drbalek
* Craig de Stigter
* Jean-Francois Doyon
* David Eastcott
* Seth Fitzsimmons
* Sean Gillies
* Krzysztof Godlewski
* Beau Gunderson
* John Hague
* Dominic Hargreaves
* Axel Haustant
* Aubrey Holland
* Jordan Hollinger
* Tom Hughes
* Konstantin Käfer
* Mak Kolybabi
* Peter Körner
* Hermann Kraus
* Stella Laurenzo
* XinGang Li
* lightmare
* David Leaver
* Carlos López
* Dennis Luxen
* Tom MacWright
* Sara Metz
* Michal Migurski
* Andrii Mishkovskyi
* Ben Moores
* Mike Morris
* Dražen Odobašić
* Cameron Patrick
* Clint Pells
* Igor Podolskiy
* Reid Priedhorsky
* Brian Quinion
* Even Rouault
* Marcin Rudowski
* Sandro Santilli
* Christopher Schmidt
* Andreas Schneider
* Vincent Schut
@ -65,13 +49,9 @@ Mapnik is written by Artem Pavlenko with contributions from:
* Vince Spader
* Philipp Spitzer
* Dane Springmeyer
* Craig de Stigter
* Dave Stubbs
* River Tarnell
* Cezary Tarnowski
* Blake Thompson
* Oliver Tonnhofer
* Jochen Topf
* Alberto Valverde
* Martijn van Oosterhout
* Andreas Volz
@ -80,4 +60,3 @@ Mapnik is written by Artem Pavlenko with contributions from:
* Rich Wareham
* Nick Whitelegg
* Leslie Wu
* Roman Galacz

File diff suppressed because it is too large Load diff

View file

@ -1,34 +0,0 @@
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: mapnik
message: >-
If you use this software, please cite it using the
metadata from this file.
type: software
authors:
- given-names: Artem
family-names: Pavlenko
identifiers:
- type: url
value: 'https://github.com/mapnik/mapnik'
description: GitHub Repository
- type: swh
value: >-
swh:1:dir:3f5758e17e9d54016ca694268da68cf6856fab58
description: Software Archive
repository-code: 'https://github.com/mapnik/mapnik'
url: 'https://mapnik.org/'
abstract: >-
Mapnik is an open source toolkit for developing
mapping applications. At the core is a C++ shared
library providing algorithms and patterns for
spatial data access and visualization.
keywords:
- mapping
- gis
- cartography
- beautiful-maps
- rendering
license: LGPL-2.1

View file

@ -1,472 +0,0 @@
cmake_minimum_required(VERSION 3.15)
# 3.15 is required since the Boost::XXXX targets was first added. https://cmake.org/cmake/help/latest/module/FindBoost.html#imported-targets
# 3.14 is required since SQLite3 Module was first added. https://cmake.org/cmake/help/latest/module/FindSQLite3.html#findsqlite3
include(cmake/GetVersion.cmake)
get_mapnik_version()
project(mapnik
VERSION ${MAPNIK_MAJOR_VERSION}.${MAPNIK_MINOR_VERSION}.${MAPNIK_PATCH_VERSION}
HOMEPAGE_URL "https://mapnik.org/"
DESCRIPTION "Mapnik is an open source toolkit for developing mapping applications"
LANGUAGES CXX
)
message(STATUS "mapnik version: ${PROJECT_VERSION}")
# https://cliutils.gitlab.io/modern-cmake/chapters/features/ides.html
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL ON) # with newer cmake versions put all find_package in global scope
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(FeatureSummary)
include(MapnikOption)
include(MapnikMinimumVersions)
include(MapnikFindPackage)
include(MapnikInstall)
include(CTest)
add_feature_info(BUILD_TESTING BUILD_TESTING "Adds tests")
mapnik_option(INSTALL_DEPENDENCIES "if ON, all dependencies (eg. required dlls) will be copied into CMAKE_INSTALL_PREFIX/MAPNIK_BIN_DIR." ON)
mapnik_option(BUILD_SHARED_LIBS "build mapnik dynamic(ON) or static(OFF)" ON)
mapnik_option(BUILD_SHARED_PLUGINS "build dynamic plugins" ${BUILD_SHARED_LIBS}) # use BUILD_SHARED_LIBS as default option
mapnik_option(BUILD_SHARED_CRT "(only windows with msvc) use msvc shared crt" ON)
if(WIN32 AND BUILD_SHARED_PLUGINS AND NOT BUILD_SHARED_LIBS)
message(FATAL_ERROR "static libmapnik and dynamic plugins won't work correctly")
endif()
mapnik_option(USE_EXTERNAL_MAPBOX_GEOMETRY "Use a external mapnik/geometry.hpp. If off, use the submodule" OFF)
mapnik_option(USE_EXTERNAL_MAPBOX_POLYLABEL "Use a external mapnik/polylabel. If off, use the submodule" OFF)
mapnik_option(USE_EXTERNAL_MAPBOX_PROTOZERO "Use a external mapnik/protozero. If off, use the submodule" OFF)
mapnik_option(USE_EXTERNAL_MAPBOX_VARIANT "Use a external mapnik/variant. If off, use the submodule" OFF)
mapnik_option(USE_JPEG "adds jpeg support" ON)
mapnik_option(USE_PNG "adds png support" ON)
mapnik_option(USE_TIFF "adds tiff support" ON)
mapnik_option(USE_WEBP "adds webp support" ON)
mapnik_option(USE_LIBXML2 "adds libxml2 support" ON)
mapnik_option(USE_CAIRO "adds the cairo renderer" ON)
mapnik_option(USE_PROJ "adds proj support" ON)
mapnik_option(USE_GRID_RENDERER "adds grid renderer" ON)
mapnik_option(USE_SVG_RENDERER "adds svg renderer" ON)
mapnik_option(USE_BIGINT "uses 64 bit instead of 32" ON)
mapnik_option(USE_BOOST_FILESYSTEM "use boost::filesytem even if `std::filesystem` is available (since c++17)" OFF)
mapnik_option(USE_MEMORY_MAPPED_FILE "uses file cache" ON)
mapnik_option(USE_MULTITHREADED "enables the multithreaded features (threadsafe)" ON)
mapnik_option(USE_NO_ATEXIT "disable atexit" OFF)
mapnik_option(USE_NO_DLCLOSE "disable dlclose" OFF)
mapnik_option(USE_DEBUG_OUTPUT "enables some debug messages for development" OFF)
mapnik_option(USE_LOG "enables logging output. See log severity level." OFF)
# 0 = debug
# 1 = warn
# 2 = error
# 3 = none
set(USE_LOG_SEVERITY "1" CACHE STRING "sets the logging severity (only applies when USE_LOG is ON")
mapnik_option(USE_STATS "Enable statistics reporting" OFF)
mapnik_option(DISABLE_MAPNIK_AUTOSETUP "disables the autosetup. Need to call mapnik::setup() then" OFF)
mapnik_option(USE_PLUGIN_INPUT_CSV "adds plugin input csv" ON)
mapnik_option(USE_PLUGIN_INPUT_GDAL "adds plugin input gdal" ON)
mapnik_option(USE_PLUGIN_INPUT_GEOBUF "adds plugin input geobuf" ON)
mapnik_option(USE_PLUGIN_INPUT_GEOJSON "adds plugin input geojson" ON)
mapnik_option(USE_PLUGIN_INPUT_OGR "adds plugin input ogr" ON)
mapnik_option(USE_PLUGIN_INPUT_PGRASTER "adds plugin input pgraster" ON)
mapnik_option(USE_PLUGIN_INPUT_POSTGIS "adds plugin input postgis" ON)
mapnik_option(USE_PLUGIN_INPUT_RASTER "adds plugin input raster" ON)
mapnik_option(USE_PLUGIN_INPUT_SHAPE "adds plugin input shape" ON)
mapnik_option(USE_PLUGIN_INPUT_SQLITE "adds plugin input sqlite" ON)
mapnik_option(USE_PLUGIN_INPUT_TOPOJSON "adds plugin input topojson" ON)
mapnik_option(BUILD_DEMO_VIEWER "builds the demo viewer" ON)
mapnik_option(BUILD_DEMO_CPP "builds the demo c++ application" ON)
mapnik_option(BUILD_BENCHMARK "builds benchmark project" ON)
mapnik_option(BUILD_UTILITY_GEOMETRY_TO_WKB "builds the utility program geometry_to_wkb" ON)
mapnik_option(BUILD_UTILITY_MAPNIK_INDEX "builds the utility program mapnik_index" ON)
mapnik_option(BUILD_UTILITY_MAPNIK_RENDER "builds the utility program mapnik_render" ON)
mapnik_option(BUILD_UTILITY_OGRINDEX "builds the utility program ogrindex" OFF)
mapnik_option(BUILD_UTILITY_PGSQL2SQLITE "builds the utility program pgsql2sqlite" ON)
mapnik_option(BUILD_UTILITY_SHAPEINDEX "builds the utility program shapeindex" ON)
mapnik_option(BUILD_UTILITY_SVG2PNG "builds the utility program svg2png" ON)
mapnik_option(USE_BOOST_REGEX_ICU_WORKAROUND "if you don't use your system libraries and get double linked icu libraries set this to ON" OFF)
mapnik_option(USE_GLIBC_WORKAROUND "see https://github.com/mapnik/mapnik/pull/3792 if you building with libstdc++-4.9" OFF)
feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
feature_summary(FILENAME "${CMAKE_CURRENT_BINARY_DIR}/features.log" WHAT ENABLED_FEATURES DISABLED_FEATURES)
include(GNUInstallDirs)
# See for more details: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html
set(MAPNIK_BIN_DIR ${CMAKE_INSTALL_BINDIR} CACHE STRING "Install directory for binaries")
set(MAPNIK_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING "Install directory for libraries")
set(MAPNIK_ARCHIVE_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING "Install directory for archives")
set(MAPNIK_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING "Install directory for the headers")
set(MAPNIK_CMAKE_DIR ${MAPNIK_LIB_DIR}/cmake/mapnik CACHE STRING "Install directory of the cmake targets")
set(MAPNIK_PKGCONF_DIR ${MAPNIK_LIB_DIR}/pkgconfig CACHE STRING "Install directory for the .pc files for pkg-config")
set(MAPNIK_OUTPUT_DIR "${CMAKE_BINARY_DIR}/out")
if(WIN32)
set(DEFAULT_PLUGINS_INSTALL_DIR ${MAPNIK_BIN_DIR}/mapnik/input)
else()
set(DEFAULT_PLUGINS_INSTALL_DIR ${MAPNIK_LIB_DIR}/mapnik/input)
endif()
set(PLUGINS_INSTALL_DIR ${DEFAULT_PLUGINS_INSTALL_DIR} CACHE STRING "installs the plugins in the specified directory")
message(STATUS "Installing plugins to ${PLUGINS_INSTALL_DIR}")
set(FONTS_INSTALL_DIR ${MAPNIK_LIB_DIR}/mapnik/fonts CACHE STRING "installs the fonts in the specified directory")
message(STATUS "Installing fonts to ${FONTS_INSTALL_DIR}")
set(MAPNIK_COMPILE_DEFS "")
set(MAPNIK_OPTIONAL_LIBS "")
set(MAPNIK_OPTIONAL_LIBS_INCLUDE "")
#############################
#############################
# Begin project configuration
#############################
#############################
set(CMAKE_CXX_STANDARD 17 CACHE STRING "Sets the c++ standard. c++17 is minimum.")
set(CMAKE_CXX_STANDARD_REQUIRED ON) # require the specified CMAKE_CXX_STANDARD
set(CMAKE_CXX_EXTENSIONS OFF CACHE STRING "Enables the compiler specific extensions.") # Fallsback to -std=c++<ver> if off
message(STATUS "Using c++${CMAKE_CXX_STANDARD}")
message(STATUS "Using c++ extensions: ${CXX_EXTENSIONS}")
# add debug postfix to the libraries
set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "sets the debug library postfix on mapnik, wkt and json")
message(STATUS "postfix for debug libraries: ${CMAKE_DEBUG_POSTFIX}")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<BOOL:${BUILD_SHARED_CRT}>:DLL>")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${MAPNIK_OUTPUT_DIR}/lib")
# needs to be before the first call of find_boost.
if(CMAKE_CXX_STANDARD VERSION_LESS 17)
list(APPEND MAPNIK_COMPILE_DEFS BOOST_SPIRIT_X3_HIDE_CXX17_WARNING)
endif()
if(USE_MULTITHREADED)
set(Boost_USE_MULTITHREADED ON)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_THREADSAFE)
else()
set(Boost_USE_MULTITHREADED OFF)
endif()
mapnik_find_package(PkgConfig REQUIRED)
mapnik_find_threads()
mapnik_find_package(ICU REQUIRED COMPONENTS uc i18n data)
mapnik_find_package(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS regex)
if(CMAKE_CXX_STANDARD VERSION_LESS 17)
set(USE_BOOST_FILESYSTEM ON CACHE BOOL "Use boost::filesystem" FORCE)
endif()
if(USE_BOOST_FILESYSTEM)
mapnik_find_package(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS filesystem system)
endif()
list(APPEND MAPNIK_COMPILE_DEFS BOOST_REGEX_HAS_ICU)
if(USE_BOOST_REGEX_ICU_WORKAROUND)
message(STATUS "using boost regex workaround")
set_property(TARGET Boost::regex PROPERTY INTERFACE_LINK_LIBRARIES)
endif()
include(CheckBoostRegexIcu)
check_boost_regex()
if(BOOST_REGEX_HAS_ICU)
message(STATUS "boost regex has icu support")
list(APPEND MAPNIK_COMPILE_DEFS BOOST_REGEX_HAS_ICU)
endif()
mapnik_find_package(Freetype REQUIRED)
# try to find harfbuzz with the native configuration and fallback to our "own" FindHarfBuzz
mapnik_find_package(harfbuzz CONFIG QUIET)
if(harfbuzz_FOUND)
message(STATUS "Found harfbuzz native cmake")
list(APPEND MAPNIK_OPTIONAL_LIBS harfbuzz::harfbuzz)
else()
# Use pkg-config when harfbuzz is not found.
# It might be possible that in future version harfbuzz could only be found via pkg-config.
# harfbuzz related discussion: https://github.com/harfbuzz/harfbuzz/issues/2653
message(STATUS "harfbuzz not found via cmake. Searching via pkg-config...")
mapnik_pkg_check_modules(harfbuzz REQUIRED IMPORTED_TARGET harfbuzz>=${HARFBUZZ_MIN_VERSION})
list(APPEND MAPNIK_OPTIONAL_LIBS PkgConfig::harfbuzz)
endif()
if(USE_EXTERNAL_MAPBOX_GEOMETRY)
# this is used to provide a way to specify include dirs with CACHE VARIABLES
if(NOT MAPBOX_GEOMETRY_INCLUDE_DIRS)
message(STATUS "Searching for the include dir of mapbox/geometry.hpp")
find_path(MAPBOX_GEOMETRY_INCLUDE_DIRS "mapbox/geometry.hpp" REQUIRED)
endif()
else()
set(MAPBOX_GEOMETRY_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/geometry/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_GEOMETRY_INCLUDE_DIRS)
message(FATAL_ERROR "Set -DMAPBOX_GEOMETRY_INCLUDE_DIRS to the mapbox/geometry.hpp include dir")
endif()
if(USE_EXTERNAL_MAPBOX_POLYLABEL)
if(NOT MAPBOX_POLYLABEL_INCLUDE_DIRS)
message(STATUS "Searching for the include dir of mapbox/polylabel")
find_path(MAPBOX_POLYLABEL_INCLUDE_DIRS "mapbox/polylabel.hpp")
endif()
else()
set(MAPBOX_POLYLABEL_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/polylabel/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_POLYLABEL_INCLUDE_DIRS)
message(FATAL_ERROR "Set MAPBOX_POLYLABEL_INCLUDE_DIRS to the mapbox/geometry include dir")
endif()
if(USE_EXTERNAL_MAPBOX_PROTOZERO)
if(NOT MAPBOX_PROTOZERO_INCLUDE_DIRS)
message(STATUS "Searching for the include dir of mapbox/protozero")
find_path(MAPBOX_PROTOZERO_INCLUDE_DIRS "protozero/pbf_message.hpp")
endif()
else()
set(MAPBOX_PROTOZERO_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/protozero/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_PROTOZERO_INCLUDE_DIRS)
message(FATAL_ERROR "Set MAPBOX_PROTOZERO_INCLUDE_DIRS to the mapbox/protozero include dir")
endif()
if(USE_EXTERNAL_MAPBOX_VARIANT)
if(NOT MAPBOX_VARIANT_INCLUDE_DIRS)
message(STATUS "Searching for the include dir of mapbox/variant")
find_path(MAPBOX_VARIANT_INCLUDE_DIRS "mapbox/variant.hpp")
endif()
else()
set(MAPBOX_VARIANT_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/variant/include>
$<INSTALL_INTERFACE:include>
)
endif()
if(NOT MAPBOX_VARIANT_INCLUDE_DIRS)
message(FATAL_ERROR "Set MAPBOX_VARIANT_INCLUDE_DIRS to the mapbox/variant include dir")
endif()
# (used by MapnikInstall.cmake. properties are needed since "set(...)" will be out of scope
set_property(GLOBAL PROPERTY TARGETS "")
set_property(GLOBAL PROPERTY PLUGINS "")
set_property(GLOBAL PROPERTY MAPNIK_UTILITIES "")
if(USE_GLIBC_WORKAROUND)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_ENABLE_GLIBC_WORKAROUND)
endif()
if(USE_BIGINT)
list(APPEND MAPNIK_COMPILE_DEFS BIGINT)
endif()
if(USE_BOOST_FILESYSTEM)
list(APPEND MAPNIK_COMPILE_DEFS USE_BOOST_FILESYSTEM)
list(APPEND MAPNIK_OPTIONAL_LIBS Boost::filesystem)
endif()
if(USE_MEMORY_MAPPED_FILE)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_MEMORY_MAPPED_FILE)
endif()
if(USE_NO_ATEXIT)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_NO_ATEXIT)
endif()
if(USE_NO_DLCLOSE)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_NO_DLCLOSE)
endif()
if(USE_DEBUG_OUTPUT)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_DEBUG)
endif()
if(USE_LOG)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_LOG MAPNIK_DEFAULT_LOG_SEVERITY=${USE_LOG_SEVERITY})
endif()
if(USE_STATS)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_STATS)
endif()
if(USE_LIBXML2)
mapnik_find_package(LibXml2 REQUIRED)
list(APPEND MAPNIK_COMPILE_DEFS HAVE_LIBXML2)
list(APPEND MAPNIK_OPTIONAL_LIBS LibXml2::LibXml2)
endif()
if(USE_PNG)
mapnik_find_package(PNG REQUIRED)
list(APPEND MAPNIK_COMPILE_DEFS HAVE_PNG)
list(APPEND MAPNIK_OPTIONAL_LIBS PNG::PNG)
endif()
if(USE_JPEG)
mapnik_find_package(JPEG REQUIRED)
list(APPEND MAPNIK_COMPILE_DEFS HAVE_JPEG)
list(APPEND MAPNIK_OPTIONAL_LIBS JPEG::JPEG)
endif()
if(USE_TIFF)
mapnik_find_package(TIFF REQUIRED)
list(APPEND MAPNIK_COMPILE_DEFS HAVE_TIFF)
list(APPEND MAPNIK_OPTIONAL_LIBS TIFF::TIFF)
endif()
if(USE_WEBP)
mapnik_pkg_check_modules(WebP REQUIRED IMPORTED_TARGET libwebp)
list(APPEND MAPNIK_COMPILE_DEFS HAVE_WEBP)
list(APPEND MAPNIK_OPTIONAL_LIBS PkgConfig::WebP)
endif()
if(USE_CAIRO)
mapnik_pkg_check_modules(Cairo REQUIRED IMPORTED_TARGET cairo)
list(APPEND MAPNIK_COMPILE_DEFS HAVE_CAIRO)
list(APPEND MAPNIK_OPTIONAL_LIBS PkgConfig::Cairo)
endif()
if(USE_PROJ)
#https://proj.org/development/cmake.html
mapnik_find_package(PROJ QUIET)
# currently the cmake files are not installed, when installing proj via apt-get. So search via pkg-config
if(NOT PROJ_FOUND)
message(STATUS "PROJ not found via FindPROJ. Searching via pkg-config...")
mapnik_pkg_check_modules(PROJ REQUIRED IMPORTED_TARGET proj>=${PROJ_MIN_VERSION})
string(REGEX MATCH "([0-9]+)\.([0-9]+)\.([0-9]+)" _dummy "${PROJ_VERSION}")
set(PROJ_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(PROJ_VERSION_MINOR "${CMAKE_MATCH_2}")
set(PROJ_VERSION_PATCH "${CMAKE_MATCH_3}")
list(APPEND MAPNIK_OPTIONAL_LIBS PkgConfig::PROJ)
else()
if(PROJ_VERSION VERSION_LESS PROJ_MIN_VERSION)
message(FATAL_ERROR "Proj needs to be at least version ${PROJ_MIN_VERSION}")
endif()
list(APPEND MAPNIK_OPTIONAL_LIBS ${PROJ_LIBRARIES})
list(APPEND MAPNIK_OPTIONAL_LIBS_INCLUDE $<BUILD_INTERFACE:${PROJ_INCLUDE_DIRS}>)
endif()
math(EXPR MAPNIK_PROJ_VERSION "${PROJ_VERSION_MAJOR}*10000 + ${PROJ_VERSION_MINOR}*100 + ${PROJ_VERSION_PATCH}" OUTPUT_FORMAT DECIMAL)
message(STATUS "Using mapnik PROJ version: ${MAPNIK_PROJ_VERSION}")
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_USE_PROJ MAPNIK_PROJ_VERSION=${MAPNIK_PROJ_VERSION})
endif()
if(USE_GRID_RENDERER)
list(APPEND MAPNIK_COMPILE_DEFS GRID_RENDERER)
endif()
if(USE_SVG_RENDERER)
list(APPEND MAPNIK_COMPILE_DEFS SVG_RENDERER)
endif()
if(NOT WIN32)
message(STATUS "Compiling with -DMAPNIK_HAS_DLCFN")
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_HAS_DLCFN)
list(APPEND MAPNIK_OPTIONAL_LIBS ${CMAKE_DL_LIBS})
endif()
if(NOT BUILD_SHARED_PLUGINS)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_STATIC_PLUGINS)
endif()
# when building static, this have to be public so that all depending libs know about
if(NOT BUILD_SHARED_LIBS)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_STATIC_DEFINE)
endif()
if(DISABLE_MAPNIK_AUTOSETUP)
list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_DISABLE_AUTOSETUP)
endif()
# force utf-8 source code processing
# see https://docs.microsoft.com/de-de/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170
add_compile_options(
"$<$<CXX_COMPILER_ID:MSVC>:/utf-8>"
"$<$<CXX_COMPILER_ID:MSVC>:/EHsc>"
)
add_library(core INTERFACE)
add_library(mapnik::core ALIAS core)
target_include_directories(core INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${MAPBOX_GEOMETRY_INCLUDE_DIRS}>
$<BUILD_INTERFACE:${MAPBOX_POLYLABEL_INCLUDE_DIRS}>
$<BUILD_INTERFACE:${MAPBOX_VARIANT_INCLUDE_DIRS}>
$<BUILD_INTERFACE:${MAPBOX_PROTOZERO_INCLUDE_DIRS}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps>
$<INSTALL_INTERFACE:include>
${MAPNIK_OPTIONAL_LIBS_INCLUDE}
)
target_link_libraries(core INTERFACE
Threads::Threads
ICU::uc
ICU::data
ICU::i18n
Boost::headers
Boost::regex
Freetype::Freetype
${MAPNIK_OPTIONAL_LIBS}
)
target_compile_definitions(core INTERFACE ${MAPNIK_COMPILE_DEFS})
mapnik_install(core)
###
# forward declaring libraries to consume them when building static plugins (circle deps between mapnik <-> plugin_target)
add_library(mapnik "")
add_library(mapnik::mapnik ALIAS mapnik)
add_library(wkt STATIC "")
add_library(mapnik::wkt ALIAS wkt)
add_library(json STATIC "")
add_library(mapnik::json ALIAS json)
# end forward declaration
###
add_subdirectory(deps)
add_subdirectory(plugins)
add_subdirectory(src)
add_subdirectory(utils)
add_subdirectory(demo)
if(BUILD_BENCHMARK)
add_subdirectory(benchmark)
endif()
if(BUILD_TESTING)
add_subdirectory(test)
endif()
file(COPY fonts DESTINATION "${MAPNIK_OUTPUT_DIR}")
feature_summary(FILENAME "${CMAKE_CURRENT_BINARY_DIR}/packages.log" WHAT PACKAGES_FOUND PACKAGES_NOT_FOUND INCLUDE_QUIET_PACKAGES)
# start package mapnik
include(MapnikExport)
include(MapnikExportPkgConfig)
install(DIRECTORY include/mapnik/ DESTINATION "${MAPNIK_INCLUDE_DIR}/mapnik")
install(DIRECTORY deps/agg/include/ DESTINATION "${MAPNIK_INCLUDE_DIR}/mapnik/agg")
install(DIRECTORY deps/mapnik DESTINATION "${MAPNIK_INCLUDE_DIR}")
file(GLOB TTF_FONT_FILES "fonts/*/*/*.ttf")
install(FILES ${TTF_FONT_FILES} DESTINATION "${FONTS_INSTALL_DIR}")
if(NOT USE_EXTERNAL_MAPBOX_GEOMETRY)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/geometry/include/" DESTINATION "${MAPNIK_INCLUDE_DIR}")
endif()
if(NOT USE_EXTERNAL_MAPBOX_POLYLABEL)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/polylabel/include/" DESTINATION "${MAPNIK_INCLUDE_DIR}")
endif()
if(NOT USE_EXTERNAL_MAPBOX_PROTOZERO)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/protozero/include/" DESTINATION "${MAPNIK_INCLUDE_DIR}")
endif()
if(NOT USE_EXTERNAL_MAPBOX_VARIANT)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deps/mapbox/variant/include/" DESTINATION "${MAPNIK_INCLUDE_DIR}")
endif()
mapnik_install_targets()
include(pack)

View file

@ -1,350 +0,0 @@
{
"version": 6,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 0
},
"configurePresets": [
{
"name": "use-ninja",
"hidden": true,
"generator": "Ninja",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "default-build-dir",
"hidden": true,
"binaryDir": "${sourceDir}/build"
},
{
"name": "debug-build",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"USE_DEBUG_OUTPUT": "ON",
"USE_LOG": "ON",
"USE_LOG_SEVERITY": "0"
}
},
{
"name": "release-with-debug-build",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"USE_DEBUG_OUTPUT": "OFF",
"USE_LOG": "OFF"
}
},
{
"name": "release-build",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"USE_DEBUG_OUTPUT": "OFF",
"USE_LOG": "OFF"
}
},
{
"name": "use-clang",
"hidden": true,
"inherits": [
"default-build-dir",
"use-ninja"
],
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_CXX_FLAGS": "-stdlib=libc++",
"CMAKE_EXE_LINKER_FLAGS": "-stdlib=libc++",
"CMAKE_SHARED_LINKER_FLAGS": "-stdlib=libc++"
}
},
{
"name": "use-gcc",
"hidden": true,
"inherits": [
"default-build-dir",
"use-ninja"
],
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc",
"CMAKE_CXX_COMPILER": "g++"
}
},
{
"name": "use-msvc-cl",
"hidden": true,
"inherits": [
"default-build-dir",
"use-ninja"
],
"cacheVariables": {
"CMAKE_C_COMPILER": "cl",
"CMAKE_CXX_COMPILER": "cl"
}
},
{
"name": "use-msvc-clang-cl",
"hidden": true,
"inherits": [
"default-build-dir",
"use-ninja"
],
"cacheVariables": {
"CMAKE_C_COMPILER": "clang-cl",
"CMAKE_CXX_COMPILER": "clang-cl"
}
},
{
"name": "linux-clang-debug",
"displayName": "Linux clang debug",
"inherits": [
"use-clang",
"debug-build"
]
},
{
"name": "linux-clang-release",
"displayName": "Linux clang release",
"inherits": [
"use-clang",
"release-build"
]
},
{
"name": "linux-gcc-debug",
"displayName": "Linux gcc debug",
"inherits": [
"use-gcc",
"debug-build"
]
},
{
"name": "linux-gcc-release",
"displayName": "Linux gcc release",
"inherits": [
"use-gcc",
"release-build"
]
},
{
"name": "windows-arch-x64",
"hidden": true,
"architecture": {
"value": "x64",
"strategy": "external"
},
"toolset": {
"value": "host=x64",
"strategy": "external"
}
},
{
"name": "windows-default",
"displayName": "Windows x64 Debug",
"hidden": true,
"inherits": [
"use-msvc-cl",
"windows-arch-x64"
],
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
"hostOS": [
"Windows"
]
}
}
},
{
"name": "windows-debug",
"displayName": "Windows x64 Debug",
"inherits": [
"windows-default",
"debug-build"
]
},
{
"name": "windows-release",
"displayName": "Windows x64 Release",
"inherits": [
"windows-default",
"release-build"
]
},
{
"name": "ci-options",
"hidden": true,
"cacheVariables": {
"BUILD_TESTING": "ON",
"BUILD_DEMO_VIEWER": "OFF",
"DISABLE_MAPNIK_AUTOSETUP": "ON"
},
"toolchainFile": "vcpkg/scripts/buildsystems/vcpkg.cmake"
},
{
"name": "windows-ci",
"description": "used by the ci pipeline",
"inherits": [
"windows-release",
"ci-options"
],
"cacheVariables": {
"INSTALL_DEPENDENCIES": "ON",
"ADDITIONAL_LIBARIES_PATHS": "${sourceDir}/build/vcpkg_installed/x64-windows/bin"
},
"environment": {
"PROJ_LIB": "${sourceDir}/build/vcpkg_installed/x64-windows/share/proj"
}
},
{
"name": "linux-ci",
"description": "used by the ci pipeline",
"inherits": [
"release-with-debug-build",
"use-gcc",
"ci-options"
],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "--coverage"
},
"environment": {
"PROJ_LIB": "${sourceDir}/build/vcpkg_installed/x64-linux/share/proj"
}
},
{
"name": "linux-ci-release",
"description": "used by the ci pipeline for releasing",
"inherits": [
"release-build",
"linux-gcc-release"
],
"cacheVariables": {
"BUILD_TESTING": "OFF",
"BUILD_DEMO_VIEWER": "OFF",
"USE_MEMORY_MAPPED_FILE": "ON"
}
},
{
"name": "macos-ci-arm64",
"description": "used by the ci pipeline",
"inherits": [
"use-ninja",
"release-with-debug-build",
"default-build-dir",
"ci-options"
],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fprofile-arcs -ftest-coverage"
},
"environment": {
"PROJ_LIB": "${sourceDir}/build/vcpkg_installed/arm64-osx/share/proj"
}
},
{
"name": "macos-ci-x64",
"description": "used by the ci pipeline",
"inherits": [
"use-ninja",
"release-with-debug-build",
"default-build-dir",
"ci-options"
],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fprofile-arcs -ftest-coverage"
},
"environment": {
"PROJ_LIB": "${sourceDir}/build/vcpkg_installed/x64-osx/share/proj"
}
}
],
"buildPresets": [
{
"name": "windows-debug",
"configurePreset": "windows-debug"
},
{
"name": "windows-release",
"configurePreset": "windows-release"
},
{
"name": "linux-clang-debug",
"configurePreset": "linux-clang-debug"
},
{
"name": "linux-clang-release",
"configurePreset": "linux-clang-release"
},
{
"name": "linux-gcc-debug",
"configurePreset": "linux-gcc-debug"
},
{
"name": "linux-gcc-release",
"configurePreset": "linux-gcc-release"
},
{
"name": "windows-ci",
"configurePreset": "windows-ci"
},
{
"name": "linux-ci",
"configurePreset": "linux-ci"
},
{
"name": "linux-ci-release",
"configurePreset": "linux-ci-release"
},
{
"name": "macos-ci-arm64",
"configurePreset": "macos-ci-arm64"
},
{
"name": "macos-ci-x64",
"configurePreset": "macos-ci-x64"
}
],
"testPresets": [
{
"name": "test-default",
"hidden": true,
"output": {
"outputOnFailure": true
},
"execution": {
"noTestsAction": "error",
"stopOnFailure": false
}
},
{
"name": "windows-ci",
"configurePreset": "windows-ci",
"inherits": [
"test-default"
]
},
{
"name": "linux-ci",
"configurePreset": "linux-ci",
"inherits": [
"test-default"
]
},
{
"name": "macos-ci-arm64",
"configurePreset": "macos-ci-arm64",
"inherits": [
"test-default"
]
},
{
"name": "macos-ci-x64",
"configurePreset": "macos-ci-x64",
"inherits": [
"test-default"
]
}
]
}

View file

@ -1,22 +0,0 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)

View file

@ -1,64 +1,31 @@
# Mapnik Installation
Mapnik runs on Linux, OS X, Windows, and BSD systems.
## Package managers
### vcpkg
To install mapnik with vcpkg type `vcpkg install mapnik`. It will install a minimal version of mapnik and all the needed dependencies.
To install more features, type `vcpkg search mapnik` to see all available features.
## Source build
First clone mapnik from github and initialize submodules
```bash
git clone https://github.com/mapnik/mapnik.git
cd mapnik
git submodule update --init
```
Mapnik is cross platform and runs on Linux, Mac OSX, Solaris, *BSD, and Windows.
To configure and build Mapnik do:
```bash
./configure
make
```
To trigger parallel compilation you can pass a JOBS value to make:
```bash
JOBS=4 make
```
Mapnik needs > 2 GB of RAM to build. If you use parallel compilation it needs more.
If you are on a system with less memory make sure you only build with one JOB:
```bash
JOBS=1 make
```
./configure
make
To use a Python interpreter that is not named `python` for your build, do
something like the following instead:
```bash
$ PYTHON=python3 ./configure
$ make PYTHON=python3
```
PYTHON=python2 ./configure
make PYTHON=python2
NOTE: the above will not work on windows, rather see https://github.com/mapnik/mapnik/wiki/WindowsInstallation
Then to run the tests locally (without needing to install):
make test
make test-local
Install like:
make install
sudo make install
If you need to uninstall do:
make uninstall
sudo make uninstall
For more details see the `Building` Section below.
@ -71,25 +38,25 @@ For troubleshooting help see https://github.com/mapnik/mapnik/wiki/InstallationT
Build system dependencies are:
* C++ compiler supporting `-std=c++17` (like >= g++ 9 or >= clang++ 5)
* \>= 2 GB RAM (> 5 GB for g++)
* Python 3
* Scons (a copy is bundled) or CMake >= 3.15 see [docs/cmake-usage.md](./docs/cmake-usage.md)
* C++ compiler (like g++ or clang++)
* >= 2 GB RAM
* Python 2.4-2.7
* Scons (a copy is bundled)
Mapnik Core depends on:
* Boost
- \>= 1.73 is required
- >= 1.47 is required.
- These libraries are used:
- filesystem
- system
- thread (if mapnik threadsafe support is required, default on)
- regex (optionally built with icu regex support)
- program_options (optionally for mapnik command line programs)
* libicuuc >= 4.0 (ideally >= 4.2) - International Components for Unicode
* libz - Zlib compression
* libfreetype - Freetype2 for font support (Install requires freetype-config)
* libxml2 - XML parsing (Install requires xml2-config)
* libharfbuzz - an OpenType text shaping engine (>=0.9.34 needed for CSS font-feature-settings support)
Mapnik Core optionally depends on:
@ -97,17 +64,29 @@ Mapnik Core optionally depends on:
* libjpeg - JPEG graphics (Default enabled, if found)
* libtiff - TIFF graphics (Default enabled, if found)
* libwebp - WEBP graphics (Default enabled, if found)
* libproj >= 7.2.0 - PROJ projection library (Default enabled, if found)
* libproj - PROJ.4 projection library (Default enabled, if found)
Mapnik Python bindings depend on:
* Python 2.5-2.7 or >= 3.2
* Boost python
* simplejson module if using <= 2.5
Note: Python 3.x is supported, see: https://github.com/mapnik/mapnik/wiki/Python3k
Additional optional dependencies:
* Cairo >= 1.6.0 - Graphics library for output formats like PDF, PS, and SVG
- pkg-config - Required for building with cairo support
- pycairo - Python bindings for cairo
* PostgreSQL (for PostGIS plugin support)
- libpq - PostreSQL libraries
- pg_config - PostgreSQL installation capabilities
* libgdal - GDAL/OGR input (For gdal and ogr plugin support) (>= GDAL 2.0.2 for thread safety - https://github.com/mapnik/mapnik/issues/3339)
* libgdal - GDAL/OGR input (For gdal and ogr plugin support)
* libsqlite3 - SQLite input (needs RTree support builtin) (sqlite plugin support)
* libocci - Oracle input plugin support
* libcurl - OSM input plugin support
* librasterlite - Rasterlite input plugin support
Instructions for installing many of these dependencies on
various platforms can be found at the Mapnik Wiki:
@ -168,13 +147,17 @@ For more details on usage see:
You can run the Mapnik tests locally (without installing) like:
make test
make test-local # see the Makefile for how this works
## Python Bindings
Or you can install and test like:
Python bindings are not included by default. You'll need to add those separately.
make install && make test
Many of the tests are written in python and you can run them individually like:
make install
python tests/python_tests/shapefile_test.py
* Build from source: https://github.com/mapnik/python-mapnik
## Learning Mapnik
@ -191,7 +174,7 @@ If you need help or want to participate starting points include:
### Cartographers
TileMill, which uses Mapnik internally, offers great step by step tutorials for
learning advanced map styling: https://tilemill-project.github.io/tilemill/docs/crashcourse/introduction/
learning advanced map styling: http://mapbox.com/tilemill/docs/crashcourse/introduction/
### Programmers
@ -199,6 +182,6 @@ Mapnik is great for building your own mapping applications. Visit
https://github.com/mapnik/mapnik/wiki/LearningMapnik for basic
tutorials on how to programmatically use Mapnik.
### Contributors
### Contributers
Read [docs/contributing.md](docs/contributing.md) for resources for getting involved with Mapnik development.
Read docs/contributing.markdown for resources for getting involved with Mapnik development.

View file

@ -1,50 +1,18 @@
OS := $(shell uname -s)
PYTHON = python
ifeq ($(JOBS),)
JOBS:=1
endif
ifeq ($(HEAVY_JOBS),)
HEAVY_JOBS:=1
endif
all: mapnik
install:
$(PYTHON) scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1 install
release:
./scripts/publish_release.sh
test-release:
./scripts/test_release.sh
src/json/libmapnik-json.a:
# we first build memory intensive files with -j$(HEAVY_JOBS)
$(PYTHON) scons/scons.py -j$(HEAVY_JOBS) \
--config=cache --implicit-cache --max-drift=1 \
src/renderer_common/render_group_symbolizer.os \
src/renderer_common/render_markers_symbolizer.os \
src/renderer_common/render_thunk_extractor.os \
src/json/libmapnik-json.a \
src/wkt/libmapnik-wkt.a \
src/css/css_grammar_x3.os \
src/css/css_color_grammar_x3.os \
src/expression_grammar_x3.os \
src/transform_expression_grammar_x3.os \
src/image_filter_grammar_x3.os \
src/marker_helpers.os \
src/svg/svg_transform_parser.os \
src/agg/process_line_symbolizer.os \
plugins/input/geojson/geojson_datasource.os \
src/svg/svg_path_parser.os \
src/svg/svg_parser.os \
src/svg/svg_points_parser.os \
src/svg/svg_transform_parser.os \
mapnik: src/json/libmapnik-json.a
# then install the rest with -j$(JOBS)
mapnik:
$(PYTHON) scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1
clean:
@ -55,12 +23,12 @@ clean:
@if test -e ".sconf_temp/"; then rm -r ".sconf_temp/"; fi
@find ./ -name "*.pyc" -exec rm {} \;
@find ./ -name "*.os" -exec rm {} \;
@find ./src/ -name "*.dylib" -exec rm {} \;
@find ./src/ -name "*.so" -exec rm {} \;
@find ./ -name "*.dylib" -exec rm {} \;
@find ./ -name "*.so" -exec rm {} \;
@find ./ -name "*.o" -exec rm {} \;
@find ./src/ -name "*.a" -exec rm {} \;
@find ./ -name "*.gcda" -exec rm {} \;
@find ./ -name "*.gcno" -exec rm {} \;
@find ./ -name "*.a" -exec rm {} \;
@find ./ -name "*.pyc" -exec rm {} \;
@if test -e "bindings/python/mapnik/paths.py"; then rm "bindings/python/mapnik/paths.py"; fi
distclean:
if test -e "config.py"; then mv "config.py" "config.py.backup"; fi
@ -73,14 +41,17 @@ rebuild:
uninstall:
@$(PYTHON) scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1 uninstall
test/data-visual:
./scripts/ensure_test_data.sh
test:
./run_tests
test/data:
./scripts/ensure_test_data.sh
test-visual:
bash -c "source ./localize.sh && python tests/visual_tests/test.py -q"
test: ./test/data test/data-visual
@./test/run
test-python:
bash -c "source ./localize.sh && python tests/run_tests.py -q"
test-cpp:
./tests/cpp_tests/run
check: test
@ -90,16 +61,17 @@ bench:
demo:
cd demo/c++; ./rundemo `mapnik-config --prefix`
# note: pass --gen-suppressions=yes to create new suppression entries
pep8:
# https://gist.github.com/1903033
# gsed on osx
@pep8 -r --select=W293 -q --filename=*.py `pwd`/tests/ | xargs gsed -i 's/^[ \r\t]*$$//'
@pep8 -r --select=W391 -q --filename=*.py `pwd`/tests/ | xargs gsed -i -e :a -e '/^\n*$$/{$$d;N;ba' -e '}'
@pep8 -r --select=W391 -q --filename=*.py `pwd`/tests/ | xargs ged -i '/./,/^$$/!d'
grind:
@source localize.sh && \
valgrind --suppressions=./test/unit/valgrind.supp --leak-check=full --log-fd=1 ./test/visual/run | grep definitely;
@source localize.sh && \
for FILE in test/standalone/*-bin; do \
valgrind --suppressions=./test/unit/valgrind.supp --leak-check=full --log-fd=1 $${FILE} | grep definitely; \
@for FILE in tests/cpp_tests/*-bin; do \
valgrind --leak-check=full --log-fd=1 $${FILE} | grep definitely; \
done
@source localize.sh && \
valgrind --suppressions=./test/unit/valgrind.supp --leak-check=full --log-fd=1 ./test/unit/run | grep definitely;
render:
@for FILE in tests/data/good_maps/*xml; do \

View file

@ -8,23 +8,22 @@ _/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
_/
```
[![TravisCI](https://api.travis-ci.com/mapnik/mapnik.svg?branch=master)](http://travis-ci.com/mapnik/mapnik)
[![codecov](https://codecov.io/gh/mapnik/mapnik/branch/master/graph/badge.svg)](https://codecov.io/gh/mapnik/mapnik)
[![Build Status](https://secure.travis-ci.org/mapnik/mapnik.png)](http://travis-ci.org/mapnik/mapnik)
Mapnik is an open source toolkit for developing mapping applications. At the core is a C++ shared library providing algorithms and patterns for spatial data access and visualization.
# What is Mapnik?
Mapnik is an open source toolkit for developing mapping applications. At the core is a C++ shared library providing algorithms and patterns for spatial data access and visualization. High-level bindings for JavaScript, Python, and Ruby facilitate rapid application development in a variety of environments.
# Overview
Mapnik is basically a collection of geographic objects like maps, layers, datasources, features, and geometries. The library doesn't rely on any OS specific "windowing systems" and it can be deployed to any server environment. It is intended to play fair in a multi-threaded environment and is aimed primarily, but not exclusively, at web-based development.
For further information see [http://mapnik.org](http://mapnik.org) and also our [wiki documentation](https://github.com/mapnik/mapnik/wiki).
For further information see [http://mapnik.org](http://mapnik.org) and also our [wiki documentation](https://github.com/mapnik/mapnik/wiki) here on GitHub.
# Installation
See [INSTALL.md](INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides.
# Code of Conduct
Please note that this project is released with a [Contributor Code of Conduct](https://github.com/mapnik/mapnik/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
See [INSTALL.md](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides.
# License
Mapnik software is free and is released under the LGPL v2.1 ([GNU Lesser General Public License, version 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information.
Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information.

1204
SConstruct

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
multicolor-hextree-actual.png
multicolor-hextree-actual.png
polygon_clipping_boost_actual.png
polygon_clipping_clipper_actual.png
polygon_clipping_agg_actual.png
out

View file

@ -1,52 +0,0 @@
project(mapnik-benchmark)
set(BENCHMARK_SRCS
src/normalize_angle.cpp
src/test_array_allocation.cpp
src/test_expression_parse.cpp
src/test_face_ptr_creation.cpp
src/test_font_registration.cpp
src/test_getline.cpp
src/test_marker_cache.cpp
src/test_noop_rendering.cpp
src/test_numeric_cast_vs_static_cast.cpp
src/test_offset_converter.cpp
src/test_png_encoding1.cpp
src/test_png_encoding2.cpp
src/test_polygon_clipping_rendering.cpp
src/test_polygon_clipping.cpp
src/test_proj_transform1.cpp
src/test_quad_tree.cpp
src/test_rendering_shared_map.cpp
src/test_rendering.cpp
src/test_to_bool.cpp
src/test_to_double.cpp
src/test_to_int.cpp
src/test_to_string1.cpp
src/test_to_string2.cpp
src/test_utf_encoding.cpp
)
function(mapnik_create_benchmark)
get_filename_component(BENCHNAME ${ARGV0} NAME_WE)
set(TARGET_NAME "mapnik-benchmark-${BENCHNAME}")
add_executable(${TARGET_NAME} ${ARGV0})
target_include_directories(${TARGET_NAME} PRIVATE include)
target_link_libraries(${TARGET_NAME} PRIVATE
mapnik::agg
mapnik::mapnik
ICU::data ICU::i18n ICU::uc # needed for the static build (TODO: why isn't this correctly propagated from mapnik::mapnik?)
)
set_target_properties(${TARGET_NAME} PROPERTIES
OUTPUT_NAME "${BENCHNAME}"
)
endfunction()
foreach(benchmark ${BENCHMARK_SRCS})
mapnik_create_benchmark(${benchmark})
endforeach()
file(COPY data DESTINATION "${MAPNIK_OUTPUT_DIR}/benchmark")
file(COPY run_benchmarks
DESTINATION "${MAPNIK_OUTPUT_DIR}"
FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE GROUP_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ
)

View file

@ -0,0 +1,130 @@
#ifndef __MAPNIK_BENCH_FRAMEWORK_HPP__
#define __MAPNIK_BENCH_FRAMEWORK_HPP__
// mapnik
#include <mapnik/params.hpp>
#include <mapnik/value_types.hpp>
// boost
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/chrono/process_cpu_clocks.hpp>
#include <boost/chrono.hpp>
#include <boost/thread/thread.hpp>
// stl
#include <iostream>
#include <vector>
#include <set>
#include <iomanip>
namespace benchmark {
class test_case
{
protected:
mapnik::parameters params_;
std::size_t threads_;
std::size_t iterations_;
public:
test_case(mapnik::parameters const& params)
: params_(params),
threads_(*params.get<mapnik::value_integer>("threads",0)),
iterations_(*params.get<mapnik::value_integer>("iterations",0))
{}
std::size_t threads() const
{
return threads_;
}
std::size_t iterations() const
{
return iterations_;
}
virtual bool validate() const = 0;
virtual void operator()() const = 0;
virtual ~test_case() {}
};
void handle_args(int argc, char** argv, mapnik::parameters & params)
{
if (argc > 0) {
for (int i=1;i<argc;++i) {
std::string opt(argv[i]);
// parse --foo bar
if (!opt.empty() && (opt.find("--") != 0)) {
std::string key = std::string(argv[i-1]);
if (!key.empty() && (key.find("--") == 0)) {
key = key.substr(key.find_first_not_of("-"));
params[key] = opt;
}
}
}
}
}
#define BENCHMARK(test_class,name) \
int main(int argc, char** argv) \
{ \
try \
{ \
mapnik::parameters params; \
benchmark::handle_args(argc,argv,params); \
test_class test_runner(params); \
return run(test_runner,name); \
} \
catch (std::exception const& ex) \
{ \
std::clog << ex.what() << "\n"; \
return -1; \
} \
} \
template <typename T>
int run(T const& test_runner, std::string const& name)
{
try
{
if (!test_runner.validate())
{
std::clog << "test did not validate: " << name << "\n";
return -1;
}
boost::chrono::process_cpu_clock::time_point start;
boost::chrono::process_cpu_clock::duration elapsed;
std::stringstream s;
s << name << ":"
<< std::setw(45 - (int)s.tellp()) << std::right
<< " t:" << test_runner.threads()
<< " i:" << test_runner.iterations();
if (test_runner.threads() > 0)
{
boost::thread_group threads;
for (unsigned i=0;i<test_runner.threads();++i)
{
threads.create_thread(test_runner);
}
start = boost::chrono::process_cpu_clock::now();
threads.join_all();
elapsed = boost::chrono::process_cpu_clock::now() - start;
}
else
{
start = boost::chrono::process_cpu_clock::now();
test_runner();
elapsed = boost::chrono::process_cpu_clock::now() - start;
}
s << std::setw(65 - (int)s.tellp()) << std::right
<< boost::chrono::duration_cast<boost::chrono::milliseconds>(elapsed) << "\n";
std::clog << s.str();
return 0;
}
catch (std::exception const& ex)
{
std::clog << "test runner did not complete: " << ex.what() << "\n";
return -1;
}
return 0;
}
}
#endif // __MAPNIK_BENCH_FRAMEWORK_HPP__

View file

@ -8,8 +8,6 @@ test_env = env.Clone()
test_env['LIBS'] = [env['MAPNIK_NAME']]
test_env.AppendUnique(LIBS=copy(env['LIBMAPNIK_LIBS']))
test_env.AppendUnique(LIBS='mapnik-wkt')
test_env.AppendUnique(LIBS='sqlite3')
if env['PLATFORM'] == 'Linux':
test_env.AppendUnique(LIBS='dl')
test_env.AppendUnique(LIBS='rt')
@ -19,19 +17,14 @@ test_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
if test_env['HAS_CAIRO']:
test_env.PrependUnique(CPPPATH=test_env['CAIRO_CPPPATHS'])
test_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
test_env.PrependUnique(CPPPATH='include', delete_existing=True)
test_env['LINKFLAGS'] = copy(test_env['LIBMAPNIK_LINKFLAGS'])
if env['PLATFORM'] == 'Darwin':
test_env.Append(LINKFLAGS='-F/ -framework CoreFoundation')
test_env_local = test_env.Clone()
benchmarks = glob.glob("src/*.cpp")
for src in benchmarks:
name, ext = os.path.splitext(os.path.basename(src))
out = os.path.join("out", name)
test_program = test_env_local.Program(out, source=[src])
for cpp_test in glob.glob('*cpp'):
test_program = test_env_local.Program('out/'+cpp_test.replace('.cpp',''), source=[cpp_test])
if 'install' in COMMAND_LINE_TARGETS:
env.Alias('install',test_program)
#Depends(test_program, env.subst('../src/%s' % env['MAPNIK_LIB_NAME']))

View file

@ -0,0 +1,52 @@
#ifndef __MAPNIK_COMPARE_IMAGES_HPP__
#define __MAPNIK_COMPARE_IMAGES_HPP__
#include <mapnik/graphics.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_reader.hpp>
#include <boost/make_shared.hpp>
using namespace mapnik;
namespace benchmark {
bool compare_images(std::string const& src_fn,std::string const& dest_fn)
{
std::auto_ptr<mapnik::image_reader> reader1(mapnik::get_image_reader(dest_fn,"png"));
if (!reader1.get())
{
throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
}
boost::shared_ptr<image_32> image_ptr1 = boost::make_shared<image_32>(reader1->width(),reader1->height());
reader1->read(0,0,image_ptr1->data());
std::auto_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn,"png"));
if (!reader2.get())
{
throw mapnik::image_reader_exception("Failed to load: " + src_fn);
}
boost::shared_ptr<image_32> image_ptr2 = boost::make_shared<image_32>(reader2->width(),reader2->height());
reader2->read(0,0,image_ptr2->data());
image_data_32 const& dest = image_ptr1->data();
image_data_32 const& src = image_ptr2->data();
unsigned int width = src.width();
unsigned int height = src.height();
if ((width != dest.width()) || height != dest.height()) return false;
for (unsigned int y = 0; y < height; ++y)
{
const unsigned int* row_from = src.getRow(y);
const unsigned int* row_to = dest.getRow(y);
for (unsigned int x = 0; x < width; ++x)
{
if (row_from[x] != row_to[x]) return false;
}
}
return true;
}
}
#endif // __MAPNIK_COMPARE_IMAGES_HPP__

View file

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map
srs="epsg:4326"
background-color="#dfd8c9">
<Style name="style">
<Rule>
<RasterSymbolizer />
</Rule>
</Style>
<Layer name="layer"
srs="epsg:4326">
<StyleName>style</StyleName>
<Datasource>
<Parameter name="file">./valid.geotiff.tif</Parameter>
<Parameter name="type">gdal</Parameter>
</Datasource>
</Layer>
</Map>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -7,7 +7,7 @@
<Layer name="world" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<Parameter name="file">../../test/data/shp/world_merc.shp</Parameter>
<Parameter name="file">../../tests/data/shp/world_merc.shp</Parameter>
<Parameter name="type">shape</Parameter>
</Datasource>
</Layer>

View file

@ -7,7 +7,7 @@
<Layer name="world" srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<Parameter name="file">../../test/data/shp/world_merc.shp</Parameter>
<Parameter name="file">../../tests/data/shp/world_merc.shp</Parameter>
<Parameter name="type">shape</Parameter>
</Datasource>
</Layer>

View file

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map
srs="epsg:4326"
background-color="#dfd8c9">
<Style name="style">
<Rule>
<RasterSymbolizer />
</Rule>
</Style>
<Layer name="layer"
srs="epsg:4326">
<StyleName>style</StyleName>
<Datasource>
<Parameter name="file">./valid.geotiff.tif</Parameter>
<Parameter name="type">raster</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -2,7 +2,7 @@
<!DOCTYPE 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"
font-directory="../../fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf"
font-directory="../../fonts/dejavu-fonts-ttf-2.33/ttf/DejaVuSans.ttf"
background-color="#dfd8c9">
<Style name="marking" filter-mode="first">
@ -76,12 +76,12 @@
<StyleName>labels</StyleName>
<Datasource>
<!--
ogr2ogr -f CSV tests/visual_tests/data/roads.csv -lco GEOMETRY=AS_WKT tests/visual_tests/data/grouped-rendering.sqlite roads -sql "SELECT fid,geometry, type, tunnel, bridge, oneway, class, z_order, CAST((z_order / 10.0) AS INTEGER) AS z FROM roads ORDER BY z_order"
-->
ogr2ogr -f CSV tests/visual_tests/data/roads.csv -lco GEOMETRY=AS_WKT tests/visual_tests/data/grouped-rendering.sqlite roads -sql "SELECT fid,geometry, type, tunnel, bridge, oneway, class, z_order, CAST((z_order / 10.0) AS INTEGER) AS z FROM roads ORDER BY z_order"
-->
<Parameter name="file">./roads.csv</Parameter>
<Parameter name="extent">1477001.12245,6890242.37746,1480004.49012,6892244.62256</Parameter>
<Parameter name="type">csv</Parameter>
</Datasource>
</Layer>
</Map>
</Map>

Binary file not shown.

View file

@ -1,302 +0,0 @@
#ifndef MAPNIK_BENCH_FRAMEWORK_HPP
#define MAPNIK_BENCH_FRAMEWORK_HPP
// mapnik
#include <mapnik/mapnik.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/params.hpp>
#include <mapnik/value/types.hpp>
#include <mapnik/safe_cast.hpp>
#include "../test/cleanup.hpp"
// stl
#include <chrono>
#include <cmath> // log10, round
#include <cstdio> // snprintf
#include <iomanip>
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
namespace benchmark {
template<typename T>
using milliseconds = std::chrono::duration<T, std::milli>;
template<typename T>
using seconds = std::chrono::duration<T>;
class test_case
{
protected:
mapnik::parameters params_;
std::size_t threads_;
std::size_t iterations_;
public:
test_case(mapnik::parameters const& params)
: params_(params)
, threads_(mapnik::safe_cast<std::size_t>(*params.get<mapnik::value_integer>("threads", 0)))
, iterations_(mapnik::safe_cast<std::size_t>(*params.get<mapnik::value_integer>("iterations", 0)))
{}
std::size_t threads() const { return threads_; }
std::size_t iterations() const { return iterations_; }
mapnik::parameters const& params() const { return params_; }
virtual bool validate() const = 0;
virtual bool operator()() const = 0;
};
// gathers --long-option values in 'params';
// returns the index of the first non-option argument,
// or negated index of an ill-formed option argument
inline int parse_args(int argc, char** argv, mapnik::parameters& params)
{
for (int i = 1; i < argc; ++i)
{
const char* opt = argv[i];
if (opt[0] != '-')
{
// non-option argument, return its index
return i;
}
if (opt[1] != '-')
{
// we only accept --long-options, but instead of throwing,
// just issue a warning and let the caller decide what to do
std::clog << argv[0] << ": invalid option '" << opt << "'\n";
return -i; // negative means ill-formed option #i
}
if (opt[2] == '\0')
{
// option-list terminator '--'
return i + 1;
}
// take option name without the leading '--'
std::string key(opt + 2);
size_t eq = key.find('=');
if (eq != std::string::npos)
{
// one-argument form '--foo=bar'
params[key.substr(0, eq)] = key.substr(eq + 1);
}
else if (i + 1 < argc)
{
// two-argument form '--foo' 'bar'
params[key] = std::string(argv[++i]);
}
else
{
// missing second argument
std::clog << argv[0] << ": missing option '" << opt << "' value\n";
return -i; // negative means ill-formed option #i
}
}
return argc; // there were no non-option arguments
}
inline void handle_common_args(mapnik::parameters const& params)
{
if (auto severity = params.get<std::string>("log"))
{
if (*severity == "debug")
mapnik::logger::set_severity(mapnik::logger::debug);
else if (*severity == "warn")
mapnik::logger::set_severity(mapnik::logger::warn);
else if (*severity == "error")
mapnik::logger::set_severity(mapnik::logger::error);
else if (*severity == "none")
mapnik::logger::set_severity(mapnik::logger::none);
else
std::clog << "ignoring option --log='" << *severity << "' (allowed values are: debug, warn, error, none)\n";
}
}
inline int handle_args(int argc, char** argv, mapnik::parameters& params)
{
int res = parse_args(argc, argv, params);
handle_common_args(params);
return res;
}
#define BENCHMARK(test_class, name) \
int main(int argc, char** argv) \
{ \
mapnik::setup(); \
try \
{ \
mapnik::parameters params; \
benchmark::handle_args(argc, argv, params); \
test_class test_runner(params); \
auto result = run(test_runner, name); \
testing::run_cleanup(); \
return result; \
} \
catch (std::exception const& ex) \
{ \
std::clog << ex.what() << "\n"; \
testing::run_cleanup(); \
return -1; \
} \
}
struct big_number_fmt
{
int w;
double v;
const char* u;
big_number_fmt(int width, double value, int base = 1000)
: w(width)
, v(value)
, u("")
{
static const char* suffixes = "\0\0k\0M\0G\0T\0P\0E\0Z\0Y\0\0";
u = suffixes;
while (v > 1 && std::log10(std::round(v)) >= width && u[2])
{
v /= base;
u += 2;
}
// adjust width for proper alignment without suffix
w += (u == suffixes);
}
};
template<typename T>
int run(T const& test_runner, std::string const& name)
{
try
{
if (!test_runner.validate())
{
std::clog << "test did not validate: " << name << "\n";
return 1;
}
// run test once before timing
// if it returns false then we'll abort timing
if (!test_runner())
{
return 2;
}
std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::duration elapsed;
auto opt_min_duration = test_runner.params().template get<double>("min-duration", 0.0);
std::chrono::duration<double> min_seconds(*opt_min_duration);
auto min_duration = std::chrono::duration_cast<decltype(elapsed)>(min_seconds);
auto num_iters = test_runner.iterations();
auto num_threads = test_runner.threads();
auto total_iters = 0;
if (num_threads > 0)
{
std::mutex mtx_ready;
std::unique_lock<std::mutex> lock_ready(mtx_ready);
auto stub = [&](T const& test_copy) {
// workers will wait on this mutex until the main thread
// constructs all of them and starts measuring time
std::unique_lock<std::mutex> my_lock(mtx_ready);
my_lock.unlock();
test_copy();
};
std::vector<std::thread> tg;
tg.reserve(num_threads);
for (auto i = num_threads; i-- > 0;)
{
tg.emplace_back(stub, test_runner);
}
start = std::chrono::high_resolution_clock::now();
lock_ready.unlock();
// wait for all workers to finish
for (auto& t : tg)
{
if (t.joinable())
t.join();
}
elapsed = std::chrono::high_resolution_clock::now() - start;
// this is actually per-thread count, not total, but I think
// reporting average 'iters/thread/second' is more useful
// than 'iters/second' multiplied by the number of threads
total_iters += num_iters;
}
else
{
start = std::chrono::high_resolution_clock::now();
do
{
test_runner();
elapsed = std::chrono::high_resolution_clock::now() - start;
total_iters += num_iters;
} while (elapsed < min_duration);
}
char msg[200];
double dur_total = milliseconds<double>(elapsed).count();
auto elapsed_nonzero = std::max(elapsed, decltype(elapsed){1});
big_number_fmt itersf(4, total_iters);
big_number_fmt ips(5, total_iters / seconds<double>(elapsed_nonzero).count());
std::clog << std::left << std::setw(43) << name;
std::clog << std::resetiosflags(std::ios::adjustfield);
if (num_threads > 0)
{
std::clog << ' ' << std::setw(3) << num_threads << " worker" << (num_threads > 1 ? "s" : " ");
}
else
{
std::clog << " main thread";
}
std::snprintf(msg,
sizeof(msg),
" %*.0f%s iters %6.0f milliseconds %*.0f%s i/t/s\n",
itersf.w,
itersf.v,
itersf.u,
dur_total,
ips.w,
ips.v,
ips.u);
std::clog << msg;
return 0;
}
catch (std::exception const& ex)
{
std::clog << "test runner did not complete: " << ex.what() << "\n";
return 4;
}
}
struct sequencer
{
sequencer(int argc, char** argv)
: exit_code_(0)
{
benchmark::handle_args(argc, argv, params_);
}
int done() const { return exit_code_; }
template<typename Test, typename... Args>
sequencer& run(std::string const& name, Args&&... args)
{
// Test instance lifetime is confined to this function
Test test_runner(params_, std::forward<Args>(args)...);
// any failing test run will make exit code non-zero
exit_code_ |= benchmark::run(test_runner, name);
return *this; // allow chaining calls
}
protected:
mapnik::parameters params_;
int exit_code_;
};
} // namespace benchmark
#endif // MAPNIK_BENCH_FRAMEWORK_HPP

View file

@ -1,35 +0,0 @@
#ifndef MAPNIK_COMPARE_IMAGES_HPP
#define MAPNIK_COMPARE_IMAGES_HPP
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_reader.hpp>
namespace benchmark {
bool compare_images(std::string const& src_fn, std::string const& dest_fn)
{
std::unique_ptr<mapnik::image_reader> reader1(mapnik::get_image_reader(dest_fn, "png"));
if (!reader1.get())
{
throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
}
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn, "png"));
if (!reader2.get())
{
throw mapnik::image_reader_exception("Failed to load: " + src_fn);
}
const mapnik::image_any desc_any = reader1->read(0, 0, reader1->width(), reader1->height());
const mapnik::image_any src_any = reader2->read(0, 0, reader2->width(), reader2->height());
mapnik::image_rgba8 const& dest = mapnik::util::get<mapnik::image_rgba8>(desc_any);
mapnik::image_rgba8 const& src = mapnik::util::get<mapnik::image_rgba8>(src_any);
return compare(dest, src, 0, true) == 0;
}
} // namespace benchmark
#endif // MAPNIK_COMPARE_IMAGES_HPP

View file

@ -6,32 +6,21 @@ source ./localize.sh
BASE=./benchmark/out
function run {
local runner="$BASE/$1 --log=none"
local threads="$2"
local iters="$3"
shift 3
$runner --threads 0 --iterations $iters "$@"
if test $threads -gt 0; then
$runner --threads $threads --iterations $((iters/threads)) "$@"
fi
${BASE}/$1 --threads 0 --iterations $3;
${BASE}/$1 --threads $2 --iterations $(expr $3 / $2);
}
run test_getline 30 10000000
#run test_array_allocation 20 100000
#run test_png_encoding1 10 1000
#run test_png_encoding2 10 50
#run test_to_string1 10 100000
#run test_to_string2 10 100000
#run test_polygon_clipping 10 1000
#run test_polygon_clipping_rendering 10 100
run test_array_allocation 20 100000
run test_png_encoding1 10 1000
run test_png_encoding2 10 50
run test_to_string1 10 100000
run test_to_string2 10 100000
run test_proj_transform1 10 100
run test_expression_parse 10 10000
run test_face_ptr_creation 10 1000
run test_font_registration 10 100
run test_offset_converter 10 1000
#run normalize_angle 0 1000000 --min-duration=0.2
run test_face_ptr_creation 10 10000
run test_polygon_clipping 10 1000
run test_polygon_clipping_rendering 10 100
# commented since this is really slow on travis
: '
./benchmark/out/test_rendering \
--name "text rendering" \
--map benchmark/data/roads.xml \
@ -39,31 +28,4 @@ run test_offset_converter 10 1000
--width 600 \
--height 600 \
--iterations 20 \
--threads 10
'
./benchmark/out/test_rendering \
--name "gdal tiff rendering" \
--map benchmark/data/gdal-wgs.xml \
--extent -180.0,-120.0,180.0,120.0 \
--width 600 \
--height 600 \
--iterations 20 \
--threads 10
./benchmark/out/test_rendering \
--name "raster tiff rendering" \
--map benchmark/data/raster-wgs.xml \
--extent -180.0,-120.0,180.0,120.0 \
--width 600 \
--height 600 \
--iterations 20 \
--threads 10
./benchmark/out/test_quad_tree \
--iterations 10000 \
--threads 1
./benchmark/out/test_quad_tree \
--iterations 1000 \
--threads 10
--threads 10

View file

@ -1,65 +0,0 @@
#!/bin/bash
BASE=.
function run {
local runner="$BASE/$1 --log=none"
local threads="$2"
local iters="$3"
shift 3
$runner --threads 0 --iterations $iters "$@"
if test $threads -gt 0; then
$runner --threads $threads --iterations $((iters/threads)) "$@"
fi
}
run test_getline 30 10000000
#run test_array_allocation 20 100000
#run test_png_encoding1 10 1000
#run test_png_encoding2 10 50
#run test_to_string1 10 100000
#run test_to_string2 10 100000
#run test_polygon_clipping 10 1000
#run test_polygon_clipping_rendering 10 100
run test_proj_transform1 10 100
run test_expression_parse 10 10000
run test_face_ptr_creation 10 1000
run test_font_registration 10 100
run test_offset_converter 10 1000
#run normalize_angle 0 1000000 --min-duration=0.2
# commented since this is really slow on travis
: '
$BASE/test_rendering \
--name "text rendering" \
--map benchmark/data/roads.xml \
--extent 1477001.12245,6890242.37746,1480004.49012,6892244.62256 \
--width 600 \
--height 600 \
--iterations 20 \
--threads 10
'
$BASE/test_rendering \
--name "gdal tiff rendering" \
--map benchmark/data/gdal-wgs.xml \
--extent -180.0,-120.0,180.0,120.0 \
--width 600 \
--height 600 \
--iterations 20 \
--threads 10
$BASE/test_rendering \
--name "raster tiff rendering" \
--map benchmark/data/raster-wgs.xml \
--extent -180.0,-120.0,180.0,120.0 \
--width 600 \
--height 600 \
--iterations 20 \
--threads 10
$BASE/test_quad_tree \
--iterations 10000 \
--threads 1
$BASE/test_quad_tree \
--iterations 1000 \
--threads 10

View file

@ -1,72 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/util/math.hpp>
template<typename T>
struct bench_func : benchmark::test_case
{
T (*const func_)(T);
T const value_;
bench_func(mapnik::parameters const& params, T (*func)(T), T value)
: test_case(params)
, func_(func)
, value_(value)
{}
bool validate() const { return true; }
bool operator()() const
{
for (auto i = this->iterations_; i-- > 0;)
{
func_(value_);
}
return true;
}
};
#define BENCH_FUNC1(func, value) run<bench_func<double>>(#func "(" #value ")", func, value)
int main(int argc, char** argv)
{
mapnik::setup();
return benchmark::sequencer(argc, argv)
.BENCH_FUNC1(mapnik::util::normalize_angle, +3)
.BENCH_FUNC1(mapnik::util::normalize_angle, +6)
.BENCH_FUNC1(mapnik::util::normalize_angle, +9)
.BENCH_FUNC1(mapnik::util::normalize_angle, +12)
.BENCH_FUNC1(mapnik::util::normalize_angle, +15)
.BENCH_FUNC1(mapnik::util::normalize_angle, +20)
.BENCH_FUNC1(mapnik::util::normalize_angle, +30)
.BENCH_FUNC1(mapnik::util::normalize_angle, +40)
.BENCH_FUNC1(mapnik::util::normalize_angle, +50)
.BENCH_FUNC1(mapnik::util::normalize_angle, +70)
.BENCH_FUNC1(mapnik::util::normalize_angle, +90)
.BENCH_FUNC1(mapnik::util::normalize_angle, +110)
.BENCH_FUNC1(mapnik::util::normalize_angle, +130)
.BENCH_FUNC1(mapnik::util::normalize_angle, +157)
.BENCH_FUNC1(mapnik::util::normalize_angle, +209)
.BENCH_FUNC1(mapnik::util::normalize_angle, +314)
.BENCH_FUNC1(mapnik::util::normalize_angle, +628)
.BENCH_FUNC1(mapnik::util::normalize_angle, +942)
.BENCH_FUNC1(mapnik::util::normalize_angle, -3)
.BENCH_FUNC1(mapnik::util::normalize_angle, -6)
.BENCH_FUNC1(mapnik::util::normalize_angle, -9)
.BENCH_FUNC1(mapnik::util::normalize_angle, -12)
.BENCH_FUNC1(mapnik::util::normalize_angle, -15)
.BENCH_FUNC1(mapnik::util::normalize_angle, -20)
.BENCH_FUNC1(mapnik::util::normalize_angle, -30)
.BENCH_FUNC1(mapnik::util::normalize_angle, -40)
.BENCH_FUNC1(mapnik::util::normalize_angle, -50)
.BENCH_FUNC1(mapnik::util::normalize_angle, -70)
.BENCH_FUNC1(mapnik::util::normalize_angle, -90)
.BENCH_FUNC1(mapnik::util::normalize_angle, -110)
.BENCH_FUNC1(mapnik::util::normalize_angle, -130)
.BENCH_FUNC1(mapnik::util::normalize_angle, -157)
.BENCH_FUNC1(mapnik::util::normalize_angle, -209)
.BENCH_FUNC1(mapnik::util::normalize_angle, -314)
.BENCH_FUNC1(mapnik::util::normalize_angle, -628)
.BENCH_FUNC1(mapnik::util::normalize_angle, -942)
.done();
}

View file

@ -1,370 +0,0 @@
#include "bench_framework.hpp"
#include <cstring>
#include <cstdlib>
#include <deque>
#include <stdexcept>
#include <array>
#include <valarray>
#include <boost/version.hpp>
#if BOOST_VERSION >= 105400
#include <boost/container/static_vector.hpp>
#endif
// http://stackoverflow.com/questions/17347254/why-is-allocation-and-deallocation-of-stdvector-slower-than-dynamic-array-on-m
#define FULL_ZERO_CHECK
inline void ensure_zero(uint8_t* data, uint32_t size)
{
#ifdef FULL_ZERO_CHECK
for (std::size_t i = 0; i < size; ++i)
{
if (data[i] != 0)
{
throw std::runtime_error("found non zero value");
}
}
#else
if (data[0] != 0)
{
throw std::runtime_error("found non zero value");
}
#endif
}
class test1 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test1(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
// NOTE: sizeof(uint8_t) == 1
uint8_t* data = (uint8_t*)malloc(sizeof(uint8_t) * size_);
memcpy(data, &array_[0], size_);
ensure_zero(data, size_);
free(data);
}
return true;
}
};
class test1b : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test1b(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
// NOTE: sizeof(uint8_t) == 1
uint8_t* data = (uint8_t*)malloc(sizeof(uint8_t) * size_);
memset(data, 0, sizeof(uint8_t) * size_);
ensure_zero(data, size_);
free(data);
}
return true;
}
};
class test1c : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test1c(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
uint8_t* data = static_cast<uint8_t*>(::operator new(sizeof(uint8_t) * size_));
std::fill(data, data + size_, 0);
ensure_zero(data, size_);
::operator delete(data);
}
return true;
}
};
class test2 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test2(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
uint8_t* data = static_cast<uint8_t*>(::operator new(sizeof(uint8_t) * size_));
memcpy(data, &array_[0], size_);
ensure_zero(data, size_);
::operator delete(data), data = 0;
}
return true;
}
};
class test3 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::vector<uint8_t> data(size_);
ensure_zero(&data[0], data.size());
}
return true;
}
};
class test3b : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3b(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::vector<uint8_t> data(0);
data.resize(size_, 0);
ensure_zero(&data[0], data.size());
}
return true;
}
};
class test3c : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3c(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::vector<uint8_t> data(0);
data.assign(size_, 0);
ensure_zero(&data[0], data.size());
}
return true;
}
};
class test3d : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3d(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::deque<uint8_t> data(size_);
for (std::size_t i = 0; i < size_; ++i)
{
if (data[i] != 0)
{
throw std::runtime_error("found non zero value");
}
}
}
return true;
}
};
class test4 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test4(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
uint8_t* data = (uint8_t*)calloc(size_, sizeof(uint8_t));
ensure_zero(data, size_);
free(data);
}
return true;
}
};
class test5 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test5(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::string data(array_.begin(), array_.end());
ensure_zero((uint8_t*)&data[0], size_);
}
return true;
}
};
class test5b : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<char> array_;
test5b(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::string data(&array_[0], array_.size());
ensure_zero((uint8_t*)&data[0], size_);
}
return true;
}
};
// C++14 dynarray<T>
// http://isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meeting
// http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130909/088700.html
// http://stackoverflow.com/questions/17303902/any-alternative-to-stddynarray-presently-available
class test6 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test6(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
std::valarray<uint8_t> data(static_cast<uint8_t>(0), static_cast<size_t>(size_));
ensure_zero(&data[0], size_);
}
return true;
}
};
#if BOOST_VERSION >= 105400
// http://i42.co.uk/stuff/vecarray.htm
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost/container/static_vector.html
class test7 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test7(mapnik::parameters const& params)
: test_case(params)
, size_(*params.get<mapnik::value_integer>("size", 256 * 256))
, array_(size_, 0)
{}
bool validate() const { return true; }
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
boost::container::static_vector<uint8_t, 256 * 256> data(size_, 0);
ensure_zero(&data[0], size_);
}
return true;
}
};
#endif
int main(int argc, char** argv)
{
mapnik::setup();
return benchmark::sequencer(argc, argv)
.run<test4>("calloc")
.run<test1>("malloc/memcpy")
.run<test1b>("malloc/memset")
.run<test1c>("operator new/std::fill")
.run<test2>("operator new/memcpy")
.run<test3>("vector(N)")
.run<test3b>("vector/resize")
.run<test3c>("vector/assign")
.run<test3d>("deque(N)")
.run<test5>("std::string range")
.run<test5b>("std::string &[0]")
.run<test6>("valarray")
#if BOOST_VERSION >= 105400
.run<test7>("static_vector")
#endif
.done();
}

View file

@ -1,44 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/unicode.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
class test : public benchmark::test_case
{
std::string expr_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, expr_("((([mapnik::geometry_type]=2) and ([oneway]=1)) and ([class]='path'))")
{}
bool validate() const
{
mapnik::expression_ptr expr = mapnik::parse_expression(expr_);
std::string result = mapnik::to_expression_string(*expr);
bool ret = (result == expr_);
if (!ret)
{
std::clog << result << " != " << expr_ << "\n";
}
return ret;
}
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
mapnik::expression_ptr expr = mapnik::parse_expression(expr_);
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
test test_runner(params);
return run(test_runner, "expr parsing");
}

View file

@ -1,74 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/font_engine_freetype.hpp>
#include <boost/format.hpp>
class test : public benchmark::test_case
{
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const
{
std::size_t count = 0;
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
mapnik::freetype_engine::font_memory_cache_type font_cache;
mapnik::font_library library;
for (std::string const& name : mapnik::freetype_engine::face_names())
{
mapnik::face_ptr f = mapnik::freetype_engine::create_face(name,
library,
font_file_mapping,
font_cache,
mapnik::freetype_engine::get_mapping(),
mapnik::freetype_engine::get_cache());
if (f)
++count;
}
return count == expected_count;
}
bool operator()() const
{
std::size_t expected_count = mapnik::freetype_engine::face_names().size();
for (unsigned i = 0; i < iterations_; ++i)
{
std::size_t count = 0;
mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
mapnik::freetype_engine::font_memory_cache_type font_cache;
mapnik::font_library library;
for (std::string const& name : mapnik::freetype_engine::face_names())
{
mapnik::face_ptr f = mapnik::freetype_engine::create_face(name,
library,
font_file_mapping,
font_cache,
mapnik::freetype_engine::get_mapping(),
mapnik::freetype_engine::get_cache());
if (f)
++count;
}
if (count != expected_count)
{
std::clog << "warning: face creation not working as expected\n";
}
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
bool success = mapnik::freetype_engine::register_fonts("./fonts", true);
if (!success)
{
std::clog << "warning, did not register any new fonts!\n";
return -1;
}
std::size_t face_count = mapnik::freetype_engine::face_names().size();
test test_runner(params);
return run(test_runner, (boost::format("font_engine: creating %ld faces") % (face_count)).str());
}

View file

@ -1,24 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/font_engine_freetype.hpp>
#include <boost/format.hpp>
class test : public benchmark::test_case
{
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return mapnik::freetype_engine::register_fonts("./fonts", true); }
bool operator()() const
{
unsigned long count = 0;
for (unsigned i = 0; i < iterations_; ++i)
{
mapnik::freetype_engine::register_fonts("./fonts", true);
count++;
}
return true;
}
};
BENCHMARK(test, "font registration")

View file

@ -1,125 +0,0 @@
#include "bench_framework.hpp"
#include "../plugins/input/csv/csv_getline.hpp"
class test : public benchmark::test_case
{
public:
std::string line_data_;
test(mapnik::parameters const& params)
: test_case(params)
, line_data_("this is one line\nand this is a second line\nand a third line")
{
auto line_data = params.get<std::string>("line");
if (line_data)
{
line_data_ = *line_data;
}
}
bool validate() const
{
std::string first = line_data_.substr(line_data_.find_first_not_of('\n'));
char newline = '\n';
std::string csv_line;
std::stringstream s;
s << line_data_;
std::getline(s, csv_line, newline);
if (csv_line != first)
{
return true;
}
else
{
std::clog << "Error: the parsed line (" << csv_line << ") should be a subset of the original line ("
<< line_data_ << ") (ensure you pass a line with a \\n)\n";
}
return true;
}
bool operator()() const
{
char newline = '\n';
std::string csv_line;
std::stringstream s;
s << line_data_;
for (unsigned i = 0; i < iterations_; ++i)
{
std::getline(s, csv_line, newline);
}
return true;
}
};
class test2 : public benchmark::test_case
{
public:
std::string line_data_;
test2(mapnik::parameters const& params)
: test_case(params)
, line_data_("this is one line\nand this is a second line\nand a third line")
{
auto line_data = params.get<std::string>("line");
if (line_data)
{
line_data_ = *line_data;
}
}
bool validate() const
{
std::string first = line_data_.substr(line_data_.find_first_not_of('\n'));
char newline = '\n';
char quote = '"';
std::string csv_line;
std::stringstream s;
s << line_data_;
csv_utils::getline_csv(s, csv_line, newline, quote);
if (csv_line != first)
{
return true;
}
else
{
std::clog << "Error: the parsed line (" << csv_line << ") should be a subset of the original line ("
<< line_data_ << ") (ensure you pass a line with a \\n)\n";
}
return true;
}
bool operator()() const
{
char newline = '\n';
char quote = '"';
std::string csv_line;
std::stringstream s;
s << line_data_;
for (unsigned i = 0; i < iterations_; ++i)
{
csv_utils::getline_csv(s, csv_line, newline, quote);
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
int return_value = 0;
try
{
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
{
test test_runner(params);
return_value = return_value | run(test_runner, "std::getline");
}
{
test2 test_runner2(params);
return_value = return_value | run(test_runner2, "csv_utils::getline_csv");
}
}
catch (std::exception const& ex)
{
std::clog << ex.what() << "\n";
return -1;
}
return return_value;
}

View file

@ -1,40 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/marker_cache.hpp>
class test : public benchmark::test_case
{
std::vector<std::string> images_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, images_{"./test/data/images/dummy.jpg",
"./test/data/images/dummy.jpeg",
"./test/data/images/dummy.png",
"./test/data/images/dummy.tif",
"./test/data/images/dummy.tiff",
//"./test/data/images/landusepattern.jpeg", // will fail since it is a png
//"./test/data/images/xcode-CgBI.png", // will fail since its an invalid png
"./test/data/svg/octocat.svg",
"./test/data/svg/place-of-worship-24.svg",
"./test/data/svg/point_sm.svg",
"./test/data/svg/point.svg",
"./test/data/svg/airfield-12.svg"}
{}
bool validate() const { return true; }
bool operator()() const
{
unsigned count = 0;
for (std::size_t i = 0; i < iterations_; ++i)
{
for (auto filename : images_)
{
auto marker = mapnik::marker_cache::instance().find(filename, true);
}
++count;
}
return (count == iterations_);
}
};
BENCHMARK(test, "marker cache")

View file

@ -1,51 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <stdexcept>
#include <mapnik/layer.hpp>
#include <mapnik/memory_datasource.hpp>
#include <mapnik/feature_type_style.hpp>
#include <memory>
class test : public benchmark::test_case
{
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return true; }
bool operator()() const
{
mapnik::Map m(256, 256, "epsg:3857");
mapnik::parameters params;
params["type"] = "memory";
auto ds = std::make_shared<mapnik::memory_datasource>(params);
// add whitespace to trigger phony "reprojection"
mapnik::layer lay("layer", m.srs() + " ");
lay.set_datasource(ds);
lay.add_style("style");
m.add_layer(lay);
// dummy style to ensure that layer is processed
m.insert_style("style", mapnik::feature_type_style());
// dummy bbox, but "valid" because minx and miny are less
// with an invalid bbox then layer.visible() returns false
// and the initial rendering setup is not run
m.zoom_to_box(mapnik::box2d<double>(-1, -1, 0, 0));
for (unsigned i = 0; i < iterations_; ++i)
{
mapnik::image_rgba8 im(256, 256);
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
ren.apply();
}
return true;
}
};
BENCHMARK(test, "rendering with reprojection")

View file

@ -1,81 +0,0 @@
#include "bench_framework.hpp"
// boost
#include <boost/numeric/conversion/cast.hpp>
static double STEP_NUM = 0.0000000001;
static std::uint8_t START_NUM = 2;
class test_static : public benchmark::test_case
{
double step_;
std::uint8_t start_;
public:
test_static(mapnik::parameters const& params)
: test_case(params)
, step_(STEP_NUM)
, start_(START_NUM)
{}
bool validate() const { return true; }
bool operator()() const
{
double value_ = 0.0;
std::uint8_t x;
for (std::size_t i = 0; i < iterations_; ++i)
{
double c = static_cast<double>(start_) * value_;
if (c >= 256.0)
c = 255.0;
if (c < 0.0)
c = 0.0;
x = static_cast<std::uint8_t>(c);
value_ += step_;
}
return static_cast<double>(x) < (static_cast<double>(start_) * value_);
}
};
using boost::numeric::negative_overflow;
using boost::numeric::positive_overflow;
class test_numeric : public benchmark::test_case
{
double step_;
std::uint8_t start_;
public:
test_numeric(mapnik::parameters const& params)
: test_case(params)
, step_(STEP_NUM)
, start_(START_NUM)
{}
bool validate() const { return true; }
bool operator()() const
{
double value_ = 0.0;
std::uint8_t x;
for (std::size_t i = 0; i < iterations_; ++i)
{
try
{
x = boost::numeric_cast<std::uint8_t>(start_ * value_);
}
catch (negative_overflow&)
{
x = std::numeric_limits<std::uint8_t>::min();
}
catch (positive_overflow&)
{
x = std::numeric_limits<std::uint8_t>::max();
}
value_ += step_;
}
return static_cast<double>(x) < (static_cast<double>(start_) * value_);
}
};
int main(int argc, char** argv)
{
mapnik::setup();
return benchmark::sequencer(argc, argv).run<test_static>("static_cast").run<test_numeric>("numeric_cast").done();
}

View file

@ -1,104 +0,0 @@
#include "bench_framework.hpp"
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/offset_converter.hpp>
struct fake_path
{
using coord_type = std::tuple<double, double, unsigned>;
using cont_type = std::vector<coord_type>;
cont_type vertices_;
cont_type::iterator itr_;
fake_path(std::initializer_list<double> l)
: fake_path(l.begin(), l.size())
{}
fake_path(std::vector<double> const& v)
: fake_path(v.begin(), v.size())
{}
template<typename Itr>
fake_path(Itr itr, size_t sz)
{
size_t num_coords = sz >> 1;
vertices_.reserve(num_coords);
for (size_t i = 0; i < num_coords; ++i)
{
double x = *itr++;
double y = *itr++;
unsigned cmd = (i == 0) ? mapnik::SEG_MOVETO : mapnik::SEG_LINETO;
vertices_.push_back(std::make_tuple(x, y, cmd));
if (i == num_coords - 1)
cmd = mapnik::SEG_END;
vertices_.push_back(std::make_tuple(x, y, cmd));
}
itr_ = vertices_.begin();
}
unsigned vertex(double* x, double* y)
{
if (itr_ == vertices_.end())
{
return mapnik::SEG_END;
}
*x = std::get<0>(*itr_);
*y = std::get<1>(*itr_);
unsigned cmd = std::get<2>(*itr_);
++itr_;
return cmd;
}
void rewind(unsigned) { itr_ = vertices_.begin(); }
};
class test_offset : public benchmark::test_case
{
public:
test_offset(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return true; }
bool operator()() const
{
std::vector<double> path;
int mysize = 2500;
int x1 = 0;
path.reserve(mysize * 2);
for (int i = 0; i < mysize; i++)
{
path.push_back(i);
path.push_back(0);
}
fake_path fpath(path);
for (std::size_t i = 0; i < iterations_; ++i)
{
mapnik::offset_converter<fake_path> off_path(fpath);
off_path.set_offset(10);
unsigned cmd;
double x, y;
while ((cmd = off_path.vertex(&x, &y)) != mapnik::SEG_END)
{
x1++;
}
}
return x1 > 0;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
int return_value = 0;
{
test_offset test_runner(params);
return_value = run(test_runner, "offset_test");
}
return return_value;
}

View file

@ -1,26 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/image_util.hpp>
class test : public benchmark::test_case
{
mapnik::image_rgba8 im_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, im_(256, 256)
{}
bool validate() const { return true; }
bool operator()() const
{
std::string out;
for (std::size_t i = 0; i < iterations_; ++i)
{
out.clear();
out = mapnik::save_to_string(im_, "png8:m=h:z=1");
}
return true;
}
};
BENCHMARK(test, "encoding blank png")

View file

@ -1,41 +0,0 @@
#include "bench_framework.hpp"
#include "compare_images.hpp"
#include <memory>
class test : public benchmark::test_case
{
std::shared_ptr<mapnik::image_rgba8> im_;
public:
test(mapnik::parameters const& params)
: test_case(params)
{
std::string filename("./benchmark/data/multicolor.png");
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, "png"));
if (!reader.get())
{
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
im_ = std::make_shared<mapnik::image_rgba8>(reader->width(), reader->height());
reader->read(0, 0, *im_);
}
bool validate() const
{
std::string expected("./benchmark/data/multicolor-hextree-expected.png");
std::string actual("./benchmark/data/multicolor-hextree-actual.png");
mapnik::save_to_file(*im_, actual, "png8:m=h:z=1");
return benchmark::compare_images(actual, expected);
}
bool operator()() const
{
std::string out;
for (std::size_t i = 0; i < iterations_; ++i)
{
out.clear();
out = mapnik::save_to_string(*im_, "png8:m=h:z=1");
}
return true;
}
};
BENCHMARK(test, "encoding multicolor png")

View file

@ -1,550 +0,0 @@
#include "bench_framework.hpp"
#include "compare_images.hpp"
#include <mapnik/vertex.hpp>
#include <mapnik/transform_path_adapter.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/util/fs.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/vertex_adapters.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geometry/boost_adapters.hpp>
#include <mapnik/geometry/envelope.hpp>
#include <mapnik/geometry/correct.hpp>
#include <mapnik/geometry/is_empty.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/color.hpp>
// boost geometry
#include <boost/geometry.hpp>
// agg
#include "agg_conv_clip_polygon.h"
// clipper
#include "agg_path_storage.h"
// rendering
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
// stl
#include <fstream>
#include <iostream>
#include <cstdlib>
void render(mapnik::geometry::multi_polygon<double> const& geom,
mapnik::box2d<double> const& extent,
std::string const& name)
{
using path_type =
mapnik::transform_path_adapter<mapnik::view_transform, mapnik::geometry::polygon_vertex_adapter<double>>;
using ren_base = agg::renderer_base<agg::pixfmt_rgba32_plain>;
using renderer = agg::renderer_scanline_aa_solid<ren_base>;
mapnik::image_rgba8 im(256, 256);
mapnik::fill(im, mapnik::color("white"));
mapnik::box2d<double> padded_extent(155, 134, 665, 466); // extent;
padded_extent.pad(10);
mapnik::view_transform tr(im.width(), im.height(), padded_extent, 0, 0);
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
agg::pixfmt_rgba32_plain pixf(buf);
ren_base renb(pixf);
renderer ren(renb);
mapnik::proj_transform prj_trans(mapnik::projection("epsg:4326"), mapnik::projection("epsg:4326"));
ren.color(agg::rgba8(127, 127, 127, 255));
agg::rasterizer_scanline_aa<> ras;
for (auto const& poly : geom)
{
mapnik::geometry::polygon_vertex_adapter<double> va(poly);
path_type path(tr, va, prj_trans);
ras.add_path(path);
}
agg::scanline_u8 sl;
agg::render_scanlines(ras, sl, ren);
mapnik::save_to_file(im, name);
}
class test1 : public benchmark::test_case
{
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
using conv_clip = agg::conv_clip_polygon<mapnik::geometry::polygon_vertex_adapter<double>>;
test1(mapnik::parameters const& params, std::string const& wkt_in, mapnik::box2d<double> const& extent)
: test_case(params)
, wkt_in_(wkt_in)
, extent_(extent)
, expected_("./benchmark/data/polygon_clipping_agg")
{}
bool validate() const
{
mapnik::geometry::geometry<double> geom;
if (!mapnik::from_wkt(wkt_in_, geom))
{
throw std::runtime_error("Failed to parse WKT");
}
if (mapnik::geometry::is_empty(geom))
{
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double>>())
{
std::clog << "not a polygon!\n";
return false;
}
mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
mapnik::geometry::polygon_vertex_adapter<double> va(poly);
conv_clip clipped(va);
clipped.clip_box(extent_.minx(), extent_.miny(), extent_.maxx(), extent_.maxy());
clipped.rewind(0);
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring;
// exterior ring
unsigned cmd;
double x, y, x0, y0;
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
{
if (cmd == mapnik::SEG_MOVETO)
{
x0 = x;
y0 = y;
}
if (cmd == mapnik::SEG_CLOSE)
{
ring.emplace_back(x0, y0);
break;
}
ring.emplace_back(x, y);
}
poly2.push_back(std::move(ring));
// interior rings
ring.clear();
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
{
if (cmd == mapnik::SEG_MOVETO)
{
x0 = x;
y0 = y;
}
else if (cmd == mapnik::SEG_CLOSE)
{
ring.emplace_back(x0, y0);
poly2.push_back(std::move(ring));
ring.clear();
continue;
}
ring.emplace_back(x, y);
}
std::string expect = expected_ + ".png";
std::string actual = expected_ + "_actual.png";
mapnik::geometry::multi_polygon<double> mp;
mp.emplace_back(poly2);
auto env = mapnik::geometry::envelope(mp);
if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
{
std::clog << "generating expected image: " << expect << "\n";
render(mp, env, expect);
}
render(mp, env, actual);
return benchmark::compare_images(actual, expect);
}
bool operator()() const
{
mapnik::geometry::geometry<double> geom;
if (!mapnik::from_wkt(wkt_in_, geom))
{
throw std::runtime_error("Failed to parse WKT");
}
if (mapnik::geometry::is_empty(geom))
{
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double>>())
{
std::clog << "not a polygon!\n";
return false;
}
bool valid = true;
for (unsigned i = 0; i < iterations_; ++i)
{
unsigned count = 0;
mapnik::geometry::polygon<double> const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
mapnik::geometry::polygon_vertex_adapter<double> va(poly);
conv_clip clipped(va);
clipped.clip_box(extent_.minx(), extent_.miny(), extent_.maxx(), extent_.maxy());
unsigned cmd;
double x, y;
// NOTE: this rewind is critical otherwise
// agg_conv_adapter_vpgen will give garbage
// values for the first vertex
clipped.rewind(0);
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END)
{
count++;
}
unsigned expected_count = 30;
if (count != expected_count)
{
std::clog << "test1: clipping failed: processed " << count << " verticies but expected "
<< expected_count << "\n";
valid = false;
}
}
return valid;
}
};
class test3 : public benchmark::test_case
{
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
test3(mapnik::parameters const& params, std::string const& wkt_in, mapnik::box2d<double> const& extent)
: test_case(params)
, wkt_in_(wkt_in)
, extent_(extent)
, expected_("./benchmark/data/polygon_clipping_boost")
{}
bool validate() const
{
mapnik::geometry::geometry<double> geom;
if (!mapnik::from_wkt(wkt_in_, geom))
{
throw std::runtime_error("Failed to parse WKT");
}
if (mapnik::geometry::is_empty(geom))
{
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double>>())
{
std::clog << "not a polygon!\n";
return false;
}
mapnik::geometry::polygon<double>& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
mapnik::geometry::correct(poly);
mapnik::geometry::linear_ring<double> bbox;
bbox.emplace_back(extent_.minx(), extent_.miny());
bbox.emplace_back(extent_.minx(), extent_.maxy());
bbox.emplace_back(extent_.maxx(), extent_.maxy());
bbox.emplace_back(extent_.maxx(), extent_.miny());
bbox.emplace_back(extent_.minx(), extent_.miny());
std::deque<mapnik::geometry::polygon<double>> result;
boost::geometry::intersection(bbox, poly, result);
std::string expect = expected_ + ".png";
std::string actual = expected_ + "_actual.png";
mapnik::geometry::multi_polygon<double> mp;
for (auto const& _geom : result)
{
// std::clog << boost::geometry::dsv(geom) << "\n";
mp.emplace_back(_geom);
}
mapnik::geometry::geometry<double> geom2(mp);
auto env = mapnik::geometry::envelope(geom2);
if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
{
std::clog << "generating expected image: " << expect << "\n";
render(mp, env, expect);
}
render(mp, env, actual);
return benchmark::compare_images(actual, expect);
}
bool operator()() const
{
mapnik::geometry::geometry<double> geom;
if (!mapnik::from_wkt(wkt_in_, geom))
{
throw std::runtime_error("Failed to parse WKT");
}
if (mapnik::geometry::is_empty(geom))
{
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double>>())
{
std::clog << "not a polygon!\n";
return false;
}
mapnik::geometry::polygon<double>& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geom);
mapnik::geometry::correct(poly);
mapnik::geometry::linear_ring<double> bbox;
bbox.emplace_back(extent_.minx(), extent_.miny());
bbox.emplace_back(extent_.minx(), extent_.maxy());
bbox.emplace_back(extent_.maxx(), extent_.maxy());
bbox.emplace_back(extent_.maxx(), extent_.miny());
bbox.emplace_back(extent_.minx(), extent_.miny());
bool valid = true;
for (unsigned i = 0; i < iterations_; ++i)
{
std::deque<mapnik::geometry::polygon<double>> result;
boost::geometry::intersection(bbox, poly, result);
unsigned count = 0;
for (auto const& _geom : result)
{
mapnik::geometry::polygon_vertex_adapter<double> va(_geom);
unsigned cmd;
double x, y;
while ((cmd = va.vertex(&x, &y)) != mapnik::SEG_END)
{
++count;
}
unsigned expected_count = 29;
if (count != expected_count)
{
std::clog << "test3: clipping failed: processed " << count << " verticies but expected "
<< expected_count << "\n";
valid = false;
}
}
}
return valid;
}
};
/*
Commented out section because clipper moved out of mapnik core.
inline void process_polynode_branch(ClipperLib::PolyNode* polynode,
mapnik::geometry::multi_polygon<double> & mp)
{
mapnik::geometry::polygon<double> polygon;
mapnik::geometry::linear_ring<double> outer;
for (auto const& pt : polynode->Contour)
{
outer.emplace_back(static_cast<double>(pt.x),static_cast<double>(pt.y));
}
if (outer.front() != outer.back())
{
outer.emplace_back(outer.front().x, outer.front().y);
}
polygon.set_exterior_ring(std::move(outer));
for (auto * ring : polynode->Childs)
{
mapnik::geometry::linear_ring<double> inner;
for (auto const& pt : ring->Contour)
{
inner.emplace_back(static_cast<double>(pt.x),static_cast<double>(pt.y));
}
if (inner.front() != inner.back())
{
inner.emplace_back(inner.front().x, inner.front().y);
}
polygon.add_hole(std::move(inner));
}
mp.emplace_back(std::move(polygon));
for (auto * ring : polynode->Childs)
{
for (auto * sub_ring : ring->Childs)
{
process_polynode_branch(sub_ring, mp);
}
}
}
class test4 : public benchmark::test_case
{
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
test4(mapnik::parameters const& params,
std::string const& wkt_in,
mapnik::box2d<double> const& extent)
: test_case(params),
wkt_in_(wkt_in),
extent_(extent),
expected_("./benchmark/data/polygon_clipping_clipper") {}
bool validate() const
{
mapnik::geometry::geometry<double> geom;
if (!mapnik::from_wkt(wkt_in_, geom))
{
throw std::runtime_error("Failed to parse WKT");
}
if (mapnik::geometry::is_empty(geom))
{
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double> >())
{
std::clog << "not a polygon!\n";
return false;
}
mapnik::geometry::polygon<double> & poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geom);
mapnik::geometry::correct(poly);
ClipperLib::Clipper clipper;
mapnik::geometry::line_string<std::int64_t> path;
for (auto const& pt : poly.exterior_ring)
{
double x = pt.x;
double y = pt.y;
path.emplace_back(static_cast<ClipperLib::cInt>(x),static_cast<ClipperLib::cInt>(y));
}
double area = ClipperLib::Area(path);
if (area > 0)
{
std::reverse(path.begin(), path.end());
}
if (!clipper.AddPath(path, ClipperLib::ptSubject, true))
{
std::clog << "ptSubject ext failed!\n";
}
for (auto const& ring : poly.interior_rings)
{
path.clear();
for (auto const& pt : ring)
{
double x = pt.x;
double y = pt.y;
path.emplace_back(static_cast<ClipperLib::cInt>(x),static_cast<ClipperLib::cInt>(y));
}
area = ClipperLib::Area(path);
if (area < 0)
{
std::reverse(path.begin(), path.end());
}
if (!clipper.AddPath(path, ClipperLib::ptSubject, true))
{
std::clog << "ptSubject ext failed!\n";
}
}
std::cerr << "path size=" << path.size() << std::endl;
mapnik::geometry::line_string<std::int64_t> clip_box;
clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.minx()),static_cast<ClipperLib::cInt>(extent_.miny()));
clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.maxx()),static_cast<ClipperLib::cInt>(extent_.miny()));
clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.maxx()),static_cast<ClipperLib::cInt>(extent_.maxy()));
clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.minx()),static_cast<ClipperLib::cInt>(extent_.maxy()));
clip_box.emplace_back(static_cast<ClipperLib::cInt>(extent_.minx()),static_cast<ClipperLib::cInt>(extent_.miny()));
if (!clipper.AddPath( clip_box, ClipperLib::ptClip, true ))
{
std::clog << "ptClip failed!\n";
}
ClipperLib::PolyTree polygons;
clipper.Execute(ClipperLib::ctIntersection, polygons);// ClipperLib::pftNonZero);
clipper.Clear();
mapnik::geometry::multi_polygon<double> mp;
for (auto * polynode : polygons.Childs)
{
process_polynode_branch(polynode, mp);
}
std::string expect = expected_+".png";
std::string actual = expected_+"_actual.png";
//mapnik::geometry::geometry<double> geom2(mp);
auto env = mapnik::geometry::envelope(mp);
if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
{
std::clog << "generating expected image: " << expect << "\n";
render(mp,env,expect);
}
render(mp,env,actual);
return benchmark::compare_images(actual,expect);
}
bool operator()() const
{
mapnik::geometry::geometry<double> geom;
if (!mapnik::from_wkt(wkt_in_, geom))
{
throw std::runtime_error("Failed to parse WKT");
}
if (mapnik::geometry::is_empty(geom))
{
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double> >())
{
std::clog << "not a polygon!\n";
return false;
}
mapnik::geometry::polygon<double> & poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geom);
mapnik::geometry::correct(poly);
bool valid = true;
for (unsigned i=0;i<iterations_;++i)
{
std::deque<mapnik::geometry::polygon<double> > result;
boost::geometry::intersection(extent_,poly,result);
unsigned count = 0;
for (auto const& geom : result)
{
mapnik::geometry::polygon_vertex_adapter<double> va(geom);
unsigned cmd;
double x,y;
while ((cmd = va.vertex(&x, &y)) != mapnik::SEG_END) {
++count;
}
unsigned expected_count = 29;
if (count != expected_count) {
std::clog << "test3: clipping failed: processed " << count << " verticies but expected " <<
expected_count << "\n"; valid = false;
}
}
}
return valid;
}
};
*/
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
// polygon/rect clipping
// IN : POLYGON ((155 203, 233 454, 315 340, 421 446, 463 324, 559 466, 665 253, 528 178, 394 229, 329 138, 212 134,
// 183 228, 200 264, 155 203),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343
// 287, 249 334, 229 191, 313 190)) RECT : POLYGON ((181 106, 181 470, 631 470, 631 106, 181 106)) OUT (expected)
// POLYGON ((181 286.6666666666667, 233 454, 315 340, 421 446, 463 324, 559 466, 631 321.3207547169811, 631
// 234.38686131386862, 528 178, 394 229, 329 138, 212 134, 183 228, 200 264, 181 238.24444444444444, 181
// 286.6666666666667),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343 287, 249
// 334, 229 191, 313 190))
#if 0
mapnik::box2d<double> clipping_box(181,106,631,470);
std::string filename_("./benchmark/data/polygon.wkt");
std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
if (!in.is_open())
throw std::runtime_error("could not open: '" + filename_ + "'");
std::string wkt_in( (std::istreambuf_iterator<char>(in) ),
(std::istreambuf_iterator<char>()) );
int return_value = 0;
{
test1 test_runner(params,wkt_in,clipping_box);
return_value = return_value | run(test_runner,"clipping polygon with agg");
}
{
test3 test_runner(params,wkt_in,clipping_box);
return_value = return_value | run(test_runner,"clipping polygon with boost");
}
/*
{
test4 test_runner(params,wkt_in,clipping_box);
return_value = return_value | run(test_runner,"clipping polygon with clipper_tree");
}
*/
#endif
return 0; // return_value;
}

View file

@ -1,59 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
class test : public benchmark::test_case
{
std::string xml_;
mapnik::box2d<double> extent_;
public:
test(mapnik::parameters const& params, std::string const& xml, mapnik::box2d<double> const& extent)
: test_case(params)
, xml_(xml)
, extent_(extent)
{}
bool validate() const
{
mapnik::Map m(256, 256);
mapnik::load_map(m, xml_);
m.zoom_to_box(extent_);
mapnik::image_rgba8 im(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
ren.apply();
// mapnik::save_to_file(im.data(),"test.png");
return true;
}
bool operator()() const
{
mapnik::Map m(256, 256);
mapnik::load_map(m, xml_);
m.zoom_to_box(extent_);
for (unsigned i = 0; i < iterations_; ++i)
{
mapnik::image_rgba8 im(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
ren.apply();
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
mapnik::box2d<double> z1(-20037508.3428, -8317435.0606, 20037508.3428, 18399242.7298);
// bbox for 16/10491/22911.png
mapnik::box2d<double> z16(-13622912.929097254, 6026906.8062295765, -13621689.93664469, 6028129.79868214);
return benchmark::sequencer(argc, argv)
.run<test>("polygon clip render z1", "benchmark/data/polygon_rendering_clip.xml", z1)
.run<test>("polygon noclip render z1", "benchmark/data/polygon_rendering_no_clip.xml", z1)
.run<test>("polygon clip render z16", "benchmark/data/polygon_rendering_clip.xml", z16)
.run<test>("polygon noclip render z16", "benchmark/data/polygon_rendering_no_clip.xml", z16)
.done();
}

View file

@ -1,77 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/geometry/box2d.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
class test : public benchmark::test_case
{
std::string src_;
std::string dest_;
mapnik::box2d<double> from_;
mapnik::box2d<double> to_;
bool defer_proj_init_;
public:
test(mapnik::parameters const& params,
std::string const& src,
std::string const& dest,
mapnik::box2d<double> const& from,
mapnik::box2d<double> const& to,
bool defer_proj)
: test_case(params)
, src_(src)
, dest_(dest)
, from_(from)
, to_(to)
, defer_proj_init_(defer_proj)
{}
bool validate() const
{
mapnik::projection src(src_, defer_proj_init_);
mapnik::projection dest(dest_, defer_proj_init_);
mapnik::proj_transform tr(src, dest);
mapnik::box2d<double> bbox = from_;
if (!tr.forward(bbox))
return false;
return ((std::fabs(bbox.minx() - to_.minx()) < .5) && (std::fabs(bbox.maxx() - to_.maxx()) < .5) &&
(std::fabs(bbox.miny() - to_.miny()) < .5) && (std::fabs(bbox.maxy() - to_.maxy()) < .5));
}
bool operator()() const
{
mapnik::projection src(src_, defer_proj_init_);
mapnik::projection dest(dest_, defer_proj_init_);
mapnik::proj_transform tr(src, dest);
for (std::size_t i = 0; i < iterations_; ++i)
{
for (int j = -180; j < 180; j = j + 5)
{
for (int k = -85; k < 85; k = k + 5)
{
mapnik::box2d<double> box(j, k, j, k);
if (!tr.forward(box))
throw std::runtime_error("could not transform coords");
}
}
}
return true;
}
};
// echo -180 -60 | cs2cs -f "%.10f" epsg:4326 +to epsg:3857
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::box2d<double> from(-180, -80, 180, 80);
mapnik::box2d<double> to(-20037508.3427892476, -15538711.0963092316, 20037508.3427892476, 15538711.0963092316);
std::string from_str("epsg:4326");
std::string to_str("epsg:3857");
std::string from_str2("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
std::string to_str2("+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");
return benchmark::sequencer(argc, argv)
.run<test>("lonlat->merc epsg (internal)", from_str, to_str, from, to, true)
.run<test>("lonlat->merc literal (libproj)", from_str2, to_str2, from, to, true)
.run<test>("merc->lonlat epsg (internal)", to_str, from_str, to, from, true)
.run<test>("merc->lonlat literal (libproj)", to_str2, from_str2, to, from, true)
.done();
}

View file

@ -1,52 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/quad_tree.hpp>
#include <random>
using quad_tree_type = mapnik::quad_tree<std::size_t>;
class test : public benchmark::test_case
{
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return true; }
bool operator()() const
{
std::random_device rd;
std::default_random_engine engine(rd());
std::uniform_int_distribution<int> uniform_dist(0, 2048);
quad_tree_type tree(mapnik::box2d<double>(0, 0, 2048, 2048));
// populate
for (size_t i = 0; i < iterations_; ++i)
{
int cx = uniform_dist(engine);
int cy = uniform_dist(engine);
int sx = 0.2 * uniform_dist(engine);
int sy = 0.2 * uniform_dist(engine);
mapnik::box2d<double> box(cx - sx, cy - sy, cx + sx, cy + sy);
tree.insert(i, box);
}
// bounding box query
std::size_t count = 0;
for (size_t i = 0; i < iterations_; ++i)
{
int cx = uniform_dist(engine);
int cy = uniform_dist(engine);
int sx = 0.4 * uniform_dist(engine);
int sy = 0.4 * uniform_dist(engine);
mapnik::box2d<double> box(cx - sx, cy - sy, cx + sx, cy + sy);
auto itr = tree.query_in_box(box);
auto end = tree.query_end();
for (; itr != end; ++itr)
{
++count;
}
}
return true;
}
};
BENCHMARK(test, "quad_tree creation")

View file

@ -1,123 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <stdexcept>
class test : public benchmark::test_case
{
std::string xml_;
mapnik::box2d<double> extent_;
mapnik::value_integer width_;
mapnik::value_integer height_;
double scale_factor_;
std::string preview_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, xml_()
, extent_()
, width_(*params.get<mapnik::value_integer>("width", 256))
, height_(*params.get<mapnik::value_integer>("height", 256))
, scale_factor_(*params.get<mapnik::value_double>("scale_factor", 1.0))
, preview_(*params.get<std::string>("preview", ""))
{
const auto map = params.get<std::string>("map");
if (!map)
{
throw std::runtime_error("please provide a --map <path to xml> arg");
}
xml_ = *map;
const auto ext = params.get<std::string>("extent");
if (ext && !ext->empty())
{
if (!extent_.from_string(*ext))
throw std::runtime_error("could not parse `extent` string" + *ext);
}
/*
else
{
throw std::runtime_error("please provide a --extent=<minx,miny,maxx,maxy> arg");
}*/
}
bool validate() const
{
mapnik::Map m(width_, height_);
mapnik::load_map(m, xml_, true);
if (extent_.valid())
{
m.zoom_to_box(extent_);
}
else
{
m.zoom_all();
}
mapnik::image_rgba8 im(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im, scale_factor_);
ren.apply();
if (!preview_.empty())
{
std::clog << "preview available at " << preview_ << "\n";
mapnik::save_to_file(im, preview_);
}
return true;
}
bool operator()() const
{
if (!preview_.empty())
{
return false;
}
mapnik::Map m(width_, height_);
mapnik::load_map(m, xml_);
if (extent_.valid())
{
m.zoom_to_box(extent_);
}
else
{
m.zoom_all();
}
for (unsigned i = 0; i < iterations_; ++i)
{
mapnik::image_rgba8 im(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im, scale_factor_);
ren.apply();
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
int return_value = 0;
try
{
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
const auto name = params.get<std::string>("name");
if (!name)
{
std::clog << "please provide a name for this test\n";
return -1;
}
mapnik::freetype_engine::register_fonts("./fonts/", true);
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
{
test test_runner(params);
return_value = run(test_runner, *name);
}
}
catch (std::exception const& ex)
{
std::clog << ex.what() << "\n";
return -1;
}
return return_value;
}

View file

@ -1,178 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/datasource_cache.hpp>
#include <stdexcept>
template<typename Renderer>
void process_layers(Renderer& ren,
mapnik::request const& m_req,
mapnik::projection const& map_proj,
std::vector<mapnik::layer> const& layers,
double scale_denom)
{
unsigned layers_size = layers.size();
for (unsigned i = 0; i < layers_size; ++i)
{
mapnik::layer const& lyr = layers[i];
if (lyr.visible(scale_denom))
{
std::set<std::string> names;
mapnik::layer l(lyr);
ren.apply_to_layer(l,
ren,
map_proj,
m_req.scale(),
scale_denom,
m_req.width(),
m_req.height(),
m_req.extent(),
m_req.buffer_size(),
names);
}
}
}
class test : public benchmark::test_case
{
std::string xml_;
mapnik::box2d<double> extent_;
mapnik::value_integer width_;
mapnik::value_integer height_;
std::shared_ptr<mapnik::Map> m_;
double scale_factor_;
std::string preview_;
mutable mapnik::image_rgba8 im_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, xml_()
, extent_()
, width_(*params.get<mapnik::value_integer>("width", 256))
, height_(*params.get<mapnik::value_integer>("height", 256))
, m_(new mapnik::Map(width_, height_))
, scale_factor_(*params.get<mapnik::value_double>("scale_factor", 2.0))
, preview_(*params.get<std::string>("preview", ""))
, im_(m_->width(), m_->height())
{
const auto map = params.get<std::string>("map");
if (!map)
{
throw std::runtime_error("please provide a --map=<path to xml> arg");
}
xml_ = *map;
auto ext = params.get<std::string>("extent");
mapnik::load_map(*m_, xml_, true);
if (ext && !ext->empty())
{
if (!extent_.from_string(*ext))
throw std::runtime_error("could not parse `extent` string" + *ext);
}
else
{
m_->zoom_all();
extent_ = m_->get_current_extent();
std::clog << "Defaulting to max extent " << extent_ << "\n";
std::clog << " (pass --extent=<minx,miny,maxx,maxy> to restrict bounds)\n";
}
}
bool validate() const
{
mapnik::request m_req(width_, height_, extent_);
mapnik::attributes variables;
m_req.set_buffer_size(m_->buffer_size());
mapnik::projection map_proj(m_->srs(), true);
double scale_denom = mapnik::scale_denominator(m_req.scale(), map_proj.is_geographic());
scale_denom *= scale_factor_;
mapnik::agg_renderer<mapnik::image_rgba8> ren(*m_, m_req, variables, im_, scale_factor_);
ren.start_map_processing(*m_);
std::vector<mapnik::layer> const& layers = m_->layers();
process_layers(ren, m_req, map_proj, layers, scale_denom);
ren.end_map_processing(*m_);
if (!preview_.empty())
{
std::clog << "preview available at " << preview_ << "\n";
mapnik::save_to_file(im_, preview_);
}
return true;
}
bool operator()() const
{
if (!preview_.empty())
{
return false;
}
for (unsigned i = 0; i < iterations_; ++i)
{
mapnik::request m_req(width_, height_, extent_);
mapnik::image_rgba8 im(m_->width(), m_->height());
mapnik::attributes variables;
m_req.set_buffer_size(m_->buffer_size());
mapnik::projection map_proj(m_->srs(), true);
double scale_denom = mapnik::scale_denominator(m_req.scale(), map_proj.is_geographic());
scale_denom *= scale_factor_;
mapnik::agg_renderer<mapnik::image_rgba8> ren(*m_, m_req, variables, im, scale_factor_);
ren.start_map_processing(*m_);
std::vector<mapnik::layer> const& layers = m_->layers();
process_layers(ren, m_req, map_proj, layers, scale_denom);
ren.end_map_processing(*m_);
bool diff = false;
mapnik::image_rgba8 const& dest = im;
mapnik::image_rgba8 const& src = im_;
for (unsigned int y = 0; y < height_; ++y)
{
const unsigned int* row_from = src.get_row(y);
const unsigned int* row_to = dest.get_row(y);
for (unsigned int x = 0; x < width_; ++x)
{
if (row_from[x] != row_to[x])
diff = true;
}
}
if (diff)
throw std::runtime_error("images differ");
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
int return_value = 0;
try
{
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
const auto name = params.get<std::string>("name");
if (!name)
{
std::clog << "please provide a name for this test\n";
return -1;
}
mapnik::freetype_engine::register_fonts("./fonts/", true);
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
{
test test_runner(params);
return_value = run(test_runner, *name);
}
}
catch (std::exception const& ex)
{
std::clog << ex.what() << "\n";
return -1;
}
return return_value;
}

View file

@ -1,34 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
std::string value_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_("true")
{}
bool validate() const
{
bool result = false;
mapnik::util::string2bool(value_.data(), value_.data() + value_.size(), result);
if (!result)
return result;
mapnik::util::string2bool(value_, result);
return (result == true);
}
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
bool result = false;
mapnik::util::string2bool(value_, result);
mapnik::util::string2bool(value_.data(), value_.data() + value_.size(), result);
}
return true;
}
};
BENCHMARK(test, "string->bool")

View file

@ -1,39 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
std::string value_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_("1.23456789")
{}
bool validate() const
{
double result = 0;
if (!mapnik::util::string2double(value_.data(), value_.data() + value_.size(), result))
return false;
if (result != 1.23456789)
return false;
result = 0;
if (!mapnik::util::string2double(value_, result))
return false;
if (result != 1.23456789)
return false;
return true;
}
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
double result = 0;
mapnik::util::string2double(value_, result);
mapnik::util::string2double(value_.data(), value_.data() + value_.size(), result);
}
return true;
}
};
BENCHMARK(test, "string->double")

View file

@ -1,39 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
std::string value_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_("123456789")
{}
bool validate() const
{
mapnik::value_integer result = 0;
if (!mapnik::util::string2int(value_.data(), value_.data() + value_.size(), result))
return false;
if (result != 123456789)
return false;
result = 0;
if (!mapnik::util::string2int(value_, result))
return false;
if (result != 123456789)
return false;
return true;
}
bool operator()() const
{
for (std::size_t i = 0; i < iterations_; ++i)
{
mapnik::value_integer result = 0;
mapnik::util::string2int(value_, result);
mapnik::util::string2int(value_.data(), value_.data() + value_.size(), result);
}
return true;
}
};
BENCHMARK(test, "string->int")

View file

@ -1,31 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
double value_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_(-0.1234)
{}
bool validate() const
{
std::string s;
mapnik::util::to_string(s, value_);
return (s == "-0.1234");
}
bool operator()() const
{
std::string out;
for (std::size_t i = 0; i < iterations_; ++i)
{
out.clear();
mapnik::util::to_string(out, value_);
}
return true;
}
};
BENCHMARK(test, "to_string double->string")

View file

@ -1,32 +0,0 @@
#include "bench_framework.hpp"
#include <sstream>
class test : public benchmark::test_case
{
double value_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_(-0.1234)
{}
bool validate() const
{
std::ostringstream s;
s << value_;
return (s.str() == "-0.1234");
}
bool operator()() const
{
std::string out;
for (std::size_t i = 0; i < iterations_; ++i)
{
std::ostringstream s;
s << value_;
out = s.str();
}
return true;
}
};
BENCHMARK(test, "ostringstream double->string")

View file

@ -1,124 +0,0 @@
#include "bench_framework.hpp"
#include <mapnik/unicode.hpp>
#include <mapnik/util/from_u8string.hpp>
#include <mapnik/value.hpp>
#include <boost/locale.hpp>
#ifndef __linux__
#include <codecvt>
#endif
using mapnik::util::from_u8string;
#ifndef __linux__
class test : public benchmark::test_case
{
std::string utf8_;
public:
test(mapnik::parameters const& params)
: test_case(params)
, utf8_(from_u8string(u8"שלום"))
{}
bool validate() const
{
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf32conv;
std::u32string utf32 = utf32conv.from_bytes(utf8_);
if (utf32.size() != 4)
return false;
if (utf32[0] != 0x5e9 && utf32[1] != 0x5dc && utf32[2] != 0x5d5 && utf32[3] != 0x5dd)
return false;
return true;
}
bool operator()() const
{
std::u32string utf32;
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf32conv;
for (std::size_t i = 0; i < iterations_; ++i)
{
utf32 = utf32conv.from_bytes(utf8_);
}
return true;
}
};
#endif
class test2 : public benchmark::test_case
{
std::string utf8_;
public:
test2(mapnik::parameters const& params)
: test_case(params)
, utf8_(from_u8string(u8"שלום"))
{}
bool validate() const
{
std::u32string utf32 = boost::locale::conv::utf_to_utf<char32_t>(utf8_);
if (utf32.size() != 4)
return false;
if (utf32[0] != 0x5e9 && utf32[1] != 0x5dc && utf32[2] != 0x5d5 && utf32[3] != 0x5dd)
return false;
return true;
}
bool operator()() const
{
std::u32string utf32;
for (std::size_t i = 0; i < iterations_; ++i)
{
utf32 = boost::locale::conv::utf_to_utf<char32_t>(utf8_);
}
return true;
}
};
class test3 : public benchmark::test_case
{
std::string utf8_;
public:
test3(mapnik::parameters const& params)
: test_case(params)
, utf8_(from_u8string(u8"שלום"))
{}
bool validate() const
{
mapnik::transcoder tr_("utf-8");
mapnik::value_unicode_string utf32 = tr_.transcode(utf8_.data(), utf8_.size());
// std::u32string utf32 = boost::locale::conv::utf_to_utf<char32_t>(utf8_);
if (utf32.length() != 4)
return false;
if (utf32[0] != 0x5e9 && utf32[1] != 0x5dc && utf32[2] != 0x5d5 && utf32[3] != 0x5dd)
return false;
return true;
}
bool operator()() const
{
mapnik::transcoder tr_("utf-8");
mapnik::value_unicode_string utf32;
for (std::size_t i = 0; i < iterations_; ++i)
{
utf32 = tr_.transcode(utf8_.data(), utf8_.size());
}
return true;
}
};
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
int return_value = 0;
#ifndef __linux__
test test_runner(params);
return_value = return_value | run(test_runner, "utf encode std::codecvt");
#else
std::clog << "skipping 'utf encode std::codecvt' test since <codecvt> is not supported on __linux__\n";
#endif
test2 test_runner2(params);
return_value = return_value | run(test_runner2, "utf encode boost::locale");
test3 test_runner3(params);
return_value = return_value | run(test_runner3, "utf encode ICU");
return return_value;
}

View file

@ -2,12 +2,16 @@
class test : public benchmark::test_case
{
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return true; }
void operator()() const {}
: test_case(params) {}
bool validate() const
{
return true;
}
void operator()() const
{
}
};
BENCHMARK(test, "test name")
BENCHMARK(test,"test name")

View file

@ -0,0 +1,347 @@
#include "bench_framework.hpp"
#include <cstring>
#include <cstdlib>
#include <stdexcept>
//#include <array>
#include <valarray>
#include <boost/version.hpp>
#if BOOST_VERSION >= 105400
#include <boost/container/static_vector.hpp>
#endif
// http://stackoverflow.com/questions/17347254/why-is-allocation-and-deallocation-of-stdvector-slower-than-dynamic-array-on-m
#define FULL_ZERO_CHECK
inline void ensure_zero(uint8_t * data, uint32_t size) {
#ifdef FULL_ZERO_CHECK
for (std::size_t i=0;i<size;++i) {
if (data[i] != 0) {
throw std::runtime_error("found non zero value");
}
}
#else
if (data[0] != 0) {
throw std::runtime_error("found non zero value");
}
#endif
}
class test1 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test1(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
// NOTE: sizeof(uint8_t) == 1
uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t)*size_);
memcpy(data, &array_[0], size_);
ensure_zero(data,size_);
free(data);
}
}
};
class test1b : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test1b(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
// NOTE: sizeof(uint8_t) == 1
uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t)*size_);
memset(data, 0, sizeof(uint8_t)*size_);
ensure_zero(data,size_);
free(data);
}
}
};
class test2 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test2(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
uint8_t * data = static_cast<uint8_t*>(::operator new(sizeof(uint8_t)*size_));
memcpy(data, &array_[0], size_);
ensure_zero(data,size_);
::operator delete(data),data=0;
}
}
};
class test3 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
std::vector<uint8_t> data(size_);
ensure_zero(&data[0],data.size());
}
}
};
class test3b : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3b(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
std::vector<uint8_t> data(0);
data.resize(size_,0);
ensure_zero(&data[0],data.size());
}
}
};
class test3c : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test3c(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
std::vector<uint8_t> data(0);
data.assign(size_,0);
ensure_zero(&data[0],data.size());
}
}
};
class test4 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test4(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
uint8_t *data = (uint8_t *)calloc(size_,sizeof(uint8_t));
ensure_zero(data,size_);
free(data);
}
}
};
class test5 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test5(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
std::string data(array_.begin(),array_.end());
ensure_zero((uint8_t *)&data[0],size_);
}
}
};
class test5b : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<char> array_;
test5b(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
std::string data(&array_[0],array_.size());
ensure_zero((uint8_t *)&data[0],size_);
}
}
};
// C++14 dynarray<T>
// http://isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meeting
// http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130909/088700.html
// http://stackoverflow.com/questions/17303902/any-alternative-to-stddynarray-presently-available
class test6 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test6(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
std::valarray<uint8_t> data(static_cast<uint8_t>(0),static_cast<size_t>(size_));
ensure_zero(&data[0],size_);
}
}
};
#if BOOST_VERSION >= 105400
// http://i42.co.uk/stuff/vecarray.htm
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost/container/static_vector.html
class test7 : public benchmark::test_case
{
public:
uint32_t size_;
std::vector<uint8_t> array_;
test7(mapnik::parameters const& params)
: test_case(params),
size_(*params.get<mapnik::value_integer>("size",256*256)),
array_(size_,0) { }
bool validate() const
{
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
boost::container::static_vector<uint8_t,256*256> data(size_,0);
ensure_zero(&data[0],size_);
}
}
};
#endif
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
{
test4 test_runner4(params);
run(test_runner4,"calloc");
}
{
test1 test_runner(params);
run(test_runner,"malloc/memcpy");
}
{
test1b test_runner(params);
run(test_runner,"malloc/memset");
}
{
test2 test_runner(params);
run(test_runner,"new");
}
{
test3 test_runner(params);
run(test_runner,"vector(N)");
}
{
test3b test_runner(params);
run(test_runner,"vector/resize");
}
{
test3c test_runner(params);
run(test_runner,"vector/assign");
}
{
test5 test_runner(params);
run(test_runner,"std::string range");
}
{
test5b test_runner(params);
run(test_runner,"std::string &[0]");
}
{
test6 test_runner(params);
run(test_runner,"valarray");
}
#if BOOST_VERSION >= 105400
{
test7 test_runner(params);
run(test_runner,"static_vector");
}
#endif
return 0;
}

View file

@ -0,0 +1,40 @@
#include "bench_framework.hpp"
#include <mapnik/unicode.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/expression_grammar.hpp>
class test : public benchmark::test_case
{
std::string expr_;
public:
test(mapnik::parameters const& params)
: test_case(params),
expr_("((([mapnik::geometry_type]=2) and ([oneway]=1)) and ([class]='path'))") {}
bool validate() const
{
mapnik::expression_ptr expr = mapnik::parse_expression(expr_,"utf-8");
std::string result = mapnik::to_expression_string(*expr);
bool ret = (result == expr_);
if (!ret)
{
std::clog << result << " != " << expr_ << "\n";
}
return ret;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
mapnik::expression_ptr expr = mapnik::parse_expression(expr_,"utf-8");
}
}
};
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
test test_runner(params);
run(test_runner,"expr parsing");
}

View file

@ -0,0 +1,43 @@
#include "bench_framework.hpp"
#include <mapnik/font_engine_freetype.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
class test : public benchmark::test_case
{
public:
test(mapnik::parameters const& params)
: test_case(params) {}
bool validate() const
{
return true;
}
void operator()() const
{
mapnik::freetype_engine engine;
unsigned long count = 0;
for (unsigned i=0;i<iterations_;++i)
{
BOOST_FOREACH ( std::string const& name , mapnik::freetype_engine::face_names())
{
mapnik::face_ptr f = engine.create_face(name);
if (f) ++count;
}
}
}
};
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
bool success = mapnik::freetype_engine::register_fonts("./fonts", true);
if (!success) {
std::clog << "warning, did not register any new fonts!\n";
return -1;
}
std::size_t face_count = mapnik::freetype_engine::face_names().size();
test test_runner(params);
return run(test_runner,(boost::format("font_engine: creating %ld faces") % (face_count * 1000 * 10)).str());
}

View file

@ -0,0 +1,26 @@
#include "bench_framework.hpp"
#include <mapnik/font_engine_freetype.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
class test : public benchmark::test_case
{
public:
test(mapnik::parameters const& params)
: test_case(params) {}
bool validate() const
{
return mapnik::freetype_engine::register_fonts("./fonts", true);
}
void operator()() const
{
unsigned long count = 0;
for (unsigned i=0;i<iterations_;++i)
{
mapnik::freetype_engine::register_fonts("./fonts", true);
count++;
}
}
};
BENCHMARK(test,"font registration")

View file

@ -0,0 +1,26 @@
#include "bench_framework.hpp"
#include <mapnik/image_util.hpp>
#include <mapnik/graphics.hpp>
class test : public benchmark::test_case
{
mapnik::image_data_32 im_;
public:
test(mapnik::parameters const& params)
: test_case(params),
im_(256,256) {}
bool validate() const
{
return true;
}
void operator()() const
{
std::string out;
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
out = mapnik::save_to_string(im_,"png8:m=h:z=1");
}
}
};
BENCHMARK(test,"encoding blank png")

View file

@ -0,0 +1,36 @@
#include "bench_framework.hpp"
#include "compare_images.hpp"
class test : public benchmark::test_case
{
boost::shared_ptr<image_32> im_;
public:
test(mapnik::parameters const& params)
: test_case(params) {
std::string filename("./benchmark/data/multicolor.png");
std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"png"));
if (!reader.get())
{
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
im_ = boost::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,im_->data());
}
bool validate() const
{
std::string expected("./benchmark/data/multicolor-hextree-expected.png");
std::string actual("./benchmark/data/multicolor-hextree-actual.png");
mapnik::save_to_file(im_->data(),actual, "png8:m=h:z=1");
return benchmark::compare_images(actual,expected);
}
void operator()() const
{
std::string out;
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
out = mapnik::save_to_string(im_->data(),"png8:m=h:z=1");
}
}
};
BENCHMARK(test,"encoding multicolor png")

View file

@ -0,0 +1,321 @@
#include "bench_framework.hpp"
#include "compare_images.hpp"
#include "agg_conv_clip_polygon.h"
#include <mapnik/geometry.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
//#include <mapnik/util/geometry_to_wkt.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/util/fs.hpp>
// agg
#include "agg_conv_clip_polygon.h"
// clipper
#include "agg_conv_clipper.h"
#include "agg_path_storage.h"
// boost
#include <mapnik/polygon_clipper.hpp>
// rendering
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include <mapnik/image_util.hpp>
#include <boost/foreach.hpp>
#include <fstream>
void render(mapnik::geometry_type & geom,
mapnik::box2d<double> const& extent,
std::string const& name)
{
typedef mapnik::coord_transform<mapnik::CoordTransform,mapnik::geometry_type> path_type;
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
mapnik::image_32 im(256,256);
im.set_background(mapnik::color("white"));
mapnik::box2d<double> padded_extent = extent;
padded_extent.pad(10);
mapnik::CoordTransform tr(im.width(),im.height(),padded_extent,0,0);
agg::rendering_buffer buf(im.raw_data(),im.width(),im.height(), im.width() * 4);
agg::pixfmt_rgba32_plain pixf(buf);
ren_base renb(pixf);
renderer ren(renb);
ren.color(agg::rgba8(127,127,127,255));
agg::rasterizer_scanline_aa<> ras;
mapnik::proj_transform prj_trans(mapnik::projection("+init=epsg:4326"),mapnik::projection("+init=epsg:4326"));
geom.rewind(0);
path_type path(tr,geom,prj_trans);
ras.add_path(path);
agg::scanline_u8 sl;
agg::render_scanlines(ras, sl, ren);
mapnik::save_to_file(im,name);
geom.rewind(0);
}
class test1 : public benchmark::test_case
{
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
typedef agg::conv_clip_polygon<mapnik::geometry_type> conv_clip;
test1(mapnik::parameters const& params,
std::string const& wkt_in,
mapnik::box2d<double> const& extent)
: test_case(params),
wkt_in_(wkt_in),
extent_(extent),
expected_("./benchmark/data/polygon_clipping_agg") {}
bool validate() const
{
std::string expected_wkt("Polygon((181 286.666667,233 454,315 340,421 446,463 324,559 466,631 321.320755,631 234.386861,528 178,394 229,329 138,212 134,183 228,200 264,181 238.244444),(313 190,440 256,470 248,510 305,533 237,613 263,553 397,455 262,405 378,343 287,249 334,229 191,313 190,313 190))");
boost::ptr_vector<mapnik::geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
if (paths.size() != 1)
{
std::clog << "paths.size() != 1\n";
return false;
}
mapnik::geometry_type & geom = paths[0];
conv_clip clipped(geom);
clipped.clip_box(
extent_.minx(),
extent_.miny(),
extent_.maxx(),
extent_.maxy());
unsigned cmd;
double x,y;
mapnik::geometry_type geom2(mapnik::Polygon);
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
}
std::string expect = expected_+".png";
std::string actual = expected_+"_actual.png";
if (!mapnik::util::exists(expect))
{
std::clog << "generating expected image: " << expect << "\n";
render(geom2,geom.envelope(),expect);
}
render(geom2,geom.envelope(),actual);
return benchmark::compare_images(actual,expect);
}
void operator()() const
{
boost::ptr_vector<mapnik::geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
for (unsigned i=0;i<iterations_;++i)
{
BOOST_FOREACH (mapnik::geometry_type & geom , paths)
{
conv_clip clipped(geom);
clipped.clip_box(
extent_.minx(),
extent_.miny(),
extent_.maxx(),
extent_.maxy());
unsigned cmd;
double x,y;
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
}
}
}
};
class test2 : public benchmark::test_case
{
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
typedef agg::conv_clipper<mapnik::geometry_type, agg::path_storage> poly_clipper;
test2(mapnik::parameters const& params,
std::string const& wkt_in,
mapnik::box2d<double> const& extent)
: test_case(params),
wkt_in_(wkt_in),
extent_(extent),
expected_("./benchmark/data/polygon_clipping_clipper") {}
bool validate() const
{
std::string expected_wkt("Polygon((212 134,329 138,394 229,528 178,631 234.4,631 321.3,559 466,463 324,421 446,315 340,233 454,181 286.7,181 238.2,200 264,183 228),(313 190,229 191,249 334,343 287,405 378,455 262,553 397,613 263,533 237,510 305,470 248,440 256))");
boost::ptr_vector<mapnik::geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
agg::path_storage ps;
ps.move_to(extent_.minx(), extent_.miny());
ps.line_to(extent_.minx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.miny());
ps.close_polygon();
if (paths.size() != 1)
{
std::clog << "paths.size() != 1\n";
return false;
}
mapnik::geometry_type & geom = paths[0];
poly_clipper clipped(geom,ps,
agg::clipper_and,
agg::clipper_non_zero,
agg::clipper_non_zero,
1);
clipped.rewind(0);
unsigned cmd;
double x,y;
mapnik::geometry_type geom2(mapnik::Polygon);
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
}
std::string expect = expected_+".png";
std::string actual = expected_+"_actual.png";
if (!mapnik::util::exists(expect))
{
std::clog << "generating expected image: " << expect << "\n";
render(geom2,geom.envelope(),expect);
}
render(geom2,geom.envelope(),actual);
return benchmark::compare_images(actual,expect);
}
void operator()() const
{
boost::ptr_vector<mapnik::geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
agg::path_storage ps;
ps.move_to(extent_.minx(), extent_.miny());
ps.line_to(extent_.minx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.maxy());
ps.line_to(extent_.maxx(), extent_.miny());
ps.close_polygon();
for (unsigned i=0;i<iterations_;++i)
{
BOOST_FOREACH (mapnik::geometry_type & geom , paths)
{
poly_clipper clipped(geom,ps,
agg::clipper_and,
agg::clipper_non_zero,
agg::clipper_non_zero,
1);
clipped.rewind(0);
unsigned cmd;
double x,y;
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
}
}
}
};
class test3 : public benchmark::test_case
{
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
typedef mapnik::polygon_clipper<mapnik::geometry_type> poly_clipper;
test3(mapnik::parameters const& params,
std::string const& wkt_in,
mapnik::box2d<double> const& extent)
: test_case(params),
wkt_in_(wkt_in),
extent_(extent),
expected_("./benchmark/data/polygon_clipping_boost") {}
bool validate() const
{
std::string expected_wkt("Polygon((181 286.666667,233 454,315 340,421 446,463 324,559 466,631 321.320755,631 234.386861,528 178,394 229,329 138,212 134,183 228,200 264,181 238.244444,181 286.666667),(313 190,440 256,470 248,510 305,533 237,613 263,553 397,455 262,405 378,343 287,249 334,229 191,313 190))");
boost::ptr_vector<mapnik::geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
if (paths.size() != 1)
{
std::clog << "paths.size() != 1\n";
return false;
}
mapnik::geometry_type & geom = paths[0];
poly_clipper clipped(extent_, geom);
unsigned cmd;
double x,y;
mapnik::geometry_type geom2(mapnik::Polygon);
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {
geom2.push_vertex(x,y,(mapnik::CommandType)cmd);
}
std::string expect = expected_+".png";
std::string actual = expected_+"_actual.png";
if (!mapnik::util::exists(expect))
{
std::clog << "generating expected image: " << expect << "\n";
render(geom2,geom.envelope(),expect);
}
render(geom2,geom.envelope(),actual);
return benchmark::compare_images(actual,expect);
}
void operator()() const
{
boost::ptr_vector<mapnik::geometry_type> paths;
if (!mapnik::from_wkt(wkt_in_, paths))
{
throw std::runtime_error("Failed to parse WKT");
}
for (unsigned i=0;i<iterations_;++i)
{
BOOST_FOREACH ( mapnik::geometry_type & geom , paths)
{
poly_clipper clipped(extent_, geom);
unsigned cmd;
double x,y;
while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {}
}
}
}
};
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
// polygon/rect clipping
// IN : POLYGON ((155 203, 233 454, 315 340, 421 446, 463 324, 559 466, 665 253, 528 178, 394 229, 329 138, 212 134, 183 228, 200 264, 155 203),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343 287, 249 334, 229 191, 313 190))
// RECT : POLYGON ((181 106, 181 470, 631 470, 631 106, 181 106))
// OUT (expected)
// POLYGON ((181 286.6666666666667, 233 454, 315 340, 421 446, 463 324, 559 466, 631 321.3207547169811, 631 234.38686131386862, 528 178, 394 229, 329 138, 212 134, 183 228, 200 264, 181 238.24444444444444, 181 286.6666666666667),(313 190, 440 256, 470 248, 510 305, 533 237, 613 263, 553 397, 455 262, 405 378, 343 287, 249 334, 229 191, 313 190))
mapnik::box2d<double> clipping_box(181,106,631,470);
std::string filename_("./benchmark/data/polygon.wkt");
std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
if (!in.is_open())
throw std::runtime_error("could not open: '" + filename_ + "'");
std::string wkt_in( (std::istreambuf_iterator<char>(in) ),
(std::istreambuf_iterator<char>()) );
{
test1 test_runner(params,wkt_in,clipping_box);
run(test_runner,"clipping polygon with agg");
}
{
test2 test_runner(params,wkt_in,clipping_box);
run(test_runner,"clipping polygon with clipper");
}
{
test3 test_runner(params,wkt_in,clipping_box);
run(test_runner,"clipping polygon with boost");
}
return 0;
}

View file

@ -0,0 +1,79 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
class test : public benchmark::test_case
{
std::string xml_;
mapnik::box2d<double> extent_;
public:
test(mapnik::parameters const& params,
std::string const& xml,
mapnik::box2d<double> const& extent)
: test_case(params),
xml_(xml),
extent_(extent)
{}
bool validate() const
{
mapnik::Map m(256,256);
mapnik::load_map(m,xml_);
m.zoom_to_box(extent_);
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
ren.apply();
//mapnik::save_to_file(im,"test.png");
return true;
}
void operator()() const
{
mapnik::Map m(256,256);
mapnik::load_map(m,xml_);
m.zoom_to_box(extent_);
for (unsigned i=0;i<iterations_;++i)
{
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
ren.apply();
}
}
};
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
mapnik::box2d<double> z1(-20037508.3428,-8317435.0606,20037508.3428,18399242.7298);
// bbox for 16/10491/22911.png
mapnik::box2d<double> z16(-13622912.929097254,6026906.8062295765,-13621689.93664469,6028129.79868214);
{
test test_runner(params,
"benchmark/data/polygon_rendering_clip.xml",
z1);
run(test_runner,"polygon clip render z1");
}
{
test test_runner(params,
"benchmark/data/polygon_rendering_no_clip.xml",
z1);
run(test_runner,"polygon noclip render z1");
}
{
test test_runner(params,
"benchmark/data/polygon_rendering_clip.xml",
z16);
run(test_runner,"polygon clip render z16");
}
{
test test_runner(params,
"benchmark/data/polygon_rendering_no_clip.xml",
z16);
run(test_runner,"polygon noclip render z16");
}
return 0;
}

View file

@ -0,0 +1,96 @@
#include "bench_framework.hpp"
#include <mapnik/box2d.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
class test : public benchmark::test_case
{
std::string src_;
std::string dest_;
mapnik::box2d<double> from_;
mapnik::box2d<double> to_;
bool defer_proj4_init_;
public:
test(mapnik::parameters const& params,
std::string const& src,
std::string const& dest,
mapnik::box2d<double> const& from,
mapnik::box2d<double> const& to,
bool defer_proj)
: test_case(params),
src_(src),
dest_(dest),
from_(from),
to_(to),
defer_proj4_init_(defer_proj) {}
bool validate() const
{
mapnik::projection src(src_,defer_proj4_init_);
mapnik::projection dest(dest_,defer_proj4_init_);
mapnik::proj_transform tr(src,dest);
mapnik::box2d<double> bbox = from_;
if (!tr.forward(bbox)) return false;
return ((std::fabs(bbox.minx() - to_.minx()) < .5) &&
(std::fabs(bbox.maxx() - to_.maxx()) < .5) &&
(std::fabs(bbox.miny() - to_.miny()) < .5) &&
(std::fabs(bbox.maxy() - to_.maxy()) < .5)
);
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
for (int i=-180;i<180;++i)
{
for (int j=-85;j<85;++j)
{
mapnik::projection src(src_,defer_proj4_init_);
mapnik::projection dest(dest_,defer_proj4_init_);
mapnik::proj_transform tr(src,dest);
mapnik::box2d<double> box(i,j,i,j);
if (!tr.forward(box)) throw std::runtime_error("could not transform coords");
}
}
}
}
};
// echo -180 -60 | cs2cs -f "%.10f" +init=epsg:4326 +to +init=epsg:3857
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
mapnik::box2d<double> from(-180,-80,180,80);
mapnik::box2d<double> to(-20037508.3427892476,-15538711.0963092316,20037508.3427892476,15538711.0963092316);
std::string from_str("+init=epsg:4326");
std::string to_str("+init=epsg:3857");
std::string from_str2("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
std::string to_str2("+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");
test test_runner(params,
from_str,
to_str,
from,
to,
true);
run(test_runner,"lonlat->merc epsg");
test test_runner2(params,
from_str2,
to_str2,
from,
to,
true);
run(test_runner2,"lonlat->merc literal");
test test_runner3(params,
to_str,
from_str,
to,
from,
true);
run(test_runner3,"merc->lonlat epsg");
test test_runner4(params,
to_str2,
from_str2,
to,
from,
true);
return run(test_runner4,"merc->lonlat literal");
}

View file

@ -0,0 +1,100 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <stdexcept>
class test : public benchmark::test_case
{
std::string xml_;
mapnik::box2d<double> extent_;
mapnik::value_integer width_;
mapnik::value_integer height_;
std::string preview_;
public:
test(mapnik::parameters const& params)
: test_case(params),
xml_(),
extent_(),
width_(*params.get<mapnik::value_integer>("width",256)),
height_(*params.get<mapnik::value_integer>("height",256)),
preview_(*params.get<std::string>("preview",""))
{
boost::optional<std::string> map = params.get<std::string>("map");
if (!map)
{
throw std::runtime_error("please provide a --map=<path to xml> arg");
}
xml_ = *map;
boost::optional<std::string> ext = params.get<std::string>("extent");
if (ext && !ext->empty())
{
if (!extent_.from_string(*ext))
throw std::runtime_error("could not parse `extent` string" + *ext);
}
else
{
throw std::runtime_error("please provide a --extent=<minx,miny,maxx,maxy> arg");
}
}
bool validate() const
{
mapnik::Map m(width_,height_);
mapnik::load_map(m,xml_,true);
m.zoom_to_box(extent_);
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
ren.apply();
if (!preview_.empty()) mapnik::save_to_file(im,preview_);
return true;
}
void operator()() const
{
mapnik::Map m(width_,height_);
mapnik::load_map(m,xml_);
m.zoom_to_box(extent_);
for (unsigned i=0;i<iterations_;++i)
{
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
ren.apply();
}
}
};
int main(int argc, char** argv)
{
try
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
boost::optional<std::string> name = params.get<std::string>("name");
if (!name)
{
std::clog << "please provide a name for this test\n";
return -1;
}
bool success = mapnik::freetype_engine::register_fonts("./fonts", true);
if (!success) {
std::clog << "warning, did not register any new fonts!\n";
return -1;
}
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
{
test test_runner(params);
run(test_runner,*name);
}
}
catch (std::exception const& ex)
{
std::clog << ex.what() << "\n";
return -1;
}
return 0;
}

View file

@ -0,0 +1,29 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
std::string value_;
public:
test(mapnik::parameters const& params)
: test_case(params),
value_("true") {}
bool validate() const
{
bool result = false;
mapnik::util::string2bool(value_.data(),value_.data()+value_.size(),result);
if (!result) return result;
mapnik::util::string2bool(value_,result);
return (result == true);
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
bool result = false;
mapnik::util::string2bool(value_,result);
mapnik::util::string2bool(value_.data(),value_.data()+value_.size(),result);
}
}
};
BENCHMARK(test,"string->bool")

View file

@ -0,0 +1,31 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
std::string value_;
public:
test(mapnik::parameters const& params)
: test_case(params),
value_("1.23456789") {}
bool validate() const
{
double result = 0;
if (!mapnik::util::string2double(value_.data(),value_.data()+value_.size(),result)) return false;
if (result != 1.23456789) return false;
result = 0;
if (!mapnik::util::string2double(value_,result)) return false;
if (result != 1.23456789) return false;
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
double result = 0;
mapnik::util::string2double(value_,result);
mapnik::util::string2double(value_.data(),value_.data()+value_.size(),result);
}
}
};
BENCHMARK(test,"string->double")

31
benchmark/test_to_int.cpp Normal file
View file

@ -0,0 +1,31 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
std::string value_;
public:
test(mapnik::parameters const& params)
: test_case(params),
value_("123456789") {}
bool validate() const
{
mapnik::value_integer result = 0;
if (!mapnik::util::string2int(value_.data(),value_.data()+value_.size(),result)) return false;
if (result != 123456789) return false;
result = 0;
if (!mapnik::util::string2int(value_,result)) return false;
if (result != 123456789) return false;
return true;
}
void operator()() const
{
for (std::size_t i=0;i<iterations_;++i) {
mapnik::value_integer result = 0;
mapnik::util::string2int(value_,result);
mapnik::util::string2int(value_.data(),value_.data()+value_.size(),result);
}
}
};
BENCHMARK(test,"string->int")

View file

@ -0,0 +1,27 @@
#include "bench_framework.hpp"
#include <mapnik/util/conversions.hpp>
class test : public benchmark::test_case
{
double value_;
public:
test(mapnik::parameters const& params)
: test_case(params),
value_(-0.1234) {}
bool validate() const
{
std::string s;
mapnik::util::to_string(s,value_);
return (s == "-0.1234");
}
void operator()() const
{
std::string out;
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
mapnik::util::to_string(out,value_);
}
}
};
BENCHMARK(test,"to_string double->string")

View file

@ -0,0 +1,28 @@
#include "bench_framework.hpp"
#include <sstream>
class test : public benchmark::test_case
{
double value_;
public:
test(mapnik::parameters const& params)
: test_case(params),
value_(-0.1234) {}
bool validate() const
{
std::ostringstream s;
s << value_;
return (s.str() == "-0.1234");
}
void operator()() const
{
std::string out;
for (std::size_t i=0;i<iterations_;++i) {
std::ostringstream s;
s << value_;
out = s.str();
}
}
};
BENCHMARK(test,"ostringstream double->string")

View file

@ -0,0 +1,36 @@
#include "bench_framework.hpp"
#include <mapnik/unicode.hpp>
#include <mapnik/value.hpp>
class test : public benchmark::test_case
{
std::string expr_;
public:
test(mapnik::parameters const& params)
: test_case(params),
expr_("this is a fairly long string that might contain unicode") {}
bool validate() const
{
mapnik::transcoder tr_("utf-8");
mapnik::value_unicode_string ustr = tr_.transcode(expr_.data(),expr_.size());
std::string utf8;
mapnik::to_utf8(ustr,utf8);
return utf8 == expr_;
}
void operator()() const
{
mapnik::transcoder tr_("utf-8");
mapnik::value_unicode_string ustr;
for (std::size_t i=0;i<iterations_;++i) {
ustr = tr_.transcode(expr_.data(),expr_.size());
}
}
};
int main(int argc, char** argv)
{
mapnik::parameters params;
benchmark::handle_args(argc,argv,params);
test test_runner(params);
return run(test_runner,"transcode");
}

View file

@ -3,8 +3,8 @@ import random
im = mapnik.Image(256,256)
for x in range(im.width()):
for y in range(im.height()):
for x in xrange(0,im.width()):
for y in xrange(0,im.height()):
r = int(random.random() * 255)
g = random.random() * 255
b = random.random() * 255

211
bindings/python/build.py Normal file
View file

@ -0,0 +1,211 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2013 Artem Pavlenko
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#
import os, re, sys, glob
from subprocess import Popen, PIPE
Import('env')
def call(cmd, silent=True):
stdin, stderr = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).communicate()
if not stderr:
return stdin.strip()
elif not silent:
print stderr
def run_2to3(*args,**kwargs):
call('2to3 -w %s' % os.path.dirname(kwargs['target'][0].path))
def is_py3():
return 'True' in os.popen('''%s -c "import sys as s;s.stdout.write(str(s.version_info[0] == 3))"''' % env['PYTHON']).read().strip()
prefix = env['PREFIX']
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
py_env = env.Clone()
py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
py_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
py_env['LIBS'] = [env['MAPNIK_NAME'],env['BOOST_PYTHON_LIB']]
link_all_libs = env['LINKING'] == 'static' or env['RUNTIME_LINK'] == 'static' or (env['PLATFORM'] == 'Darwin' and not env['PYTHON_DYNAMIC_LOOKUP'])
if link_all_libs:
py_env.AppendUnique(LIBS=env['LIBMAPNIK_LIBS'])
# even though boost_thread is no longer used in mapnik core
# we need to link in for boost_python to avoid missing symbol: _ZN5boost6detail12get_tss_dataEPKv / boost::detail::get_tss_data
py_env.AppendUnique(LIBS = 'boost_thread%s' % env['BOOST_APPEND'])
# note: on linux -lrt must be linked after thread to avoid: undefined symbol: clock_gettime
if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
py_env.AppendUnique(LIBS='rt')
# TODO - do solaris/fedora need direct linking too?
if env['PLATFORM'] == 'Darwin':
##### Python linking on OS X is tricky ###
# Confounding problems are:
# 1) likelyhood of multiple python installs of the same major.minor version
# because apple supplies python built-in and many users may have installed
# further versions using macports
# 2) boost python directly links to a python version
# 3) the below will directly link _mapnik.so to a python version
# 4) _mapnik.so must link to the same python lib as boost_python.dylib otherwise
# python will Abort with a Version Mismatch error.
# See https://github.com/mapnik/mapnik/issues/453 for the seeds of a better approach
# for now we offer control over method of direct linking...
# The default below is to link against the python dylib in the form of
#/path/to/Python.framework/Python instead of -lpython
# http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man1/ld.1.html
if env['PYTHON_DYNAMIC_LOOKUP']:
python_link_flag = '-undefined dynamic_lookup'
elif env['FRAMEWORK_PYTHON']:
if env['FRAMEWORK_SEARCH_PATH']:
# if the user has supplied a custom root path to search for
# a given Python framework, then use that to direct the linker
python_link_flag = '-F%s -framework Python -Z' % env['FRAMEWORK_SEARCH_PATH']
else:
# otherwise be as explicit as possible for linking to the same Framework
# as the executable we are building with (or is pointed to by the PYTHON variable)
# otherwise we may accidentally link against either:
# /System/Library/Frameworks/Python.framework/Python/Versions/
# or
# /Library/Frameworks/Python.framework/Python/Versions/
# See: https://github.com/mapnik/mapnik/issues/380
link_prefix = env['PYTHON_SYS_PREFIX']
if '.framework' in link_prefix:
python_link_flag = '-F%s -framework Python -Z' % os.path.dirname(link_prefix.split('.')[0])
elif '/System' in link_prefix:
python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z'
else:
# should we fall back to -lpython here?
python_link_flag = '-F/ -framework Python'
# if we are not linking to a framework then use the *nix standard approach
else:
# TODO - do we need to pass -L/?
python_link_flag = '-lpython%s' % env['PYTHON_VERSION']
elif env['PLATFORM'] == 'SunOS':
# make sure to explicitly link mapnik.so against
# libmapnik in its installed location
python_link_flag = '-R%s' % env['MAPNIK_LIB_BASE']
else:
# all other platforms we don't directly link python
python_link_flag = ''
if env['CUSTOM_LDFLAGS']:
linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], python_link_flag)
else:
linkflags = python_link_flag
paths = '''
"""Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons)."""
from os.path import normpath,join,dirname
mapniklibpath = '%s'
mapniklibpath = normpath(join(dirname(__file__),mapniklibpath))
'''
paths += "inputpluginspath = join(mapniklibpath,'input')\n"
if env['SYSTEM_FONTS']:
paths += "fontscollectionpath = normpath('%s')\n" % env['SYSTEM_FONTS']
else:
paths += "fontscollectionpath = join(mapniklibpath,'fonts')\n"
paths += "__all__ = [mapniklibpath,inputpluginspath,fontscollectionpath]\n"
if not os.path.exists('mapnik'):
os.mkdir('mapnik')
file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR']))
# force open perms temporarily so that `sudo scons install`
# does not later break simple non-install non-sudo rebuild
try:
os.chmod('mapnik/paths.py',0666)
except: pass
# install the shared object beside the module directory
sources = glob.glob('*.cpp')
if 'install' in COMMAND_LINE_TARGETS:
# install the core mapnik python files, including '__init__.py'
init_files = glob.glob('mapnik/*.py')
if 'mapnik/paths.py' in init_files:
init_files.remove('mapnik/paths.py')
init_module = env.Install(target_path, init_files)
env.Alias(target='install', source=init_module)
# install mapnik2 module which redirects to mapnik and issues DeprecatedWarning
init_mapnik2 = env.Install(target_path_deprecated, 'mapnik2/__init__.py')
env.Alias(target='install', source=init_mapnik2)
# fix perms and install the custom generated 'paths.py'
targetp = os.path.join(target_path,'paths.py')
env.Alias("install", targetp)
# use env.Command rather than env.Install
# to enable setting proper perms on `paths.py`
env.Command( targetp, 'mapnik/paths.py',
[
Copy("$TARGET","$SOURCE"),
Chmod("$TARGET", 0644),
])
if 'uninstall' not in COMMAND_LINE_TARGETS:
if env['HAS_CAIRO']:
py_env.Append(CPPPATH = env['CAIRO_CPPPATHS'])
py_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
if link_all_libs:
py_env.Append(LIBS=env['CAIRO_ALL_LIBS'])
if env['HAS_PYCAIRO']:
py_env.Append(CPPDEFINES = '-DHAVE_PYCAIRO')
py_env.Append(CPPPATH = env['PYCAIRO_PATHS'])
_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
Depends(_mapnik, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
if env['PLATFORM'] == 'SunOS' and env['PYTHON_IS_64BIT']:
# http://mail.python.org/pipermail/python-dev/2006-August/068528.html
cxx_module_path = os.path.join(target_path,'64')
else:
cxx_module_path = target_path
if 'uninstall' not in COMMAND_LINE_TARGETS:
pymapniklib = env.Install(cxx_module_path,_mapnik)
py_env.Alias(target='install',source=pymapniklib)
if 'install' in COMMAND_LINE_TARGETS:
if is_py3():
env.AddPostAction(pymapniklib, run_2to3)
env['create_uninstall_target'](env, target_path)
env['create_uninstall_target'](env, target_path_deprecated)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
#
# This file is part of Mapnik (C++/Python mapping toolkit)
# Copyright (C) 2011 Artem Pavlenko
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# mapnik2 module (Deprecated)
import warnings
from mapnik import *
warnings.simplefilter("default")
msg=""" mapnik2 module has been deprecated,
please use 'import mapnik' """
warnings.warn(msg, DeprecationWarning)

View file

@ -0,0 +1,95 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
//mapnik
#include <mapnik/color.hpp>
using mapnik::color;
struct color_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const color& c)
{
using namespace boost::python;
return boost::python::make_tuple(c.red(),c.green(),c.blue(),c.alpha());
}
};
void export_color ()
{
using namespace boost::python;
class_<color>("Color", init<int,int,int,int>(
( arg("r"), arg("g"), arg("b"), arg("a") ),
"Creates a new color from its RGB components\n"
"and an alpha value.\n"
"All values between 0 and 255.\n")
)
.def(init<int,int,int>(
( arg("r"), arg("g"), arg("b") ),
"Creates a new color from its RGB components.\n"
"All values between 0 and 255.\n")
)
.def(init<std::string>(
( arg("color_string") ),
"Creates a new color from its CSS string representation.\n"
"The string may be a CSS color name (e.g. 'blue')\n"
"or a hex color string (e.g. '#0000ff').\n")
)
.add_property("r",
&color::red,
&color::set_red,
"Gets or sets the red component.\n"
"The value is between 0 and 255.\n")
.add_property("g",
&color::green,
&color::set_green,
"Gets or sets the green component.\n"
"The value is between 0 and 255.\n")
.add_property("b",
&color::blue,
&color::set_blue,
"Gets or sets the blue component.\n"
"The value is between 0 and 255.\n")
.add_property("a",
&color::alpha,
&color::set_alpha,
"Gets or sets the alpha component.\n"
"The value is between 0 and 255.\n")
.def(self == self)
.def(self != self)
.def_pickle(color_pickle_suite())
.def("__str__",&color::to_string)
.def("packed",&color::rgba)
.def("to_hex_string",&color::to_hex_string,
"Returns the hexadecimal representation of this color.\n"
"\n"
"Example:\n"
">>> c = Color('blue')\n"
">>> c.to_hex_string()\n"
"'#0000ff'\n")
;
}

View file

@ -0,0 +1,64 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
// mapnik
#include <mapnik/coord.hpp>
using mapnik::coord;
struct coord_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const coord<double,2>& c)
{
using namespace boost::python;
return boost::python::make_tuple(c.x,c.y);
}
};
void export_coord()
{
using namespace boost::python;
class_<coord<double,2> >("Coord",init<double, double>(
// class docstring is in mapnik/__init__.py, class _Coord
(arg("x"), arg("y")),
"Constructs a new point with the given coordinates.\n")
)
.def_pickle(coord_pickle_suite())
.def_readwrite("x", &coord<double,2>::x,
"Gets or sets the x/lon coordinate of the point.\n")
.def_readwrite("y", &coord<double,2>::y,
"Gets or sets the y/lat coordinate of the point.\n")
.def(self == self) // __eq__
.def(self + self) // __add__
.def(self + float())
.def(float() + self)
.def(self - self) // __sub__
.def(self - float())
.def(self * float()) //__mult__
.def(float() * self)
.def(self / float()) // __div__
;
}

View file

@ -0,0 +1,197 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
// stl
#include <vector>
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/memory_datasource.hpp>
using mapnik::datasource;
using mapnik::memory_datasource;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
namespace
{
//user-friendly wrapper that uses Python dictionary
using namespace boost::python;
boost::shared_ptr<mapnik::datasource> create_datasource(dict const& d)
{
mapnik::parameters params;
boost::python::list keys=d.keys();
for (int i=0; i < len(keys); ++i)
{
std::string key = extract<std::string>(keys[i]);
object obj = d[key];
if (PyUnicode_Check(obj.ptr()))
{
PyObject* temp = PyUnicode_AsUTF8String(obj.ptr());
if (temp)
{
#if PY_VERSION_HEX >= 0x03000000
char* c_str = PyBytes_AsString(temp);
#else
char* c_str = PyString_AsString(temp);
#endif
params[key] = std::string(c_str);
Py_DecRef(temp);
}
continue;
}
extract<std::string> ex0(obj);
extract<mapnik::value_integer> ex1(obj);
extract<double> ex2(obj);
if (ex0.check())
{
params[key] = ex0();
}
else if (ex1.check())
{
params[key] = ex1();
}
else if (ex2.check())
{
params[key] = ex2();
}
}
return mapnik::datasource_cache::instance().create(params);
}
boost::python::dict describe(boost::shared_ptr<mapnik::datasource> const& ds)
{
boost::python::dict description;
mapnik::layer_descriptor ld = ds->get_descriptor();
description["type"] = ds->type();
description["name"] = ld.get_name();
description["geometry_type"] = ds->get_geometry_type();
description["encoding"] = ld.get_encoding();
return description;
}
boost::python::list fields(boost::shared_ptr<mapnik::datasource> const& ds)
{
boost::python::list flds;
if (ds)
{
layer_descriptor ld = ds->get_descriptor();
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
for (; it != end; ++it)
{
flds.append(it->get_name());
}
}
return flds;
}
boost::python::list field_types(boost::shared_ptr<mapnik::datasource> const& ds)
{
boost::python::list fld_types;
if (ds)
{
layer_descriptor ld = ds->get_descriptor();
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
for (; it != end; ++it)
{
unsigned type = it->get_type();
if (type == mapnik::Integer)
// this crashes, so send back strings instead
//fld_types.append(boost::python::object(boost::python::handle<>(&PyInt_Type)));
fld_types.append(boost::python::str("int"));
else if (type == mapnik::Float)
fld_types.append(boost::python::str("float"));
else if (type == mapnik::Double)
fld_types.append(boost::python::str("float"));
else if (type == mapnik::String)
fld_types.append(boost::python::str("str"));
else if (type == mapnik::Boolean)
fld_types.append(boost::python::str("bool"));
else if (type == mapnik::Geometry)
fld_types.append(boost::python::str("geometry"));
else if (type == mapnik::Object)
fld_types.append(boost::python::str("object"));
else
fld_types.append(boost::python::str("unknown"));
}
}
return fld_types;
}}
mapnik::parameters const& (mapnik::datasource::*params_const)() const = &mapnik::datasource::params;
void export_datasource()
{
using namespace boost::python;
enum_<mapnik::datasource::datasource_t>("DataType")
.value("Vector",mapnik::datasource::Vector)
.value("Raster",mapnik::datasource::Raster)
;
enum_<mapnik::datasource::geometry_t>("DataGeometryType")
.value("Point",mapnik::datasource::Point)
.value("LineString",mapnik::datasource::LineString)
.value("Polygon",mapnik::datasource::Polygon)
.value("Collection",mapnik::datasource::Collection)
;
class_<datasource,boost::shared_ptr<datasource>,
boost::noncopyable>("Datasource",no_init)
.def("type",&datasource::type)
.def("geometry_type",&datasource::get_geometry_type)
.def("describe",&describe)
.def("envelope",&datasource::envelope)
.def("features",&datasource::features)
.def("fields",&fields)
.def("field_types",&field_types)
.def("features_at_point",&datasource::features_at_point, (arg("coord"),arg("tolerance")=0))
.def("params",make_function(params_const,return_value_policy<copy_const_reference>()),
"The configuration parameters of the data source. "
"These vary depending on the type of data source.")
;
def("CreateDatasource",&create_datasource);
class_<memory_datasource, bases<datasource>, boost::noncopyable>("MemoryDatasource", init<>())
.def("add_feature",&memory_datasource::push,
"Adds a Feature:\n"
">>> ms = MemoryDatasource()\n"
">>> feature = Feature(1)\n"
">>> ms.add_feature(Feature(1))\n")
.def("num_features",&memory_datasource::size)
;
}

View file

@ -0,0 +1,92 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#include <mapnik/datasource_cache.hpp>
namespace {
using namespace boost::python;
boost::shared_ptr<mapnik::datasource> create_datasource(const dict& d)
{
mapnik::parameters params;
boost::python::list keys=d.keys();
for (int i=0; i<len(keys); ++i)
{
std::string key = extract<std::string>(keys[i]);
object obj = d[key];
extract<std::string> ex0(obj);
extract<mapnik::value_integer> ex1(obj);
extract<double> ex2(obj);
if (ex0.check())
{
params[key] = ex0();
}
else if (ex1.check())
{
params[key] = ex1();
}
else if (ex2.check())
{
params[key] = ex2();
}
}
return mapnik::datasource_cache::instance().create(params);
}
void register_datasources(std::string const& path)
{
mapnik::datasource_cache::instance().register_datasources(path);
}
std::vector<std::string> plugin_names()
{
return mapnik::datasource_cache::instance().plugin_names();
}
std::string plugin_directories()
{
return mapnik::datasource_cache::instance().plugin_directories();
}
}
void export_datasource_cache()
{
using mapnik::datasource_cache;
class_<datasource_cache,
boost::noncopyable>("DatasourceCache",no_init)
.def("create",&create_datasource)
.staticmethod("create")
.def("register_datasources",&register_datasources)
.staticmethod("register_datasources")
.def("plugin_names",&plugin_names)
.staticmethod("plugin_names")
.def("plugin_directories",&plugin_directories)
.staticmethod("plugin_directories")
;
}

View file

@ -0,0 +1,95 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED
#define MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED
#include <boost/python/converter/registered.hpp> // for registered
#include <boost/python/enum.hpp> // for enum_
#include <boost/python/implicit.hpp> // for implicitly_convertible
#include <boost/python/to_python_converter.hpp>
namespace mapnik {
template <typename EnumWrapper>
class enumeration_ :
public boost::python::enum_<typename EnumWrapper::native_type>
{
// some short cuts
typedef boost::python::enum_<typename EnumWrapper::native_type> base_type;
typedef typename EnumWrapper::native_type native_type;
public:
enumeration_() :
base_type( EnumWrapper::get_name().c_str() )
{
init();
}
enumeration_(const char * python_alias) :
base_type( python_alias )
{
init();
}
#if BOOST_VERSION >= 103500
enumeration_(const char * python_alias, const char * doc) :
base_type( python_alias, doc )
#else
enumeration_(const char * python_alias, const char * /*doc*/) :
// Boost.Python < 1.35.0 doesn't support
// docstrings for enums so we ignore it.
base_type( python_alias )
#endif
{
init();
}
private:
struct converter
{
static PyObject* convert(EnumWrapper const& v)
{
// Redirect conversion to a static method of our base class's
// base class. A free template converter will not work because
// the base_type::base typedef is protected.
// Lets hope MSVC agrees that this is legal C++
using namespace boost::python::converter;
return base_type::base::to_python(
registered<native_type>::converters.m_class_object
, static_cast<long>( v ));
}
};
void init() {
boost::python::implicitly_convertible<native_type, EnumWrapper>();
boost::python::to_python_converter<EnumWrapper, converter >();
for (unsigned i = 0; i < EnumWrapper::MAX; ++i)
{
// Register the strings already defined for this enum.
base_type::value( EnumWrapper::get_string( i ), native_type( i ) );
}
}
};
} // end of namespace mapnik
#endif // MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED

View file

@ -0,0 +1,293 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/value_error.hpp>
using mapnik::coord;
using mapnik::box2d;
struct envelope_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const box2d<double>& e)
{
using namespace boost::python;
return boost::python::make_tuple(e.minx(),e.miny(),e.maxx(),e.maxy());
}
};
box2d<double> from_string(std::string const& s)
{
box2d<double> bbox;
bool success = bbox.from_string(s);
if (success)
{
return bbox;
}
else
{
std::stringstream ss;
ss << "Could not parse bbox from string: '" << s << "'";
throw mapnik::value_error(ss.str());
}
}
//define overloads here
void (box2d<double>::*width_p1)(double) = &box2d<double>::width;
double (box2d<double>::*width_p2)() const = &box2d<double>::width;
void (box2d<double>::*height_p1)(double) = &box2d<double>::height;
double (box2d<double>::*height_p2)() const = &box2d<double>::height;
void (box2d<double>::*expand_to_include_p1)(double,double) = &box2d<double>::expand_to_include;
void (box2d<double>::*expand_to_include_p2)(coord<double,2> const& ) = &box2d<double>::expand_to_include;
void (box2d<double>::*expand_to_include_p3)(box2d<double> const& ) = &box2d<double>::expand_to_include;
bool (box2d<double>::*contains_p1)(double,double) const = &box2d<double>::contains;
bool (box2d<double>::*contains_p2)(coord<double,2> const&) const = &box2d<double>::contains;
bool (box2d<double>::*contains_p3)(box2d<double> const&) const = &box2d<double>::contains;
//intersects
bool (box2d<double>::*intersects_p1)(double,double) const = &box2d<double>::intersects;
bool (box2d<double>::*intersects_p2)(coord<double,2> const&) const = &box2d<double>::intersects;
bool (box2d<double>::*intersects_p3)(box2d<double> const&) const = &box2d<double>::intersects;
// intersect
box2d<double> (box2d<double>::*intersect)(box2d<double> const&) const = &box2d<double>::intersect;
// re_center
void (box2d<double>::*re_center_p1)(double,double) = &box2d<double>::re_center;
void (box2d<double>::*re_center_p2)(coord<double,2> const& ) = &box2d<double>::re_center;
// clip
void (box2d<double>::*clip)(box2d<double> const&) = &box2d<double>::clip;
// pad
void (box2d<double>::*pad)(double) = &box2d<double>::pad;
// deepcopy
box2d<double> box2d_deepcopy(box2d<double> & obj, boost::python::dict memo)
{
// FIXME::ignore memo for now
box2d<double> result(obj);
return result;
}
void export_envelope()
{
using namespace boost::python;
class_<box2d<double> >("Box2d",
// class docstring is in mapnik/__init__.py, class _Coord
init<double,double,double,double>(
(arg("minx"),arg("miny"),arg("maxx"),arg("maxy")),
"Constructs a new envelope from the coordinates\n"
"of its lower left and upper right corner points.\n"))
.def(init<>("Equivalent to Box2d(0, 0, -1, -1).\n"))
.def(init<const coord<double,2>&, const coord<double,2>&>(
(arg("ll"),arg("ur")),
"Equivalent to Box2d(ll.x, ll.y, ur.x, ur.y).\n"))
.def("from_string",from_string)
.staticmethod("from_string")
.add_property("minx", &box2d<double>::minx,
"X coordinate for the lower left corner")
.add_property("miny", &box2d<double>::miny,
"Y coordinate for the lower left corner")
.add_property("maxx", &box2d<double>::maxx,
"X coordinate for the upper right corner")
.add_property("maxy", &box2d<double>::maxy,
"Y coordinate for the upper right corner")
.def("center", &box2d<double>::center,
"Returns the coordinates of the center of the bounding box.\n"
"\n"
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.center()\n"
"Coord(50, 50)\n")
.def("center", re_center_p1,
(arg("x"), arg("y")),
"Moves the envelope so that the given coordinates become its new center.\n"
"The width and the height are preserved.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.center(60, 60)\n"
">>> e.center()\n"
"Coord(60.0,60.0)\n"
">>> (e.width(), e.height())\n"
"(100.0, 100.0)\n"
">>> e\n"
"Box2d(10.0, 10.0, 110.0, 110.0)\n"
)
.def("center", re_center_p2,
(arg("Coord")),
"Moves the envelope so that the given coordinates become its new center.\n"
"The width and the height are preserved.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.center(Coord60, 60)\n"
">>> e.center()\n"
"Coord(60.0,60.0)\n"
">>> (e.width(), e.height())\n"
"(100.0, 100.0)\n"
">>> e\n"
"Box2d(10.0, 10.0, 110.0, 110.0)\n"
)
.def("clip", clip,
(arg("other")),
"Clip the envelope based on the bounds of another envelope.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> c = Box2d(-50, -50, 50, 50)\n"
">>> e.clip(c)\n"
">>> e\n"
"Box2d(0.0,0.0,50.0,50.0\n"
)
.def("pad", pad,
(arg("padding")),
"Pad the envelope based on a padding value.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.pad(10)\n"
">>> e\n"
"Box2d(-10.0,-10.0,110.0,110.0\n"
)
.def("width", width_p1,
(arg("new_width")),
"Sets the width to new_width of the envelope preserving its center.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.width(120)\n"
">>> e.center()\n"
"Coord(50.0,50.0)\n"
">>> e\n"
"Box2d(-10.0, 0.0, 110.0, 100.0)\n"
)
.def("width", width_p2,
"Returns the width of this envelope.\n"
)
.def("height", height_p1,
(arg("new_height")),
"Sets the height to new_height of the envelope preserving its center.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.height(120)\n"
">>> e.center()\n"
"Coord(50.0,50.0)\n"
">>> e\n"
"Box2d(0.0, -10.0, 100.0, 110.0)\n"
)
.def("height", height_p2,
"Returns the height of this envelope.\n"
)
.def("expand_to_include",expand_to_include_p1,
(arg("x"),arg("y")),
"Expands this envelope to include the point given by x and y.\n"
"\n"
"Example:\n",
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.expand_to_include(110, 110)\n"
">>> e\n"
"Box2d(0.0, 00.0, 110.0, 110.0)\n"
)
.def("expand_to_include",expand_to_include_p2,
(arg("p")),
"Equivalent to expand_to_include(p.x, p.y)\n"
)
.def("expand_to_include",expand_to_include_p3,
(arg("other")),
"Equivalent to:\n"
" expand_to_include(other.minx, other.miny)\n"
" expand_to_include(other.maxx, other.maxy)\n"
)
.def("contains",contains_p1,
(arg("x"),arg("y")),
"Returns True iff this envelope contains the point\n"
"given by x and y.\n"
)
.def("contains",contains_p2,
(arg("p")),
"Equivalent to contains(p.x, p.y)\n"
)
.def("contains",contains_p3,
(arg("other")),
"Equivalent to:\n"
" contains(other.minx, other.miny) and contains(other.maxx, other.maxy)\n"
)
.def("intersects",intersects_p1,
(arg("x"),arg("y")),
"Returns True iff this envelope intersects the point\n"
"given by x and y.\n"
"\n"
"Note: For points, intersection is equivalent\n"
"to containment, i.e. the following holds:\n"
" e.contains(x, y) == e.intersects(x, y)\n"
)
.def("intersects",intersects_p2,
(arg("p")),
"Equivalent to contains(p.x, p.y)\n")
.def("intersects",intersects_p3,
(arg("other")),
"Returns True iff this envelope intersects the other envelope,\n"
"This relationship is symmetric."
"\n"
"Example:\n"
">>> e1 = Box2d(0, 0, 100, 100)\n"
">>> e2 = Box2d(50, 50, 150, 150)\n"
">>> e1.intersects(e2)\n"
"True\n"
">>> e1.contains(e2)\n"
"False\n"
)
.def("intersect",intersect,
(arg("other")),
"Returns the overlap of this envelope and the other envelope\n"
"as a new envelope.\n"
"\n"
"Example:\n"
">>> e1 = Box2d(0, 0, 100, 100)\n"
">>> e2 = Box2d(50, 50, 150, 150)\n"
">>> e1.intersect(e2)\n"
"Box2d(50.0, 50.0, 100.0, 100.0)\n"
)
.def(self == self) // __eq__
.def(self != self) // __neq__
.def(self + self) // __add__
.def(self * float()) // __mult__
.def(float() * self)
.def(self / float()) // __div__
.def("__getitem__",&box2d<double>::operator[])
.def("valid",&box2d<double>::valid)
.def_pickle(envelope_pickle_suite())
.def("__deepcopy__", &box2d_deepcopy)
;
}

View file

@ -0,0 +1,102 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
#include <boost/variant.hpp>
#include <boost/noncopyable.hpp>
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/value.hpp>
using mapnik::expression_ptr;
using mapnik::parse_expression;
using mapnik::to_expression_string;
using mapnik::path_expression_ptr;
// expression
expression_ptr parse_expression_(std::string const& wkt)
{
return parse_expression(wkt,"utf8");
}
std::string expression_to_string_(mapnik::expr_node const& expr)
{
return mapnik::to_expression_string(expr);
}
mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::feature_impl const& f)
{
// will be auto-converted to proper python type by `mapnik_value_to_python`
return boost::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value>(f),expr);
}
bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::feature_impl const& f)
{
return boost::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value>(f),expr).to_bool();
}
// path expression
path_expression_ptr parse_path_(std::string const& path)
{
return mapnik::parse_path(path);
}
std::string path_to_string_(mapnik::path_expression const& expr)
{
return mapnik::path_processor_type::to_string(expr);
}
std::string path_evaluate_(mapnik::path_expression const& expr, mapnik::feature_impl const& f)
{
return mapnik::path_processor_type::evaluate(expr, f);
}
void export_expression()
{
using namespace boost::python;
class_<mapnik::expr_node ,boost::noncopyable>("Expression",
"TODO"
"",no_init)
.def("evaluate", &expression_evaluate_)
.def("to_bool", &expression_evaluate_to_bool_)
.def("__str__",&expression_to_string_);
;
def("Expression",&parse_expression_,(arg("expr")),"Expression string");
class_<mapnik::path_expression ,boost::noncopyable>("PathExpression",
"TODO"
"",no_init)
.def("evaluate", &path_evaluate_) // note: "pass" is a reserved word in Python
.def("__str__",&path_to_string_);
;
def("PathExpression",&parse_path_,(arg("expr")),"PathExpression string");
}

View file

@ -0,0 +1,256 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python/suite/indexing/indexing_suite.hpp>
//#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
// mapnik
#include <mapnik/value_types.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/json/feature_parser.hpp>
#include <mapnik/json/geojson_generator.hpp>
#include <mapnik/json/generic_json.hpp>
// stl
#include <stdexcept>
namespace {
using mapnik::geometry_utils;
using mapnik::from_wkt;
using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;
mapnik::geometry_type const& (mapnik::feature_impl::*get_geometry_by_const_ref)(std::size_t) const = &mapnik::feature_impl::get_geometry;
boost::ptr_vector<mapnik::geometry_type> const& (mapnik::feature_impl::*get_paths_by_const_ref)() const = &mapnik::feature_impl::paths;
void feature_add_geometries_from_wkb(mapnik::feature_impl &feature, std::string wkb)
{
bool result = geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
if (!result) throw std::runtime_error("Failed to parse WKB");
}
void feature_add_geometries_from_wkt(mapnik::feature_impl &feature, std::string wkt)
{
bool result = mapnik::from_wkt(wkt, feature.paths());
if (!result) throw std::runtime_error("Failed to parse WKT");
}
mapnik::feature_ptr from_geojson_impl(std::string const& json, mapnik::context_ptr const& ctx)
{
mapnik::transcoder tr("utf8");
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
mapnik::json::generic_json<std::string::const_iterator> json_base;
mapnik::json::feature_parser<std::string::const_iterator> parser(json_base, tr);
if (!parser.parse(json.begin(), json.end(), *feature))
{
throw std::runtime_error("Failed to parse geojson feature");
}
return feature;
}
std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
std::string json;
mapnik::json::feature_generator g;
if (!g.generate(json,feature))
{
throw std::runtime_error("Failed to generate GeoJSON");
}
return json;
}
mapnik::value __getitem__(mapnik::feature_impl const& feature, std::string const& name)
{
return feature.get(name);
}
mapnik::value __getitem2__(mapnik::feature_impl const& feature, std::size_t index)
{
return feature.get(index);
}
void __setitem__(mapnik::feature_impl & feature, std::string const& name, mapnik::value const& val)
{
feature.put_new(name,val);
}
boost::python::dict attributes(mapnik::feature_impl const& f)
{
boost::python::dict attributes;
feature_kv_iterator itr = f.begin();
feature_kv_iterator end = f.end();
for ( ;itr!=end; ++itr)
{
attributes[boost::get<0>(*itr)] = boost::get<1>(*itr);
}
return attributes;
}
} // end anonymous namespace
struct unicode_string_from_python_str
{
unicode_string_from_python_str()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<mapnik::value_unicode_string>());
}
static void* convertible(PyObject* obj_ptr)
{
if (!(
#if PY_VERSION_HEX >= 0x03000000
PyBytes_Check(obj_ptr)
#else
PyString_Check(obj_ptr)
#endif
|| PyUnicode_Check(obj_ptr)))
return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
char * value=0;
if (PyUnicode_Check(obj_ptr)) {
PyObject *encoded = PyUnicode_AsEncodedString(obj_ptr, "utf8", "replace");
if (encoded) {
#if PY_VERSION_HEX >= 0x03000000
value = PyBytes_AsString(encoded);
#else
value = PyString_AsString(encoded);
#endif
Py_DecRef(encoded);
}
} else {
#if PY_VERSION_HEX >= 0x03000000
value = PyBytes_AsString(obj_ptr);
#else
value = PyString_AsString(obj_ptr);
#endif
}
if (value == 0) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage<mapnik::value_unicode_string>*)
data)->storage.bytes;
new (storage) mapnik::value_unicode_string(value);
data->convertible = storage;
}
};
struct value_null_from_python
{
value_null_from_python()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<mapnik::value_null>());
}
static void* convertible(PyObject* obj_ptr)
{
if (obj_ptr == Py_None) return obj_ptr;
return 0;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
if (obj_ptr != Py_None) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage<mapnik::value_null>*)
data)->storage.bytes;
new (storage) mapnik::value_null();
data->convertible = storage;
}
};
void export_feature()
{
using namespace boost::python;
// Python to mapnik::value converters
// NOTE: order matters here. For example value_null must be listed before
// bool otherwise Py_None will be interpreted as bool (false)
implicitly_convertible<mapnik::value_unicode_string,mapnik::value>();
implicitly_convertible<mapnik::value_null,mapnik::value>();
implicitly_convertible<mapnik::value_integer,mapnik::value>();
implicitly_convertible<mapnik::value_double,mapnik::value>();
implicitly_convertible<mapnik::value_bool,mapnik::value>();
// http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
unicode_string_from_python_str();
value_null_from_python();
class_<context_type,context_ptr,boost::noncopyable>
("Context",init<>("Default ctor."))
.def("push", &context_type::push)
;
class_<mapnik::feature_impl,boost::shared_ptr<mapnik::feature_impl>,
boost::noncopyable>("Feature",init<context_ptr,mapnik::value_integer>("Default ctor."))
.def("id",&mapnik::feature_impl::id)
.def("__str__",&mapnik::feature_impl::to_string)
.def("add_geometries_from_wkb", &feature_add_geometries_from_wkb)
.def("add_geometries_from_wkt", &feature_add_geometries_from_wkt)
.def("add_geometry", &mapnik::feature_impl::add_geometry)
.def("num_geometries",&mapnik::feature_impl::num_geometries)
.def("get_geometry", make_function(get_geometry_by_const_ref,return_value_policy<reference_existing_object>()))
.def("geometries",make_function(get_paths_by_const_ref,return_value_policy<reference_existing_object>()))
.def("envelope", &mapnik::feature_impl::envelope)
.def("has_key", &mapnik::feature_impl::has_key)
.add_property("attributes",&attributes)
.def("__setitem__",&__setitem__)
.def("__contains__",&__getitem__)
.def("__getitem__",&__getitem__)
.def("__getitem__",&__getitem2__)
.def("__len__", &mapnik::feature_impl::size)
.def("context",&mapnik::feature_impl::context)
.def("to_geojson",&feature_to_geojson)
.def("from_geojson",from_geojson_impl)
.staticmethod("from_geojson")
;
}

View file

@ -0,0 +1,84 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
namespace {
using namespace boost::python;
inline list features(mapnik::featureset_ptr const& itr)
{
list l;
while (true)
{
mapnik::feature_ptr fp = itr->next();
if (!fp)
{
break;
}
l.append(fp);
}
return l;
}
inline object pass_through(object const& o) { return o; }
inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr)
{
mapnik::feature_ptr f = itr->next();
if (!f)
{
PyErr_SetString(PyExc_StopIteration, "No more features.");
boost::python::throw_error_already_set();
}
return f;
}
}
void export_featureset()
{
using namespace boost::python;
class_<mapnik::Featureset,boost::shared_ptr<mapnik::Featureset>,
boost::noncopyable>("Featureset",no_init)
.def("__iter__",pass_through)
.def("next",next)
.add_property("features",features,
"The list of features.\n"
"\n"
"Usage:\n"
">>> m.query_map_point(0, 10, 10)\n"
"<mapnik._mapnik.Featureset object at 0x1004d2938>\n"
">>> fs = m.query_map_point(0, 10, 10)\n"
">>> for f in fs.features:\n"
">>> print f\n"
"<mapnik.Feature object at 0x105e64140>\n"
)
;
}

View file

@ -0,0 +1,49 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#include <mapnik/font_engine_freetype.hpp>
void export_font_engine()
{
using mapnik::freetype_engine;
using mapnik::singleton;
using mapnik::CreateStatic;
using namespace boost::python;
class_<singleton<freetype_engine,CreateStatic>,boost::noncopyable>("Singleton",no_init)
.def("instance",&singleton<freetype_engine,CreateStatic>::instance,
return_value_policy<reference_existing_object>())
.staticmethod("instance")
;
class_<freetype_engine,bases<singleton<freetype_engine,CreateStatic> >,
boost::noncopyable>("FontEngine",no_init)
.def("register_font",&freetype_engine::register_font)
.def("register_fonts",&freetype_engine::register_fonts)
.def("face_names",&freetype_engine::face_names)
.staticmethod("register_font")
.staticmethod("register_fonts")
.staticmethod("face_names")
;
}

View file

@ -0,0 +1,56 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
//mapnik
#include <mapnik/font_set.hpp>
using mapnik::font_set;
void export_fontset ()
{
using namespace boost::python;
class_<font_set>("FontSet", init<std::string const&>("default fontset constructor")
)
.add_property("name",
make_function(&font_set::get_name,return_value_policy<copy_const_reference>()),
&font_set::set_name,
"Get/Set the name of the FontSet.\n"
)
.def("add_face_name",&font_set::add_face_name,
(arg("name")),
"Add a face-name to the fontset.\n"
"\n"
"Example:\n"
">>> fs = Fontset('book-fonts')\n"
">>> fs.add_face_name('DejaVu Sans Book')\n")
.add_property("names",make_function
(&font_set::get_face_names,
return_value_policy<reference_existing_object>()),
"List of face names belonging to a FontSet.\n"
)
;
}

View file

@ -0,0 +1,40 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <boost/python.hpp>
#include <mapnik/gamma_method.hpp>
#include "mapnik_enumeration.hpp"
void export_gamma_method()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::gamma_method_e>("gamma_method")
.value("POWER", mapnik::GAMMA_POWER)
.value("LINEAR",mapnik::GAMMA_LINEAR)
.value("NONE", mapnik::GAMMA_NONE)
.value("THRESHOLD", mapnik::GAMMA_THRESHOLD)
.value("MULTIPLY", mapnik::GAMMA_MULTIPLY)
;
}

View file

@ -0,0 +1,315 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/iterator.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp>
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/json/geometry_parser.hpp>
#include <mapnik/json/geojson_generator.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION >= 104700
#include <mapnik/util/geometry_to_wkb.hpp>
#include <mapnik/util/geometry_to_wkt.hpp>
#include <mapnik/util/geometry_to_svg.hpp>
#endif
// stl
#include <stdexcept>
namespace {
using mapnik::from_wkt;
using mapnik::geometry_type;
typedef boost::ptr_vector<geometry_type> path_type;
geometry_type const& getitem_impl(path_type & p, int key)
{
if (key >=0 && key < static_cast<int>(p.size()))
return p[key];
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
}
void add_wkt_impl(path_type& p, std::string const& wkt)
{
if (!mapnik::from_wkt(wkt , p))
throw std::runtime_error("Failed to parse WKT");
}
void add_wkb_impl(path_type& p, std::string const& wkb)
{
if (!mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size()))
throw std::runtime_error("Failed to parse WKB");
}
void add_geojson_impl(path_type& p, std::string const& json)
{
if (!mapnik::json::from_geojson(json, p))
throw std::runtime_error("Failed to parse geojson geometry");
}
boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
if (!mapnik::from_wkt(wkt, *paths))
throw std::runtime_error("Failed to parse WKT");
return paths;
}
boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
if (!mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size()))
throw std::runtime_error("Failed to parse WKB");
return paths;
}
boost::shared_ptr<path_type> from_geojson_impl(std::string const& json)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
if (! mapnik::json::from_geojson(json, *paths))
throw std::runtime_error("Failed to parse geojson geometry");
return paths;
}
mapnik::box2d<double> envelope_impl(path_type & p)
{
mapnik::box2d<double> b;
bool first = true;
BOOST_FOREACH(mapnik::geometry_type const& geom, p)
{
if (first)
{
b = geom.envelope();
first=false;
}
else
{
b.expand_to_include(geom.envelope());
}
}
return b;
}
}
inline std::string boost_version()
{
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
return s.str();
}
#if BOOST_VERSION >= 104700
PyObject* to_wkb( geometry_type const& geom, mapnik::util::wkbByteOrder byte_order)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,byte_order);
if (wkb)
{
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)wkb->buffer(),wkb->size());
}
else
{
Py_RETURN_NONE;
}
}
#else
PyObject* to_wkb( geometry_type const& geom)
{
throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
}
#endif
#if BOOST_VERSION >= 104700
PyObject* to_wkb2( path_type const& p, mapnik::util::wkbByteOrder byte_order)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(p,byte_order);
if (wkb)
{
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)wkb->buffer(),wkb->size());
}
else
{
Py_RETURN_NONE;
}
}
#else
PyObject* to_wkb2( path_type const& p)
{
throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
}
#endif
std::string to_wkt( geometry_type const& geom)
{
#if BOOST_VERSION >= 104700
std::string wkt; // Use Python String directly ?
bool result = mapnik::util::to_wkt(wkt,geom);
if (!result)
{
throw std::runtime_error("Generate WKT failed");
}
return wkt;
#else
throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
#endif
}
std::string to_wkt2( path_type const& geom)
{
#if BOOST_VERSION >= 104700
std::string wkt; // Use Python String directly ?
bool result = mapnik::util::to_wkt(wkt,geom);
if (!result)
{
throw std::runtime_error("Generate WKT failed");
}
return wkt;
#else
throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
#endif
}
std::string to_geojson( path_type const& geom)
{
std::string json;
mapnik::json::geometry_generator g;
if (!g.generate(json,geom))
{
throw std::runtime_error("Failed to generate GeoJSON");
}
return json;
}
std::string to_svg( geometry_type const& geom)
{
#if BOOST_VERSION >= 104700
std::string svg; // Use Python String directly ?
bool result = mapnik::util::to_svg(svg,geom);
if (!result)
{
throw std::runtime_error("Generate SVG failed");
}
return svg;
#else
throw std::runtime_error("mapnik::to_svg() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
#endif
}
/*
// https://github.com/mapnik/mapnik/issues/1437
std::string to_svg2( path_type const& geom)
{
#if BOOST_VERSION >= 104700
std::string svg; // Use Python String directly ?
bool result = mapnik::util::to_svg(svg,geom);
if (!result)
{
throw std::runtime_error("Generate WKT failed");
}
return svg;
#else
throw std::runtime_error("mapnik::to_svg() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
#endif
}*/
void export_geometry()
{
using namespace boost::python;
enum_<mapnik::eGeomType>("GeometryType")
.value("Point",mapnik::Point)
.value("LineString",mapnik::LineString)
.value("Polygon",mapnik::Polygon)
;
#if BOOST_VERSION >= 104700
enum_<mapnik::util::wkbByteOrder>("wkbByteOrder")
.value("XDR",mapnik::util::wkbXDR)
.value("NDR",mapnik::util::wkbNDR)
;
#endif
using mapnik::geometry_type;
class_<geometry_type, std::auto_ptr<geometry_type>, boost::noncopyable>("Geometry2d",no_init)
.def("envelope",&geometry_type::envelope)
// .def("__str__",&geometry_type::to_string)
.def("type",&geometry_type::type)
.def("to_wkb",&to_wkb)
.def("to_wkt",&to_wkt)
.def("to_svg",&to_svg)
// TODO add other geometry_type methods
;
class_<path_type, boost::shared_ptr<path_type>, boost::noncopyable>("Path")
.def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
.def("__len__", &path_type::size)
.def("envelope",envelope_impl)
.def("add_wkt",add_wkt_impl)
.def("add_wkb",add_wkb_impl)
.def("add_geojson",add_geojson_impl)
.def("to_wkt",&to_wkt2)
//.def("to_svg",&to_svg2)
.def("to_wkb",&to_wkb2)
.def("from_wkt",from_wkt_impl)
.def("from_wkb",from_wkb_impl)
.def("from_geojson",from_geojson_impl)
.def("to_geojson",to_geojson)
.staticmethod("from_wkt")
.staticmethod("from_wkb")
.staticmethod("from_geojson")
;
}

View file

@ -0,0 +1,86 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
// mapnik
#include <mapnik/grid/grid.hpp>
#include "python_grid_utils.hpp"
using namespace boost::python;
// help compiler see template definitions
static dict (*encode)( mapnik::grid const&, std::string const& , bool, unsigned int) = mapnik::grid_encode;
bool painted(mapnik::grid const& grid)
{
return grid.painted();
}
mapnik::grid::value_type get_pixel(mapnik::grid const& grid, int x, int y)
{
if (x < static_cast<int>(grid.width()) && y < static_cast<int>(grid.height()))
{
mapnik::grid::data_type const & data = grid.data();
return data(x,y);
}
PyErr_SetString(PyExc_IndexError, "invalid x,y for grid dimensions");
boost::python::throw_error_already_set();
return 0;
}
void export_grid()
{
class_<mapnik::grid,boost::shared_ptr<mapnik::grid> >(
"Grid",
"This class represents a feature hitgrid.",
init<int,int,std::string,unsigned>(
( boost::python::arg("width"), boost::python::arg("height"),boost::python::arg("key")="__id__", boost::python::arg("resolution")=1 ),
"Create a mapnik.Grid object\n"
))
.def("painted",&painted)
.def("width",&mapnik::grid::width)
.def("height",&mapnik::grid::height)
.def("view",&mapnik::grid::get_view)
.def("get_pixel",&get_pixel)
.def("clear",&mapnik::grid::clear)
.def("encode",encode,
( boost::python::arg("encoding")="utf", boost::python::arg("features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
.add_property("key",
make_function(&mapnik::grid::get_key,return_value_policy<copy_const_reference>()),
&mapnik::grid::set_key,
"Get/Set key to be used as unique indentifier for features\n"
"The value should either be __id__ to refer to the feature.id()\n"
"or some globally unique integer or string attribute field\n"
)
;
}
#endif

View file

@ -0,0 +1,55 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
// mapnik
#include <string>
#include <mapnik/grid/grid_view.hpp>
#include <mapnik/grid/grid.hpp>
#include "python_grid_utils.hpp"
using namespace boost::python;
// help compiler see template definitions
static dict (*encode)( mapnik::grid_view const&, std::string const& , bool, unsigned int) = mapnik::grid_encode;
void export_grid_view()
{
class_<mapnik::grid_view,
boost::shared_ptr<mapnik::grid_view> >("GridView",
"This class represents a feature hitgrid subset.",no_init)
.def("width",&mapnik::grid_view::width)
.def("height",&mapnik::grid_view::height)
.def("encode",encode,
( boost::python::arg("encoding")="utf",boost::python::arg("add_features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
;
}
#endif

View file

@ -0,0 +1,302 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/make_shared.hpp>
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/palette.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_reader.hpp>
#include <mapnik/image_compositing.hpp>
// cairo
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <mapnik/cairo_context.hpp>
#include <pycairo.h>
#include <cairo.h>
#endif
using mapnik::image_32;
using mapnik::image_reader;
using mapnik::get_image_reader;
using mapnik::type_from_filename;
using mapnik::save_to_file;
using mapnik::save_to_string;
using namespace boost::python;
// output 'raw' pixels
PyObject* tostring1( image_32 const& im)
{
int size = im.width() * im.height() * 4;
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)im.raw_data(),size);
}
// encode (png,jpeg)
PyObject* tostring2(image_32 const & im, std::string const& format)
{
std::string s = save_to_string(im, format);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = save_to_string(im, format, pal);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
void save_to_file1(mapnik::image_32 const& im, std::string const& filename)
{
save_to_file(im,filename);
}
void save_to_file2(mapnik::image_32 const& im, std::string const& filename, std::string const& type)
{
save_to_file(im,filename,type);
}
void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal)
{
save_to_file(im,filename,type,pal);
}
bool painted(mapnik::image_32 const& im)
{
return im.painted();
}
bool is_solid(mapnik::image_32 const& im)
{
if (im.width() > 0 && im.height() > 0)
{
mapnik::image_data_32 const & data = im.data();
mapnik::image_data_32::pixel_type const* first_row = data.getRow(0);
mapnik::image_data_32::pixel_type const first_pixel = first_row[0];
for (unsigned y = 0; y < im.height(); ++y)
{
mapnik::image_data_32::pixel_type const * row = data.getRow(y);
for (unsigned x = 0; x < im.width(); ++x)
{
if (first_pixel != row[x])
{
return false;
}
}
}
}
return true;
}
unsigned get_pixel(mapnik::image_32 const& im, int x, int y)
{
if (x < static_cast<int>(im.width()) && y < static_cast<int>(im.height()))
{
mapnik::image_data_32 const & data = im.data();
return data(x,y);
}
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return 0;
}
void set_pixel(mapnik::image_32 & im, unsigned x, unsigned y, mapnik::color const& c)
{
im.setPixel(x, y, c.rgba());
}
boost::shared_ptr<image_32> open_from_file(std::string const& filename)
{
boost::optional<std::string> type = type_from_filename(filename);
if (type)
{
std::auto_ptr<image_reader> reader(get_image_reader(filename,*type));
if (reader.get())
{
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
}
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
throw mapnik::image_reader_exception("Unsupported image format:" + filename);
}
boost::shared_ptr<image_32> fromstring(std::string const& str)
{
std::auto_ptr<image_reader> reader(get_image_reader(str.c_str(),str.size()));
if (reader.get())
{
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
}
throw mapnik::image_reader_exception("Failed to load image from buffer" );
}
boost::shared_ptr<image_32> frombuffer(PyObject * obj)
{
void const* buffer=0;
Py_ssize_t buffer_len;
if (PyObject_AsReadBuffer(obj, &buffer, &buffer_len) == 0)
{
std::auto_ptr<image_reader> reader(get_image_reader(reinterpret_cast<char const*>(buffer),buffer_len));
if (reader.get())
{
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
}
}
throw mapnik::image_reader_exception("Failed to load image from buffer" );
}
void blend (image_32 & im, unsigned x, unsigned y, image_32 const& im2, float opacity)
{
im.set_rectangle_alpha2(im2.data(),x,y,opacity);
}
void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, float opacity)
{
mapnik::composite(dst.data(),src.data(),mode,opacity,0,0,false);
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
boost::shared_ptr<image_32> from_cairo(PycairoSurface* py_surface)
{
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(surface);
return image_ptr;
}
#endif
void export_image()
{
using namespace boost::python;
// NOTE: must match list in include/mapnik/image_compositing.hpp
enum_<mapnik::composite_mode_e>("CompositeOp")
.value("clear", mapnik::clear)
.value("src", mapnik::src)
.value("dst", mapnik::dst)
.value("src_over", mapnik::src_over)
.value("dst_over", mapnik::dst_over)
.value("src_in", mapnik::src_in)
.value("dst_in", mapnik::dst_in)
.value("src_out", mapnik::src_out)
.value("dst_out", mapnik::dst_out)
.value("src_atop", mapnik::src_atop)
.value("dst_atop", mapnik::dst_atop)
.value("xor", mapnik::_xor)
.value("plus", mapnik::plus)
.value("minus", mapnik::minus)
.value("multiply", mapnik::multiply)
.value("screen", mapnik::screen)
.value("overlay", mapnik::overlay)
.value("darken", mapnik::darken)
.value("lighten", mapnik::lighten)
.value("color_dodge", mapnik::color_dodge)
.value("color_burn", mapnik::color_burn)
.value("hard_light", mapnik::hard_light)
.value("soft_light", mapnik::soft_light)
.value("difference", mapnik::difference)
.value("exclusion", mapnik::exclusion)
.value("contrast", mapnik::contrast)
.value("invert", mapnik::invert)
.value("grain_merge", mapnik::grain_merge)
.value("grain_extract", mapnik::grain_extract)
.value("hue", mapnik::hue)
.value("saturation", mapnik::saturation)
.value("color", mapnik::_color)
.value("value", mapnik::_value)
;
class_<image_32,boost::shared_ptr<image_32> >("Image","This class represents a 32 bit RGBA image.",init<int,int>())
.def("width",&image_32::width)
.def("height",&image_32::height)
.def("view",&image_32::get_view)
.def("painted",&painted)
.def("is_solid",&is_solid)
.add_property("background",make_function
(&image_32::get_background,return_value_policy<copy_const_reference>()),
&image_32::set_background, "The background color of the image.")
.def("set_grayscale_to_alpha",&image_32::set_grayscale_to_alpha, "Set the grayscale values to the alpha channel of the Image")
.def("set_color_to_alpha",&image_32::set_color_to_alpha, "Set a given color to the alpha channel of the Image")
.def("set_alpha",&image_32::set_alpha, "Set the overall alpha channel of the Image")
.def("blend",&blend)
.def("composite",&composite,
( arg("self"),
arg("image"),
arg("mode")=mapnik::src_over,
arg("opacity")=1.0f
))
.def("premultiplied",&image_32::premultiplied)
.def("premultiply",&image_32::premultiply)
.def("demultiply",&image_32::demultiply)
.def("set_pixel",&set_pixel)
.def("get_pixel",&get_pixel)
.def("clear",&image_32::clear)
//TODO(haoyu) The method name 'tostring' might be confusing since they actually return bytes in Python 3
.def("tostring",&tostring1)
.def("tostring",&tostring2)
.def("tostring",&tostring3)
.def("save", &save_to_file1)
.def("save", &save_to_file2)
.def("save", &save_to_file3)
.def("open",open_from_file)
.staticmethod("open")
.def("frombuffer",&frombuffer)
.staticmethod("frombuffer")
.def("fromstring",&fromstring)
.staticmethod("fromstring")
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
.def("from_cairo",&from_cairo)
.staticmethod("from_cairo")
#endif
;
}

View file

@ -0,0 +1,136 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <boost/python.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/palette.hpp>
#include <mapnik/image_view.hpp>
#include <sstream>
using mapnik::image_data_32;
using mapnik::image_view;
using mapnik::save_to_file;
// output 'raw' pixels
PyObject* view_tostring1(image_view<image_data_32> const& view)
{
std::ostringstream ss(std::ios::out|std::ios::binary);
for (unsigned i=0;i<view.height();i++)
{
ss.write(reinterpret_cast<const char*>(view.getRow(i)),
view.width() * sizeof(image_view<image_data_32>::pixel_type));
}
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)ss.str().c_str(),ss.str().size());
}
// encode (png,jpeg)
PyObject* view_tostring2(image_view<image_data_32> const & view, std::string const& format)
{
std::string s = save_to_string(view, format);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
PyObject* view_tostring3(image_view<image_data_32> const & view, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = save_to_string(view, format, pal);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
bool is_solid(image_view<image_data_32> const& view)
{
if (view.width() > 0 && view.height() > 0)
{
mapnik::image_view<image_data_32>::pixel_type const* first_row = view.getRow(0);
mapnik::image_view<image_data_32>::pixel_type const first_pixel = first_row[0];
for (unsigned y = 0; y < view.height(); ++y)
{
mapnik::image_view<image_data_32>::pixel_type const * row = view.getRow(y);
for (unsigned x = 0; x < view.width(); ++x)
{
if (first_pixel != row[x])
{
return false;
}
}
}
}
return true;
}
void save_view1(image_view<image_data_32> const& view,
std::string const& filename)
{
save_to_file(view,filename);
}
void save_view2(image_view<image_data_32> const& view,
std::string const& filename,
std::string const& type)
{
save_to_file(view,filename,type);
}
void save_view3(image_view<image_data_32> const& view,
std::string const& filename,
std::string const& type,
mapnik::rgba_palette const& pal)
{
save_to_file(view,filename,type,pal);
}
void export_image_view()
{
using namespace boost::python;
class_<image_view<image_data_32> >("ImageView","A view into an image.",no_init)
.def("width",&image_view<image_data_32>::width)
.def("height",&image_view<image_data_32>::height)
.def("is_solid",&is_solid)
.def("tostring",&view_tostring1)
.def("tostring",&view_tostring2)
.def("tostring",&view_tostring3)
.def("save",&save_view1)
.def("save",&save_view2)
.def("save",&save_view3)
;
}

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