Compare commits

..

296 commits

Author SHA1 Message Date
Artem Pavlenko
7754b6f70b update CHANGELOG for mapnik v3.0.24 release [skip ci] 2021-01-05 12:32:19 +00:00
Artem Pavlenko
be0904fcd1 setting up for mapnik v3.0.24 release [skip ci] 2021-01-05 12:31:01 +00:00
Artem Pavlenko
268fb53511 Update version to v3.0.24 (rc1) 2021-01-05 12:24:44 +00:00
Artem Pavlenko
80bc8ef819 Update CHANGELOG 2021-01-05 12:23:05 +00:00
Artem Pavlenko
4d9669bf42 update copyright (C) 2021 2021-01-05 11:59:41 +00:00
Artem Pavlenko
2d0582187a Fix most compiler warnings 2021-01-05 11:54:55 +00:00
Artem Pavlenko
255e2977a7 travis-ci - remove gcc build 2020-12-16 10:51:32 +00:00
Artem Pavlenko
6f0bab6246 Backport support for boost 1.74 via patch from @redneb 2020-12-15 16:23:59 +00:00
Artem Pavlenko
473e6f51b0 Update bootstrap.sh 2020-12-15 16:23:31 +00:00
Artem Pavlenko
23b8ecc997
Merge pull request #4171 from msitu/decode_darwin_value
fix pg_config error for darwin os
2020-09-04 14:16:05 +01:00
msitu@ceresimaging.net
a103f5e66a fix pg_config error for darwin os 2020-08-27 12:50:45 -07:00
Raul Marin
bc01c22c33 Use pkg-config to find FreeType2 if available (ref #4164) 2020-08-06 09:53:37 +01:00
Artem Pavlenko
d8346dd963 update CHANGELOG for mapnik v3.0.23 release [skip ci] 2020-02-18 09:18:42 +00:00
Artem Pavlenko
bdb30f47a5 setting up for mapnik v3.0.23 release [skip ci] 2020-02-18 09:16:39 +00:00
Artem Pavlenko
b94f00f7c5
Remove appveyor ci badge 2020-02-13 15:17:19 +00:00
Artem Pavlenko
489baf8423
Merge pull request #4126 from cpaulik/v3.0.x-gdal-int32-support
v3.0.x - Add Int32 support for gdal driver
2020-02-13 15:12:55 +00:00
Christoph Paulik
efc65126db Add Int32 support for gdal driver 2020-02-12 12:28:06 +01:00
Artem Pavlenko
f1cf712d50 Add support for BOOST >= 1_72 (backport relevant changes from master) 2020-01-23 14:48:43 +00:00
Mickey Rose
78756a9056 better tests for logical expressions
Two of the original checks were not testing what they were supposed to
test, because the result of eval didn't depend on correct parsing:

    eval("not true or not true")
    correct parse:      ((not true) or (not true)) == false
    incorrect parse:    (not (true or (not true))) == false

    eval("not false and not false")
    correct parse:      ((not false) and (not false)) == true
    incorrect parse:    (not (false and (not false))) == true

(cherry picked from commit d38d16ade9)
2020-01-02 19:32:12 +01:00
Mickey Rose
4b0bdd8630 2to3 last remnants of Python 2 syntax 2019-12-31 12:25:21 +01:00
Mickey Rose
745e393fd6 scons: minor cleanup 2019-09-01 11:54:23 +02:00
Mickey Rose
0d68464194 scons: define OPTIONAL_LIBSHEADERS before use
Fixes #4075
2019-09-01 10:25:46 +02:00
Mickey Rose
d5856a2e9d travis: move variables not relevant to cache contents out of env
(so that changing these later doesn't invalidate the cache)

(cherry picked from commit 2929c4ae6d)
2019-08-14 15:53:51 +02:00
Mickey Rose
fc7e2e1e3a travis: remove downstream trigger (refs #3366)
(cherry picked from commit a6057af11f)
2019-08-14 15:53:10 +02:00
Mickey Rose
fe96110e1d travis: install clang from apt
(cherry picked from commit f432f5f1cc)
2019-08-14 15:50:43 +02:00
Mickey Rose
19ad1f1156 travis: shortcut
(cherry picked from commit 5d51bdde7a)
2019-08-14 15:33:31 +02:00
Mickey Rose
d09fdd78a9 travis: silence gcov output and errors flooding build log
Also added ignore paths from `codecov.yml` to the command, because
codecov-bash doesn't pull those from there. Currently its `parse_yaml`
function simply ignores arrays, so they don't even check for "ignore".
4678d212cc/codecov (L834)
2019-08-14 13:36:44 +02:00
Artem Pavlenko
2ab8602f71 update CHANGELOG for mapnik v3.0.22 release [skip ci] 2019-01-22 10:58:22 +00:00
Artem Pavlenko
c338cacd71 setting up for mapnik v3.0.22 release [skip ci] 2019-01-22 10:56:47 +00:00
Tomek Dubrownik
a1543b359f Compatibility patch for Boost GIL v1.68
A number of basic typedef were removed in the Boost GIL 1.68 release,
notably `bits32` and `bits32f`. Additionally the
`GIL_DEFINE_ALL_TYPEDEFS` macro signature changed.

This commit introduces compatibility type aliases and conditionally
calls the new macro if `BOOST_VERSION` is high enough.
2019-01-22 10:50:23 +00:00
Artem Pavlenko
4698d43234 fix Boost.GIL includes for BOOST_VERSION >= 1.69 (ref #4000) 2019-01-22 10:36:12 +00:00
Artem Pavlenko
24425f9ba5 explicit cast to native enum type in switch statements to address error: case value is not a constant expression
(clang version 8.0.0 (trunk 347189))
2019-01-22 10:33:41 +00:00
Artem Pavlenko
a1e91dcf35
Merge pull request #4017 from mapycz/changelog-3.0.22
Changelog for 3.0.22
2019-01-22 09:15:45 +00:00
Jiri Drbalek
2c396a52ad Changelog for 3.0.22 2019-01-05 16:03:42 +00:00
Artem Pavlenko
bc64766d32
Merge pull request #4012 from mapycz/v3.0.x-cairo-polygon-pattern-vectorial
v3.0.x: Vector patterns with Cairo
2018-11-29 20:02:10 +00:00
Jiri Drbalek
8b7427bf6b Update visual tests 2018-11-29 17:57:35 +00:00
Jiri Drbalek
378b19b53d Vector patterns with Cairo 2018-11-29 17:45:51 +00:00
talaj
38fa2a9792
Merge pull request #4005 from mapycz/v3.0.x-fix-pattern-alignment
v3.0.x: True global pattern alignment, fixed local alignment
2018-11-06 18:05:30 +01:00
Jiri Drbalek
0213b0d8c7 Update visual tests 2018-10-27 20:32:26 +00:00
Jiri Drbalek
e472ad965e True global pattern alignment, fixed local alignment 2018-10-27 20:27:42 +00:00
Jiri Drbalek
73b8369178 render_pattern() needs its own rasterizer 2018-10-27 20:27:42 +00:00
talaj
0a7665a52d
Merge pull request #4004 from mapycz/v3.0.x-line-pattern-repeat
v3.0.x: Line pattern "repeat"
2018-10-27 21:46:55 +02:00
Jiri Drbalek
68cb0c2a03 Update tests 2018-10-23 19:54:26 +00:00
Jiri Drbalek
e49abfc90e Polygon pattern on line geometries for Grid backend 2018-10-23 19:48:34 +00:00
Jiri Drbalek
0709a251e0 Polygon pattern on line geometries for Cairo backend 2018-10-23 19:48:34 +00:00
Jiri Drbalek
33443575f4 Polygon pattern on line geometries for AGG backend 2018-10-23 19:48:34 +00:00
talaj
1a043342f2
Merge pull request #4001 from mapycz/v3.0.x-offset_clip
v3.0.x: Improve padding calculation
2018-10-23 21:47:03 +02:00
Jiri Drbalek
3f9970075d Update visual tests 2018-10-21 19:54:36 +00:00
Raul Marin
fd961048ea Improve padding calculation 2018-10-21 19:42:56 +00:00
Artem Pavlenko
dbcd1b5fef update CHANGELOG for mapnik v3.0.21 release [skip ci] 2018-10-08 10:12:20 +01:00
Artem Pavlenko
1dbb1d2c1e setting up for mapnik v3.0.21 release [skip ci] 2018-10-08 10:08:44 +01:00
Artem Pavlenko
6b15fa8e7d enable unsupported attributes handling + skip any elements inside <symbol> + add clipPath to unsupported elments. 2018-10-02 10:13:15 +01:00
Artem Pavlenko
3e7146911b remove unused variable 2018-10-02 09:43:07 +01:00
Mickey Rose
fd0ed46225 travis: switch to trusty, tweaks from master 2018-08-25 11:57:24 +02:00
Mickey Rose
5531dad9ea update changelog [skip ci] 2018-08-07 23:54:25 +02:00
lightmare
cdfba12f07
Merge pull request #3963 from mapycz/icu-namespace
v3.0.x: Qualify ICU types explicitly
2018-08-02 17:54:30 +02:00
Jiri Drbalek
a42ac13cd8 Force full qualification of ICU types
https://github.com/mapnik/mapnik/issues/3961
2018-08-02 08:49:37 +00:00
Raul Marin
c3ec239699 Qualify ICU types explicitly
ICU 61 has dropped the global `using namespace icu;`
http://site.icu-project.org/download/61#TOC-Migration-Issues
2018-08-02 08:48:58 +00:00
talaj
cabcc079ff
Merge pull request #3939 from mapycz/v3.0.x-fix-overviews
v3.0.x: GDAL: Fixes of overviews
2018-08-01 15:44:53 +02:00
lightmare
d832b3cf1e
Merge pull request #3940 from lightmare/fix-bbox-reprojection-v3.0.x
Backport Fix bbox reprojection to v3.0.x
2018-07-20 19:23:05 +02:00
Jiri Drbalek
2e87bf3586 Update test data 2018-07-17 10:34:18 +00:00
Mickey Rose
d4af8f177b Revert "allow visual test failures with g++"
This reverts commit 05936826b3.
2018-07-17 11:47:48 +02:00
Mickey Rose
b2f8c0816b proj_transform: fix bbox reprojection
- remove buggy calculate_bbox, use boost::geometry::envelope instead
- move helper envelope_points to anonymous namespace and make it always
  produce exactly the requested number of points, even if it's not
  evenly divisible by 4
2018-07-17 11:41:41 +02:00
Mickey Rose
6714207379 proj_transform test: use reference values from cs2cs tool 2018-07-17 11:38:44 +02:00
Jiri Drbalek
7cc52b12d5 Backport Python test of bbox reprojection
Originaly in Python from https://github.com/mapnik/mapnik/pull/2657
2018-07-17 11:38:44 +02:00
Jiri Drbalek
d3e34297c2 gdal: Refactoring 2018-07-17 08:37:33 +00:00
Jiri Drbalek
69f38549c5 gdal: Do not shrink query extent 2018-07-17 08:37:27 +00:00
Jiri Drbalek
a20c1fc1c4 gdal: Count in filter_factor 2018-07-17 08:37:19 +00:00
Jiri Drbalek
5ab034a35b gdal: Fix finding closest overview 2018-07-17 08:37:10 +00:00
lightmare
142b0ad463
Merge pull request #3927 from lightmare/test-ds-attr-types-3.0
Also check types of values in datasource tests
2018-07-02 14:06:31 +02:00
Mickey Rose
de14f92019 datasource tests: typos 2018-07-02 11:48:35 +02:00
Mickey Rose
482cd02585 datasource tests: fix failing csv test
- it was indeed the test that was wrong; the coordinates in nypd.csv are
  specified with a decimal point, thus should be `value_double`
2018-07-02 11:48:35 +02:00
Mickey Rose
93c379820e datasource tests: use macro REQUIRE_ATTRIBUTES instead of function
- failing checks report location inside the function, not where it's
  called from; using macro reports proper location
2018-07-02 11:48:35 +02:00
Mickey Rose
fa0d4c923f datasource tests: also check value types in REQUIRE_ATTRIBUTES 2018-07-02 11:48:33 +02:00
Artem Pavlenko
bf1c55b627 update CHANGELOG for mapnik v3.0.20 release [skip ci] 2018-04-12 11:25:09 +02:00
Artem Pavlenko
f02c7bcdbf git commit -a -m "setting up for mapnik v3.0.20 release [skip ci]" 2018-04-12 11:19:12 +02:00
Artem Pavlenko
d1f041dad0
Merge pull request #3882 from mapycz/fix-grid-placement-nested-template
v3.0.x: fix compiler warning
2018-04-11 10:29:18 +02:00
Artem Pavlenko
8e933607a7 follow up on 5b8b75e680 2018-04-11 08:36:43 +00:00
Artem Pavlenko
4510c77d55 fix compiler warning
```include/mapnik/text/symbolizer_helpers.hpp:164:45: warning: template template parameter using 'typename' is a C++17 extension
      [-Wc++17-extensions]
    template <template <typename, typename> typename GridAdapter>
                                            ^~~~~~~~
                                            class
```
2018-04-11 08:32:22 +00:00
Blake Thompson
d4f95642ca
Merge pull request #3872 from mapnik/gdal_overview_fix_v3.0.x
GDAL Driver Overview Fix and Memory Reduction
2018-03-30 15:44:07 -05:00
Blake Thompson
ba950893af
Merge pull request #3879 from mapnik/raster-colorizer-image-size-v3.0.x
Raster colorizer: check image bounds
2018-03-30 14:54:37 -05:00
Jiri Drbalek
a93dd6b17d Raster colorizer: check image bounds 2018-03-30 14:48:21 -05:00
Blake Thompson
e128d75366 Make max_image_area a datasource parameter for GDAL. 2018-03-30 14:47:34 -05:00
Blake Thompson
9bcd733def Update test data and data-visual to main line 2018-03-20 15:04:30 -04:00
Blake Thompson
361f40f486 A fix for two distinct issues associated with gdal featuresets, the first is overviews were not properly being utilized based on the resolution of the final image requested. The second is that allocation of far too much memory could be possible in GDAL to attempt to do resampling internally in mapnik. This now has a hard cap so that we allocate less memory in these situations but are still able to resample internally in mapnik. 2018-03-20 13:18:46 -04:00
Artem Pavlenko
a08ba860da update CHANGELOG for mapnik v3.0.19 release [skip ci] 2018-03-06 09:48:28 +01:00
Artem Pavlenko
d50562d547 setting up for mapnik v3.0.19 release [skip ci] 2018-03-06 09:47:25 +01:00
Artem Pavlenko
d635b9f436 update CHANGELOG 2018-03-05 11:46:26 +01:00
Artem Pavlenko
96435b2a3a update version to 3.0.19 2018-03-05 11:46:07 +01:00
Raul Marin
2cef98d7f7 ICU DATA: Default to icu-config if u_getDataDirectory fails 2018-02-26 16:25:20 +01:00
Artem Pavlenko
98d39ff398
Merge pull request #3824 from albertov/v3.0.x
Backport "Export all text_placements_ classes from mapnik.dll"
2018-02-26 12:17:11 +01:00
Raul Marin
44f1ae3a6e PROJ_LIB: Fix detection code
.sconf_temp/conftest_24.cpp:30:42: error: use of undeclared identifier 'strlen'
2018-02-20 09:22:44 -08:00
Artem Pavlenko
baf5cdbd71
Merge pull request #3858 from mapycz/port-grid-placement-v3.0.x
Grid placement for v3.0.x
2018-02-15 10:08:22 +01:00
Jiri Drbalek
f91d37d93d Update visual tests 2018-02-14 12:13:17 +00:00
Jiri Drbalek
2f2dcf1eea grid_vertex_converter: Fix handling of empty polygon 2018-02-14 11:58:21 +00:00
Jiri Drbalek
a602c65354 AGG: Fix invalid memory access if input buffer size is zero 2018-02-14 11:58:21 +00:00
Jiri Drbalek
098fd27291 Add grid placement for text and shield symbolizer 2018-02-12 17:07:35 +00:00
Artem Pavlenko
1bb070c842
Merge pull request #3846 from mapycz/interior-scale-invariant-v3.0.x
v3.0.x: Interior, polylabel: Scale precision by polygon size
2018-02-06 13:20:51 +01:00
Jiri Drbalek
75381d217f Update visual tests 2018-02-06 11:52:53 +00:00
Jiri Drbalek
95a4bff127 interior, polylabel: Scale precision by polygon size 2018-02-06 09:54:47 +00:00
Artem Pavlenko
110b7b8185 update CHANGELOG for mapnik v3.0.18 release [skip ci] 2018-01-26 14:59:46 +01:00
Artem Pavlenko
44ef46c810 update CHANGELOG for mapnik v3.0.18 release [skip ci] 2018-01-26 09:55:33 +01:00
Artem Pavlenko
a30f8ed20c Backport #3838 to v3.0.x branch (fixes #3842) 2018-01-25 16:01:39 +01:00
Artem Pavlenko
0259ad8041 Merge remote-tracking branch 'origin/v3.0.x' into v3.0.x 2018-01-24 17:24:19 +01:00
Artem Pavlenko
3c2d65779e
Merge pull request #3840 from mapycz/port-new-interior
New interior for v3.0.x
2018-01-24 17:21:00 +01:00
talaj
cfd9668fdb visual tests: report failed tests (#3765) 2018-01-24 15:39:13 +00:00
talaj
f8c6ad1e29 visual tests: allow to ignore particular renderer (#3768)
* visual tests: refactor parsing parameters from the style

* visual tests: allow to ignore particular renderer

* update visual tests
2018-01-24 15:19:39 +00:00
Jiri Drbalek
2e478ddd37 Update visual tests 2018-01-24 13:54:46 +00:00
Jiri Drbalek
72989d440b Interior: cover the case of empty polygon or exterior ring 2018-01-24 13:54:46 +00:00
Jiri Drbalek
fe3c2762c0 Fix crash in case of empty ring 2018-01-24 13:54:46 +00:00
Jiri Drbalek
64b874ecb1 New interior algorithm 2018-01-24 13:54:46 +00:00
Ben Harper
7ce142a5aa Export all text_placements_ classes from mapnik.dll
Previously, only text_placements_dummy had a MAPNIK_DECL annotation.
This commit adds that annotation to text_placements_simple and
text_placements_list, so that they are also exposed from the Windows DLL
build.
2018-01-06 22:48:16 +01:00
Artem Pavlenko
11a164803d update CHANGELOG 2017-12-13 15:12:21 +01:00
Artem Pavlenko
497b516feb bump up version 2017-12-13 11:57:15 +01:00
Artem Pavlenko
5227f84e07 Don't apply preserveAscpectRatio logic logic if width and height expressed as % values (#3812) 2017-12-06 11:00:06 +01:00
Artem Pavlenko
2f28d9897f update CHANGELOG for mapnik v3.0.17 release [skip ci] 2017-11-29 14:34:40 +01:00
Artem Pavlenko
ebdd96c618 Update CHANGELOG 2017-11-29 10:14:49 +01:00
Artem Pavlenko
237d3b0714
Merge pull request #3806 from mapnik/3.0.x-fix-glibcxx
3.0.x fix glibcxx symbols
2017-11-28 16:18:41 +01:00
Artem Pavlenko
0b480e0dca add missing header + update visual tests 2017-11-28 14:56:18 +01:00
Artem Pavlenko
6a6891252c Revert "check if FT_PIXEL_MODE_BGRA is defined (freetype < 2.5.0) (#3797)"
This reverts commit 6eafffaf57.
Revert "fix memory leak (#3775)"
This reverts commit 995ab49f23.

(6eafffaf57 (commitcomment-25894906))
2017-11-28 14:18:23 +01:00
Artem Pavlenko
6eafffaf57 check if FT_PIXEL_MODE_BGRA is defined (freetype < 2.5.0) (#3797) 2017-11-28 11:23:13 +01:00
Dane Springmeyer
5d44eab802 update mason version to make available latest boost 1.65.1 packages 2017-11-27 10:14:37 -08:00
Dane Springmeyer
a559c01d4a use latest mason package for boost (which is built against libstdc++-4.8-dev) to avoid GLIBCXX 3.4.21 symbols 2017-11-27 09:37:55 -08:00
Dane Springmeyer
da86e99577 use lowercase boolean to match check in scripts/check_glibcxx.sh 2017-11-27 09:37:15 -08:00
Artem Pavlenko
498142f700 bump up version to 3.0.17 2017-11-27 09:55:20 +01:00
Artem Pavlenko
c3704c968b Fix licence link (#3804) 2017-11-27 09:54:46 +01:00
Artem Pavlenko
b0f3f1aed7 port Scons3 support from master 2017-11-24 11:29:14 +01:00
Dane Springmeyer
f5ea42b11f at workaround for throw_out_of_range_fmt
remove inadvertent change

also dump glibcxx symbols on circle

add glibc_workaround.cpp if option is chosen

This reverts commit 751d9bff1672f6b8cbd2b5ebe2eb460223746806.

add script that asserts on expected symbols

check symbols for all modes, only error if symbols exist + ENABLE_GLIBC_WORKAROUND
2017-11-21 16:07:41 +01:00
Artem Pavlenko
51b177802f update CHANGELOG for mapnik v3.0.16 release [skip ci] 2017-11-16 15:41:24 +01:00
Artem Pavlenko
8d7b75ed6b update CHANGELOG in preparation to v3.0.16 release. 2017-11-14 14:49:01 +01:00
Artem Pavlenko
a408b0732e Don't collect invalid bounding boxes (ref #3709) 2017-11-07 14:32:33 +01:00
Artem Pavlenko
0a15a955a2 SVG parser - fix default gradient vector in linear gradient [0,0,1,0] + support units in offset attribute. 2017-11-06 12:38:33 +01:00
talaj
995ab49f23 fix memory leak (#3775) 2017-11-03 10:48:55 +01:00
talaj
5996fb07ec Fix centroid and interior algorithms (#3771)
* fix interior algorithm - closing segment handling

* fix centroid algorithm - closing segment handling

* update visual tests
2017-11-03 10:17:54 +01:00
Dane Springmeyer
9466965725 bump to v3.0.16 2017-09-10 11:24:21 -07:00
Dane Springmeyer
bd3bbd7d59 Merge pull request #3759 from mapnik/collect-dep-data-paths
Fix mapnik-config reporting of --proj-lib, --gdal-data, and --icu-data
2017-09-10 11:07:39 -07:00
Dane Springmeyer
f3c71785e4 adapt to spelling fix in svg tests 2017-09-10 10:21:39 -07:00
Dane Springmeyer
fa057a8d06 fix spelling in svg parser error 2017-09-10 08:59:27 -07:00
Dane Springmeyer
5a97602aa1 make the configure script actually bash 2017-09-10 08:40:46 -07:00
Dane Springmeyer
8631ae0e74 keep using dist:precise for now after travis default switched 2017-09-09 15:06:03 -07:00
Dane Springmeyer
58a864d133 Query ICU_DATA, PROJ_LIB, and GDAL_DATA
- ensure the paths are correct and on the system
 - make the results available in mapnik-config
2017-09-09 11:52:10 -07:00
artemp
f64c7573b1 Ensure svg number + units parser fails on cur != end condition (got missed via cherry-pick) 2017-08-08 13:12:11 +01:00
artemp
3597c585be svg-parser - unify error messages text + update unit test 2017-08-08 12:42:17 +01:00
artemp
8cdd61e846 add missing ' in error message. 2017-08-02 10:30:37 +01:00
artemp
a6230559f1 Enforce consistent error handling policy - always throw on fatal errors (both strict and non-strict). In strict mode throw on first parsing error. Remove return values from parse,parse_from_string and traverse_tree methods. Update unit tests. 2017-07-31 10:58:57 +01:00
artemp
7f4adc2d73 only include <unicode/unistr.h> if ICU >= 59 (attempting to fix current coverage build on travis). 2017-07-21 10:11:29 +02:00
artemp
d3ec91b29b Add support for U_ICU_VERSION_MAJOR_NUM >= 59 (#3729) 2017-07-19 16:09:22 +02:00
artemp
9447c185d4 Update CHANGELOG with missing #3688 [skip-ci] 2017-07-18 10:10:15 +02:00
Artem Pavlenko
f06147b454 Merge pull request #3721 from mapnik/tiff_alpha_rgba_fix
Use alpha in rgba of tiffs even if there is a no data value set.
2017-07-17 09:25:35 +02:00
Jiri Drbalek
2890add8e6 remove superfluous line 2017-07-17 09:06:58 +02:00
artemp
ed3e2454d5 disable handling unsupported attributes (leaving only well-known unsupported elements) to reduce verbosity. 2017-07-07 10:12:00 +02:00
Blake Thompson
3c0a387af7 Use alpha in rgba of tiffs even if there is a no data value set. Fixes #3714 2017-07-06 09:03:08 -05:00
artemp
249d6cc311 wkb_reader : pre-allocate number of polygons in multi_polygon and number of geometries in geometry_collection via vector.reserce(...) 2017-07-03 15:27:28 +02:00
artemp
1f5583b433 don't set depth on git submodule update 2017-06-27 11:58:31 +02:00
artemp
d09f49b377 port "strict" SVG parsing, support for <use> element and use of switch statements from https://github.com/mapnik/mapnik/tree/svg-strict-parsing 2017-06-27 11:41:26 +02:00
artemp
0ac9cc091a remove depth setting from git subodule update 2017-06-19 10:37:59 +02:00
artemp
15d18070aa update CHANGELOG for mapnik v3.0.15 release [skip ci] 2017-06-16 10:36:55 +02:00
artemp
6e6cf8433b update CHANGELOG.md 2017-06-15 12:08:43 +02:00
artemp
9b4df8ebc8 tiff_reader - use memory mapped files if MAPNIK_MEMORY_MAPPED_FILE is defined (ported from master) 2017-06-15 11:59:47 +02:00
artemp
36a23851f3 bump up version to 3.0.15 2017-06-15 11:06:41 +02:00
Blake Thompson
2f8485ba89 Merge pull request #3699 from mapnik/fix_filter_factor
Restore Filter Factor in Image Scaling
2017-06-13 08:21:33 -05:00
Blake Thompson
af95ca85e9 Updated tests 2017-06-13 07:47:23 -05:00
Blake Thompson
061b29f108 Restoring the way filter factors operate so that select algorithms still are passed variables in the form of filter factor to change their operation. Added this operation to raster plugin where it never existed prior. Additionally added a test that was created for #3698 proving that it is not currently an issue 2017-06-13 07:31:17 -05:00
artemp
08d8746b3a update visual-data 2017-06-13 13:24:11 +02:00
artemp
d2627dfad8 tiff_reader - fix num_rows logic in read_stripped method ref #3679 2017-06-12 17:56:33 +02:00
artemp
bc528e4c8f Update SHA 2017-06-06 17:44:26 +02:00
artemp
2b42e174fd Update after #3696 2017-06-06 17:42:15 +02:00
Artem Pavlenko
0c1863aa7e Merge pull request #3696 from mapnik/raster_limit
Fixes bug in raster plugin
2017-06-06 17:25:05 +02:00
Blake Thompson
a35a064ce4 Fixes bug in raster plugin 2017-06-06 10:11:53 -05:00
artemp
735eeb4702 CHANGELOG - update release date + SHA [skip ci] 2017-06-05 16:26:51 +02:00
artemp
7660b9e74a update CHANGELOG for mapnik v3.0.14 release [skip ci] 2017-06-05 10:34:54 +02:00
artemp
5b88f687a1 Scons - update to 2.5.1 2017-06-05 10:29:21 +02:00
artemp
c4fb727076 bump version to 3.0.14 2017-06-02 20:25:13 +02:00
artemp
75e7a44c90 Merge branch 'webp_tests' into v3.0.x 2017-06-02 20:15:51 +02:00
Blake Thompson
3fcd54123c Updated data-visual with tiff changes 2017-06-02 12:38:39 -05:00
artemp
d6bf258f3a Merge branch 'webp_tests' into v3.0.x 2017-06-02 18:32:08 +02:00
Blake Thompson
20fd003618 Added new tests for webp data 2017-06-01 15:38:00 -05:00
artemp
9940193c0b return error code when no feature can be read from shapefile + update unit test (ref #3198) 2017-06-01 15:45:14 +02:00
artemp
9f19fa8943 freetype_engine : revert back to original APIs usage.
This reverts commit 1c101c3243.
2017-06-01 12:35:14 +02:00
Artem Pavlenko
98fa7699f3 Merge pull request #3688 from mapnik/font-engine-singleton
make font-engine-singleton to have better control over objects life-t…
2017-06-01 11:31:18 +02:00
artemp
c09f6a8434 freetype_engine - re-use base class mutex. 2017-06-01 10:51:59 +02:00
artemp
d1327dea88 freetype_engine - preserve original intetface via static methods + make impl methods private. 2017-06-01 10:45:09 +02:00
Dane Springmeyer
e4b5ddb1aa add missing include / fix windows compile 2017-05-31 12:50:27 -07:00
Dane Springmeyer
ce47610677 update font path in test file 2017-05-31 10:41:34 -07:00
artemp
648f9698a0 use sigleton interface when calling freetype_engine methods. 2017-05-30 12:53:20 +02:00
artemp
a054ee0a31 c++ minor formatting. 2017-05-29 12:33:32 +02:00
artemp
4d6a1c5cfc font_engine_freetype - remove default constructor and virtual destructor (??). 2017-05-29 10:46:40 +02:00
artemp
3b6f3ff36f c++ formatting 2017-05-29 10:46:21 +02:00
artemp
1c101c3243 make font-engine-singleton to have better control over objects life-time. 2017-05-26 16:52:50 +02:00
Dane Springmeyer
e6173385ca use latest version of mason 2017-05-25 11:31:16 -07:00
artemp
09933916d6 fix spelling 2017-05-19 14:40:47 +02:00
artemp
185d788ea4 Backport TIFF I/O fixes from master (ref #3669 #3670) 2017-05-19 13:47:11 +02:00
artemp
99a7fa5044 Revert "update visual data one more time." : wrong branch
This reverts commit de533ab712.
2017-05-17 21:21:02 +02:00
artemp
de533ab712 update visual data one more time. 2017-05-17 21:17:11 +02:00
Blake Thompson
125cd694b8 Updated changelog 2017-05-12 12:16:25 -05:00
Blake Thompson
5911fe6374 Merge pull request #3668 from mapnik/raster_overzoom_quest
Raster Overzoom Quest
2017-05-12 11:48:34 -05:00
Blake Thompson
b29e56051c Merge branch 'v3.0.x' into raster_overzoom_quest 2017-05-12 10:59:32 -05:00
Blake Thompson
7222129e6c Update visual test data to 3.0.x branch 2017-05-12 10:55:48 -05:00
artemp
ab783cbec4 Merge branch 'raster_overzoom_quest' of https://github.com/mapnik/mapnik into raster_overzoom_quest 2017-05-12 15:25:44 +02:00
Blake Thompson
baf6c9f321 Updated tests, changed boostrap to use latest released mason 2017-05-11 09:57:18 -05:00
Blake Thompson
e945eb74fe Merge pull request #3672 from mapnik/filter_factor_removal
Removed filter factor
2017-05-10 16:02:17 -05:00
Blake Thompson
bc9dcdc584 Updated visual test data 2017-05-10 13:31:11 -05:00
Dane Springmeyer
2fd1f098f5 update to latest 3.0.x test-data-visual branch 2017-05-10 10:06:31 -07:00
Blake Thompson
318be793f9 Removed filter factor 2017-05-10 09:04:29 -05:00
Blake Thompson
adacb16a2c Removed 0.5 limit on width and height in gdal plugin, added new visual tests 2017-05-09 12:15:03 -05:00
artemp
85d7f28610 remove QMAKE_MAC_SDK requirement - just use what is available 2017-05-09 09:54:51 +02:00
Blake Thompson
170e20e864 First attempt at making raster overzooming and scaling work correctly and handle offsets properly. 2017-05-08 22:37:35 -05:00
Dane Springmeyer
b53db334af link -ldl last 2017-04-19 18:30:34 -07:00
Dane Springmeyer
1632018a14 pgsql2sqlite:also link -ldl on linux 2017-04-19 18:10:03 -07:00
artemp
9f4a138b8b fix formatting 2017-04-06 10:43:12 +01:00
artemp
149d2ca0a1 Avoid using c++14 extensions as v3.0.x should only require c++11 compliant compiler (fixes #3645). 2017-03-29 10:09:48 +01:00
Dane Springmeyer
635af3f4a3 point at 3.0.x branch of visual test data - refs mapnik/test-data-visual#46 2017-03-28 15:47:12 -07:00
Dane Springmeyer
9c4613f934 remove explicit instantiation of 'image_view<mapnik::image<mapnik::null_t> >' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] (clang 4.x) 2017-03-28 15:25:17 -07:00
Dane Springmeyer
520f3fd0a0 improve check padding script to see deps via submodules 2017-03-28 15:18:48 -07:00
artemp
15fb2debb0 fix compilation - auto args in lambda is c++14 oops 2017-03-23 16:21:38 +00:00
artemp
fa549b380a GeoJSON IO test - ensure geometries round-trip. 2017-03-23 15:01:50 +00:00
artemp
60d891f094 add "invalid" empty geometry tests 2017-03-22 15:07:07 +00:00
artemp
7caa0cffd4 from_geojson - catch all exceptions. 2017-03-22 15:06:34 +00:00
artemp
dbbf18c752 GeoJSON test - add empty geometries tests. 2017-03-22 14:41:08 +00:00
artemp
a1084e0c09 port GeoJSON parser/generator logic from master 2017-03-22 14:40:07 +00:00
Dane Springmeyer
c2fd522d0f remove mason latest publishing and triggered builds - refs #3639 2017-03-19 17:57:10 -07:00
Dane Springmeyer
dfccc5f6bb Merge pull request #3640 from mapnik/build-fixes
v3.0.x build fixes
2017-03-19 13:07:42 -07:00
Dane Springmeyer
284842a9d3 Merge pull request #3641 from mapnik/v3.0.x-more-dep-updates
Update mason deps
2017-03-19 12:39:30 -07:00
Dane Springmeyer
40753edadc Merge branch 'v3.0.x-more-dep-updates' into build-fixes 2017-03-19 12:38:57 -07:00
Dane Springmeyer
e0db6b9a47 consistently use pkg-config in both postgis plugin and pgsql2sqlite + use GDAL_CONFIG var in plugins 2017-03-18 19:40:18 -07:00
Dane Springmeyer
91515cad69 update sqlite, icu, ccache, and libpq 2017-03-18 19:39:09 -07:00
Dane Springmeyer
0c232313d6 update visual test down now that mapnik/test-data-visual#44 is merged 2017-03-10 16:51:46 -08:00
Dane Springmeyer
8665fc7313 Merge pull request #3614 from mapnik/3.0.x-mason-upgrades
3.0.x mason upgrades
2017-03-10 14:58:14 -08:00
Dane Springmeyer
08822729cc use zlib 1.2.8 package 2017-03-09 17:26:17 -08:00
Dane Springmeyer
f8e5f146ec update mason version 2017-03-09 17:20:31 -08:00
Dane Springmeyer
07de7155f1 upgrade to latest harfbuzz 2017-03-09 17:10:34 -08:00
Mickey Rose
3fbe7f61a6 load_map: avoid segfault when ShieldSymbolizer has invalid placements 2017-02-22 03:21:48 +01:00
Dane Springmeyer
3706fcf587 use mason v0.7.0 2017-02-09 18:00:01 -08:00
Dane Springmeyer
947ac81ee4 point at mason master until mason is tagged 2017-02-08 19:24:33 -08:00
Dane Springmeyer
163af7a40f update test-data - refs mapnik/test-data-visual#44 2017-02-08 17:31:46 -08:00
Dane Springmeyer
55e3e14f4d more code coverage adjustments 2017-02-08 15:05:48 -08:00
Dane Springmeyer
7483f6328c Add codecov.yml ignores 2017-02-08 15:02:47 -08:00
Dane Springmeyer
941a7eaf69 try codecov 2017-02-08 15:02:16 -08:00
artemp
489b7f2aca fix typo 2017-02-08 14:04:59 -08:00
artemp
4c22e631a7 remove remaining usage of deprecated dymamic exceptions: dtors are implicitely noexcept + qualify what methods with noexcept 2017-02-08 13:47:02 -08:00
artemp
2845cdc121 remove bogus throw() specifier from 'add_attribute' 2017-02-08 13:46:51 -08:00
artemp
0cd3bd8737 dynamic exceptions deprecated in c++11 and removed in c++17 (http://en.cppreference.com/w/cpp/language/except_spec) 2017-02-08 13:46:40 -08:00
Dane Springmeyer
85da8ef128 port fix for std::fread from master - a220bda05d 2017-02-08 13:33:41 -08:00
Dane Springmeyer
7affd674fd remove unused var [skip ci] 2017-02-08 13:31:13 -08:00
Dane Springmeyer
1f2de83531 also upgrade libpq 2017-02-08 13:04:35 -08:00
Dane Springmeyer
887964ae97 upgrade mason deps 2017-02-08 10:57:27 -08:00
artemp
c1267ebcd5 update CHANGELOG for mapnik v3.0.13 release [skip ci] 2017-02-08 14:06:42 +01:00
Dane Springmeyer
2a153c0d1f fix linking of postgis to boost_regex (when boost regex is statically linked to icu libs) 2017-02-07 12:54:12 -08:00
artemp
4f3e6f4846 update CHANGELOG 2017-02-06 16:00:00 +01:00
Artem Pavlenko
391a9f835b Merge pull request #3612 from mapnik/v3.0.x-3611
V3.0.x ref #3611
2017-02-06 14:26:01 +01:00
artemp
74e66bac58 test - update malformed featurecollection test (ref #3611) 2017-02-03 17:36:28 +01:00
artemp
d2d62bc95c Return failure on invalid bounding box when --validate-features option is used. (ref #3611) 2017-02-03 17:23:48 +01:00
artemp
8cc7060ef1 remove bounding box validity check (ref #3611) 2017-02-03 17:20:25 +01:00
Artem Pavlenko
e35bca7381 Merge pull request #3610 from mapnik/v3.0.x-3609
GeoJSON - backport positions grammar changes from master, fixes #3609
2017-02-03 11:28:22 +01:00
artemp
6cb3bce2d7 GeoJSON - backport positions grammar changes from master, fixes #3609 2017-02-03 11:22:24 +01:00
lightmare
17dcffaf78 Merge pull request #3583 from mapnik/v3.0.x-cherry-pr3566
v3.0.x cherry-pick #3566
2017-02-02 15:32:29 +01:00
Dane Springmeyer
1a268343a9 fix clang++ package name 2017-02-01 21:57:34 -08:00
Dane Springmeyer
7578534dc8 pass std::string to std::out_of_range 2017-02-01 21:54:27 -08:00
Dane Springmeyer
adcf611fab upgrad clang++ on circle too 2017-01-31 16:34:50 -08:00
Dane Springmeyer
8f06db6ac0 ensure mason check works via tag 2017-01-31 16:32:50 -08:00
Dane Springmeyer
401aade813 use clang++ 3.9.1 / pin mason to v0.5.0 2017-01-31 16:18:55 -08:00
artemp
ab206321b5 update version to 3.0.13 2017-01-20 14:40:35 +01:00
artemp
5db03aeb03 update test-data 2017-01-19 11:14:20 +01:00
artemp
2db538c470 update in prep for v3.0.13 release 2017-01-18 14:27:49 +01:00
artemp
8a3a380b3b fix blank line test for require headers.size() == 1 + reduce stderr verbosity. 2017-01-18 10:16:44 +01:00
artemp
ff4a1c1e9b use variant v1.1.5 2017-01-18 10:09:52 +01:00
Dane Springmeyer
7ce68e2c08 fix variant_io include 2017-01-04 15:22:36 -08:00
Dane Springmeyer
5b1c5f83cb Avoid -Winstantiation-after-specialization warnings 2017-01-04 15:08:08 -08:00
Dane Springmeyer
5d28a25ad3 Point as latest mason rather than branch 2017-01-04 11:45:55 -08:00
Artem Pavlenko
c71c1bc0a8 Merge pull request #3586 from lightmare/v3.0.x-groupsym-thunk-list
backport render_thunk_list change #3585 to v3.0.x branch
2017-01-04 10:30:05 +01:00
Mickey Rose
63128fdba1 can't store noncopyable list in std::vector
std::list can have a throwing move constructor.
std::vector of such lists makes copies when growing its storage array,
it doesn't move them.
render_thunk_list is noncopyable (because render_thunk is noncopyable),
and so can't be stored in std::vector in some STL implementations.
2017-01-03 22:53:39 +01:00
Mickey Rose
0a5495e442 change render_thunk_list to std::list<render_thunk>
Wrapping render_thunk in std::unique_ptr is one extra allocation per
element, with no purpose. The somewhat costly xyz_render_thunk move
constructor is only called once upon insertion, regardless of whether
we're emplacing render_thunk or unique_ptr.
2017-01-03 22:53:39 +01:00
Jiri Drbalek
b5c04cc132 find max element instead of std::sort 2017-01-02 03:53:53 +01:00
Jiri Drbalek
cdefee3524 remove redundant code 2017-01-02 03:53:53 +01:00
Dane Springmeyer
47443526a0 Merge pull request #3580 from mapnik/v3.0.x-cherry
Cherry pick stable commits from master into v3.0.x branch
2016-12-21 11:44:34 -08:00
Dane Springmeyer
a3b4e1f575 remove duplicate sudo:false from travis 2016-12-15 13:33:29 -08:00
Dane Springmeyer
283481b347 backport warnings fix from master for enumeration 2016-12-15 11:33:23 -08:00
Mickey Rose
fdd542a3c4 make mapnik_value_type_t C++11-friendly 2016-12-15 12:13:42 +01:00
Mickey Rose
06201e3842 bring C++14 type traits aliases for C++11 support 2016-12-15 12:12:12 +01:00
Dane Springmeyer
96ce2d8b3b update to latest variant 2016-12-14 18:25:41 -08:00
Mickey Rose
f00470dc02 simplify mapnik::value conversion rules
- fixes #3570

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

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

1
.gitattributes vendored
View file

@ -1,2 +1 @@
*.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

7
.gitignore vendored
View file

@ -1,6 +1,4 @@
.DS_Store
.vscode
.cache
*.gcov
*.gcda
*.gcno
@ -58,8 +56,3 @@ demo/viewer/ui_layer_info.h
test/standalone/*-bin
test/unit/run
test/visual/run
# cmake
build
.vs
CMakeUserPresets.json

14
.gitmodules vendored
View file

@ -5,19 +5,7 @@
[submodule "test/data-visual"]
path = test/data-visual
url = https://github.com/mapnik/test-data-visual.git
branch = master
branch = 3.0.x
[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]

100
.travis.yml Normal file
View file

@ -0,0 +1,100 @@
language: generic
git:
depth: 10
submodules: false
env:
global:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- PREFIX=/tmp/mapnik
- secure: "F6ivqDNMBQQnrDGA9+7IX+GDswuIqQQd7YPJdQqa2Ked9jddAQDeJClb05ig3JlwfOlYLGZOd43ZX0pKuMtI2Gbkwz211agGP9S3YunwlRg8iWtJlO5kYFUdKCmJNhjg4icfkGELCgwXn+zuEWFSLpkPcjqAFKFlQrIJeAJJgKM="
cache:
directories:
- $HOME/.ccache
dist: trusty
sudo: false
matrix:
include:
- os: linux
name: Linux clang-3.9
env: >-
CXX="ccache clang++-3.9 -Qunused-arguments"
CC="clang-3.9"
ENABLE_GLIBC_WORKAROUND=true
before_install:
- export LINKFLAGS="-fuse-ld=gold-2.26"
addons:
postgresql: "9.4"
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'clang-3.9', 'libstdc++-4.9-dev', 'xutils-dev', 'postgresql-9.4-postgis-2.3' ]
- os: linux
name: Linux clang-3.9 + coverage
env: >-
CXX="ccache clang++-3.9 -Qunused-arguments"
CC="clang-3.9"
COVERAGE=true
before_install:
- export LINKFLAGS="-fuse-ld=gold-2.26"
- export LLVM_COV="llvm-cov-3.9"
addons:
postgresql: "9.4"
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'clang-3.9', 'llvm-3.9', 'libstdc++-4.9-dev', 'xutils-dev', 'postgresql-9.4-postgis-2.3' ]
- os: osx
name: OSX clang
# https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions
osx_image: xcode7.3 # upgrades clang from 6 -> 7
env: >-
CXX="ccache clang++ -Qunused-arguments"
install:
- source scripts/travis-common.sh
# workaround travis rvm bug
# http://superuser.com/questions/1044130/why-am-i-having-how-can-i-fix-this-error-shell-session-update-command-not-f
- on 'osx' rvm get head || true
- export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PATH}
- export COVERAGE=${COVERAGE:-false}
- export BENCH=${BENCH:-false}
- on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres
- on 'osx' rm -rf ${DATA_PATH}
- on 'osx' initdb ${DATA_PATH} -E utf8
- on 'osx' pg_ctl -w start -l postgres.log --pgdata ${DATA_PATH};
- on 'osx' cat postgres.log;
- on 'osx' createuser -s postgres
- psql -c 'create database template_postgis;' -U postgres
- psql -c 'create extension postgis;' -d template_postgis -U postgres
- enabled ${COVERAGE} curl -S -f https://codecov.io/bash -o codecov
- enabled ${COVERAGE} chmod +x codecov
before_script:
- export JOBS=${JOBS:-4}
- export HEAVY_JOBS=${HEAVY_JOBS:-2}
- export SCONSFLAGS='--debug=time'
- source bootstrap.sh
- ccache --version
- ccache -p || true
- ccache --show-stats || true
- commit_message_parse
script:
- git_submodule_update --init deps/
- configure BENCHMARK=${BENCH} ENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-false}
- cat config.log
# we limit the `make` to 40 min
# to ensure that slow builds still upload their
# ccache results and therefore should be faster
# (and might work) for the next build
- DEADLINE=$(( $(date +%s) + 40 * 60 ))
- scripts/travis-command-wrapper.py -s "date" -i 120 --deadline="$DEADLINE" make
- test_ok && git_submodule_update --init test/
- test_ok && make test
- test_ok && enabled ${COVERAGE} coverage
- test_ok && enabled ${BENCH} make bench
- ./scripts/check_glibcxx.sh

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

@ -2,18 +2,10 @@
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
```
@ -42,8 +34,8 @@ 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
@ -71,15 +63,15 @@ 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 supporting `-std=c++11` (like >= g++ 4.8 or >= clang++ 3.4)
* >= 2 GB RAM (> 5 GB for g++)
* Python 2.4-2.7
* Scons (a copy is bundled)
Mapnik Core depends on:
* Boost
- \>= 1.73 is required
- >= 1.47 is required and >= 1.56 recommended
- These libraries are used:
- filesystem
- system
@ -97,7 +89,7 @@ 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)
Additional optional dependencies:
@ -191,7 +183,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 +191,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.md for resources for getting involved with Mapnik development.

View file

@ -1,5 +1,8 @@
OS := $(shell uname -s)
PYTHON = python
ifeq ($(JOBS),)
JOBS:=1
endif
@ -19,6 +22,11 @@ release:
test-release:
./scripts/test_release.sh
python:
if [ ! -d ./bindings/python ]; then git clone git@github.com:mapnik/python-mapnik.git --recursive ./bindings/python; else (cd bindings/python && git pull && git submodule update --init); fi;
make
python bindings/python/test/visual.py -q
src/json/libmapnik-json.a:
# we first build memory intensive files with -j$(HEAVY_JOBS)
$(PYTHON) scons/scons.py -j$(HEAVY_JOBS) \
@ -28,15 +36,15 @@ src/json/libmapnik-json.a:
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/css_color_grammar.os \
src/expression_grammar.os \
src/transform_expression_grammar.os \
src/image_filter_grammar.os \
src/marker_helpers.os \
src/svg/svg_transform_parser.os \
src/agg/process_line_symbolizer.os \
plugins/input/geojson/geojson_datasource.os \
utils/mapnik-index/process_geojson_file.o \
src/svg/svg_path_parser.os \
src/svg/svg_parser.os \
src/svg/svg_points_parser.os \
@ -90,6 +98,13 @@ bench:
demo:
cd demo/c++; ./rundemo `mapnik-config --prefix`
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'
# note: pass --gen-suppressions=yes to create new suppression entries
grind:
@source localize.sh && \

View file

@ -8,8 +8,8 @@ _/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
_/
```
[![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 Linux](https://api.travis-ci.org/mapnik/mapnik.svg?branch=master)](http://travis-ci.org/mapnik/mapnik)
[![Coverage Status](https://coveralls.io/repos/mapnik/mapnik/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapnik/mapnik?branch=master)
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.

File diff suppressed because it is too large Load diff

39
appveyor.yml Normal file
View file

@ -0,0 +1,39 @@
environment:
msvs_toolset: 14
FASTBUILD: 1
matrix:
- platform: x64
configuration: Release
os: Visual Studio 2015
#shallow_clone: true
# limit clone to latest 5 commits
clone_depth: 5
services:
- postgresql94 #if changing this, also change PATH below
install:
- SET PGUSER=postgres
- SET PGPASSWORD=Password12!
- SET PATH=C:\Program Files\PostgreSQL\9.4\bin\;%PATH%
build_script:
- scripts\build-appveyor.bat
after_build:
- 7z a visual-test-results.zip C:\tmp\mapnik-visual-images\visual-test-results
artifacts:
- path: mapnik-gyp\msbuild-summary.txt
name: msbuild-summary.txt
- path: mapnik-gyp\msbuild-errors.txt
name: msbuild-errors.txt
- path: mapnik-gyp\msbuild-warnings.txt
name: msbuild-warnings.txt
- path: visual-test-results.zip
name: visual-test-results.zip
test: off
deploy: off

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

@ -2,47 +2,54 @@
#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/value_types.hpp>
#include <mapnik/safe_cast.hpp>
#include "../test/cleanup.hpp"
// stl
#include <chrono>
#include <cmath> // log10, round
#include <cmath> // log10, round
#include <cstdio> // snprintf
#include <iomanip>
#include <iostream>
#include <set>
#include <sstream>
#include <thread>
#include <mutex>
#include <vector>
namespace benchmark {
template<typename T>
template <typename T>
using milliseconds = std::chrono::duration<T, std::milli>;
template<typename T>
template <typename T>
using seconds = std::chrono::duration<T>;
class test_case
{
protected:
protected:
mapnik::parameters params_;
std::size_t threads_;
std::size_t iterations_;
public:
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_; }
: 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;
};
@ -50,25 +57,21 @@ class test_case
// 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)
inline int parse_args(int argc, char** argv, mapnik::parameters & params)
{
for (int i = 1; i < argc; ++i)
{
for (int i = 1; i < argc; ++i) {
const char* opt = argv[i];
if (opt[0] != '-')
{
if (opt[0] != '-') {
// non-option argument, return its index
return i;
}
if (opt[1] != '-')
{
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')
{
if (opt[2] == '\0') {
// option-list terminator '--'
return i + 1;
}
@ -76,18 +79,15 @@ inline int parse_args(int argc, char** argv, mapnik::parameters& params)
// take option name without the leading '--'
std::string key(opt + 2);
size_t eq = key.find('=');
if (eq != std::string::npos)
{
if (eq != std::string::npos) {
// one-argument form '--foo=bar'
params[key.substr(0, eq)] = key.substr(eq + 1);
}
else if (i + 1 < argc)
{
else if (i + 1 < argc) {
// two-argument form '--foo' 'bar'
params[key] = std::string(argv[++i]);
}
else
{
else {
// missing second argument
std::clog << argv[0] << ": missing option '" << opt << "' value\n";
return -i; // negative means ill-formed option #i
@ -98,8 +98,7 @@ inline int parse_args(int argc, char** argv, mapnik::parameters& params)
inline void handle_common_args(mapnik::parameters const& params)
{
if (auto severity = params.get<std::string>("log"))
{
if (auto severity = params.get<std::string>("log")) {
if (*severity == "debug")
mapnik::logger::set_severity(mapnik::logger::debug);
else if (*severity == "warn")
@ -109,37 +108,37 @@ inline void handle_common_args(mapnik::parameters const& params)
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";
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)
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; \
} \
}
#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); \
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
{
@ -148,9 +147,7 @@ struct big_number_fmt
const char* u;
big_number_fmt(int width, double value, int base = 1000)
: w(width)
, v(value)
, u("")
: w(width), v(value), u("")
{
static const char* suffixes = "\0\0k\0M\0G\0T\0P\0E\0Z\0Y\0\0";
u = suffixes;
@ -166,7 +163,7 @@ struct big_number_fmt
}
};
template<typename T>
template <typename T>
int run(T const& test_runner, std::string const& name)
{
try
@ -197,7 +194,8 @@ int run(T const& test_runner, std::string const& name)
std::mutex mtx_ready;
std::unique_lock<std::mutex> lock_ready(mtx_ready);
auto stub = [&](T const& test_copy) {
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);
@ -207,14 +205,14 @@ int run(T const& test_runner, std::string const& name)
std::vector<std::thread> tg;
tg.reserve(num_threads);
for (auto i = num_threads; i-- > 0;)
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)
for (auto & t : tg)
{
if (t.joinable())
t.join();
@ -228,8 +226,7 @@ int run(T const& test_runner, std::string const& name)
else
{
start = std::chrono::high_resolution_clock::now();
do
{
do {
test_runner();
elapsed = std::chrono::high_resolution_clock::now() - start;
total_iters += num_iters;
@ -242,26 +239,14 @@ int run(T const& test_runner, std::string const& name)
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::snprintf(msg, sizeof(msg),
"%-43s %3zu threads %*.0f%s iters %6.0f milliseconds %*.0f%s i/s\n",
name.c_str(),
num_threads,
itersf.w, itersf.v, itersf.u,
dur_total,
ips.w, ips.v, ips.u
);
std::clog << msg;
return 0;
}
@ -275,15 +260,18 @@ int run(T const& test_runner, std::string const& name)
struct sequencer
{
sequencer(int argc, char** argv)
: exit_code_(0)
: exit_code_(0)
{
benchmark::handle_args(argc, argv, params_);
}
int done() const { return exit_code_; }
int done() const
{
return exit_code_;
}
template<typename Test, typename... Args>
sequencer& run(std::string const& name, Args&&... args)
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)...);
@ -292,11 +280,11 @@ struct sequencer
return *this; // allow chaining calls
}
protected:
protected:
mapnik::parameters params_;
int exit_code_;
};
} // namespace benchmark
}
#endif // MAPNIK_BENCH_FRAMEWORK_HPP

View file

@ -9,7 +9,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 +18,40 @@ 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])
#benchmarks = glob.glob('test*cpp')
benchmarks = [
#"test_array_allocation.cpp",
#"test_png_encoding1.cpp",
#"test_png_encoding2.cpp",
#"test_to_string1.cpp",
#"test_to_string2.cpp",
#"test_to_bool.cpp",
#"test_to_double.cpp",
#"test_to_int.cpp",
#"test_utf_encoding.cpp"
"test_polygon_clipping.cpp",
#"test_polygon_clipping_rendering.cpp",
"test_proj_transform1.cpp",
"test_expression_parse.cpp",
"test_face_ptr_creation.cpp",
"test_font_registration.cpp",
"test_rendering.cpp",
"test_rendering_shared_map.cpp",
"test_offset_converter.cpp",
"test_marker_cache.cpp",
"test_quad_tree.cpp",
"test_noop_rendering.cpp",
"test_getline.cpp",
# "test_numeric_cast_vs_static_cast.cpp",
]
for cpp_test in benchmarks:
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,36 @@
#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;
}
}
#endif // MAPNIK_COMPARE_IMAGES_HPP

View file

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

View file

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

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

@ -24,11 +24,10 @@ run test_getline 30 10000000
#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_expression_parse 10 1000
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
: '

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,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,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,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

@ -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,379 @@
#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)
{
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,18 +1,16 @@
#include "bench_framework.hpp"
#include <mapnik/unicode.hpp>
#include <mapnik/attribute.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:
public:
test(mapnik::parameters const& params)
: test_case(params)
, expr_("((([mapnik::geometry_type]=2) and ([oneway]=1)) and ([class]='path'))")
{}
: 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_);
@ -20,25 +18,24 @@ class test : public benchmark::test_case
bool ret = (result == expr_);
if (!ret)
{
std::clog << result << " != " << expr_ << "\n";
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;
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);
benchmark::handle_args(argc,argv,params);
test test_runner(params);
return run(test_runner, "expr parsing");
return run(test_runner,"expr parsing");
}

View file

@ -4,10 +4,9 @@
class test : public benchmark::test_case
{
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
: test_case(params) {}
bool validate() const
{
std::size_t count = 0;
@ -23,15 +22,14 @@ class test : public benchmark::test_case
font_cache,
mapnik::freetype_engine::get_mapping(),
mapnik::freetype_engine::get_cache());
if (f)
++count;
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)
for (unsigned i=0;i<iterations_;++i)
{
std::size_t count = 0;
mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
@ -45,11 +43,9 @@ class test : public benchmark::test_case
font_cache,
mapnik::freetype_engine::get_mapping(),
mapnik::freetype_engine::get_cache());
if (f)
++count;
if (f) ++count;
}
if (count != expected_count)
{
if (count != expected_count) {
std::clog << "warning: face creation not working as expected\n";
}
}
@ -59,16 +55,15 @@ class test : public benchmark::test_case
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, 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;
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());
return run(test_runner,(boost::format("font_engine: creating %ld faces") % (face_count)).str());
}

View file

@ -1,18 +1,21 @@
#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:
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return mapnik::freetype_engine::register_fonts("./fonts", true); }
: 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)
for (unsigned i=0;i<iterations_;++i)
{
mapnik::freetype_engine::register_fonts("./fonts", true);
count++;
@ -21,4 +24,4 @@ class test : public benchmark::test_case
}
};
BENCHMARK(test, "font registration")
BENCHMARK(test,"font registration")

View file

@ -1,20 +1,22 @@
#include "bench_framework.hpp"
#include "../plugins/input/csv/csv_getline.hpp"
class test : public benchmark::test_case
{
public:
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;
}
}
: test_case(params),
line_data_("this is one line\nand this is a second line\nand a third line")
{
boost::optional<std::string> line_data = params.get<std::string>("line");
if (line_data)
{
line_data_ = *line_data;
}
}
bool validate() const
{
@ -23,15 +25,14 @@ class test : public benchmark::test_case
std::string csv_line;
std::stringstream s;
s << line_data_;
std::getline(s, csv_line, newline);
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";
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;
}
@ -41,28 +42,29 @@ class test : public benchmark::test_case
std::string csv_line;
std::stringstream s;
s << line_data_;
for (unsigned i = 0; i < iterations_; ++i)
for (unsigned i=0;i<iterations_;++i)
{
std::getline(s, csv_line, newline);
std::getline(s,csv_line,newline);
}
return true;
}
};
class test2 : public benchmark::test_case
{
public:
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;
}
}
: test_case(params),
line_data_("this is one line\nand this is a second line\nand a third line")
{
boost::optional<std::string> line_data = params.get<std::string>("line");
if (line_data)
{
line_data_ = *line_data;
}
}
bool validate() const
{
@ -72,15 +74,14 @@ class test2 : public benchmark::test_case
std::string csv_line;
std::stringstream s;
s << line_data_;
csv_utils::getline_csv(s, csv_line, newline, quote);
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";
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;
}
@ -91,9 +92,9 @@ class test2 : public benchmark::test_case
std::string csv_line;
std::stringstream s;
s << line_data_;
for (unsigned i = 0; i < iterations_; ++i)
for (unsigned i=0;i<iterations_;++i)
{
csv_utils::getline_csv(s, csv_line, newline, quote);
csv_utils::getline_csv(s,csv_line,newline,quote);
}
return true;
}
@ -101,19 +102,18 @@ class test2 : public benchmark::test_case
int main(int argc, char** argv)
{
mapnik::setup();
int return_value = 0;
try
{
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
benchmark::handle_args(argc,argv,params);
{
test test_runner(params);
return_value = return_value | run(test_runner, "std::getline");
return_value = return_value | run(test_runner,"std::getline");
}
{
test2 test_runner2(params);
return_value = return_value | run(test_runner2, "csv_utils::getline_csv");
return_value = return_value | run(test_runner2,"csv_utils::getline_csv");
}
}
catch (std::exception const& ex)

View file

@ -0,0 +1,42 @@
#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

@ -14,38 +14,40 @@
class test : public benchmark::test_case
{
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
: test_case(params) {}
bool validate() const { return true; }
bool validate() const
{
return true;
}
bool operator()() const
{
mapnik::Map m(256, 256, "epsg:3857");
mapnik::Map m(256,256,"+init=epsg:3857");
mapnik::parameters params;
params["type"] = "memory";
params["type"]="memory";
auto ds = std::make_shared<mapnik::memory_datasource>(params);
// add whitespace to trigger phony "reprojection"
mapnik::layer lay("layer", m.srs() + " ");
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());
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)
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);
mapnik::image_rgba8 im(256,256);
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im);
ren.apply();
}
return true;
}
};
BENCHMARK(test, "rendering with reprojection")
BENCHMARK(test,"rendering with reprojection")

View file

@ -9,25 +9,23 @@ class test_static : public benchmark::test_case
{
double step_;
std::uint8_t start_;
public:
public:
test_static(mapnik::parameters const& params)
: test_case(params)
, step_(STEP_NUM)
, start_(START_NUM)
{}
bool validate() const { return true; }
: 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)
{
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;
if (c >= 256.0) c = 255.0;
if (c < 0.0) c = 0.0;
x = static_cast<std::uint8_t>(c);
value_ += step_;
}
@ -35,36 +33,35 @@ class test_static : public benchmark::test_case
}
};
using boost::numeric::negative_overflow;
using boost::numeric::positive_overflow;
using boost::numeric::negative_overflow;
class test_numeric : public benchmark::test_case
{
double step_;
std::uint8_t start_;
public:
public:
test_numeric(mapnik::parameters const& params)
: test_case(params)
, step_(STEP_NUM)
, start_(START_NUM)
{}
bool validate() const { return true; }
: 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
{
for (std::size_t i=0;i<iterations_;++i) {
try {
x = boost::numeric_cast<std::uint8_t>(start_ * value_);
}
catch (negative_overflow&)
catch(negative_overflow&)
{
x = std::numeric_limits<std::uint8_t>::min();
}
catch (positive_overflow&)
catch(positive_overflow&)
{
x = std::numeric_limits<std::uint8_t>::max();
}
@ -76,6 +73,8 @@ class test_numeric : public benchmark::test_case
int main(int argc, char** argv)
{
mapnik::setup();
return benchmark::sequencer(argc, argv).run<test_static>("static_cast").run<test_numeric>("numeric_cast").done();
return benchmark::sequencer(argc, argv)
.run<test_static>("static_cast")
.run<test_numeric>("numeric_cast")
.done();
}

View file

@ -14,36 +14,31 @@ struct fake_path
cont_type::iterator itr_;
fake_path(std::initializer_list<double> l)
: fake_path(l.begin(), l.size())
{}
: fake_path(l.begin(), l.size()) {
}
fake_path(std::vector<double> const& v)
: fake_path(v.begin(), v.size())
{}
fake_path(std::vector<double> const &v)
: fake_path(v.begin(), v.size()) {
}
template<typename Itr>
fake_path(Itr itr, size_t sz)
{
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)
{
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;
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())
{
unsigned vertex(double *x, double *y) {
if (itr_ == vertices_.end()) {
return mapnik::SEG_END;
}
*x = std::get<0>(*itr_);
@ -53,30 +48,33 @@ struct fake_path
return cmd;
}
void rewind(unsigned) { itr_ = vertices_.begin(); }
void rewind(unsigned) {
itr_ = vertices_.begin();
}
};
class test_offset : public benchmark::test_case
{
public:
public:
test_offset(mapnik::parameters const& params)
: test_case(params)
{}
bool validate() const { return true; }
: 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.reserve(mysize*2);
for( int i = 0; i < mysize; i++ )
{
path.push_back(i);
path.push_back(0);
path.push_back( i );
path.push_back( 0 );
}
fake_path fpath(path);
for (std::size_t i = 0; i < iterations_; ++i)
{
for (std::size_t i=0;i<iterations_;++i) {
mapnik::offset_converter<fake_path> off_path(fpath);
off_path.set_offset(10);
unsigned cmd;
@ -90,15 +88,15 @@ class test_offset : public benchmark::test_case
}
};
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, params);
benchmark::handle_args(argc,argv,params);
int return_value = 0;
{
test_offset test_runner(params);
return_value = run(test_runner, "offset_test");
return_value = run(test_runner,"offset_test");
}
return return_value;
}

View file

@ -4,23 +4,23 @@
class test : public benchmark::test_case
{
mapnik::image_rgba8 im_;
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
, im_(256, 256)
{}
bool validate() const { return true; }
: 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)
{
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
out = mapnik::save_to_string(im_, "png8:m=h:z=1");
out = mapnik::save_to_string(im_,"png8:m=h:z=1");
}
return true;
}
};
BENCHMARK(test, "encoding blank png")
BENCHMARK(test,"encoding blank png")

View file

@ -1,41 +1,37 @@
#include "bench_framework.hpp"
#include "compare_images.hpp"
#include <memory>
class test : public benchmark::test_case
{
std::shared_ptr<mapnik::image_rgba8> im_;
public:
std::shared_ptr<image_rgba8> im_;
public:
test(mapnik::parameters const& params)
: test_case(params)
{
: test_case(params) {
std::string filename("./benchmark/data/multicolor.png");
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, "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_);
im_ = std::make_shared<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);
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)
{
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
out = mapnik::save_to_string(*im_, "png8:m=h:z=1");
out = mapnik::save_to_string(*im_,"png8:m=h:z=1");
}
return true;
}
};
BENCHMARK(test, "encoding multicolor png")
BENCHMARK(test,"encoding multicolor png")

View file

@ -10,10 +10,10 @@
#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/geometry_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
@ -39,31 +39,30 @@ 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 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::image_rgba8 im(256,256);
mapnik::fill(im, mapnik::color("white"));
mapnik::box2d<double> padded_extent(155, 134, 665, 466); // extent;
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());
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));
mapnik::proj_transform prj_trans(mapnik::projection("+init=epsg:4326"),mapnik::projection("+init=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);
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);
mapnik::save_to_file(im,name);
}
class test1 : public benchmark::test_case
@ -71,15 +70,15 @@ class test1 : public benchmark::test_case
std::string wkt_in_;
mapnik::box2d<double> extent_;
std::string expected_;
public:
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")
{}
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;
@ -100,8 +99,14 @@ class test1 : public benchmark::test_case
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.clip_box(
extent_.minx(),
extent_.miny(),
extent_.maxx(),
extent_.maxy());
clipped.rewind(0);
mapnik::geometry::polygon<double> poly2;
@ -113,49 +118,47 @@ class test1 : public benchmark::test_case
{
if (cmd == mapnik::SEG_MOVETO)
{
x0 = x;
y0 = y;
x0 = x; y0 = y;
}
if (cmd == mapnik::SEG_CLOSE)
{
ring.emplace_back(x0, y0);
ring.add_coord(x0, y0);
break;
}
ring.emplace_back(x, y);
ring.add_coord(x,y);
}
poly2.push_back(std::move(ring));
poly2.set_exterior_ring(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;
x0 = x; y0 = y;
}
else if (cmd == mapnik::SEG_CLOSE)
{
ring.emplace_back(x0, y0);
poly2.push_back(std::move(ring));
ring.add_coord(x0,y0);
poly2.add_hole(std::move(ring));
ring.clear();
continue;
}
ring.emplace_back(x, y);
ring.add_coord(x,y);
}
std::string expect = expected_ + ".png";
std::string actual = expected_ + "_actual.png";
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,expect);
}
render(mp, env, actual);
return benchmark::compare_images(actual, expect);
render(mp,env,actual);
return benchmark::compare_images(actual,expect);
}
bool operator()() const
{
@ -175,28 +178,29 @@ class test1 : public benchmark::test_case
return false;
}
bool valid = true;
for (unsigned i = 0; i < iterations_; ++i)
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());
clipped.clip_box(
extent_.minx(),
extent_.miny(),
extent_.maxx(),
extent_.maxy());
unsigned cmd;
double x, y;
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)
{
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";
if (count != expected_count) {
std::clog << "test1: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
valid = false;
}
}
@ -204,19 +208,20 @@ class test1 : public benchmark::test_case
}
};
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")
{}
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;
@ -229,30 +234,30 @@ class test3 : public benchmark::test_case
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double>>())
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::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());
bbox.add_coord(extent_.minx(), extent_.miny());
bbox.add_coord(extent_.minx(), extent_.maxy());
bbox.add_coord(extent_.maxx(), extent_.maxy());
bbox.add_coord(extent_.maxx(), extent_.miny());
bbox.add_coord(extent_.minx(), extent_.miny());
std::deque<mapnik::geometry::polygon<double>> result;
std::deque<mapnik::geometry::polygon<double> > result;
boost::geometry::intersection(bbox, poly, result);
std::string expect = expected_ + ".png";
std::string actual = expected_ + "_actual.png";
std::string expect = expected_+".png";
std::string actual = expected_+"_actual.png";
mapnik::geometry::multi_polygon<double> mp;
for (auto const& _geom : result)
for (auto const& _geom: result)
{
// std::clog << boost::geometry::dsv(geom) << "\n";
//std::clog << boost::geometry::dsv(geom) << "\n";
mp.emplace_back(_geom);
}
mapnik::geometry::geometry<double> geom2(mp);
@ -260,10 +265,10 @@ class test3 : public benchmark::test_case
if (!mapnik::util::exists(expect) || (std::getenv("UPDATE") != nullptr))
{
std::clog << "generating expected image: " << expect << "\n";
render(mp, env, expect);
render(mp,env,expect);
}
render(mp, env, actual);
return benchmark::compare_images(actual, expect);
render(mp,env,actual);
return benchmark::compare_images(actual,expect);
}
bool operator()() const
{
@ -277,41 +282,38 @@ class test3 : public benchmark::test_case
std::clog << "empty geom!\n";
return false;
}
if (!geom.is<mapnik::geometry::polygon<double>>())
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::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());
bbox.add_coord(extent_.minx(), extent_.miny());
bbox.add_coord(extent_.minx(), extent_.maxy());
bbox.add_coord(extent_.maxx(), extent_.maxy());
bbox.add_coord(extent_.maxx(), extent_.miny());
bbox.add_coord(extent_.minx(), extent_.miny());
bool valid = true;
for (unsigned i = 0; i < iterations_; ++i)
for (unsigned i=0;i<iterations_;++i)
{
std::deque<mapnik::geometry::polygon<double>> result;
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)
{
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";
if (count != expected_count) {
std::clog << "test3: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
valid = false;
}
}
@ -498,8 +500,8 @@ public:
}
unsigned expected_count = 29;
if (count != expected_count) {
std::clog << "test3: clipping failed: processed " << count << " verticies but expected " <<
expected_count << "\n"; valid = false;
std::clog << "test3: clipping failed: processed " << count << " verticies but expected " << expected_count << "\n";
valid = false;
}
}
}
@ -510,19 +512,15 @@ expected_count << "\n"; valid = false;
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, 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
// 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);
@ -545,6 +543,5 @@ int main(int argc, char** argv)
return_value = return_value | run(test_runner,"clipping polygon with clipper_tree");
}
*/
#endif
return 0; // return_value;
return return_value;
}

View file

@ -0,0 +1,60 @@
#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::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

@ -0,0 +1,74 @@
#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)
);
}
bool operator()() const
{
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::projection src(src_,defer_proj4_init_);
mapnik::projection dest(dest_,defer_proj4_init_);
mapnik::proj_transform tr(src,dest);
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" +init=epsg:4326 +to +init=epsg:3857
int main(int argc, char** argv)
{
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");
return benchmark::sequencer(argc, argv)
.run<test>("lonlat->merc epsg", from_str, to_str, from, to, true)
.run<test>("lonlat->merc literal", from_str2, to_str2, from, to, true)
.run<test>("merc->lonlat epsg", to_str, from_str, to, from, true)
.run<test>("merc->lonlat literal", to_str2, from_str2, to, from, true)
.done();
}

View file

@ -6,41 +6,43 @@ using quad_tree_type = mapnik::quad_tree<std::size_t>;
class test : public benchmark::test_case
{
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
{}
: test_case(params) {}
bool validate() const { return true; }
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
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);
mapnik::box2d<double> box(cx - sx,cy - sy, cx + sx, cy + sy);
tree.insert(i, box);
}
// bounding box query
std::size_t count = 0;
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);
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)
for ( ;itr != end; ++itr)
{
++count;
}
@ -49,4 +51,4 @@ class test : public benchmark::test_case
}
};
BENCHMARK(test, "quad_tree creation")
BENCHMARK(test,"quad_tree creation")

View file

@ -15,25 +15,24 @@ class test : public benchmark::test_case
mapnik::value_integer height_;
double scale_factor_;
std::string preview_;
public:
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");
: 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",""))
{
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;
const auto ext = params.get<std::string>("extent");
boost::optional<std::string> ext = params.get<std::string>("extent");
if (ext && !ext->empty())
{
if (!extent_.from_string(*ext))
@ -44,74 +43,67 @@ class test : public benchmark::test_case
{
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())
{
mapnik::Map m(width_,height_);
mapnik::load_map(m,xml_,true);
if (extent_.valid()) {
m.zoom_to_box(extent_);
}
else
{
} else {
m.zoom_all();
}
mapnik::image_rgba8 im(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im, scale_factor_);
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im,scale_factor_);
ren.apply();
if (!preview_.empty())
{
if (!preview_.empty()) {
std::clog << "preview available at " << preview_ << "\n";
mapnik::save_to_file(im, preview_);
mapnik::save_to_file(im,preview_);
}
return true;
}
bool operator()() const
{
if (!preview_.empty())
{
if (!preview_.empty()) {
return false;
}
mapnik::Map m(width_, height_);
mapnik::load_map(m, xml_);
if (extent_.valid())
{
mapnik::Map m(width_,height_);
mapnik::load_map(m,xml_);
if (extent_.valid()) {
m.zoom_to_box(extent_);
}
else
{
} else {
m.zoom_all();
}
for (unsigned i = 0; i < iterations_; ++i)
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_);
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");
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;
}
mapnik::freetype_engine::register_fonts("./fonts/", true);
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);
return_value = run(test_runner,*name);
}
}
catch (std::exception const& ex)

View file

@ -12,15 +12,14 @@
#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)
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)
for (unsigned i=0; i < layers_size; ++i)
{
mapnik::layer const& lyr = layers[i];
if (lyr.visible(scale_denom))
@ -51,28 +50,27 @@ class test : public benchmark::test_case
double scale_factor_;
std::string preview_;
mutable mapnik::image_rgba8 im_;
public:
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())
: 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");
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;
auto ext = params.get<std::string>("extent");
mapnik::load_map(*m_, xml_, true);
boost::optional<std::string> ext = params.get<std::string>("extent");
mapnik::load_map(*m_,xml_,true);
if (ext && !ext->empty())
{
if (!extent_.from_string(*ext))
@ -89,44 +87,42 @@ class test : public benchmark::test_case
bool validate() const
{
mapnik::request m_req(width_, height_, extent_);
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());
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_);
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);
process_layers(ren,m_req,map_proj,layers,scale_denom);
ren.end_map_processing(*m_);
if (!preview_.empty())
{
if (!preview_.empty()) {
std::clog << "preview available at " << preview_ << "\n";
mapnik::save_to_file(im_, preview_);
mapnik::save_to_file(im_,preview_);
}
return true;
}
bool operator()() const
{
if (!preview_.empty())
{
if (!preview_.empty()) {
return false;
}
for (unsigned i = 0; i < iterations_; ++i)
for (unsigned i=0;i<iterations_;++i)
{
mapnik::request m_req(width_, height_, extent_);
mapnik::image_rgba8 im(m_->width(), m_->height());
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());
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_);
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);
process_layers(ren,m_req,map_proj,layers,scale_denom);
ren.end_map_processing(*m_);
bool diff = false;
mapnik::image_rgba8 const& dest = im;
@ -137,36 +133,34 @@ class test : public benchmark::test_case
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 (row_from[x] != row_to[x]) diff = true;
}
}
if (diff)
throw std::runtime_error("images differ");
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");
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;
}
mapnik::freetype_engine::register_fonts("./fonts/", true);
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);
return_value = run(test_runner,*name);
}
}
catch (std::exception const& ex)

View file

@ -0,0 +1,30 @@
#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

@ -0,0 +1,32 @@
#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")

32
benchmark/test_to_int.cpp Normal file
View file

@ -0,0 +1,32 @@
#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

@ -4,28 +4,25 @@
class test : public benchmark::test_case
{
double value_;
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_(-0.1234)
{}
: test_case(params),
value_(-0.1234) {}
bool validate() const
{
std::string s;
mapnik::util::to_string(s, value_);
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)
{
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
mapnik::util::to_string(out, value_);
mapnik::util::to_string(out,value_);
}
return true;
}
};
BENCHMARK(test, "to_string double->string")
BENCHMARK(test,"to_string double->string")

View file

@ -4,12 +4,10 @@
class test : public benchmark::test_case
{
double value_;
public:
public:
test(mapnik::parameters const& params)
: test_case(params)
, value_(-0.1234)
{}
: test_case(params),
value_(-0.1234) {}
bool validate() const
{
std::ostringstream s;
@ -19,8 +17,7 @@ class test : public benchmark::test_case
bool operator()() const
{
std::string out;
for (std::size_t i = 0; i < iterations_; ++i)
{
for (std::size_t i=0;i<iterations_;++i) {
std::ostringstream s;
s << value_;
out = s.str();
@ -29,4 +26,4 @@ class test : public benchmark::test_case
}
};
BENCHMARK(test, "ostringstream double->string")
BENCHMARK(test,"ostringstream double->string")

View file

@ -1,41 +1,34 @@
#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:
public:
test(mapnik::parameters const& params)
: test_case(params)
, utf8_(from_u8string(u8"שלום"))
{}
: test_case(params),
utf8_(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;
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_);
for (std::size_t i=0;i<iterations_;++i) {
utf32 = utf32conv.from_bytes(utf8_);
}
return true;
}
@ -46,28 +39,26 @@ class test : public benchmark::test_case
class test2 : public benchmark::test_case
{
std::string utf8_;
public:
public:
test2(mapnik::parameters const& params)
: test_case(params)
, utf8_(from_u8string(u8"שלום"))
{}
: test_case(params),
utf8_(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;
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_);
}
std::u32string utf32;
for (std::size_t i=0;i<iterations_;++i) {
utf32 = boost::locale::conv::utf_to_utf<char32_t>(utf8_);
}
return true;
}
};
@ -75,30 +66,28 @@ class test2 : public benchmark::test_case
class test3 : public benchmark::test_case
{
std::string utf8_;
public:
public:
test3(mapnik::parameters const& params)
: test_case(params)
, utf8_(from_u8string(u8"שלום"))
{}
: test_case(params),
utf8_(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;
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());
for (std::size_t i=0;i<iterations_;++i) {
utf32 = tr_.transcode(utf8_.data(),utf8_.size());
}
return true;
}
@ -106,19 +95,18 @@ class test3 : public benchmark::test_case
int main(int argc, char** argv)
{
mapnik::setup();
mapnik::parameters params;
benchmark::handle_args(argc, argv, 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");
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");
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_value = return_value | run(test_runner3,"utf encode ICU");
return return_value;
}

174
bootstrap.sh Executable file
View file

@ -0,0 +1,174 @@
#!/usr/bin/env bash
: '
todo
- docs for base setup: sudo apt-get -y install zlib1g-dev make git
- shrink icu data
'
MASON_VERSION="fde1d9f5"
function setup_mason() {
if [[ ! -d ./.mason ]]; then
git clone https://github.com/mapbox/mason.git .mason || return
elif ! git -C .mason rev-parse -q --verify "$MASON_VERSION" >/dev/null; then
git -C .mason fetch --all || true # non-fatal
fi
git -C .mason checkout --detach "$MASON_VERSION" -- || return
case ":$PATH:" in
*":$PWD/.mason:"*) : already there ;;
*) export PATH="$PWD/.mason:$PATH" ;;
esac
export CXX=${CXX:-clang++}
export CC=${CC:-clang}
}
function install() {
MASON_PLATFORM_ID=$(mason env MASON_PLATFORM_ID)
if [[ ! -d ./mason_packages/${MASON_PLATFORM_ID}/${1}/${2} ]]; then
mason install $1 $2
if [[ ${3:-false} != false ]]; then
LA_FILE=$(mason prefix $1 $2)/lib/$3.la
if [[ -f ${LA_FILE} ]]; then
perl -i -p -e 's:\Q$ENV{HOME}/build/mapbox/mason\E:$ENV{PWD}:g' ${LA_FILE}
else
echo "$LA_FILE not found"
fi
fi
fi
# the rm here is to workaround https://github.com/mapbox/mason/issues/230
rm -f ./mason_packages/.link/mason.ini
mason link $1 $2
}
ICU_VERSION="57.1"
BOOST_VERSION="1.73.0"
function install_mason_deps() {
install ccache 3.3.1
install zlib 1.2.8
install jpeg_turbo 1.5.1 libjpeg
install libpng 1.6.28 libpng
install libtiff 4.0.7 libtiff
install libpq 9.6.2
install sqlite 3.17.0 libsqlite3
install expat 2.2.0 libexpat
install icu ${ICU_VERSION}
install proj 4.9.3 libproj
install pixman 0.34.0 libpixman-1
install cairo 1.14.8 libcairo
install webp 0.6.0 libwebp
install libgdal 2.1.3 libgdal
install boost ${BOOST_VERSION}
install boost_libsystem ${BOOST_VERSION}
install boost_libfilesystem ${BOOST_VERSION}
install boost_libprogram_options ${BOOST_VERSION}
install boost_libregex_icu57 ${BOOST_VERSION}
# technically boost thread and python are not a core dep, but installing
# here by default helps make python-mapnik builds easier
install boost_libthread ${BOOST_VERSION}
install boost_libpython ${BOOST_VERSION}
install freetype 2.7.1 libfreetype
install harfbuzz 1.4.4-ft libharfbuzz
}
MASON_LINKED_ABS=$(pwd)/mason_packages/.link
MASON_LINKED_REL=./mason_packages/.link
export C_INCLUDE_PATH="${MASON_LINKED_ABS}/include"
export CPLUS_INCLUDE_PATH="${MASON_LINKED_ABS}/include"
export LIBRARY_PATH="${MASON_LINKED_ABS}/lib"
function make_config() {
echo "
CXX = '$CXX'
CC = '$CC'
CUSTOM_CXXFLAGS = '-D_GLIBCXX_USE_CXX11_ABI=0'
RUNTIME_LINK = 'static'
INPUT_PLUGINS = 'all'
PATH = '${MASON_LINKED_REL}/bin'
PKG_CONFIG_PATH = '${MASON_LINKED_REL}/lib/pkgconfig'
PATH_REMOVE = '/usr:/usr/local'
PATH_REPLACE = '$HOME/build/mapbox/mason/mason_packages:./mason_packages'
BOOST_INCLUDES = '${MASON_LINKED_REL}/include'
BOOST_LIBS = '${MASON_LINKED_REL}/lib'
ICU_INCLUDES = '${MASON_LINKED_REL}/include'
ICU_LIBS = '${MASON_LINKED_REL}/lib'
HB_INCLUDES = '${MASON_LINKED_REL}/include'
HB_LIBS = '${MASON_LINKED_REL}/lib'
PNG_INCLUDES = '${MASON_LINKED_REL}/include/libpng16'
PNG_LIBS = '${MASON_LINKED_REL}/lib'
JPEG_INCLUDES = '${MASON_LINKED_REL}/include'
JPEG_LIBS = '${MASON_LINKED_REL}/lib'
TIFF_INCLUDES = '${MASON_LINKED_REL}/include'
TIFF_LIBS = '${MASON_LINKED_REL}/lib'
WEBP_INCLUDES = '${MASON_LINKED_REL}/include'
WEBP_LIBS = '${MASON_LINKED_REL}/lib'
PROJ_INCLUDES = '${MASON_LINKED_REL}/include'
PROJ_LIBS = '${MASON_LINKED_REL}/lib'
PG_INCLUDES = '${MASON_LINKED_REL}/include'
PG_LIBS = '${MASON_LINKED_REL}/lib'
FREETYPE_INCLUDES = '${MASON_LINKED_REL}/include/freetype2'
FREETYPE_LIBS = '${MASON_LINKED_REL}/lib'
SVG_RENDERER = True
CAIRO_INCLUDES = '${MASON_LINKED_REL}/include'
CAIRO_LIBS = '${MASON_LINKED_REL}/lib'
SQLITE_INCLUDES = '${MASON_LINKED_REL}/include'
SQLITE_LIBS = '${MASON_LINKED_REL}/lib'
BENCHMARK = True
CPP_TESTS = True
PGSQL2SQLITE = True
XMLPARSER = 'ptree'
SVG2PNG = True
"
}
# NOTE: the `mapnik-settings.env` is used by test/run (which is run by `make test`)
function setup_runtime_settings() {
echo "export PROJ_LIB=${MASON_LINKED_ABS}/share/proj" > mapnik-settings.env
echo "export ICU_DATA=${MASON_LINKED_ABS}/share/icu/${ICU_VERSION}" >> mapnik-settings.env
echo "export GDAL_DATA=${MASON_LINKED_ABS}/share/gdal" >> mapnik-settings.env
}
# turn arguments of the form NAME=VALUE into exported variables;
# any other arguments are reported and cause error return status
function export_variables() {
local arg= ret=0
for arg
do
if [[ "$arg" =~ ^[[:alpha:]][_[:alnum:]]*= ]]
then
export "$arg"
else
printf >&2 "bootstrap.sh: invalid argument: %s\n" "$arg"
ret=1
fi
done
return $ret
}
function main() {
export_variables "$@" || return
# setup_mason must not run in subshell, because it sets default
# values of CC, CXX and adds mason to PATH, which we want to keep
# when sourced
setup_mason || return
(
# this is wrapped in subshell to allow sourcing this script
# without having the terminal closed on error
set -eu
set -o pipefail
install_mason_deps
make_config > ./config.py
setup_runtime_settings
printf "\n\e[1;32m%s\e[m\n" "bootstrap successful, now run:"
echo ""
echo " ./configure && make"
echo ""
)
}
main "$@"

42
circle.yml Normal file
View file

@ -0,0 +1,42 @@
machine:
xcode:
version: 7.3
environment:
XCODE_SCHEME: "no"
XCODE_WORKSPACE: "no"
JOBS: 8
CCACHE_TEMPDIR: /tmp/.ccache-temp
CCACHE_COMPRESS: 1
LLVM_VERSION: 3.9.1
checkout:
post:
- git submodule update --init
dependencies:
cache_directories:
- "~/.ccache"
- "~/.apt-cache"
pre:
# https://discuss.circleci.com/t/add-ability-to-cache-apt-get-programs/598/3
- sudo rm -rf /var/cache/apt/archives && sudo ln -s ~/.apt-cache /var/cache/apt/archives && mkdir -p ~/.apt-cache/partial
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
override:
- sudo apt-get update -y
- sudo apt-get install -y libstdc++-5-dev xutils-dev
database:
pre:
- ./bootstrap.sh
- ./.mason/mason install clang++ ${LLVM_VERSION}
- ./.mason/mason link clang++ ${LLVM_VERSION}
- ./configure CC="$(pwd)/mason_packages/.link/bin/clang" CXX="$(pwd)/mason_packages/.link/bin/ccache $(pwd)/mason_packages/.link/bin/clang++ -Qunused-arguments"
- make
- nm src/libmapnik* | grep "GLIBCXX_3.4.2[0-9]" || true
override:
- psql -c 'create database template_postgis;'
- psql -c 'create extension postgis;' -d template_postgis
test:
override:
- make test

View file

@ -1,23 +0,0 @@
include(CheckCXXSourceRuns)
function(check_boost_regex)
set(CMAKE_REQUIRED_LIBRARIES ICU::uc ICU::data ICU::i18n Boost::headers Boost::regex)
check_cxx_source_runs([[
#include <boost/regex/icu.hpp>
#include <unicode/unistr.h>
int main()
{
U_NAMESPACE_QUALIFIER UnicodeString ustr;
try {
boost::u32regex pattern = boost::make_u32regex(ustr);
}
// an exception is fine, still indicates support is
// likely compiled into regex
catch (...) {
return 0;
}
return 0;
}
]] BOOST_REGEX_HAS_ICU)
set(BOOST_REGEX_HAS_ICU ${BOOST_REGEX_HAS_ICU} PARENT_SCOPE)
endfunction(check_boost_regex)

View file

@ -1,14 +0,0 @@
macro(get_mapnik_version)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/include/mapnik/version.hpp VERSION_FILE)
string(REGEX MATCH "MAPNIK_MAJOR_VERSION ([0-9]*)" _ ${VERSION_FILE})
set(MAPNIK_MAJOR_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "MAPNIK_MINOR_VERSION ([0-9]*)" _ ${VERSION_FILE})
set(MAPNIK_MINOR_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "MAPNIK_PATCH_VERSION ([0-9]*)" _ ${VERSION_FILE})
set(MAPNIK_PATCH_VERSION ${CMAKE_MATCH_1})
set(MAPNIK_VERSION ${MAPNIK_MAJOR_VERSION}.${MAPNIK_MINOR_VERSION}.${MAPNIK_PATCH_VERSION})
endmacro()

View file

@ -1,68 +0,0 @@
include(CMakePackageConfigHelpers)
### exports mapnik cmake config files (mapnikConfigVersion and mapnikConfig)
function(mapnik_export_cmake_config)
# export mapnik configuration
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/mapnikConfigVersion.cmake"
VERSION ${MAPNIK_VERSION}
COMPATIBILITY ExactVersion
)
get_property(MAPNIK_UTILITIES GLOBAL PROPERTY MAPNIK_UTILITIES)
# generate all find_dependency and pkg_config calls
set(mapnik_find_deps)
foreach(dep IN LISTS mapnik_deps)
set(ver_comment "# ${dep} used with version ${mapnik_${dep}_version}")
set(mapnik_find_deps "${mapnik_find_deps}\n${ver_comment}\n")
if(mapnik_${dep}_find_args)
list(REMOVE_DUPLICATES mapnik_${dep}_find_args)
list(JOIN mapnik_${dep}_find_args " " m_args_joined)
set(mapnik_find_deps "${mapnik_find_deps}find_dependency(${dep} ${m_args_joined})")
else()
list(JOIN mapnik_${dep}_pkg_args " " m_args_joined)
set(mapnik_find_deps "${mapnik_find_deps}pkg_check_modules(${dep} ${m_args_joined})")
endif()
endforeach()
configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/mapnikConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/mapnikConfig.cmake"
INSTALL_DESTINATION ${MAPNIK_CMAKE_DIR}
PATH_VARS MAPNIK_INCLUDE_DIR PLUGINS_INSTALL_DIR FONTS_INSTALL_DIR mapnik_find_deps MAPNIK_UTILITIES
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/mapnikConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/mapnikConfigVersion.cmake"
DESTINATION ${MAPNIK_CMAKE_DIR}
)
endfunction()
mapnik_export_cmake_config()
install(EXPORT MapnikTargets
DESTINATION ${MAPNIK_CMAKE_DIR}
FILE mapnikTargets.cmake
NAMESPACE mapnik::
)
### install plugin cmake config files ###
# Create configuration dependend files for the plugin install dirs.
# some package managers are using different paths per configuration.
string(TOLOWER "${CMAKE_BUILD_TYPE}" _build_type)
string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_l)
set(m_mapnik_plugin_file_name mapnikPlugins-${_build_type})
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${m_mapnik_plugin_file_name}.cmake.in" "set(MAPNIK_PLUGINS_DIR_${_build_type_l} \"@PACKAGE_PLUGINS_INSTALL_DIR@\" CACHE STRING \"\")\n")
include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_CURRENT_BINARY_DIR}/${m_mapnik_plugin_file_name}.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/${m_mapnik_plugin_file_name}.cmake"
PATH_VARS PLUGINS_INSTALL_DIR
INSTALL_DESTINATION ${MAPNIK_CMAKE_DIR}
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${m_mapnik_plugin_file_name}.cmake"
DESTINATION ${MAPNIK_CMAKE_DIR}
)

View file

@ -1,92 +0,0 @@
function(create_pkg_config_file _target _lib_name _description)
string(CONFIGURE [[
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/@MAPNIK_LIB_DIR@
Name: @_lib_name@
Description: @_description@
Version: @MAPNIK_VERSION@
Libs: -L"${libdir}" -l$<TARGET_FILE_BASE_NAME:@_target@>$<TARGET_PROPERTY:@_target@,$<CONFIG>_POSTFIX>
Cflags: -I"${includedir}" -I"${includedir}/mapnik" ]]
_contents @ONLY)
file(GENERATE
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_lib_name}-$<CONFIG>.pc
CONTENT "${_contents}"
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${_lib_name}-$<CONFIG>.pc
DESTINATION ${MAPNIK_PKGCONF_DIR}
RENAME ${_lib_name}.pc
)
endfunction()
function(create_pkg_config_file_mapnik _lib_name _description)
get_target_property(m_compile_defs core INTERFACE_COMPILE_DEFINITIONS)
string(JOIN " -D" m_str_compile_defs ${m_compile_defs})
if(m_str_compile_defs)
set(m_str_compile_defs "-D${m_str_compile_defs}")
endif()
set(m_requires
libmapnikwkt
libmapnikjson
icu-uc
icu-i18n
harfbuzz
freetype2
)
if(USE_LIBXML2)
list(APPEND m_requires libxml-2.0)
endif()
if(USE_PNG)
list(APPEND m_requires libpng)
endif()
if(USE_JPEG)
list(APPEND m_requires libjpeg)
endif()
if(USE_TIFF)
list(APPEND m_requires libtiff-4)
endif()
if(USE_WEBP)
list(APPEND m_requires libwebp)
endif()
if(USE_CAIRO)
list(APPEND m_requires cairo)
endif()
if(USE_PROJ)
list(APPEND m_requires "proj >= ${PROJ_MIN_VERSION}")
endif()
string(JOIN " " m_requires ${m_requires})
string(CONFIGURE [[
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/@MAPNIK_LIB_DIR@
fonts_dir=${prefix}/@FONTS_INSTALL_DIR@
plugins_dir=${prefix}/@PLUGINS_INSTALL_DIR@
Name: @_lib_name@
Description: @_description@
Version: @MAPNIK_VERSION@
Requires: @m_requires@
Libs: -L"${libdir}" -l$<TARGET_FILE_BASE_NAME:mapnik>$<TARGET_PROPERTY:mapnik,$<CONFIG>_POSTFIX>
Cflags: -I"${includedir}" -I"${includedir}/mapnik" -I"${includedir}/mapnik/agg" @m_str_compile_defs@]]
_contents @ONLY)
file(GENERATE
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_lib_name}-$<CONFIG>.pc
CONTENT "${_contents}"
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${_lib_name}-$<CONFIG>.pc
DESTINATION ${MAPNIK_PKGCONF_DIR}
RENAME ${_lib_name}.pc
)
endfunction()
create_pkg_config_file(wkt libmapnikwkt "wkt library")
create_pkg_config_file(json libmapnikjson "json library")
create_pkg_config_file_mapnik("libmapnik" "mapnik library")

View file

@ -1,64 +0,0 @@
function(mapnik_set_dep_version dep var)
string(TOUPPER ${dep} m_package_name_upc)
set(m_package_name ${dep})
if(${m_package_name}_VERSION_STRING)
set(${var} ${${m_package_name}_VERSION_STRING} PARENT_SCOPE)
elseif(${m_package_name}_VERSION)
set(${var} ${${m_package_name}_VERSION} PARENT_SCOPE)
elseif(${m_package_name_upc}_VERSION_STRING)
set(${var} ${${m_package_name_upc}_VERSION_STRING} PARENT_SCOPE)
elseif(${m_package_name_upc}_VERSION)
set(${var} ${${m_package_name_upc}_VERSION} PARENT_SCOPE)
endif()
endfunction()
function(mapnik_print_package_info dep)
message(STATUS "Using ${dep} version: ${mapnik_${dep}_version}")
endfunction()
macro(mapnik_find_package dep)
find_package(${dep} ${ARGN})
if(${dep}_FOUND)
list(APPEND mapnik_deps ${dep})
if(mapnik_${dep}_find_args)
list(APPEND mapnik_${dep}_find_args ${ARGN})
else()
set(mapnik_${dep}_find_args ${ARGN})
endif()
mapnik_set_dep_version(${dep} mapnik_${dep}_version)
mapnik_print_package_info(${dep})
else()
message(STATUS "not found: ${dep}")
endif()
endmacro()
macro(mapnik_pkg_check_modules dep)
pkg_check_modules(${dep} ${ARGN})
if(${dep}_FOUND)
list(APPEND mapnik_deps ${dep})
set(mapnik_${dep}_pkg_args ${ARGN})
mapnik_set_dep_version(${dep} mapnik_${dep}_version)
mapnik_print_package_info(${dep})
else()
message(STATUS "not found: ${dep}")
endif()
endmacro()
macro(mapnik_find_threads)
find_package(Threads REQUIRED)
if(CMAKE_THREAD_LIBS_INIT)
message(STATUS "Using Threads (system libraries)")
elseif(CMAKE_USE_WIN32_THREADS_INIT)
message(STATUS "Using Threads (win32 threads)")
elseif(CMAKE_USE_PTHREADS_INIT)
message(STATUS "Using Threads (pthread)")
elseif(CMAKE_HP_PTHREADS_INIT)
message(STATUS "Using Threads (HP thread)")
else()
message(STATUS "Using Threads (unknown backend)")
endif()
endmacro()

View file

@ -1,98 +0,0 @@
#
# Install library targets that consuming users need.
#
function(mapnik_install _target)
install(TARGETS ${_target}
EXPORT MapnikTargets
INCLUDES DESTINATION ${MAPNIK_INCLUDE_DIR}
RUNTIME DESTINATION ${MAPNIK_BIN_DIR}
COMPONENT MapnikRuntime
LIBRARY DESTINATION ${MAPNIK_LIB_DIR}
COMPONENT MapnikRuntime
NAMELINK_COMPONENT MapnikDevelopment
ARCHIVE DESTINATION ${MAPNIK_ARCHIVE_DIR}
COMPONENT MapnikDevelopment
)
get_target_property(TARGET_TYPE "${_target}" TYPE)
if (TARGET_TYPE STREQUAL "SHARED_LIBRARY")
set_property(GLOBAL APPEND PROPERTY TARGETS ${_target})
endif()
endfunction()
#
# Install plugins
#
function(mapnik_install_plugin _target)
if(NOT BUILD_SHARED_PLUGINS)
return()
endif()
install(TARGETS ${_target}
RUNTIME DESTINATION ${PLUGINS_INSTALL_DIR}
COMPONENT MapnikPluginRuntime
LIBRARY DESTINATION ${PLUGINS_INSTALL_DIR}
COMPONENT MapnikPluginRuntime
NAMELINK_COMPONENT MapnikPluginDevelopment
ARCHIVE DESTINATION ${PLUGINS_INSTALL_DIR}
COMPONENT MapnikPluginDevelopment
)
set_property(GLOBAL APPEND PROPERTY PLUGINS ${_target})
endfunction()
#
# Install executables. These are available via COMPONENTS in find_package
#
function(mapnik_install_utility _target)
set(_target_name "mapnikUtilityTargets_${_target}")
install(TARGETS ${_target}
EXPORT ${_target_name}
INCLUDES DESTINATION ${MAPNIK_INCLUDE_DIR}
RUNTIME DESTINATION ${MAPNIK_BIN_DIR}
COMPONENT MapnikRuntime
LIBRARY DESTINATION ${MAPNIK_LIB_DIR}
COMPONENT MapnikRuntime
NAMELINK_COMPONENT MapnikDevelopment
ARCHIVE DESTINATION ${MAPNIK_ARCHIVE_DIR}
COMPONENT MapnikDevelopment
)
install(EXPORT ${_target_name}
FILE ${_target_name}.cmake
NAMESPACE mapnik::
DESTINATION ${MAPNIK_CMAKE_DIR}
)
set_property(GLOBAL APPEND PROPERTY MAPNIK_UTILITIES ${_target})
endfunction()
function(mapnik_install_targets)
if(INSTALL_DEPENDENCIES AND WIN32)
# https://cmake.org/cmake/help/latest/policy/CMP0087.html
cmake_policy(SET CMP0087 NEW)
get_property(_installed_utilities GLOBAL PROPERTY MAPNIK_UTILITIES)
get_property(_installed_targets GLOBAL PROPERTY TARGETS)
get_property(_installed_plugins GLOBAL PROPERTY PLUGINS)
set(_internal_executables "")
set(_internal_libraries "")
foreach(_target IN LISTS _installed_utilities)
list(APPEND _internal_executables "\${CMAKE_INSTALL_PREFIX}/${MAPNIK_BIN_DIR}/$<TARGET_FILE_NAME:${_target}>")
endforeach()
foreach(_target IN LISTS _installed_targets)
list(APPEND _internal_libraries "\${CMAKE_INSTALL_PREFIX}/${MAPNIK_BIN_DIR}/$<TARGET_FILE_NAME:${_target}>")
endforeach()
foreach(_target IN LISTS _installed_plugins)
list(APPEND _internal_libraries "\${CMAKE_INSTALL_PREFIX}/${PLUGINS_INSTALL_DIR}/$<TARGET_FILE_NAME:${_target}>")
endforeach()
# all other executables get auto detected and fixed.
if(_internal_executables)
list(GET _internal_executables 0 _internal_executables)
endif()
INSTALL(CODE "
message(STATUS \"internal_executables: ${_internal_executables}\")
message(STATUS \"internal_libraries: ${_internal_libraries}\")
message(STATUS \"ADDITIONAL_LIBARIES_PATHS: ${ADDITIONAL_LIBARIES_PATHS}\")
include(BundleUtilities)
fixup_bundle(\"${_internal_executables}\" \"${_internal_libraries}\" \"${ADDITIONAL_LIBARIES_PATHS}\")
" COMPONENT MapnikRuntime)
endif()
endfunction()

View file

@ -1,3 +0,0 @@
set(BOOST_MIN_VERSION 1.73)
set(HARFBUZZ_MIN_VERSION 0.9.34)
set(PROJ_MIN_VERSION 7.2.0)

View file

@ -1,4 +0,0 @@
macro(mapnik_option option_name option_description option_default_value)
option(${option_name} "${option_description}" ${option_default_value})
add_feature_info(${option_name} ${option_name} "${option_description}")
endmacro()

View file

@ -1,16 +0,0 @@
function(format_dir dir)
file(GLOB_RECURSE sources
"${dir}/*.cpp"
"${dir}/*.hpp"
)
execute_process(COMMAND clang-format -style=file -i ${sources})
endfunction()
format_dir(benchmark)
format_dir(demo)
format_dir(include)
format_dir(plugins)
format_dir(src)
format_dir(test)
format_dir(utils)

View file

@ -1,52 +0,0 @@
@PACKAGE_INIT@
set_and_check(MAPNIK_INCLUDE_DIR "@PACKAGE_MAPNIK_INCLUDE_DIR@" CACHE STRING "")
set_and_check(MAPNIK_FONTS_DIR "@PACKAGE_FONTS_INSTALL_DIR@" CACHE STRING "")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/Modules/")
include(CMakeFindDependencyMacro)
find_dependency(Threads REQUIRED)
@mapnik_find_deps@
include("${CMAKE_CURRENT_LIST_DIR}/mapnikTargets.cmake")
set(_supported_components @MAPNIK_UTILITIES@)
foreach(_comp ${mapnik_FIND_COMPONENTS})
if (NOT _comp IN_LIST _supported_components)
set(mapnik_FOUND False)
set(mapnik_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/mapnikUtilityTargets_${_comp}.cmake")
endforeach()
get_filename_component(_plugin_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
file(GLOB CONFIG_FILES "${_plugin_dir}/mapnikPlugins-*.cmake")
foreach(f ${CONFIG_FILES})
include(${f})
endforeach()
function(mapnik_find_plugin_dir PLUGIN_DIR)
string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_l)
set(_plugin_dir "${MAPNIK_PLUGINS_DIR_${_build_type_l}}")
# only release has more then one configuration
if(NOT _plugin_dir)
set(_all_rel_cfgs RELEASE RELWITHDEBINFO MINSIZEREL)
list(FIND _all_rel_cfgs ${_build_type_l} _is_rel_cfg)
# check if the current configuration is a known release configuration
if(${_is_rel_cfg} GREATER_EQUAL 0)
foreach(_rel_cfg IN LISTS _all_rel_cfgs)
set(_plugin_dir "${MAPNIK_PLUGINS_DIR_${_rel_cfg}}")
if(_plugin_dir)
break()
endif()
endforeach()
endif()
endif()
if(NOT _plugin_dir)
message(WARNING "Could not find a plugin install dir for configuration ${_build_type_l}")
endif()
set(${PLUGIN_DIR} ${_plugin_dir} PARENT_SCOPE)
endfunction()

View file

@ -1,18 +0,0 @@
include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_NAME "mapnik")
set(CPACK_PACKAGE_CONTACT "ubuntu-mathis@outlook.com")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://mapnik.org")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_GENERATOR "DEB;TGZ")
set(CPACK_SOURCE_IGNORE_FILES
\\.git/
build/
".*~$"
out/
\\.vs/
\\.vscode/
)
set(CPACK_VERBATIM_VARIABLES YES)
include(CPack)

24
configure vendored
View file

@ -1,20 +1,8 @@
#! /usr/bin/env bash
#!/bin/bash
set -eu
: ${PYTHON:=python}
# Only some shells (Bash and Z shell) support arrays. Therefore,
# the following code provides an alternative for users calling the script
# with shells other than Bash or Z shell (e.g. Debian users using Dash).
THE_SHELL=$(basename $SHELL)
if [ "$THE_SHELL" != "bash" ] && [ "$THE_SHELL" != "zsh" ]; then
if [ -f mapnik-settings.env ]; then
echo "WARNING: Reading from mapnik-settings.env is supported with Bash or Z shell only."
fi
$PYTHON scons/scons.py --implicit-deps-changed configure "$@"
exit 0
fi
PYTHON=${PYTHON:-python}
# mapnik-settings.env is an optional file to store
# environment variables that should be used before
@ -22,11 +10,9 @@ fi
# These do not normally need to be set except when
# building against binary versions of dependencies like
# done via bootstrap.sh
if [ -f mapnik-settings.env ]; then
if [[ -f mapnik-settings.env ]]; then
echo "Inheriting from mapnik-settings.env"
. ./mapnik-settings.env
VARS=( $(cat mapnik-settings.env) )
source mapnik-settings.env
fi
$PYTHON scons/scons.py --implicit-deps-changed configure ${VARS[*]:-} "$@"
$PYTHON scons/scons.py --implicit-deps-changed configure "$@"

View file

@ -1,7 +0,0 @@
if(BUILD_DEMO_VIEWER)
add_subdirectory(viewer)
endif()
if(BUILD_DEMO_CPP)
add_subdirectory(c++)
endif()

View file

@ -1,6 +0,0 @@
add_executable(mapnik-demo rundemo.cpp)
target_link_libraries(mapnik-demo 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?)
)

View file

@ -41,7 +41,7 @@ if env['HAS_CAIRO']:
demo_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
libraries = [env['MAPNIK_NAME']]
libraries.extend([copy(env['LIBMAPNIK_LIBS']), 'sqlite3', 'pthread'])
libraries.extend(copy(env['LIBMAPNIK_LIBS']))
rundemo = demo_env.Program('rundemo', source, LIBS=libraries)
Depends(rundemo, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,7 +20,6 @@
*
*****************************************************************************/
#include <mapnik/mapnik.hpp>
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/rule.hpp>
@ -46,21 +45,19 @@
#include <iostream>
int main(int, char**)
int main ( int, char** )
{
using namespace mapnik;
const std::string srs_lcc =
"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs";
const std::string srs_merc = "+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";
mapnik::setup();
try
{
const std::string srs_lcc="+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs";
const std::string srs_merc="+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";
try {
std::cout << " running demo ... \n";
datasource_cache::instance().register_datasources("plugins/input/");
freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf");
Map m(800, 600);
Map m(800,600);
m.set_background(parse_color("white"));
m.set_srs(srs_merc);
// create styles
@ -96,13 +93,13 @@ int main(int, char**)
rule r;
{
line_symbolizer line_sym;
put(line_sym, keys::stroke, color(0, 0, 0));
put(line_sym, keys::stroke_width, 1.0);
put(line_sym,keys::stroke,color(0,0,0));
put(line_sym,keys::stroke_width,1.0);
dash_array dash;
dash.emplace_back(8, 4);
dash.emplace_back(2, 2);
dash.emplace_back(2, 2);
put(line_sym, keys::stroke_dasharray, dash);
dash.emplace_back(8,4);
dash.emplace_back(2,2);
dash.emplace_back(2,2);
put(line_sym,keys::stroke_dasharray,dash);
r.append(std::move(line_sym));
}
provlines_style.add_rule(std::move(r));
@ -130,10 +127,10 @@ int main(int, char**)
r.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
{
line_symbolizer line_sym;
put(line_sym, keys::stroke, color(171, 158, 137));
put(line_sym, keys::stroke_width, 2.0);
put(line_sym, keys::stroke_linecap, line_cap_enum::ROUND_CAP);
put(line_sym, keys::stroke_linejoin, line_join_enum::ROUND_JOIN);
put(line_sym,keys::stroke,color(171,158,137));
put(line_sym,keys::stroke_width,2.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads34_style.add_rule(std::move(r));
@ -147,10 +144,10 @@ int main(int, char**)
r.set_filter(parse_expression("[CLASS] = 2"));
{
line_symbolizer line_sym;
put(line_sym, keys::stroke, color(171, 158, 137));
put(line_sym, keys::stroke_width, 4.0);
put(line_sym, keys::stroke_linecap, line_cap_enum::ROUND_CAP);
put(line_sym, keys::stroke_linejoin, line_join_enum::ROUND_JOIN);
put(line_sym,keys::stroke,color(171,158,137));
put(line_sym,keys::stroke_width,4.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_1.add_rule(std::move(r));
@ -163,10 +160,10 @@ int main(int, char**)
r.set_filter(parse_expression("[CLASS] = 2"));
{
line_symbolizer line_sym;
put(line_sym, keys::stroke, color(255, 250, 115));
put(line_sym, keys::stroke_width, 2.0);
put(line_sym, keys::stroke_linecap, line_cap_enum::ROUND_CAP);
put(line_sym, keys::stroke_linejoin, line_join_enum::ROUND_JOIN);
put(line_sym,keys::stroke,color(255,250,115));
put(line_sym,keys::stroke_width,2.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_2.add_rule(std::move(r));
@ -180,10 +177,10 @@ int main(int, char**)
r.set_filter(parse_expression("[CLASS] = 1"));
{
line_symbolizer line_sym;
put(line_sym, keys::stroke, color(188, 149, 28));
put(line_sym, keys::stroke_width, 7.0);
put(line_sym, keys::stroke_linecap, line_cap_enum::ROUND_CAP);
put(line_sym, keys::stroke_linejoin, line_join_enum::ROUND_JOIN);
put(line_sym,keys::stroke,color(188,149,28));
put(line_sym,keys::stroke_width,7.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_1.add_rule(std::move(r));
@ -196,10 +193,10 @@ int main(int, char**)
r.set_filter(parse_expression("[CLASS] = 1"));
{
line_symbolizer line_sym;
put(line_sym, keys::stroke, color(242, 191, 36));
put(line_sym, keys::stroke_width, 5.0);
put(line_sym, keys::stroke_linecap, line_cap_enum::ROUND_CAP);
put(line_sym, keys::stroke_linejoin, line_join_enum::ROUND_JOIN);
put(line_sym,keys::stroke,color(242,191,36));
put(line_sym,keys::stroke_width,5.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_2.add_rule(std::move(r));
@ -215,11 +212,10 @@ int main(int, char**)
text_placements_ptr placement_finder = std::make_shared<text_placements_dummy>();
placement_finder->defaults.format_defaults.face_name = "DejaVu Sans Book";
placement_finder->defaults.format_defaults.text_size = 10.0;
placement_finder->defaults.format_defaults.fill = color(0, 0, 0);
placement_finder->defaults.format_defaults.halo_fill = color(255, 255, 200);
placement_finder->defaults.format_defaults.fill = color(0,0,0);
placement_finder->defaults.format_defaults.halo_fill = color(255,255,200);
placement_finder->defaults.format_defaults.halo_radius = 1.0;
placement_finder->defaults.set_format_tree(
std::make_shared<mapnik::formatting::text_node>(parse_expression("[GEONAME]")));
placement_finder->defaults.set_format_tree(std::make_shared<mapnik::formatting::text_node>(parse_expression("[GEONAME]")));
put<text_placements_ptr>(text_sym, keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
}
@ -232,9 +228,9 @@ int main(int, char**)
// Provincial polygons
{
parameters p;
p["type"] = "shape";
p["file"] = "demo/data/boundaries";
p["encoding"] = "utf8";
p["type"]="shape";
p["file"]="demo/data/boundaries";
p["encoding"]="utf8";
layer lyr("Provinces");
lyr.set_datasource(datasource_cache::instance().create(p));
@ -246,8 +242,8 @@ int main(int, char**)
// Drainage
{
parameters p;
p["type"] = "shape";
p["file"] = "demo/data/qcdrainage";
p["type"]="shape";
p["file"]="demo/data/qcdrainage";
layer lyr("Quebec Hydrography");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.set_srs(srs_lcc);
@ -257,8 +253,8 @@ int main(int, char**)
{
parameters p;
p["type"] = "shape";
p["file"] = "demo/data/ontdrainage";
p["type"]="shape";
p["file"]="demo/data/ontdrainage";
layer lyr("Ontario Hydrography");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.set_srs(srs_lcc);
@ -269,8 +265,8 @@ int main(int, char**)
// Provincial boundaries
{
parameters p;
p["type"] = "shape";
p["file"] = "demo/data/boundaries_l";
p["type"]="shape";
p["file"]="demo/data/boundaries_l";
layer lyr("Provincial borders");
lyr.set_srs(srs_lcc);
lyr.set_datasource(datasource_cache::instance().create(p));
@ -281,8 +277,8 @@ int main(int, char**)
// Roads
{
parameters p;
p["type"] = "shape";
p["file"] = "demo/data/roads";
p["type"]="shape";
p["file"]="demo/data/roads";
layer lyr("Roads");
lyr.set_srs(srs_lcc);
lyr.set_datasource(datasource_cache::instance().create(p));
@ -297,8 +293,8 @@ int main(int, char**)
// popplaces
{
parameters p;
p["type"] = "shape";
p["file"] = "demo/data/popplaces";
p["type"]="shape";
p["file"]="demo/data/popplaces";
p["encoding"] = "utf8";
layer lyr("Populated Places");
lyr.set_srs(srs_lcc);
@ -307,28 +303,28 @@ int main(int, char**)
m.add_layer(lyr);
}
m.zoom_to_box(box2d<double>(-8024477.28459, 5445190.38849, -7381388.20071, 5662941.44855));
m.zoom_to_box(box2d<double>(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855));
image_rgba8 buf(m.width(), m.height());
agg_renderer<image_rgba8> ren(m, buf);
image_rgba8 buf(m.width(),m.height());
agg_renderer<image_rgba8> ren(m,buf);
ren.apply();
std::string msg("These maps have been rendered using AGG in the current directory:\n");
#ifdef HAVE_JPEG
save_to_file(buf, "demo.jpg", "jpeg");
save_to_file(buf,"demo.jpg","jpeg");
msg += "- demo.jpg\n";
#endif
#ifdef HAVE_PNG
save_to_file(buf, "demo.png", "png");
save_to_file(buf, "demo256.png", "png8");
save_to_file(buf,"demo.png","png");
save_to_file(buf,"demo256.png","png8");
msg += "- demo.png\n";
msg += "- demo256.png\n";
#endif
#ifdef HAVE_TIFF
save_to_file(buf, "demo.tif", "tiff");
save_to_file(buf,"demo.tif","tiff");
msg += "- demo.tif\n";
#endif
#ifdef HAVE_WEBP
save_to_file(buf, "demo.webp", "webp");
save_to_file(buf,"demo.webp","webp");
msg += "- demo.webp\n";
#endif
msg += "Have a look!\n";
@ -336,8 +332,8 @@ int main(int, char**)
#if defined(HAVE_CAIRO)
// save to pdf/svg files
save_to_cairo_file(m, "cairo-demo.pdf");
save_to_cairo_file(m, "cairo-demo.svg");
save_to_cairo_file(m,"cairo-demo.pdf");
save_to_cairo_file(m,"cairo-demo.svg");
/* we could also do:
@ -346,38 +342,38 @@ int main(int, char**)
but instead let's build up a surface for more flexibility
*/
cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m.width(), m.height()),
cairo_surface_closer());
cairo_surface_ptr image_surface(
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,m.width(),m.height()),
cairo_surface_closer());
double scale_factor = 1.0;
cairo_ptr image_context(create_context(image_surface));
mapnik::cairo_renderer<cairo_ptr> png_render(m, image_context, scale_factor);
mapnik::cairo_renderer<cairo_ptr> png_render(m,image_context,scale_factor);
png_render.apply();
// we can now write to png with cairo functionality
cairo_surface_write_to_png(&*image_surface, "cairo-demo.png");
// but we can also benefit from quantization by converting
// to a mapnik image object and then saving that
mapnik::image_rgba8 im_data(cairo_image_surface_get_width(&*image_surface),
cairo_image_surface_get_height(&*image_surface));
mapnik::image_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface));
cairo_image_to_rgba8(im_data, image_surface);
save_to_file(im_data, "cairo-demo256.png", "png8");
save_to_file(im_data, "cairo-demo256.png","png8");
cairo_surface_finish(&*image_surface);
std::cout << "Three maps have been rendered using Cairo in the current directory:\n"
"- cairo-demo.png\n"
"- cairo-demo256.png\n"
"- cairo-demo.pdf\n"
"- cairo-demo.svg\n"
"Have a look!\n";
"- cairo-demo.png\n"
"- cairo-demo256.png\n"
"- cairo-demo.pdf\n"
"- cairo-demo.svg\n"
"Have a look!\n";
#endif
// save map definition (data + style)
save_map(m, "map.xml");
}
catch (std::exception const& ex)
catch ( std::exception const& ex )
{
std::cerr << "### std::exception: " << ex.what() << std::endl;
return EXIT_FAILURE;
}
catch (...)
catch ( ... )
{
std::cerr << "### Unknown exception." << std::endl;
return EXIT_FAILURE;

20
demo/python/README.txt Normal file
View file

@ -0,0 +1,20 @@
This directory contains a sample python script implementing the Mapnik API.
The script is thoroughly commented and also acts as a mini tutorial. Reading
it should get you on your way, and you can use it as a base for your work.
You must compile and install mapnik and the python bindings FIRST.
Once this is done, run it:
/path/to/python rundemo.py
If all goes well, it should render 2 map images:
demo.jpg
demo.png
Have a look!
Cheers,
J.F.

379
demo/python/rundemo.py Executable file
View file

@ -0,0 +1,379 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#
#
# This file is part of Mapnik (c++ mapping toolkit)
# Copyright (C) 2005 Jean-Francois Doyon
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from __future__ import print_function
import sys
from os import path
import mapnik
# Instanciate a map, giving it a width and height. Remember: the word "map" is
# reserved in Python! :)
root = path.dirname(__file__)
m = mapnik.Map(800,600,"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs")
# Set its background colour. More on colours later ...
m.background = mapnik.Color('white')
# Now we can start adding layers, in stacking order (i.e. bottom layer first)
# Canadian Provinces (Polygons)
# Instanciate a layer. The parameters depend on the type of data:
# shape:
# type='shape'
# file='/path/to/shape'
# raster:
# type='raster'
# file='/path/to/raster'
# postgis:
# type='postgis'
# host='127.0.0.1'
# dbname='mydatabase'
# user='myusername'
# password='mypassword'
# table= TODO
provpoly_lyr = mapnik.Layer('Provinces')
provpoly_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
provpoly_lyr.datasource = mapnik.Shapefile(file=path.join(root,'../data/boundaries'), encoding='latin1')
# We then define a style for the layer. A layer can have one or many styles.
# Styles are named, so they can be shared across different layers.
# Multiple styles per layer behaves functionally like multiple layers. The
# data is completely re-scanned for each style within one layer, and a style
# will be drawn entirely "above" the previous one. Performance wise using
# multiple styles in one layer is the same has having multiple layers.
# The paradigm is useful mostly as a convenience.
provpoly_style = mapnik.Style()
# A Style needs one or more rules. A rule will normally consist of a filter
# for feature selection, and one or more symbolizers.
provpoly_rule_on = mapnik.Rule()
# A Expression() allows the selection of features to which the symbology will
# be applied. More on Mapnik expressions can be found in Tutorial #2.
# A given feature can only match one filter per rule per style.
provpoly_rule_on.filter = mapnik.Expression("[NAME_EN] = 'Ontario'")
# Here a symbolizer is defined. Available are:
# - LineSymbolizer(Color(),<width>)
# - LineSymbolizer(Stroke())
# - PolygonSymbolizer(Color())
# - PointSymbolizer(<file>,<type>,<width>,<height>)
# Some of them can accept a Color() instance, which can be created with:
# - Color(<red>, <green>, <blue>)
# - Color(<red>, <green>, <blue>, <alpha>)
# - Color(<string>) where <string> will be something like '#00FF00'
# or '#0f0' or 'green'
sym = mapnik.PolygonSymbolizer()
sym.fill = mapnik.Color(250, 190, 183);
provpoly_rule_on.symbols.append(sym)
provpoly_style.rules.append(provpoly_rule_on)
provpoly_rule_qc = mapnik.Rule()
provpoly_rule_qc.filter = mapnik.Expression("[NOM_FR] = 'Québec'")
sym = mapnik.PolygonSymbolizer()
sym.fill = mapnik.Color(217, 235, 203)
provpoly_rule_qc.symbols.append(sym)
provpoly_style.rules.append(provpoly_rule_qc)
# Add the style to the map, giving it a name. This is the name that will be
# used to refer to it from here on. Having named styles allows them to be
# re-used throughout the map.
m.append_style('provinces', provpoly_style)
# Then associate the style to the layer itself.
provpoly_lyr.styles.append('provinces')
# Then add the layer to the map. In reality, it's the order in which you
# append them to the map that will determine the drawing order, though by
# convention it is recommended to define them in drawing order as well.
m.layers.append(provpoly_lyr)
# Drainage
# A simple example ...
qcdrain_lyr = mapnik.Layer('Quebec Hydrography')
qcdrain_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
qcdrain_lyr.datasource = mapnik.Shapefile(file=path.join(root,'../data/qcdrainage'))
qcdrain_style = mapnik.Style()
qcdrain_rule = mapnik.Rule()
qcdrain_rule.filter = mapnik.Expression('[HYC] = 8')
sym = mapnik.PolygonSymbolizer()
sym.fill = mapnik.Color(153, 204, 255)
sym.smooth = 1.0 # very smooth
qcdrain_rule.symbols.append(sym)
qcdrain_style.rules.append(qcdrain_rule)
m.append_style('drainage', qcdrain_style)
qcdrain_lyr.styles.append('drainage')
m.layers.append(qcdrain_lyr)
# In this case, we have 2 data sets with similar schemas (same filtering
# attributes, and same desired style), so we're going to
# re-use the style defined in the above layer for the next one.
ondrain_lyr = mapnik.Layer('Ontario Hydrography')
ondrain_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
ondrain_lyr.datasource = mapnik.Shapefile(file=path.join(root,'../data/ontdrainage'))
ondrain_lyr.styles.append('drainage')
m.layers.append(ondrain_lyr)
# Provincial boundaries
provlines_lyr = mapnik.Layer('Provincial borders')
provlines_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
provlines_lyr.datasource = mapnik.Shapefile(file=path.join(root,'../data/boundaries_l'))
# Here we define a "dash dot dot dash" pattern for the provincial boundaries.
provlines_style = mapnik.Style()
provlines_rule = mapnik.Rule()
sym = mapnik.LineSymbolizer()
# FIXME - currently adding dash arrays is broken
# https://github.com/mapnik/mapnik/issues/2324
sym.stroke = mapnik.Color('black')
sym.stroke_width = 1.0
provlines_rule.symbols.append(sym)
provlines_style.rules.append(provlines_rule)
m.append_style('provlines', provlines_style)
provlines_lyr.styles.append('provlines')
m.layers.append(provlines_lyr)
# Roads 3 and 4 (The "grey" roads)
roads34_lyr = mapnik.Layer('Roads')
roads34_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
# create roads datasource (we're going to re-use it later)
roads34_lyr.datasource = mapnik.Shapefile(file=path.join(root,'../data/roads'))
roads34_style = mapnik.Style()
roads34_rule = mapnik.Rule()
roads34_rule.filter = mapnik.Expression('([CLASS] = 3) or ([CLASS] = 4)')
# With lines of a certain width, you can control how the ends
# are closed off using line_cap as below.
# Available options are:
# line_cap: BUTT_CAP, SQUARE_CAP, ROUND_CAP
# line_join: MITER_JOIN, MITER_REVERT_JOIN, ROUND_JOIN, BEVEL_JOIN
# And one last Stroke() attribute not used here is "opacity", which
# can be set to a numerical value.
sym = mapnik.LineSymbolizer()
sym.stroke = mapnik.Color(171,158,137)
sym.stroke_width = 2.0
sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP
roads34_rule.symbols.append(sym)
roads34_style.rules.append(roads34_rule)
m.append_style('smallroads', roads34_style)
roads34_lyr.styles.append('smallroads')
m.layers.append(roads34_lyr)
# Roads 2 (The thin yellow ones)
roads2_lyr = mapnik.Layer('Roads')
roads2_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
# Just get a copy from roads34_lyr
roads2_lyr.datasource = roads34_lyr.datasource
roads2_style_1 = mapnik.Style()
roads2_rule_1 = mapnik.Rule()
roads2_rule_1.filter = mapnik.Expression('[CLASS] = 2')
sym = mapnik.LineSymbolizer()
sym.stroke = mapnik.Color(171,158,137)
sym.stroke_width = 4.0
sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP
roads2_rule_1.symbols.append(sym)
roads2_style_1.rules.append(roads2_rule_1)
m.append_style('road-border', roads2_style_1)
roads2_style_2 = mapnik.Style()
roads2_rule_2 = mapnik.Rule()
roads2_rule_2.filter = mapnik.Expression('[CLASS] = 2')
sym = mapnik.LineSymbolizer()
sym.stroke = mapnik.Color(255,250,115)
sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP
sym.stroke_width = 2.0
roads2_rule_2.symbols.append(sym)
roads2_style_2.rules.append(roads2_rule_2)
m.append_style('road-fill', roads2_style_2)
roads2_lyr.styles.append('road-border')
roads2_lyr.styles.append('road-fill')
m.layers.append(roads2_lyr)
# Roads 1 (The big orange ones, the highways)
roads1_lyr = mapnik.Layer('Roads')
roads1_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
roads1_lyr.datasource = roads34_lyr.datasource
roads1_style_1 = mapnik.Style()
roads1_rule_1 = mapnik.Rule()
roads1_rule_1.filter = mapnik.Expression('[CLASS] = 1')
sym = mapnik.LineSymbolizer()
sym.stroke = mapnik.Color(188,149,28)
sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP
sym.stroke_width = 7.0
roads1_rule_1.symbols.append(sym)
roads1_style_1.rules.append(roads1_rule_1)
m.append_style('highway-border', roads1_style_1)
roads1_style_2 = mapnik.Style()
roads1_rule_2 = mapnik.Rule()
roads1_rule_2.filter = mapnik.Expression('[CLASS] = 1')
sym.stroke = mapnik.Color(242,191,36)
sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP
sym.stroke_width = 5.0
roads1_rule_2.symbols.append(sym)
roads1_style_2.rules.append(roads1_rule_2)
m.append_style('highway-fill', roads1_style_2)
roads1_lyr.styles.append('highway-border')
roads1_lyr.styles.append('highway-fill')
m.layers.append(roads1_lyr)
# Populated Places
popplaces_lyr = mapnik.Layer('Populated Places')
popplaces_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
popplaces_lyr.datasource = mapnik.Shapefile(file=path.join(root,'../data/popplaces'),encoding='latin1')
popplaces_style = mapnik.Style()
popplaces_rule = mapnik.Rule()
# And here we have a TextSymbolizer, used for labeling.
# The first parameter is the name of the attribute to use as the source of the
# text to label with. Then there is font size in points (I think?), and colour.
# TODO - currently broken: https://github.com/mapnik/mapnik/issues/2324
#popplaces_text_symbolizer = mapnik.TextSymbolizer(mapnik.Expression("[GEONAME]"),
# 'DejaVu Sans Book',
# 10, mapnik.Color('black'))
# We set a "halo" around the text, which looks like an outline if thin enough,
# or an outright background if large enough.
#popplaces_text_symbolizer.label_placement= mapnik.label_placement.POINT_PLACEMENT
#popplaces_text_symbolizer.halo_fill = mapnik.Color(255,255,200)
#popplaces_text_symbolizer.halo_radius = 1
#popplaces_text_symbolizer.avoid_edges = True
#popplaces_text_symbolizer.minimum_padding = 30
#popplaces_rule.symbols.append(popplaces_text_symbolizer)
popplaces_style.rules.append(popplaces_rule)
m.append_style('popplaces', popplaces_style)
popplaces_lyr.styles.append('popplaces')
m.layers.append(popplaces_lyr)
# Draw map
# Set the initial extent of the map in 'master' spherical Mercator projection
m.zoom_to_box(mapnik.Box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855))
# Render map
im = mapnik.Image(m.width,m.height)
mapnik.render(m, im)
# Save image to files
images_ = []
if mapnik.has_png():
im.save('demo.png', 'png') # true-colour RGBA
images_.append('demo.png')
# old behavior, now can do 'png8:c=256'
im.save('demo256.png', 'png256') # save to palette based (max 256 colours) png
images_.append('demo256.png')
im.save('demo64_binary_transparency.png', 'png8:c=64:t=1')
images_.append('demo64_binary_transparency.png')
im.save('demo128_colors_hextree_no_alpha.png', 'png8:c=100:m=h:t=0')
images_.append('demo128_colors_hextree_no_alpha.png')
if mapnik.has_jpeg():
im.save('demo_high.jpg', 'jpeg100')
images_.append('demo_high.jpg')
im.save('demo_low.jpg', 'jpeg50')
images_.append('demo_low.jpg')
if mapnik.has_tiff():
im.save('demo.tif', 'tiff')
images_.append('demo.tif')
if mapnik.has_webp():
im.save('demo.webp', 'webp') # default quality is 90
images_.append('demo.webp')
im.save('demo_highest.webp', 'webp:quality=100')
images_.append('demo_med.webp')
im.save('demo_low.webp', 'webp:quality=50')
images_.append('demo_low.webp')
# Render cairo examples
if mapnik.has_cairo():
mapnik.render_to_file(m,'demo.pdf')
images_.append('demo.pdf')
mapnik.render_to_file(m,'demo.ps')
images_.append('demo.ps')
mapnik.render_to_file(m,'demo.svg')
images_.append('demo.svg')
mapnik.render_to_file(m,'demo_cairo_rgb24.png','RGB24')
images_.append('demo_cairo_rgb.png')
mapnik.render_to_file(m,'demo_cairo_argb32.png','ARGB32')
images_.append('demo_cairo_argb.png')
print ("\n\n", len(images_), "maps have been rendered in the current directory:")
for im_ in images_:
print ("-", im_)
print ("\n\nHave a look!\n\n")
mapnik.save_map(m,"map.xml")

View file

@ -1,64 +0,0 @@
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
set(PROJECT_SOURCES
about_dialog.cpp
info_dialog.cpp
layerdelegate.cpp
layerlistmodel.cpp
layerwidget.cpp
layer_info_dialog.cpp
main.cpp
mainwindow.cpp
mapwidget.cpp
styles_model.cpp
forms/about.ui
forms/info.ui
forms/layer_info.ui
mapnik_viewer.qrc
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(mapnik-viewer
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
else()
if(ANDROID)
add_library(mapnik-viewer SHARED
${PROJECT_SOURCES}
)
else()
add_executable(mapnik-viewer
${PROJECT_SOURCES}
)
endif()
endif()
set_target_properties(mapnik-viewer PROPERTIES
AUTOUIC_SEARCH_PATHS forms
AUTORCC ON
AUTOUIC ON
AUTOMOC ON
)
target_link_libraries(mapnik-viewer PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
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?)
)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/viewer.ini
"[mapnik]
plugins_dir=${PLUGINS_INSTALL_DIR}
fonts/1/dir=${FONTS_INSTALL_DIR}
fonts/size=1"
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(mapnik-viewer)
endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/viewer.ini DESTINATION bin)
mapnik_install_utility(mapnik-viewer)

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "about_dialog.hpp"
about_dialog::about_dialog(QWidget* parent)
: QDialog(parent)
about_dialog::about_dialog(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
ui.setupUi(this);
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if !defined ABOUT_DIALOG_HPP
#define ABOUT_DIALOG_HPP
@ -25,12 +27,12 @@
class about_dialog : public QDialog
{
Q_OBJECT
public:
about_dialog(QWidget* parent = 0);
private:
Ui::Dialog ui;
Q_OBJECT
public:
about_dialog(QWidget * parent = 0);
private:
Ui::Dialog ui;
};
#endif // ABOUT_DIALOG_HPP
#endif //ABOUT_DIALOG_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,22 +17,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "info_dialog.hpp"
info_dialog::info_dialog(QVector<QPair<QString, QString>> const& info, QWidget* parent)
: QDialog(parent)
{
ui.setupUi(this);
ui.tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
ui.tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Value"));
ui.tableWidget->setRowCount(info.size());
ui.tableWidget->setColumnCount(2);
for (int i = 0; i < info.size(); ++i)
{
QTableWidgetItem* keyItem = new QTableWidgetItem(info[i].first);
QTableWidgetItem* valueItem = new QTableWidgetItem(info[i].second);
ui.tableWidget->setItem(i, 0, keyItem);
ui.tableWidget->setItem(i, 1, valueItem);
}
info_dialog::info_dialog(QVector<QPair<QString,QString> > const& info, QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
ui.tableWidget->setHorizontalHeaderItem(0,new QTableWidgetItem("Name"));
ui.tableWidget->setHorizontalHeaderItem(1,new QTableWidgetItem("Value"));
ui.tableWidget->setRowCount(info.size());
ui.tableWidget->setColumnCount(2);
for (int i=0;i<info.size();++i)
{
QTableWidgetItem *keyItem = new QTableWidgetItem(info[i].first);
QTableWidgetItem *valueItem = new QTableWidgetItem(info[i].second);
ui.tableWidget->setItem(i,0,keyItem);
ui.tableWidget->setItem(i,1,valueItem);
}
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef INFO_DIALOG_HPP
#define INFO_DIALOG_HPP
@ -25,12 +27,12 @@
class info_dialog : public QDialog
{
Q_OBJECT
Q_OBJECT
public:
info_dialog(QVector<QPair<QString, QString>> const& info, QWidget* parent = 0);
private:
Ui::InfoDialog ui;
info_dialog(QVector<QPair<QString,QString> > const& info,QWidget * parent = 0);
private:
Ui::InfoDialog ui;
};
#endif // INFO_DIALOG_HPP
#endif //INFO_DIALOG_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "layer_info_dialog.hpp"
// mapnik
@ -25,13 +26,14 @@
#include <mapnik/params_impl.hpp>
#include <mapnik/layer.hpp>
layer_info_dialog::layer_info_dialog(mapnik::layer& lay, QWidget* parent)
: QDialog(parent)
layer_info_dialog::layer_info_dialog(mapnik::layer& lay, QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
ui.tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
ui.tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Value"));
ui.tableWidget->setHorizontalHeaderItem(0,new QTableWidgetItem("Name"));
ui.tableWidget->setHorizontalHeaderItem(1,new QTableWidgetItem("Value"));
// Layer name
ui.layerNameEdit->setText(QString(lay.name().c_str()));
@ -48,17 +50,17 @@ layer_info_dialog::layer_info_dialog(mapnik::layer& lay, QWidget* parent)
ui.tableWidget->setColumnCount(2);
mapnik::parameters::const_iterator pos;
int index = 0;
for (pos = ps.begin(); pos != ps.end(); ++pos)
int index=0;
for (pos = ps.begin();pos != ps.end();++pos)
{
std::optional<std::string> result;
mapnik::util::apply_visitor(mapnik::value_extractor_visitor<std::string>(result), pos->second);
boost::optional<std::string> result;
mapnik::util::apply_visitor(mapnik::value_extractor_visitor<std::string>(result),pos->second);
if (result)
{
QTableWidgetItem* keyItem = new QTableWidgetItem(QString(pos->first.c_str()));
QTableWidgetItem* valueItem = new QTableWidgetItem(QString((*result).c_str()));
ui.tableWidget->setItem(index, 0, keyItem);
ui.tableWidget->setItem(index, 1, valueItem);
QTableWidgetItem *keyItem = new QTableWidgetItem(QString(pos->first.c_str()));
QTableWidgetItem *valueItem = new QTableWidgetItem(QString((*result).c_str()));
ui.tableWidget->setItem(index,0,keyItem);
ui.tableWidget->setItem(index,1,valueItem);
++index;
}
}
@ -67,5 +69,5 @@ layer_info_dialog::layer_info_dialog(mapnik::layer& lay, QWidget* parent)
Ui::LayerInfoDialog& layer_info_dialog::getUI()
{
return ui;
return ui;
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,25 +17,28 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef LAYER_INFO_DIALOG_HPP
#define LAYER_INFO_DIALOG_HPP
#include "ui_layer_info.h"
#include <QDialog>
namespace mapnik {
namespace mapnik
{
class layer;
}
class layer_info_dialog : public QDialog
{
Q_OBJECT
Q_OBJECT
public:
layer_info_dialog(mapnik::layer& l, QWidget* parent = 0);
layer_info_dialog(mapnik::layer& l, QWidget * parent = 0);
Ui::LayerInfoDialog& getUI();
private:
Ui::LayerInfoDialog ui;
private:
Ui::LayerInfoDialog ui;
};
#endif // LAYER_INFO_DIALOG_HPP
#endif //LAYER_INFO_DIALOG_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,32 +17,38 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <QtGui>
#include "layerdelegate.hpp"
LayerDelegate::LayerDelegate(QObject* parent)
LayerDelegate::LayerDelegate(QObject *parent)
: QAbstractItemDelegate(parent)
{}
{
}
void LayerDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
void LayerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(QPen(QColor(255, 0, 0), 1));
painter->setPen(QPen(QColor(255,0,0),1));
if (option.state & QStyle::State_Selected)
painter->setBrush(QBrush(QColor(0, 0, 255, 64)));
else
painter->setBrush(QBrush(QColor(255, 0, 0, 64)));
painter->drawRoundedRect(option.rect, 4, 4);
painter->drawRoundRect(option.rect,4,4);
if (option.state & QStyle::State_Selected)
painter->setBrush(option.palette.highlightedText());
else
painter->setBrush(QBrush(QColor(255, 120, 0, 127)));
}
QSize LayerDelegate::sizeHint(const QStyleOptionViewItem& /* option */, const QModelIndex& /* index */) const
QSize LayerDelegate::sizeHint(const QStyleOptionViewItem & /* option */,
const QModelIndex & /* index */) const
{
return QSize(120, 24);
return QSize(120,24);
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -33,10 +33,12 @@ class LayerDelegate : public QAbstractItemDelegate
{
Q_OBJECT
public:
LayerDelegate(QObject* parent = 0);
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
public:
LayerDelegate(QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
};
#endif // LAYER_DELEGATE_HPP
#endif //LAYER_DELEGATE_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,26 +17,27 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "layerlistmodel.hpp"
#include <QIcon>
#include <QBrush>
#include <iostream>
#include <mapnik/layer.hpp>
using mapnik::Map;
LayerListModel::LayerListModel(std::shared_ptr<Map> map, QObject* parent)
: QAbstractListModel(parent)
, map_(map)
{}
LayerListModel::LayerListModel(std::shared_ptr<Map> map,QObject *parent)
: QAbstractListModel(parent),
map_(map) {}
int LayerListModel::rowCount(QModelIndex const&) const
{
if (map_)
return map_->layers().size();
return 0;
if (map_) return map_->layers().size();
return 0;
}
QVariant LayerListModel::data(QModelIndex const& index, int role) const
QVariant LayerListModel::data(QModelIndex const& index,int role) const
{
if (!index.isValid() || !map_)
return QVariant();
@ -59,16 +60,9 @@ QVariant LayerListModel::data(QModelIndex const& index, int role) const
else if (role == Qt::CheckStateRole)
{
if (map_->layers().at(index.row()).active())
return QVariant(Qt::Checked);
return QVariant(Qt::Checked);
else
return QVariant(Qt::Unchecked);
}
else if (role == Qt::ForegroundRole)
{
if (map_->layers().at(index.row()).active())
return QBrush(QColor("black"));
else
return QBrush(QColor("lightgrey"));
return QVariant(Qt::Unchecked);
}
else
{
@ -76,7 +70,8 @@ QVariant LayerListModel::data(QModelIndex const& index, int role) const
}
}
QVariant LayerListModel::headerData(int section, Qt::Orientation orientation, int role) const
QVariant LayerListModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
@ -87,37 +82,38 @@ QVariant LayerListModel::headerData(int section, Qt::Orientation orientation, in
return QString("TODO Row %1").arg(section);
}
bool LayerListModel::setData(const QModelIndex& index, const QVariant& value, int role)
bool LayerListModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
if (!map_)
return false;
if (!map_) return false;
if (index.isValid() && role == Qt::CheckStateRole)
{
int status = value.toInt();
std::vector<mapnik::layer>& layers = const_cast<std::vector<mapnik::layer>&>(map_->layers());
layers.at(index.row()).set_active(status);
emit dataChanged(index, index);
return true;
}
return false;
if (index.isValid() && role == Qt::CheckStateRole)
{
int status = value.toInt();
std::vector<mapnik::layer> & layers = const_cast<std::vector<mapnik::layer>& >(map_->layers());
layers.at(index.row()).set_active(status);
emit dataChanged(index, index);
return true;
}
return false;
}
Qt::ItemFlags LayerListModel::flags(QModelIndex const& index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
if (index.isValid())
flags |= Qt::ItemIsUserCheckable;
flags |= Qt::ItemIsUserCheckable;
return flags;
}
boost::optional<mapnik::layer&> LayerListModel::map_layer(int i)
{
if (map_)
{
std::vector<mapnik::layer>& layers = const_cast<std::vector<mapnik::layer>&>(map_->layers());
if (i < int(layers.size()))
return boost::optional<mapnik::layer&>(layers[i]);
}
return boost::optional<mapnik::layer&>();
if (map_)
{
std::vector<mapnik::layer> & layers = const_cast<std::vector<mapnik::layer>& >(map_->layers());
if (i < int(layers.size()))
return boost::optional<mapnik::layer&>(layers[i]);
}
return boost::optional<mapnik::layer&>();
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef LAYER_LIST_MODEL_HPP
#define LAYER_LIST_MODEL_HPP
@ -30,18 +32,20 @@
class LayerListModel : public QAbstractListModel
{
Q_OBJECT
public:
LayerListModel(std::shared_ptr<mapnik::Map> map, QObject* parent = 0);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
Qt::ItemFlags flags(QModelIndex const& index) const;
boost::optional<mapnik::layer&> map_layer(int i);
Q_OBJECT
public:
LayerListModel(std::shared_ptr<mapnik::Map> map, QObject * parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole);
Qt::ItemFlags flags(QModelIndex const& index) const;
boost::optional<mapnik::layer&> map_layer(int i);
private:
std::shared_ptr<mapnik::Map> map_;
private:
std::shared_ptr<mapnik::Map> map_;
};
#endif // LAYER_LIST_MODEL_HPP
#endif //LAYER_LIST_MODEL_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "layerwidget.hpp"
#include <qabstractitemdelegate.h>
#include <qapplication.h>
@ -28,63 +29,72 @@
#include <qscrollbar.h>
#include <qrubberband.h>
#include <qdebug.h>
#include <iostream>
#include "layerlistmodel.hpp"
#include "layer_info_dialog.hpp"
LayerTab::LayerTab(QWidget* parent)
: QListView(parent)
{}
using namespace std;
void LayerTab::paintEvent(QPaintEvent* e)
LayerTab::LayerTab(QWidget* parent)
: QListView(parent) {}
void LayerTab::paintEvent(QPaintEvent *e)
{
QListView::paintEvent(e);
}
void LayerTab::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
void LayerTab::dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
emit update_mapwidget();
QListView::dataChanged(topLeft, bottomRight, roles);
QListView::dataChanged(topLeft, bottomRight);
qDebug("FIXME : update map view!");
emit update_mapwidget();
}
void LayerTab::selectionChanged(const QItemSelection& selected, const QItemSelection&)
void LayerTab::selectionChanged(const QItemSelection & selected, const QItemSelection &)
{
QModelIndexList list = selected.indexes();
if (list.size() != 0)
{
qDebug("SELECTED LAYER -> %d", list[0].row());
emit layerSelected(list[0].row());
}
QModelIndexList list = selected.indexes();
if (list.size() != 0)
{
std::cout << "SELECTED LAYER ->" << list[0].row() << "\n";
emit layerSelected(list[0].row());
}
}
void LayerTab::layerInfo()
{
qDebug("Layer info");
QModelIndexList indexes = selectedIndexes();
if (indexes.size() > 0)
{
qDebug("id = %d", indexes[0].row());
}
qDebug("Layer info");
QModelIndexList indexes = selectedIndexes();
if (indexes.size() > 0)
{
qDebug("id = %d",indexes[0].row());
}
}
void LayerTab::layerInfo2(QModelIndex const& index)
{
qDebug("LayerInfo id = %d", index.row());
QVector<QPair<QString, QString>> params;
QVector<QString> style_names;
unsigned i = index.row();
LayerListModel* model = static_cast<LayerListModel*>(this->model());
boost::optional<mapnik::layer&> layer = model->map_layer(i);
qDebug("LayerInfo id = %d",index.row());
QVector<QPair<QString,QString> > params;
QVector<QString> style_names;
unsigned i = index.row();
LayerListModel * model = static_cast<LayerListModel*>(this->model());
boost::optional<mapnik::layer&> layer = model->map_layer(i);
if (layer)
{
layer_info_dialog dlg(*layer, this);
dlg.exec();
}
if (layer)
{
layer_info_dialog dlg(*layer,this);
dlg.exec();
}
}
StyleTab::StyleTab(QWidget*) {}
void StyleTab::contextMenuEvent(QContextMenuEvent* event)
StyleTab::StyleTab(QWidget*)
{
qDebug("test");
}
void StyleTab::contextMenuEvent(QContextMenuEvent * event )
{
qDebug("test");
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef LAYERWIDGET_HPP
#define LAYERWIDGET_HPP
@ -26,29 +27,28 @@
class LayerTab : public QListView
{
Q_OBJECT
public:
LayerTab(QWidget* parent = 0);
void paintEvent(QPaintEvent* e);
signals:
void update_mapwidget();
void layerSelected(int) const;
public slots:
void layerInfo();
void layerInfo2(QModelIndex const&);
protected slots:
void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles);
void selectionChanged(const QItemSelection& selected, const QItemSelection&);
Q_OBJECT
public:
LayerTab(QWidget* parent=0);
void paintEvent(QPaintEvent *e);
signals:
void update_mapwidget();
void layerSelected(int) const;
public slots:
void layerInfo();
void layerInfo2(QModelIndex const&);
protected slots:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void selectionChanged(const QItemSelection & selected, const QItemSelection &);
};
class StyleTab : public QTreeView
{
Q_OBJECT
public:
StyleTab(QWidget* parent = 0);
protected:
void contextMenuEvent(QContextMenuEvent* event);
public:
StyleTab(QWidget* parent=0);
protected:
void contextMenuEvent(QContextMenuEvent * event );
};
#endif

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,74 +17,68 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// qt
#include <QApplication>
#include <QStringList>
#include <QSettings>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/mapnik.hpp>
#include "mainwindow.hpp"
int main(int argc, char** argv)
int main( int argc, char **argv )
{
using mapnik::datasource_cache;
using mapnik::freetype_engine;
mapnik::setup();
try
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QCoreApplication::setOrganizationName("Mapnik");
QCoreApplication::setOrganizationDomain("mapnik.org");
QCoreApplication::setApplicationName("Viewer");
QSettings settings("viewer.ini", QSettings::IniFormat);
QSettings settings("viewer.ini",QSettings::IniFormat);
// register input plug-ins
QString plugins_dir = settings.value("mapnik/plugins_dir", QVariant("/usr/local/lib/mapnik/input/")).toString();
QString plugins_dir = settings.value("mapnik/plugins_dir",
QVariant("/usr/local/lib/mapnik/input/")).toString();
datasource_cache::instance().register_datasources(plugins_dir.toStdString());
// register fonts
int count = settings.beginReadArray("mapnik/fonts");
for (int index = 0; index < count; ++index)
for (int index=0; index < count; ++index)
{
settings.setArrayIndex(index);
QString font_dir = settings.value("dir").toString();
freetype_engine::register_fonts(font_dir.toStdString());
freetype_engine::instance().register_fonts(font_dir.toStdString());
}
settings.endArray();
QApplication app(argc, argv);
QApplication app( argc, argv );
MainWindow window;
window.show();
if (argc > 1)
window.open(argv[1]);
if (argc > 1) window.open(argv[1]);
if (argc >= 3)
{
QStringList list = QString(argv[2]).split(",");
if (list.size() == 4)
if (list.size()==4)
{
bool ok;
double x0 = list[0].toDouble(&ok);
double y0 = list[1].toDouble(&ok);
double x1 = list[2].toDouble(&ok);
double y1 = list[3].toDouble(&ok);
if (ok)
window.set_default_extent(x0, y0, x1, y1);
if (ok) window.set_default_extent(x0,y0,x1,y1);
}
}
else
{
std::shared_ptr<mapnik::Map> map = window.get_map();
if (map)
map->zoom_all();
if (map) map->zoom_all();
}
if (argc == 4)
{
bool ok;
double scaling_factor = QString(argv[3]).toDouble(&ok);
if (ok)
window.set_scaling_factor(scaling_factor);
if (ok) window.set_scaling_factor(scaling_factor);
}
return app.exec();
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// stl
#include <iostream>
@ -38,7 +39,7 @@
// mapnik
#ifndef Q_MOC_RUN // QT moc chokes on BOOST_JOIN
// #include <mapnik/config_error.hpp>
//#include <mapnik/config_error.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/projection.hpp>
@ -57,27 +58,27 @@
#include <boost/algorithm/string.hpp>
MainWindow::MainWindow()
: filename_()
, default_extent_(-20037508.3428, -20037508.3428, 20037508.3428, 20037508.3428)
: filename_(),
default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
{
mapWidget_ = new MapWidget(this);
QSplitter* splitter = new QSplitter(this);
QTabWidget* tabWidget = new QTabWidget;
QSplitter *splitter = new QSplitter(this);
QTabWidget *tabWidget=new QTabWidget;
layerTab_ = new LayerTab;
layerTab_->setFocusPolicy(Qt::NoFocus);
layerTab_->setIconSize(QSize(16, 16));
layerTab_->setIconSize(QSize(16,16));
// LayerDelegate *delegate = new LayerDelegate(this);
// layerTab_->setItemDelegate(delegate);
// layerTab_->setItemDelegate(new QItemDelegate(this));
// layerTab_->setViewMode(QListView::IconMode);
//LayerDelegate *delegate = new LayerDelegate(this);
//layerTab_->setItemDelegate(delegate);
//layerTab_->setItemDelegate(new QItemDelegate(this));
//layerTab_->setViewMode(QListView::IconMode);
layerTab_->setFlow(QListView::TopToBottom);
tabWidget->addTab(layerTab_, tr("Layers"));
tabWidget->addTab(layerTab_,tr("Layers"));
// Styles tab
styleTab_ = new StyleTab;
tabWidget->addTab(styleTab_, tr("Styles"));
tabWidget->addTab(styleTab_,tr("Styles"));
splitter->addWidget(tabWidget);
splitter->addWidget(mapWidget_);
QList<int> list;
@ -88,7 +89,7 @@ MainWindow::MainWindow()
mapWidget_->setFocusPolicy(Qt::StrongFocus);
mapWidget_->setFocus();
// setCentralWidget(mapWidget_);
//setCentralWidget(mapWidget_);
setCentralWidget(splitter);
createActions();
createMenus();
@ -96,25 +97,29 @@ MainWindow::MainWindow()
createContextMenu();
setWindowTitle(tr("Mapnik Viewer"));
status = new QStatusBar(this);
status=new QStatusBar(this);
status->showMessage(tr(""));
setStatusBar(status);
resize(800, 600);
resize(800,600);
// connect mapview to layerlist
connect(mapWidget_, SIGNAL(mapViewChanged()), layerTab_, SLOT(update()));
//connect mapview to layerlist
connect(mapWidget_, SIGNAL(mapViewChanged()),layerTab_, SLOT(update()));
// slider
connect(slider_, SIGNAL(valueChanged(int)), mapWidget_, SLOT(zoomToLevel(int)));
connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int)));
// renderer selector
connect(renderer_selector_, SIGNAL(currentIndexChanged(int)), mapWidget_, SLOT(updateRenderer(int)));
connect(renderer_selector_,SIGNAL(currentIndexChanged(QString const&)),
mapWidget_, SLOT(updateRenderer(QString const&)));
// scale factor
connect(scale_factor_, SIGNAL(valueChanged(double)), mapWidget_, SLOT(updateScaleFactor(double)));
connect(scale_factor_,SIGNAL(valueChanged(double)),
mapWidget_, SLOT(updateScaleFactor(double)));
//
connect(layerTab_, SIGNAL(update_mapwidget()), mapWidget_, SLOT(updateMap()));
connect(layerTab_, SIGNAL(layerSelected(int)), mapWidget_, SLOT(layerSelected(int)));
connect(layerTab_,SIGNAL(update_mapwidget()),mapWidget_,SLOT(updateMap()));
connect(layerTab_,SIGNAL(layerSelected(int)),
mapWidget_,SLOT(layerSelected(int)));
}
MainWindow::~MainWindow()
{
delete mapWidget_;
@ -136,7 +141,8 @@ void MainWindow::open(QString const& path)
{
if (path.isNull())
{
filename_ = QFileDialog::getOpenFileName(this, tr("Open Mapnik file"), currentPath, "*.xml");
filename_ = QFileDialog::getOpenFileName(this,tr("Open Mapnik file"),
currentPath,"*.xml");
}
else
{
@ -145,15 +151,18 @@ void MainWindow::open(QString const& path)
if (!filename_.isEmpty())
{
load_map_file(filename_);
setWindowTitle(tr("%1 - Mapnik Viewer").arg(filename_));
}
}
void MainWindow::reload()
{
if (!filename_.isEmpty())
{
mapnik::box2d<double> bbox = mapWidget_->getMap()->get_current_extent();
load_map_file(filename_);
mapWidget_->zoomToBox(bbox);
@ -164,28 +173,28 @@ void MainWindow::reload()
void MainWindow::save()
{
QString initialPath = QDir::currentPath() + "/untitled.xml";
QString filename = QFileDialog::getSaveFileName(this,
tr("Save"),
QString filename = QFileDialog::getSaveFileName(this, tr("Save"),
initialPath,
tr("%1 Files (*.xml)").arg(QString("Mapnik definition")));
tr("%1 Files (*.xml)")
.arg(QString("Mapnik definition")));
if (!filename.isEmpty())
{
std::cout << "saving " << filename.toStdString() << std::endl;
mapnik::save_map(*mapWidget_->getMap(), filename.toStdString());
std::cout<<"saving "<< filename.toStdString() << std::endl;
mapnik::save_map(*mapWidget_->getMap(),filename.toStdString());
}
}
void MainWindow::load_map_file(QString const& filename)
{
std::cout << "loading " << filename.toStdString() << std::endl;
std::cout << "loading "<< filename.toStdString() << std::endl;
unsigned width = mapWidget_->width();
unsigned height = mapWidget_->height();
std::shared_ptr<mapnik::Map> map(new mapnik::Map(width, height));
std::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height));
mapWidget_->setMap(map);
try
{
mapnik::auto_cpu_timer t(std::clog, "loading map took: ");
mapnik::load_map(*map, filename.toStdString());
mapnik::load_map(*map,filename.toStdString());
}
catch (std::exception const& ex)
{
@ -195,8 +204,8 @@ void MainWindow::load_map_file(QString const& filename)
{
std::cerr << "Exception caught in load_map\n";
}
layerTab_->setModel(new LayerListModel(map, this));
styleTab_->setModel(new StyleModel(map, this));
layerTab_->setModel(new LayerListModel(map,this));
styleTab_->setModel(new StyleModel(map,this));
zoom_all();
}
@ -243,15 +252,15 @@ void MainWindow::about()
void MainWindow::export_as()
{
QAction* action = qobject_cast<QAction*>(sender());
QAction *action = qobject_cast<QAction *>(sender());
QByteArray fileFormat = action->data().toByteArray();
QString initialPath = QDir::currentPath() + "/map." + fileFormat;
QString fileName = QFileDialog::getSaveFileName(
this,
tr("Export As"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)").arg(QString(fileFormat.toUpper())).arg(QString(fileFormat)));
QString fileName = QFileDialog::getSaveFileName(this, tr("Export As"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString(fileFormat.toUpper()))
.arg(QString(fileFormat)));
if (!fileName.isEmpty())
{
QPixmap const& pix = mapWidget_->pixmap();
@ -261,76 +270,77 @@ void MainWindow::export_as()
void MainWindow::print()
{
// Q_ASSERT(mapWidget_->pixmap());
// QPrintDialog dialog(&printer, this);
// if (dialog.exec()) {
// QPainter painter(&printer);
// QRect rect = painter.viewport();
// QSize size = mapWidget_->pixmap()->size();
// size.scale(rect.size(), Qt::KeepAspectRatio);
// painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
// painter.setWindow(mapWidget_->pixmap()->rect());
// painter.drawPixmap(0, 0, *mapWidget_->pixmap());
// }
//Q_ASSERT(mapWidget_->pixmap());
//QPrintDialog dialog(&printer, this);
//if (dialog.exec()) {
// QPainter painter(&printer);
// QRect rect = painter.viewport();
// QSize size = mapWidget_->pixmap()->size();
// size.scale(rect.size(), Qt::KeepAspectRatio);
// painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
// painter.setWindow(mapWidget_->pixmap()->rect());
// painter.drawPixmap(0, 0, *mapWidget_->pixmap());
//}
}
void MainWindow::createActions()
{
// exportAct = new QAction(tr("&Export as ..."),this);
// exportAct->setShortcut(tr("Ctrl+E"));
// connect(exportAct, SIGNAL(triggered()), this, SLOT(export_as()));
zoomAllAct = new QAction(QIcon(":/images/home.png"), tr("Zoom All"), this);
//exportAct = new QAction(tr("&Export as ..."),this);
//exportAct->setShortcut(tr("Ctrl+E"));
//connect(exportAct, SIGNAL(triggered()), this, SLOT(export_as()));
zoomAllAct = new QAction(QIcon(":/images/home.png"),tr("Zoom All"),this);
connect(zoomAllAct, SIGNAL(triggered()), this, SLOT(zoom_all()));
zoomBoxAct = new QAction(QIcon(":/images/zoombox.png"), tr("Zoom To Box"), this);
zoomBoxAct = new QAction(QIcon(":/images/zoombox.png"),tr("Zoom To Box"),this);
zoomBoxAct->setCheckable(true);
connect(zoomBoxAct, SIGNAL(triggered()), this, SLOT(zoom_to_box()));
panAct = new QAction(QIcon(":/images/pan.png"), tr("Pan"), this);
panAct = new QAction(QIcon(":/images/pan.png"),tr("Pan"),this);
panAct->setCheckable(true);
connect(panAct, SIGNAL(triggered()), this, SLOT(pan()));
infoAct = new QAction(QIcon(":/images/info.png"), tr("Info"), this);
infoAct = new QAction(QIcon(":/images/info.png"),tr("Info"),this);
infoAct->setCheckable(true);
connect(infoAct, SIGNAL(triggered()), this, SLOT(info()));
toolsGroup = new QActionGroup(this);
toolsGroup=new QActionGroup(this);
toolsGroup->addAction(zoomBoxAct);
toolsGroup->addAction(panAct);
toolsGroup->addAction(infoAct);
zoomBoxAct->setChecked(true);
openAct = new QAction(tr("Open Map definition"), this);
connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
saveAct = new QAction(tr("Save Map definition"), this);
connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
openAct=new QAction(tr("Open Map definition"),this);
connect(openAct,SIGNAL(triggered()),this,SLOT(open()));
saveAct=new QAction(tr("Save Map definition"),this);
connect(saveAct,SIGNAL(triggered()),this,SLOT(save()));
panLeftAct = new QAction(QIcon(":/images/left.png"), tr("&Pan Left"), this);
panLeftAct = new QAction(QIcon(":/images/left.png"),tr("&Pan Left"),this);
connect(panLeftAct, SIGNAL(triggered()), this, SLOT(pan_left()));
panRightAct = new QAction(QIcon(":/images/right.png"), tr("&Pan Right"), this);
panRightAct = new QAction(QIcon(":/images/right.png"),tr("&Pan Right"),this);
connect(panRightAct, SIGNAL(triggered()), this, SLOT(pan_right()));
panUpAct = new QAction(QIcon(":/images/up.png"), tr("&Pan Up"), this);
panUpAct = new QAction(QIcon(":/images/up.png"),tr("&Pan Up"),this);
connect(panUpAct, SIGNAL(triggered()), this, SLOT(pan_up()));
panDownAct = new QAction(QIcon(":/images/down.png"), tr("&Pan Down"), this);
panDownAct = new QAction(QIcon(":/images/down.png"),tr("&Pan Down"),this);
connect(panDownAct, SIGNAL(triggered()), this, SLOT(pan_down()));
reloadAct = new QAction(QIcon(":/images/reload.png"), tr("Reload"), this);
reloadAct = new QAction(QIcon(":/images/reload.png"),tr("Reload"),this);
connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload()));
layerInfo = new QAction(QIcon(":/images/info.png"), tr("&Layer info"), layerTab_);
connect(layerInfo, SIGNAL(triggered()), layerTab_, SLOT(layerInfo()));
connect(layerTab_, SIGNAL(doubleClicked(QModelIndex const&)), layerTab_, SLOT(layerInfo2(QModelIndex const&)));
layerInfo = new QAction(QIcon(":/images/info.png"),tr("&Layer info"),layerTab_);
connect(layerInfo, SIGNAL(triggered()), layerTab_,SLOT(layerInfo()));
connect(layerTab_, SIGNAL(doubleClicked(QModelIndex const&)), layerTab_,SLOT(layerInfo2(QModelIndex const&)));
foreach (QByteArray format, QImageWriter::supportedImageFormats())
{
QString text = tr("%1...").arg(QString(format).toUpper());
QAction* action = new QAction(text, this);
QAction *action = new QAction(text, this);
action->setData(format);
connect(action, SIGNAL(triggered()), this, SLOT(export_as()));
exportAsActs.append(action);
}
printAct = new QAction(QIcon(":/images/print.png"), tr("&Print ..."), this);
printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this);
printAct->setShortcut(tr("Ctrl+E"));
connect(printAct, SIGNAL(triggered()), this, SLOT(print()));
@ -338,17 +348,17 @@ void MainWindow::createActions()
exitAct->setShortcut(tr("Ctrl+Q"));
connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
aboutAct = new QAction(QIcon(":/images/about.png"), tr("&About"), this);
aboutAct = new QAction(QIcon(":/images/about.png"),tr("&About"), this);
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}
void MainWindow::createMenus()
{
exportMenu = new QMenu(tr("&Export As"), this);
foreach (QAction* action, exportAsActs)
foreach (QAction *action, exportAsActs)
exportMenu->addAction(action);
fileMenu = new QMenu(tr("&File"), this);
fileMenu = new QMenu(tr("&File"),this);
fileMenu->addAction(openAct);
fileMenu->addAction(saveAct);
fileMenu->addMenu(exportMenu);
@ -387,13 +397,13 @@ void MainWindow::createToolBars()
scale_factor_ = new QDoubleSpinBox(fileToolBar);
scale_factor_->setMinimum(0.1);
scale_factor_->setMaximum(10.0);
scale_factor_->setMaximum(5.0);
scale_factor_->setSingleStep(0.1);
scale_factor_->setValue(1.0);
fileToolBar->addWidget(scale_factor_);
slider_ = new QSlider(Qt::Horizontal, fileToolBar);
slider_->setRange(1, 18);
slider_ = new QSlider(Qt::Horizontal,fileToolBar);
slider_->setRange(1,18);
slider_->setTickPosition(QSlider::TicksBelow);
slider_->setTickInterval(1);
slider_->setTracking(false);
@ -401,7 +411,9 @@ void MainWindow::createToolBars()
fileToolBar->addAction(aboutAct);
}
void MainWindow::set_default_extent(double x0, double y0, double x1, double y1)
void MainWindow::set_default_extent(double x0,double y0, double x1, double y1)
{
try
{
@ -409,15 +421,14 @@ void MainWindow::set_default_extent(double x0, double y0, double x1, double y1)
if (map_ptr)
{
mapnik::projection prj(map_ptr->srs());
prj.forward(x0, y0);
prj.forward(x1, y1);
default_extent_ = mapnik::box2d<double>(x0, y0, x1, y1);
prj.forward(x0,y0);
prj.forward(x1,y1);
default_extent_=mapnik::box2d<double>(x0,y0,x1,y1);
mapWidget_->zoomToBox(default_extent_);
std::cout << "SET DEFAULT EXT:" << default_extent_ << std::endl;
std::cout << "SET DEFAULT EXT\n";
}
}
catch (...)
{}
catch (...) {}
}
void MainWindow::set_scaling_factor(double scaling_factor)

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
@ -29,7 +30,7 @@
#include "mapwidget.hpp"
// using namespace mapnik;
//using namespace mapnik;
class LayerTab;
class StyleTab;
@ -40,24 +41,22 @@ class QDoubleSpinBox;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
public:
MainWindow();
virtual ~MainWindow();
void set_default_extent(double x0, double y0, double x1, double y1);
void set_default_extent(double x0,double y0,double x1, double y1);
void set_scaling_factor(double scaling_factor);
public:
public :
std::shared_ptr<mapnik::Map> get_map();
protected:
protected:
void closeEvent(QCloseEvent* event);
public slots:
public slots:
void zoom_all();
void zoom_to_box();
void pan();
void info();
void export_as();
void open(QString const& path = QString());
void open(QString const& path = QString());
void reload();
void save();
void print();
@ -66,8 +65,7 @@ class MainWindow : public QMainWindow
void pan_right();
void pan_up();
void pan_down();
private:
private:
void createActions();
void createMenus();
void createToolBars();
@ -76,42 +74,43 @@ class MainWindow : public QMainWindow
QString currentPath;
QString filename_;
QAbstractItemModel* model;
LayerTab* layerTab_;
StyleTab* styleTab_;
MapWidget* mapWidget_;
// actions
QList<QAction*> exportAsActs;
QActionGroup* toolsGroup;
QAbstractItemModel *model;
LayerTab *layerTab_;
StyleTab * styleTab_;
MapWidget * mapWidget_;
//actions
QList<QAction *> exportAsActs;
QActionGroup *toolsGroup;
QAction* zoomAllAct;
QAction* zoomBoxAct;
QAction* panAct;
QAction* infoAct;
QAction* openAct;
QAction* saveAct;
QAction* printAct;
QAction* exitAct;
QAction* aboutAct;
QAction* panLeftAct;
QAction* panRightAct;
QAction* panUpAct;
QAction* panDownAct;
QAction* reloadAct;
QAction* layerInfo;
// toolbars
QToolBar* fileToolBar;
QToolBar* editToolBar;
// menus
QMenu* exportMenu;
QMenu* fileMenu;
QMenu* helpMenu;
// status bar
QStatusBar* status;
QSlider* slider_;
QComboBox* renderer_selector_;
QDoubleSpinBox* scale_factor_;
QAction *zoomAllAct;
QAction *zoomBoxAct;
QAction *panAct;
QAction *infoAct;
QAction *openAct;
QAction *saveAct;
QAction *printAct;
QAction *exitAct;
QAction *aboutAct;
QAction *panLeftAct;
QAction *panRightAct;
QAction *panUpAct;
QAction *panDownAct;
QAction *reloadAct;
QAction *layerInfo;
//toolbars
QToolBar *fileToolBar;
QToolBar *editToolBar;
//menus
QMenu *exportMenu;
QMenu *fileMenu;
QMenu *helpMenu;
//status bar
QStatusBar *status;
QSlider * slider_;
QComboBox * renderer_selector_;
QDoubleSpinBox * scale_factor_;
mapnik::box2d<double> default_extent_;
};
#endif // MAINWINDOW_HPP
#endif //MAINWINDOW_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,12 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <QtGui>
#include <boost/bind.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/transform_path_adapter.hpp>
@ -40,139 +41,153 @@
#include "mapwidget.hpp"
#include "info_dialog.hpp"
using mapnik::image_rgba8;
using mapnik::Map;
using mapnik::layer;
using mapnik::box2d;
using mapnik::coord2d;
using mapnik::feature_kv_iterator;
using mapnik::feature_ptr;
using mapnik::image_rgba8;
using mapnik::layer;
using mapnik::Map;
using mapnik::view_transform;
using mapnik::projection;
using mapnik::scale_denominator;
using mapnik::view_transform;
using mapnik::feature_kv_iterator;
double scales[] = {279541132.014, 139770566.007, 69885283.0036, 34942641.5018, 17471320.7509,
8735660.37545, 4367830.18772, 2183915.09386, 1091957.54693, 545978.773466,
272989.386733, 136494.693366, 68247.3466832, 34123.6733416, 17061.8366708,
8530.9183354, 4265.4591677, 2132.72958385, 1066.36479192, 533.182395962};
double scales [] = {279541132.014,
139770566.007,
69885283.0036,
34942641.5018,
17471320.7509,
8735660.37545,
4367830.18772,
2183915.09386,
1091957.54693,
545978.773466,
272989.386733,
136494.693366,
68247.3466832,
34123.6733416,
17061.8366708,
8530.9183354,
4265.4591677,
2132.72958385,
1066.36479192,
533.182395962};
MapWidget::MapWidget(QWidget* parent)
: QWidget(parent)
, map_()
, selected_(1)
, extent_()
, cur_tool_(ZoomToBox)
, start_x_(0)
, start_y_(0)
, end_x_(0)
, end_y_(0)
, drag_(false)
, first_(true)
, pen_(QColor(0, 0, 255, 96))
, selectedLayer_(-1)
, scaling_factor_(1.0)
, cur_renderer_(AGG)
MapWidget::MapWidget(QWidget *parent)
: QWidget(parent),
map_(),
selected_(1),
extent_(),
cur_tool_(ZoomToBox),
start_x_(0),
start_y_(0),
end_x_(0),
end_y_(0),
drag_(false),
first_(true),
pen_(QColor(0,0,255,96)),
selectedLayer_(-1),
scaling_factor_(1.0),
cur_renderer_(AGG)
{
pen_.setWidth(3);
pen_.setCapStyle(Qt::RoundCap);
pen_.setJoinStyle(Qt::RoundJoin);
pen_.setWidth(3);
pen_.setCapStyle(Qt::RoundCap);
pen_.setJoinStyle(Qt::RoundJoin);
}
void MapWidget::setTool(eTool tool)
{
cur_tool_ = tool;
cur_tool_=tool;
}
void MapWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QPainter painter(this);
if (drag_)
{
if (cur_tool_ == ZoomToBox)
{
unsigned width = end_x_ - start_x_;
unsigned height = end_y_ - start_y_;
painter.drawPixmap(QPoint(0, 0), pix_);
painter.setPen(pen_);
painter.setBrush(QColor(200, 200, 255, 128));
painter.drawRect(start_x_, start_y_, width, height);
}
else if (cur_tool_ == Pan)
{
int dx = end_x_ - start_x_;
int dy = end_y_ - start_y_;
painter.setBrush(QColor(200, 200, 200, 128));
painter.drawRect(0, 0, width(), height());
painter.drawPixmap(QPoint(dx, dy), pix_);
}
}
else
{
painter.drawPixmap(QPoint(0, 0), pix_);
}
painter.end();
if (drag_)
{
if (cur_tool_ == ZoomToBox)
{
unsigned width = end_x_-start_x_;
unsigned height = end_y_-start_y_;
painter.drawPixmap(QPoint(0, 0),pix_);
painter.setPen(pen_);
painter.setBrush(QColor(200,200,255,128));
painter.drawRect(start_x_,start_y_,width,height);
}
else if (cur_tool_ == Pan)
{
int dx = end_x_-start_x_;
int dy = end_y_-start_y_;
painter.setBrush(QColor(200,200,200,128));
painter.drawRect(0,0,width(),height());
painter.drawPixmap(QPoint(dx,dy),pix_);
}
}
else
{
painter.drawPixmap(QPoint(0, 0),pix_);
}
painter.end();
}
void MapWidget::resizeEvent(QResizeEvent* ev)
void MapWidget::resizeEvent(QResizeEvent * ev)
{
if (map_)
{
map_->resize(ev->size().width(), ev->size().height());
updateMap();
}
if (map_)
{
map_->resize(ev->size().width(),ev->size().height());
updateMap();
}
}
void MapWidget::mousePressEvent(QMouseEvent* e)
{
if (e->button() == Qt::LeftButton)
{
if (cur_tool_ == ZoomToBox || cur_tool_ == Pan)
{
start_x_ = e->x();
start_y_ = e->y();
drag_ = true;
}
else if (cur_tool_ == Info)
{
if (map_)
if (e->button()==Qt::LeftButton)
{
if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
{
start_x_ = e->x();
start_y_ = e->y();
drag_=true;
}
else if (cur_tool_==Info)
{
if (map_)
{
QVector<QPair<QString,QString> > info;
projection map_proj(map_->srs()); // map projection
double scale_denom = scale_denominator(map_->scale(),map_proj.is_geographic());
view_transform t(map_->width(),map_->height(),map_->get_current_extent());
for (unsigned index = 0; index < map_->layer_count();++index)
{
QVector<QPair<QString, QString>> info;
if (int(index) != selectedLayer_) continue;
projection map_proj(map_->srs(), true); // map projection
double scale_denom = scale_denominator(map_->scale(), map_proj.is_geographic());
view_transform t(map_->width(), map_->height(), map_->get_current_extent());
layer & layer = map_->layers()[index];
if (!layer.visible(scale_denom)) continue;
std::string name = layer.name();
double x = e->x();
double y = e->y();
std::cout << "query at " << x << "," << y << "\n";
projection layer_proj(layer.srs());
mapnik::proj_transform prj_trans(map_proj,layer_proj);
//std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
mapnik::featureset_ptr fs = map_->query_map_point(index,x,y);
for (unsigned index = 0; index < map_->layer_count(); ++index)
{
if (int(index) != selectedLayer_)
continue;
if (fs)
{
feature_ptr feat = fs->next();
if (feat)
{
feature_kv_iterator itr(*feat,true);
feature_kv_iterator end(*feat);
layer& layer = map_->layers()[index];
if (!layer.visible(scale_denom))
continue;
std::string name = layer.name();
double x = e->x();
double y = e->y();
std::cout << "query at " << x << "," << y << "\n";
projection layer_proj(layer.srs(), true);
mapnik::proj_transform prj_trans(map_proj, layer_proj);
// std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
mapnik::featureset_ptr fs = map_->query_map_point(index, x, y);
if (fs)
{
feature_ptr feat = fs->next();
if (feat)
{
feature_kv_iterator itr(*feat, true);
feature_kv_iterator end(*feat);
for (; itr != end; ++itr)
{
info.push_back(QPair<QString, QString>(QString(std::get<0>(*itr).c_str()),
std::get<1>(*itr).to_string().c_str()));
}
for ( ;itr!=end; ++itr)
{
info.push_back(QPair<QString,QString>(QString(std::get<0>(*itr).c_str()),
std::get<1>(*itr).to_string().c_str()));
}
#if 0 //
using path_type = mapnik::transform_path_adapter<mapnik::view_transform,mapnik::vertex_adapter>;
@ -204,285 +219,271 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
}
}
#endif
}
}
}
}
if (info.size() > 0)
{
info_dialog info_dlg(info, this);
info_dlg.exec();
break;
}
}
// remove annotation layer
map_->layers().erase(
remove_if(map_->layers().begin(), map_->layers().end(), bind(&layer::name, _1) == "*annotations*"),
map_->layers().end());
if (info.size() > 0)
{
info_dialog info_dlg(info,this);
info_dlg.exec();
break;
}
}
}
}
else if (e->button() == Qt::RightButton)
{
// updateMap();
}
// remove annotation layer
map_->layers().erase(remove_if(map_->layers().begin(),
map_->layers().end(),
bind(&layer::name,_1) == "*annotations*")
, map_->layers().end());
}
}
}
else if (e->button()==Qt::RightButton)
{
//updateMap();
}
}
void MapWidget::mouseMoveEvent(QMouseEvent* e)
{
if (cur_tool_ == ZoomToBox || cur_tool_ == Pan)
{
end_x_ = e->x();
end_y_ = e->y();
update();
}
if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
{
end_x_ = e->x();
end_y_ = e->y();
update();
}
}
void MapWidget::mouseReleaseEvent(QMouseEvent* e)
{
if (e->button() == Qt::LeftButton)
{
end_x_ = e->x();
end_y_ = e->y();
if (cur_tool_ == ZoomToBox)
{
drag_ = false;
if (map_)
{
view_transform t(map_->width(), map_->height(), map_->get_current_extent());
box2d<double> box = t.backward(box2d<double>(start_x_, start_y_, end_x_, end_y_));
map_->zoom_to_box(box);
updateMap();
}
}
else if (cur_tool_ == Pan)
{
drag_ = false;
if (map_)
{
int cx = int(0.5 * map_->width());
int cy = int(0.5 * map_->height());
int dx = end_x_ - start_x_;
int dy = end_y_ - start_y_;
map_->pan(cx - dx, cy - dy);
updateMap();
}
}
}
if (e->button()==Qt::LeftButton)
{
end_x_ = e->x();
end_y_ = e->y();
if (cur_tool_ == ZoomToBox)
{
drag_=false;
if (map_)
{
view_transform t(map_->width(),map_->height(),map_->get_current_extent());
box2d<double> box = t.backward(box2d<double>(start_x_,start_y_,end_x_,end_y_));
map_->zoom_to_box(box);
updateMap();
}
}
else if (cur_tool_==Pan)
{
drag_=false;
if (map_)
{
int cx = int(0.5 * map_->width());
int cy = int(0.5 * map_->height());
int dx = end_x_ - start_x_;
int dy = end_y_ - start_y_;
map_->pan(cx - dx ,cy - dy);
updateMap();
}
}
}
}
void MapWidget::wheelEvent(QWheelEvent* e)
{
if (!map_)
{
return;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QPointF corner(map_->width(), map_->height());
QPointF zoomCoords;
double zoom;
if (e->angleDelta().y() > 0)
{
zoom = 0.5;
QPointF center = corner / 2;
QPointF delta = e->position() - center;
zoomCoords = zoom * delta + center;
}
else
{
zoom = 2.0;
zoomCoords = corner - e->position();
}
#else
QPoint corner(map_->width(), map_->height());
QPoint zoomCoords;
double zoom;
if (e->delta() > 0)
{
zoom = 0.5;
QPoint center = corner / 2;
QPoint delta = e->pos() - center;
zoomCoords = zoom * delta + center;
}
else
{
zoom = 2.0;
zoomCoords = corner - e->pos();
}
#endif
if (!map_)
{
return;
}
map_->pan_and_zoom(zoomCoords.x(), zoomCoords.y(), zoom);
updateMap();
QPoint corner(map_->width(), map_->height());
QPoint zoomCoords;
double zoom;
if (e->delta() > 0)
{
zoom = 0.5;
QPoint center = corner / 2;
QPoint delta = e->pos() - center;
zoomCoords = zoom * delta + center;
}
else
{
zoom = 2.0;
zoomCoords = corner - e->pos();
}
map_->pan_and_zoom(zoomCoords.x(), zoomCoords.y(), zoom);
updateMap();
}
void MapWidget::keyPressEvent(QKeyEvent* e)
void MapWidget::keyPressEvent(QKeyEvent *e)
{
std::cout << "key pressed:" << e->key() << "\n";
switch (e->key())
{
case Qt::Key_Minus:
zoomOut();
break;
case Qt::Key_Plus:
case 61:
zoomIn();
break;
case 65:
defaultView();
break;
case Qt::Key_Up:
panUp();
break;
case Qt::Key_Down:
panDown();
break;
case Qt::Key_Left:
panLeft();
break;
case Qt::Key_Right:
panRight();
break;
case 49:
zoomToLevel(10);
break;
case 50:
zoomToLevel(11);
break;
case 51:
zoomToLevel(12);
break;
case 52:
zoomToLevel(13);
break;
case 53:
zoomToLevel(14);
break;
case 54:
zoomToLevel(15);
break;
case 55:
zoomToLevel(16);
break;
case 56:
zoomToLevel(17);
break;
case 57:
zoomToLevel(18);
break;
default:
QWidget::keyPressEvent(e);
}
std::cout << "key pressed:"<< e->key()<<"\n";
switch (e->key()) {
case Qt::Key_Minus:
zoomOut();
break;
case Qt::Key_Plus:
case 61:
zoomIn();
break;
case 65:
defaultView();
break;
case Qt::Key_Up:
panUp();
break;
case Qt::Key_Down:
panDown();
break;
case Qt::Key_Left:
panLeft();
break;
case Qt::Key_Right:
panRight();
break;
case 49:
zoomToLevel(10);
break;
case 50:
zoomToLevel(11);
break;
case 51:
zoomToLevel(12);
break;
case 52:
zoomToLevel(13);
break;
case 53:
zoomToLevel(14);
break;
case 54:
zoomToLevel(15);
break;
case 55:
zoomToLevel(16);
break;
case 56:
zoomToLevel(17);
break;
case 57:
zoomToLevel(18);
break;
default:
QWidget::keyPressEvent(e);
}
}
void MapWidget::zoomToBox(mapnik::box2d<double> const& bbox)
{
if (map_)
{
map_->zoom_to_box(bbox);
updateMap();
}
if (map_)
{
map_->zoom_to_box(bbox);
updateMap();
}
}
void MapWidget::defaultView()
{
if (map_)
{
map_->resize(width(), height());
map_->zoom_all();
updateMap();
}
if (map_)
{
map_->resize(width(),height());
map_->zoom_all();
updateMap();
}
}
void MapWidget::zoomIn()
{
if (map_)
{
map_->zoom(0.5);
updateMap();
}
if (map_)
{
map_->zoom(0.5);
updateMap();
}
}
void MapWidget::zoomOut()
{
if (map_)
{
map_->zoom(2.0);
updateMap();
}
if (map_)
{
map_->zoom(2.0);
updateMap();
}
}
void MapWidget::panUp()
{
if (map_)
{
double cx = 0.5 * map_->width();
double cy = 0.5 * map_->height();
map_->pan(int(cx), int(cy - cy * 0.25));
updateMap();
}
if (map_)
{
double cx = 0.5*map_->width();
double cy = 0.5*map_->height();
map_->pan(int(cx),int(cy - cy*0.25));
updateMap();
}
}
void MapWidget::panDown()
{
if (map_)
{
double cx = 0.5 * map_->width();
double cy = 0.5 * map_->height();
map_->pan(int(cx), int(cy + cy * 0.25));
updateMap();
}
if (map_)
{
double cx = 0.5*map_->width();
double cy = 0.5*map_->height();
map_->pan(int(cx),int(cy + cy*0.25));
updateMap();
}
}
void MapWidget::panLeft()
{
if (map_)
{
double cx = 0.5 * map_->width();
double cy = 0.5 * map_->height();
map_->pan(int(cx - cx * 0.25), int(cy));
updateMap();
}
if (map_)
{
double cx = 0.5*map_->width();
double cy = 0.5*map_->height();
map_->pan(int(cx - cx * 0.25),int(cy));
updateMap();
}
}
void MapWidget::panRight()
{
if (map_)
{
double cx = 0.5 * map_->width();
double cy = 0.5 * map_->height();
map_->pan(int(cx + cx * 0.25), int(cy));
updateMap();
}
if (map_)
{
double cx = 0.5*map_->width();
double cy = 0.5*map_->height();
map_->pan(int(cx + cx * 0.25),int(cy));
updateMap();
}
}
void MapWidget::zoomToLevel(int level)
{
if (map_ && level >= 0 && level < 19)
{
double scale_denom = scales[level];
std::cerr << "scale denominator = " << scale_denom << "\n";
mapnik::box2d<double> ext = map_->get_current_extent();
double width = static_cast<double>(map_->width());
double height = static_cast<double>(map_->height());
mapnik::coord2d pt = ext.center();
if ( map_ && level >= 0 && level < 19 )
{
double scale_denom = scales[level];
std::cerr << "scale denominator = " << scale_denom << "\n";
mapnik::box2d<double> ext = map_->get_current_extent();
double width = static_cast<double>(map_->width());
double height= static_cast<double>(map_->height());
mapnik::coord2d pt = ext.center();
double res = scale_denom * 0.00028;
double res = scale_denom * 0.00028;
mapnik::box2d<double> box(pt.x - 0.5 * width * res,
pt.y - 0.5 * height * res,
pt.x + 0.5 * width * res,
pt.y + 0.5 * height * res);
map_->zoom_to_box(box);
updateMap();
}
mapnik::box2d<double> box(pt.x - 0.5 * width * res,
pt.y - 0.5 * height*res,
pt.x + 0.5 * width * res,
pt.y + 0.5 * height*res);
map_->zoom_to_box(box);
updateMap();
}
}
void MapWidget::export_to_file(unsigned, unsigned, std::string const&, std::string const&)
void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::string const&)
{
// image_rgba8 image(width,height);
// agg_renderer renderer(map,image);
// renderer.apply();
// image.saveToFile(filename,type);
//image_rgba8 image(width,height);
//agg_renderer renderer(map,image);
//renderer.apply();
//image.saveToFile(filename,type);
std::cout << "Export to file .." << std::endl;
}
@ -491,25 +492,25 @@ void MapWidget::set_scaling_factor(double scaling_factor)
scaling_factor_ = scaling_factor;
}
void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap& pix)
void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
unsigned width = map.width();
unsigned height = map.height();
unsigned width=map.width();
unsigned height=map.height();
image_rgba8 buf(width, height);
mapnik::agg_renderer<image_rgba8> ren(map, buf, scaling_factor);
image_rgba8 buf(width,height);
mapnik::agg_renderer<image_rgba8> ren(map,buf,scaling_factor);
try
{
mapnik::auto_cpu_timer t(std::clog, "rendering took: ");
ren.apply();
QImage image((uchar*)buf.data(), width, height, QImage::Format_ARGB32);
QImage image((uchar*)buf.data(),width,height,QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
}
// catch (mapnik::config_error & ex)
//catch (mapnik::config_error & ex)
//{
// std::cerr << ex.what() << std::endl;
// }
// std::cerr << ex.what() << std::endl;
//}
catch (std::exception const& ex)
{
std::cerr << "exception: " << ex.what() << std::endl;
@ -520,16 +521,18 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap& pix)
}
}
void render_grid(mapnik::Map const& map, double scaling_factor, QPixmap& pix)
void render_grid(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
std::cerr << "Not supported" << std::endl;
}
void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap& pix)
void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{
// FIXME
#ifdef HAVE_CAIRO
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,map.width(),map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_ptr cairo = mapnik::create_context(image_surface);
if (cairo)
@ -540,20 +543,17 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap& pix)
}
mapnik::image_rgba8 data(map.width(), map.height());
mapnik::cairo_image_to_rgba8(data, image_surface);
QImage image((uchar*)data.bytes(), data.width(), data.height(), QImage::Format_ARGB32);
QImage image((uchar*)data.bytes(),data.width(),data.height(),QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
#endif
}
void MapWidget::updateRenderer(int index)
void MapWidget::updateRenderer(QString const& txt)
{
std::cerr << "updateRenderer:" << index << std::endl;
if (index == 0)
cur_renderer_ = AGG;
else if (index == 1)
cur_renderer_ = Cairo;
else if (index == 2)
cur_renderer_ = Grid;
if (txt == "AGG") cur_renderer_ = AGG;
else if (txt == "Cairo") cur_renderer_ = Cairo;
else if (txt == "Grid") cur_renderer_ = Grid;
std::cerr << "Update renderer called" << std::endl;
updateMap();
}
@ -565,63 +565,59 @@ void MapWidget::updateScaleFactor(double scale_factor)
void MapWidget::updateMap()
{
if (map_)
{
if (cur_renderer_ == AGG)
{
render_agg(*map_, scaling_factor_, pix_);
}
else if (cur_renderer_ == Cairo)
{
render_cairo(*map_, scaling_factor_, pix_);
}
else if (cur_renderer_ == Grid)
{
render_grid(*map_, scaling_factor_, pix_);
}
else
{
std::cerr << "Unknown renderer..." << std::endl;
}
if (map_)
{
if (cur_renderer_== AGG)
{
render_agg(*map_, scaling_factor_, pix_);
}
else if (cur_renderer_ == Cairo)
{
render_cairo(*map_, scaling_factor_, pix_);
}
else if (cur_renderer_ == Grid)
{
render_grid(*map_, scaling_factor_, pix_);
}
else
{
std::cerr << "Unknown renderer..." << std::endl;
}
try
{
projection prj(map_->srs(), true); // map projection
box2d<double> ext = map_->get_current_extent();
double x0 = ext.minx();
double y0 = ext.miny();
double x1 = ext.maxx();
double y1 = ext.maxy();
double z = 0;
std::string dest_srs = {"epsg:4326"};
mapnik::proj_transform proj_tr(map_->srs(), dest_srs);
proj_tr.forward(x0, y0, z);
proj_tr.forward(x1, y1, z);
std::cout << "MAP SIZE:" << map_->width() << "," << map_->height() << std::endl;
std::cout << "BBOX (WGS84): " << x0 << "," << y0 << "," << x1 << "," << y1 << "\n";
update();
// emit signal to interested widgets
emit mapViewChanged();
}
catch (...)
{
std::cerr << "Unknown exception caught!\n";
}
}
try
{
projection prj(map_->srs()); // map projection
box2d<double> ext = map_->get_current_extent();
double x0 = ext.minx();
double y0 = ext.miny();
double x1 = ext.maxx();
double y1 = ext.maxy();
prj.inverse(x0,y0);
prj.inverse(x1,y1);
std::cout << "BBOX (WGS84): " << x0 << "," << y0 << "," << x1 << "," << y1 << "\n";
update();
// emit signal to interested widgets
emit mapViewChanged();
}
catch (...)
{
std::cerr << "Unknown exception caught!\n";
}
}
}
std::shared_ptr<Map> MapWidget::getMap()
{
return map_;
return map_;
}
void MapWidget::setMap(std::shared_ptr<Map> map)
{
map_ = map;
map_ = map;
}
void MapWidget::layerSelected(int index)
{
selectedLayer_ = index;
selectedLayer_ = index;
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef MAP_WIDGET_HPP
#define MAP_WIDGET_HPP
@ -29,6 +30,7 @@
#include <string>
#include <memory>
#ifndef Q_MOC_RUN
#include <mapnik/map.hpp>
#endif
@ -37,16 +39,22 @@ class MapWidget : public QWidget
{
Q_OBJECT
public:
enum eTool {
public:
enum eTool
{
ZoomToBox = 1,
Pan,
Info,
};
enum eRenderer { AGG, Cairo, Grid };
enum eRenderer
{
AGG,
Cairo,
Grid
};
private:
private:
std::shared_ptr<mapnik::Map> map_;
int selected_;
QPixmap pix_;
@ -62,12 +70,11 @@ class MapWidget : public QWidget
int selectedLayer_;
double scaling_factor_;
eRenderer cur_renderer_;
public:
MapWidget(QWidget* parent = 0);
public:
MapWidget(QWidget *parent=0);
void setTool(eTool tool);
std::shared_ptr<mapnik::Map> getMap();
inline QPixmap const& pixmap() const { return pix_; }
inline QPixmap const& pixmap() const { return pix_;}
void setMap(std::shared_ptr<mapnik::Map> map);
void defaultView();
void zoomToBox(mapnik::box2d<double> const& box);
@ -78,24 +85,26 @@ class MapWidget : public QWidget
void panUp();
void panDown();
void set_scaling_factor(double);
public slots:
public slots:
void zoomToLevel(int level);
void updateMap();
void layerSelected(int);
void updateRenderer(int);
void updateRenderer(QString const& txt);
void updateScaleFactor(double scale_factor);
signals:
signals:
void mapViewChanged();
protected:
protected:
void paintEvent(QPaintEvent* ev);
void resizeEvent(QResizeEvent* ev);
void mousePressEvent(QMouseEvent* e);
void mouseMoveEvent(QMouseEvent* e);
void mouseReleaseEvent(QMouseEvent* e);
void wheelEvent(QWheelEvent* e);
void keyPressEvent(QKeyEvent* e);
void export_to_file(unsigned width, unsigned height, std::string const& filename, std::string const& type);
void keyPressEvent(QKeyEvent *e);
void export_to_file(unsigned width,
unsigned height,
std::string const& filename,
std::string const& type);
};
#endif // MAP_WIDGET_HPP

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "styles_model.hpp"
#include <mapnik/config.hpp>
#include <mapnik/util/variant.hpp>
@ -38,50 +39,70 @@ class node : private mapnik::util::noncopyable
{
struct node_base
{
virtual QString name() const = 0;
virtual QIcon icon() const = 0;
virtual QString name() const=0;
virtual QIcon icon() const=0;
virtual ~node_base() {}
};
template<typename T>
template <typename T>
struct wrap : public node_base
{
wrap(T const& obj)
: obj_(obj)
{}
wrap(T const& obj)
: obj_(obj) {}
~wrap() {}
~wrap() {}
QString name() const { return obj_.name(); }
QString name () const
{
return obj_.name();
}
QIcon icon() const { return obj_.icon(); }
QIcon icon() const
{
return obj_.icon();
}
T obj_;
T obj_;
};
public:
template<typename T>
node(T const& obj, node* parent = 0)
: impl_(new wrap<T>(obj))
, parent_(parent)
public:
template <typename T>
node ( T const& obj, node * parent=0)
: impl_(new wrap<T>(obj)),
parent_(parent)
{}
QString name() const { return impl_->name(); }
QString name() const
{
return impl_->name();
}
QIcon icon() const { return impl_->icon(); }
QIcon icon() const
{
return impl_->icon();
}
unsigned num_children() const { return children_.count(); }
unsigned num_children() const
{
return children_.count();
}
node* child(unsigned row) const { return children_.value(row); }
node * child(unsigned row) const
{
return children_.value(row);
}
node* parent() const { return parent_; }
node * parent() const
{
return parent_;
}
node* add_child(node* child)
node * add_child(node * child)
{
children_.push_back(child);
return child;
}
int row() const
int row () const
{
if (parent_)
return parent_->children_.indexOf(const_cast<node*>(this));
@ -89,90 +110,94 @@ class node : private mapnik::util::noncopyable
return 0;
}
~node() { qDeleteAll(children_); }
~node()
{
qDeleteAll(children_);
}
private:
private:
const std::unique_ptr<node_base> impl_;
QList<node*> children_;
node* parent_;
node * parent_;
};
struct symbolizer_info
{
QString operator()(mapnik::point_symbolizer const& sym) const
QString operator() (mapnik::point_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("PointSymbolizer");
}
QString operator()(mapnik::line_symbolizer const& sym) const
QString operator() (mapnik::line_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("LineSymbolizer");
}
QString operator()(mapnik::line_pattern_symbolizer const& sym) const
QString operator() (mapnik::line_pattern_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("LinePatternSymbolizer");
}
QString operator()(mapnik::polygon_symbolizer const& sym) const
QString operator() (mapnik::polygon_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("PolygonSymbolizer");
}
QString operator()(mapnik::polygon_pattern_symbolizer const& sym) const
QString operator() (mapnik::polygon_pattern_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("PolygonSymbolizer");
}
QString operator()(mapnik::text_symbolizer const& sym) const
QString operator() (mapnik::text_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("TextSymbolizer");
}
QString operator()(mapnik::shield_symbolizer const& sym) const
QString operator() (mapnik::shield_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("ShieldSymbolizer");
}
QString operator()(mapnik::markers_symbolizer const& sym) const
QString operator() (mapnik::markers_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("MarkersSymbolizer");
}
QString operator()(mapnik::building_symbolizer const& sym) const
QString operator() (mapnik::building_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("BuildingSymbolizer");
}
template<typename T>
QString operator()(T const&) const
template <typename T>
QString operator() (T const& ) const
{
return QString("FIXME");
return QString ("FIXME");
}
};
struct symbolizer_icon
{
QIcon operator()(mapnik::polygon_symbolizer const& sym) const
QIcon operator() (mapnik::polygon_symbolizer const& sym) const
{
QPixmap pix(16, 16);
QPixmap pix(16,16);
QPainter painter(&pix);
mapnik::color const& fill = mapnik::get<mapnik::color>(sym, mapnik::keys::fill);
QBrush brush(QColor(fill.red(), fill.green(), fill.blue(), fill.alpha()));
QBrush brush(QColor(fill.red(),fill.green(),fill.blue(),fill.alpha()));
painter.fillRect(0, 0, 16, 16, brush);
return QIcon(pix);
}
QIcon operator()(mapnik::point_symbolizer const& sym) const
QIcon operator() (mapnik::point_symbolizer const& sym) const
{
// FIXME!
/*
@ -187,57 +212,55 @@ struct symbolizer_icon
*/
return QIcon();
}
QIcon operator()(mapnik::line_symbolizer const& sym) const
QIcon operator() (mapnik::line_symbolizer const& sym) const
{
QPixmap pix(48, 16);
QPixmap pix(48,16);
pix.fill();
QPainter painter(&pix);
// mapnik::stroke const& strk = sym.get_stroke();
//mapnik::stroke const& strk = sym.get_stroke();
mapnik::color const& col = mapnik::get<mapnik::color>(sym, mapnik::keys::stroke);
QPen pen(QColor(col.red(), col.green(), col.blue(), col.alpha()));
QPen pen(QColor(col.red(),col.green(),col.blue(),col.alpha()));
pen.setWidth(mapnik::get<double>(sym, mapnik::keys::width));
painter.setPen(pen);
painter.drawLine(0, 7, 47, 7);
// painter.drawLine(7,15,12,0);
// painter.drawLine(12,0,8,15);
painter.drawLine(0,7,47,7);
//painter.drawLine(7,15,12,0);
//painter.drawLine(12,0,8,15);
return QIcon(pix);
}
template<typename T>
QIcon operator()(T const&) const
template <typename T>
QIcon operator() (T const& ) const
{
return QIcon(":/images/filter.png");
return QIcon (":/images/filter.png");
}
};
class symbolizer_node
{
public:
symbolizer_node(mapnik::symbolizer const& sym)
: sym_(sym)
{}
~symbolizer_node() {}
public:
symbolizer_node(mapnik::symbolizer const & sym)
: sym_(sym) {}
~symbolizer_node(){}
QString name() const
{
// return QString("Symbolizer:fixme");
return mapnik::util::apply_visitor(symbolizer_info(), sym_);
//return QString("Symbolizer:fixme");
return mapnik::util::apply_visitor(symbolizer_info(),sym_);
}
QIcon icon() const
{
return mapnik::util::apply_visitor(symbolizer_icon(), sym_); // QIcon(":/images/filter.png");
return mapnik::util::apply_visitor(symbolizer_icon(),sym_);//QIcon(":/images/filter.png");
}
mapnik::symbolizer const& sym_;
};
class rule_node
{
public:
rule_node(QString name, mapnik::rule const& r)
: name_(name)
, rule_(r)
{}
public:
rule_node(QString name,mapnik::rule const & r)
: name_(name),
rule_(r) {}
~rule_node() {}
QString name() const
{
@ -245,68 +268,81 @@ class rule_node
return QString(mapnik::to_expression_string(*filter).c_str());
}
QIcon icon() const { return QIcon(":/images/filter.png"); }
QIcon icon() const
{
return QIcon(":/images/filter.png");
}
private:
private:
QString name_;
mapnik::rule const& rule_;
};
class style_node
{
public:
public:
style_node(QString name, mapnik::feature_type_style const& style)
: name_(name)
, style_(style)
{}
: name_(name),
style_(style) {}
~style_node() {}
QString name() const { return name_; }
QString name() const
{
return name_;
}
QIcon icon() const { return QIcon(":/images/style.png"); }
QIcon icon() const
{
return QIcon(":/images/style.png");
}
private:
private:
QString name_;
mapnik::feature_type_style const& style_;
};
class map_node
{
public:
public:
explicit map_node(std::shared_ptr<mapnik::Map> map)
: map_(map)
{}
: map_(map) {}
~map_node() {}
QString name() const { return QString("Map"); }
QString name() const
{
return QString("Map");
}
QIcon icon() const { return QIcon(":/images/map.png"); }
QIcon icon() const
{
return QIcon(":/images/map.png");
}
private:
private:
std::shared_ptr<mapnik::Map> map_;
};
StyleModel::StyleModel(std::shared_ptr<mapnik::Map> map, QObject* parent)
: QAbstractItemModel(parent)
, root_(new node(map_node(map)))
StyleModel::StyleModel(std::shared_ptr<mapnik::Map> map, QObject * parent)
: QAbstractItemModel(parent),
root_(new node(map_node(map)))
{
using style_type = std::map<std::string, mapnik::feature_type_style>;
style_type const& styles = map->styles();
using style_type = std::map<std::string,mapnik::feature_type_style>;
style_type const & styles = map->styles();
style_type::const_iterator itr = styles.begin();
style_type::const_iterator end = styles.end();
for (; itr != end; ++itr)
{
node* style_n = root_->add_child(new node(style_node(QString(itr->first.c_str()), itr->second), root_.get()));
node * style_n = root_->add_child(new node(style_node(QString(itr->first.c_str()),itr->second),root_.get()));
mapnik::rules const& rules = itr->second.get_rules();
mapnik::rules::const_iterator itr2 = rules.begin();
for (; itr2 != rules.end(); ++itr2)
for ( ; itr2 != rules.end();++itr2)
{
node* rule_n = style_n->add_child(new node(rule_node(QString("Rule"), *itr2), style_n));
node* rule_n = style_n->add_child(new node(rule_node(QString("Rule"),*itr2),style_n));
mapnik::rule::symbolizers::const_iterator itr3 = (*itr2).begin();
for (; itr3 != itr2->end(); ++itr3)
for ( ; itr3 !=itr2->end();++itr3)
{
rule_n->add_child(new node(symbolizer_node(*itr3), rule_n));
rule_n->add_child(new node(symbolizer_node(*itr3),rule_n));
}
}
}
@ -315,39 +351,38 @@ StyleModel::StyleModel(std::shared_ptr<mapnik::Map> map, QObject* parent)
StyleModel::~StyleModel() {}
// interface
QModelIndex StyleModel::index(int row, int col, QModelIndex const& parent) const
QModelIndex StyleModel::index (int row, int col, QModelIndex const& parent) const
{
// qDebug("index() row=%d col=%d parent::internalId() = %lld", row,col,parent.internalId());
node* parent_node;
// qDebug("index() row=%d col=%d parent::internalId() = %lld", row,col,parent.internalId());
node * parent_node;
if (!parent.isValid())
parent_node = root_.get();
else
parent_node = static_cast<node*>(parent.internalPointer());
node* child_node = parent_node->child(row);
node * child_node = parent_node->child(row);
if (child_node)
return createIndex(row, col, child_node);
return createIndex(row,col,child_node);
else
return QModelIndex();
}
QModelIndex StyleModel::parent(QModelIndex const& index) const
QModelIndex StyleModel::parent (QModelIndex const& index) const
{
node* child_node = static_cast<node*>(index.internalPointer());
node* parent_node = child_node->parent();
node * child_node = static_cast<node*>(index.internalPointer());
node * parent_node = child_node->parent();
if (parent_node == root_.get())
return QModelIndex();
return createIndex(parent_node->row(), 0, parent_node);
return createIndex(parent_node->row(),0,parent_node);
}
int StyleModel::rowCount(QModelIndex const& parent) const
{
// qDebug("rowCount");
node* parent_node;
if (parent.column() > 0)
return 0;
//qDebug("rowCount");
node * parent_node;
if (parent.column() > 0) return 0;
if (!parent.isValid())
parent_node = root_.get();
else
@ -355,24 +390,25 @@ int StyleModel::rowCount(QModelIndex const& parent) const
return parent_node->num_children();
}
int StyleModel::columnCount(QModelIndex const&) const
int StyleModel::columnCount( QModelIndex const&) const
{
return 1;
}
QVariant StyleModel::data(const QModelIndex& index, int role) const
QVariant StyleModel::data(const QModelIndex & index, int role) const
{
// qDebug("data index::internalId() = %lld", index.internalId());
//qDebug("data index::internalId() = %lld", index.internalId());
if (!index.isValid())
return QVariant();
node* cur_node = static_cast<node*>(index.internalPointer());
node * cur_node = static_cast<node*>(index.internalPointer());
if (cur_node)
{
if (role == Qt::DisplayRole)
{
return QVariant(cur_node->name());
}
else if (role == Qt::DecorationRole)
else if ( role == Qt::DecorationRole)
{
return cur_node->icon();
}

View file

@ -1,6 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
* Copyright (C) 2021 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef STYLE_MODEL_HPP
#define STYLE_MODEL_HPP
@ -26,23 +27,24 @@
#include <mapnik/map.hpp>
#endif
class node;
class StyleModel : public QAbstractItemModel
{
Q_OBJECT
Q_OBJECT
public:
StyleModel(std::shared_ptr<mapnik::Map> map, QObject* parent = 0);
~StyleModel();
// interface
QModelIndex index(int row, int col, QModelIndex const& parent = QModelIndex()) const;
QModelIndex parent(QModelIndex const& child) const;
int rowCount(QModelIndex const& parent = QModelIndex()) const;
int columnCount(QModelIndex const& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
private:
// std::shared_ptr<mapnik::Map> map_;
const std::unique_ptr<node> root_;
StyleModel(std::shared_ptr<mapnik::Map> map, QObject * parent=0);
~StyleModel();
// interface
QModelIndex index (int row, int col, QModelIndex const& parent = QModelIndex()) const;
QModelIndex parent (QModelIndex const& child) const;
int rowCount( QModelIndex const& parent = QModelIndex()) const;
int columnCount( QModelIndex const& parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
private:
//std::shared_ptr<mapnik::Map> map_;
const std::unique_ptr<node> root_;
};
#endif // STYLE_MODEL_HPP

View file

@ -3,12 +3,12 @@
######################################################################
TEMPLATE = app
QT += core gui widgets
LIBS += $$system(mapnik-config --libs --dep-libs)
QMAKE_CXX = $$system(mapnik-config --cxx)
QMAKE_LINK = $$system(mapnik-config --cxx)
QMAKE_CXXFLAGS += $$system(mapnik-config --cxxflags)
QMAKE_CXXFLAGS += $$system(mapnik-config --includes --dep-includes --defines)
QMAKE_LFLAGS += $$system(mapnik-config --ldflags)
QMAKE_LFLAGS += $$system(mapnik-config --libs)
QMAKE_LFLAGS += $$system(mapnik-config --ldflags --dep-libs)
# Input
CONFIG += qt debug_and_release

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