diff --git a/.travis.yml b/.travis.yml
index 6e3903def..210e9b780 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,10 +5,10 @@ compiler: clang
before_install:
- echo 'yes' | sudo add-apt-repository ppa:mapnik/boost
- sudo apt-get update -qq
- - sudo apt-get install -qq libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev
+ - sudo apt-get install -qq libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev
script:
- - ./configure DEMO=False BINDINGS='python' CPP_TESTS=False CAIRO=False INPUT_PLUGINS='' OPTIMIZATION=1 JOBS=2 FAST=True && make
+ - ./configure DEMO=False BINDINGS='python' CPP_TESTS=False CAIRO=False INPUT_PLUGINS='' OPTIMIZATION=1 FAST=True && JOBS=2 make
branches:
only:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33f5109e8..278204bb0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,9 +8,84 @@ For a complete change history, see the git log.
## Future
-- Changed scale_denominator C++ interface to take scale as first argument rather than map.
+- Added to python bindings: `has_tiff`, `has_png`, `has_webp`, `has_proj4`, `has_svg_renderer`, and `has_grid_renderer`
-- Added support for `background-image` in cairo_renderer (#1724)
+- Made it possible to disable compilation of `grid_renderer` with `./configure GRID_RENDERER=False` (#1962)
+
+- Added `webp` image encoding and decoding support (#1955)
+
+- Added `premultiplied` property on mapnik::image_32 / mapnik.Image to enable knowledge of premultiplied status of image buffer.
+
+- Added `scale-hsla` image-filter that allows scaling colors in HSL color space. RGB is converted to HSL (hue-saturation-lightness) and then each value (and the original alpha value) is stretched based on the specified scaling values. An example syntax is `scale-hsla(0,1,0,1,0,1,0,1)` which means no change because the full range will be kept (0 for lowest, 1 for highest). Other examples are: 1) `scale-hsla(0,0,0,1,0,1,0,1)` which would force all colors to be red in hue in the same way `scale-hsla(1,1,0,1,0,1,0,1)` would, 2) `scale-hsla(0,1,1,1,0,1,0,1)` which would cause all colors to become fully saturated, 3) `scale-hsla(0,1,1,1,0,1,.5,1)` which would force no colors to be any more transparent than half, and 4) `scale-hsla(0,1,1,1,0,1,0,.5)` which would force all colors to be at least half transparent. (#1954)
+
+## 2.2.0
+
+Released June 3rd, 2013
+
+(Packaged from 9231205)
+
+Summary: The 2.2.0 release is primarily a performance and stability release. The code line represents development in the master branch since the release of 2.1.0 in Aug 2012 and therefore includes nearly a year of bug-fixes and optimizations. Nearly 500 new tests have been added bring the total coverage to 925. Shapefile and PostGIS datasources have benefited from numerous stability fixes, 64 bit integer support has been added to support OSM data in the grid renderer and in attribute filtering, and many fixes have landed for higher quality output when using a custom `scale_factor` during rendering. Critical code paths have been optimized include raster rendering, xml map loading, string to number conversion, vector reprojection when using `epsg:4326` and `epsg:3857`, `hextree` encoding, halo rendering, and rendering when using a custom `gamma`. Mapnik 2.2 also compiles faster than previous releases in the 2.x series and drops several unneeded and hard to install dependencies making builds on OS X and Windows easier than any previous release.
+
+- Removed 3 depedencies without loosing any functionality: `ltdl`, `cairomm` and `libsigc++` (#1804,#806,#1681)
+
+- Added 64 bit integer support in expressions, feature ids, and the grid_renderer (#1661,#1662,#1662)
+
+- Added the ability to disable the need for various dependencies: `proj4`, `libpng`, `libtiff`, `libjpeg`
+
+- Added faster reprojection support between `epsg:3857` and `epsg:4326` (#1705,#1703,#1579)
+
+- Fixed concurrency problem when using cursors in postgis plugin (#1823,#1588)
+
+- Fixed postgres connection pool leaks when using `persist_connection=false` (#1764)
+
+- Fixed postgres connection key to respect highest value of `max_size` and `initial_size` for any layer in map (#1599)
+
+- Fixed potential crash in wkb parsing when postgis returns null geometry (#1843)
+
+- Fixed blurry rendering of image and SVG icons (#1316)
+
+- Added detection of invalid srs values when loading xml (#646)
+
+- Added support for specifying a base_path as a third, optional argument to load_xml
+
+- Removed muffling of projection errors while rendering (#646)
+
+- Improved logging system (https://github.com/mapnik/mapnik/wiki/Logging)
+
+- Added support for reading images from in memory streams (#1805)
+
+- Optimized halo rendering. When halo radius is < 1 new method will be used automatically (#1781)
+
+- Added `text-halo-rasterizer` property. Set to `fast` for lower quality but faster
+ halo rendering (#1298) which matched new default method when radius is < 1.
+
+- Added support in `shape`, `sqlite`, `geojson`, and `csv` plugin for handling non-latin characters in the paths to file-based resources (#1177)
+
+- Fixed rendering of markers when their size is greater than the specified `spacing` value (#1487)
+
+- Fixed handling of alpha premultiplication in image scaling (#1489)
+
+- Optimized rendering when a style with no symbolizers is encountered (#1517)
+
+- Optimized string handling and type conversion by removing `boost::to_lower`, `boost::trim`, and `boost::lexical_cast` usage (#1687,#1687,#1633)
+
+- Optimized alpha preserving `hextree` method for quantization of png images (#1629)
+
+- Faster rendering of rasters by reducing memory allocation of temporary buffers (#1516)
+
+- Fixed some raster reprojection artifacts (#1501)
+
+- Fixed raster alignment when width != height and raster is being scaled (#1748,#1622)
+
+- Added support for caching rasters for re-use during rendering when styling more than once per layer (#1543)
+
+- Improved compile speeds of the code - in some cases by up to 2x and removed need for freetype dependency when building code against mapnik (#1688, #1756)
+
+- Removed internal rule cache on `mapnik::Map` c++ object (#1723)
+
+- Improved the scaled rendering of various map features when using `scale_factor` > 1 (#1280,#1100,#1273,#1792,#1291,#1344,#1279,#1624,#1767,#1766)
+
+- Added C++ api for overriding scale_denominator to enable rendering at fixed scale (#1582)
- Added Layer `buffer-size` that can be used to override Map `buffer-size` to avoid
over-fetching of data that does not need to be buffered as much as other layers.
@@ -18,13 +93,49 @@ For a complete change history, see the git log.
previously undocumented parameter by the same name that impacted clipping extent and
was not needed (clipping padding should likely be a symbolizer level option) (#1566)
-- Fixed building symbolizer rendering to be fully sensitive to alpha (8b66128c892 / bc8ea1c5a7a)
+- Fixed potential file descriptor leaks in image readers when invalid images were encountered (#1783)
-- Added 64 bit integer support in the grid_renderer (#1662)
+- Fixed alpha handling in the `blur` and `invert` image filters (#1541)
+
+- Fixed error reporting in the python plugin (#1422)
+
+- Added the ability to run tests without installing with `make test-local`
+
+- Reduced library binary size by adding support for `-fvisibility-inlines-hidden` and `-fvisibility=hidden` (#1826,#1832)
+
+- Added `mapnik::map_request` class, a special object to allow passing mutable map objects to renderer (#1737)
+
+- Added the ability to use `boost::hash` on `mapnik::value` types (#1729)
+
+- Removed obsolete `geos` plugin (functionality replaced by `csv` plugin) and unmaintained `kismet` plugin (#1809,#1833)
+
+- Added new `mapnik-config` flags: `--all-flags`, `--defines`, `--git-describe`, `--includes`, `--dep-includes`, `--cxxflags`, `--cxx` (#1443)
+
+- Added support for unicode strings as arguments in python bindings (#163)
+
+- Added DebugSymbolizer which is able to render the otherwise invisible collision boxes (#1366)
+
+- Optimized rendering by reducing overhead of using `gamma` property (#1174)
+
+- Fixed rendering artifacts when using `polygon-gamma` or `line-gamma` equal to 0 (#761,#1763)
+
+- Fixed and optimized the display of excessive precision of some float data in labels (#430,#1697)
+
+- Removed the `bind` option for datasources (#1654)
+
+- Added ability to access style list from map by (name,obj) in python (#1725)
+
+- Added `is_solid` method to python mapnik.Image and mapnik.ImageView classes (#1728)
+
+- Changed scale_denominator C++ interface to take scale as first argument rather than map.
+
+- Added support for `background-image` in cairo_renderer (#1724)
+
+- Fixed building symbolizer rendering to be fully sensitive to alpha (8b66128c892 / bc8ea1c5a7a)
- `[attr]` now returns false if attr is an empty string (#1665)
-- Added 64 bit integer support in expressions and feature ids (#1661,#1662)
+- `[attr]!=null` now returns true if attr is not null (#1642)
- Added support for DBF `Logical` type: #1614
@@ -41,9 +152,7 @@ For a complete change history, see the git log.
- Added support for setting zlib `Z_FIXED` strategy with format string: `png:z=fixed`
-- Fixed handling of transparency level option in Octree-based PNG encoding (#1556)
-
-- Faster rendering of rasters by reducing memory allocation of temporary buffers (#1516)
+- Fixed handling of transparency level option in `octree` png encoding (#1556)
- Added ability to pass a pre-created collision detector to the cairo renderer (#1444)
@@ -59,6 +168,24 @@ For a complete change history, see the git log.
now the combined layer extents will be again respected: they will be clipped to the maximum-extent if possible
and only when back-projecting fails for all layers will the maximum-extent be used as a fallback (#1473)
+- Compile time flag called `PLUGIN_LINKING` to allow input datasource plugins to be statically linked with the mapnik library (#249)
+
+- Fixed `dasharray` rendering in cairo backend (#1740)
+
+- Fixed handling of `opacity` in svg rendering (#1744)
+
+- Fixed uneven rendering of markers along lines (#1693)
+
+- Fixed handling of extra bytes in some shapefile fields (#1605)
+
+- Fixed handling (finally) of null shapes and partially corrupt shapefiles (#1630,#1621)
+
+- Added ability to re-use `mapnik::image_32` and `mapnik::grid` by exposing a `clear` method (#1571)
+
+- Added support for writing RGB (no A) png images by using the format string of `png:t=0` (#1559)
+
+- Added experimental support for geometry simplification at symbolizer level (#1385)
+
## Mapnik 2.1.0
Released Aug 23, 2012
@@ -119,7 +246,7 @@ Released Aug 23, 2012
- Improved logging/debugging system with release logs and file redirection (https://github.com/mapnik/mapnik/wiki/Runtime-Logging) (#937 and partially #986, #467)
- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161)
-
+
- GDAL: respect nodata for paletted/colormapped images (#1160)
- PostGIS: Added a new option called `autodetect_key_field` (by default false) that if true will
@@ -175,7 +302,7 @@ Released Aug 3, 2012
- Fixed possible breakage registering plugins via python if a custom PREFIX or DESTDIR was used (e.g. macports/homebrew) (#1171)
-- Fixed memory leak in the case of proj >= 4.8 and a projection initialization error (#1173)
+- Fixed memory leak in the case of proj >= 4.8 and a projection initialization error (#1173)
## Mapnik 2.0.1
@@ -206,7 +333,7 @@ Released April 10, 2012
- Workaround for boost interprocess compile error with recent gcc versions (#950,#1001,#1082)
-- Fix possible memory corruption when using hextree mode for png color reduction (#1087)
+- Fix possible memory corruption when using `hextree` mode for png color reduction (#1087)
- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908)
@@ -386,14 +513,14 @@ Released March 23, 2010
- PNG: fixed png256 for large images and some improvements to reduce color corruptions ([#522](https://github.com/mapnik/mapnik/issues/522))
-- PNG: Added new quantization method for indexed png format using hextree with full support for alpha
+- PNG: Added new quantization method for indexed png format using `hextree` with full support for alpha
channel. Also new method has some optimizations for color gradients common when using elevation based
- rasters. By default old method using octree is used. (r1680, r1683, [#477](https://github.com/mapnik/mapnik/issues/477))
+ rasters. By default old method using `octree` is used. (r1680, r1683, [#477](https://github.com/mapnik/mapnik/issues/477))
- PNG: Added initial support for passing options to png writter like number of colors, transparency
support, quantization method and possibly other in future using type parameter. For example
"png8:c=128:t=1:m=h" limits palette to 128 colors, uses only binary transparency (0 - none,
- 1 - binary, 2 - full), and new method of quantization using hextree (h - hextree, o - octree).
+ 1 - binary, 2 - full), and new method of quantization using `hextree` (h - `hextree`, o - `octree`).
Existing type "png256" can be also written using "png8:c=256:m=o:t=2" (r1680, r1683, [#477](https://github.com/mapnik/mapnik/issues/477))
diff --git a/COPYING b/COPYING
index cfe59bcad..e5ab03e12 100644
--- a/COPYING
+++ b/COPYING
@@ -1,8 +1,8 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -10,7 +10,7 @@
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
-
+
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
@@ -111,8 +111,8 @@ modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
+
+ GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
@@ -146,7 +146,7 @@ such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
-
+
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
@@ -158,7 +158,7 @@ Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
-
+
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
@@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
-
+
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
@@ -267,7 +267,7 @@ Library will still fall under Section 6.)
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
-
+
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
@@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
-
+
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
@@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
-
+
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
@@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
-
+
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
@@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@@ -455,8 +455,8 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
- END OF TERMS AND CONDITIONS
-
+ END OF TERMS AND CONDITIONS
+
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
@@ -485,7 +485,7 @@ convey the exclusion of warranty; and each file should have at least the
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
diff --git a/INSTALL.md b/INSTALL.md
index f3b715d48..e7b2aeddd 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -7,7 +7,7 @@ To configure and build Mapnik do:
./configure
make
-NOTE: the above will not work on windows, rather see https://github.com/mapnik/mapnik/wiki/BuildingOnWindows
+NOTE: the above will not work on windows, rather see https://github.com/mapnik/mapnik/wiki/WindowsInstallation
Then to run the tests locally (without needing to install):
@@ -48,27 +48,33 @@ Mapnik Core depends on:
- regex (optionally built with icu regex support)
- program_options (optionally for mapnik command line programs)
* libicuuc >= 4.0 (ideally >= 4.2) - International Components for Unicode
- * libpng >= 1.2.x - PNG graphics
- * libjpeg - JPEG graphics
- * libtiff - TIFF graphics
* libz - Zlib compression
* libfreetype - Freetype2 for font support (Install requires freetype-config)
* libxml2 - XML parsing (Install requires xml2-config)
- * libproj - PROJ.4 projection library
+
+Mapnik Core optionally depends on:
+
+ * libpng >= 1.2.x - PNG graphics (Default enabled, if found)
+ * libjpeg - JPEG graphics (Default enabled, if found)
+ * libtiff - TIFF graphics (Default enabled, if found)
+ * libwebp - WEBP graphics (Default enabled, if found)
+ * libproj - PROJ.4 projection library (Default enabled, if found)
Mapnik Python bindings depend on:
* Python 2.5-2.7 or >= 3.2
* Boost python
-Note: Python3k is supported, see: https://github.com/mapnik/mapnik/wiki/Python3k
+Note: Python 3.x is supported, see: https://github.com/mapnik/mapnik/wiki/Python3k
-Optional dependencies:
+Additional optional dependencies:
- * Cairo - Graphics library for output formats like PDF, PS, and SVG
+ * Cairo >= 1.6.0 - Graphics library for output formats like PDF, PS, and SVG
- pkg-config - Required for building with cairo support
- pycairo - Python bindings for cairo
- * libpq - PostgreSQL libraries (For PostGIS plugin support)
+ * PostgreSQL (for PostGIS plugin support)
+ - libpq - PostreSQL libraries
+ - pg_config - PostgreSQL installation capabilities
* libgdal - GDAL/OGR input (For gdal and ogr plugin support)
* libsqlite3 - SQLite input (needs RTree support builtin) (sqlite plugin support)
* libocci - Oracle input plugin support
diff --git a/Makefile b/Makefile
index 87964840d..8c05035d5 100755
--- a/Makefile
+++ b/Makefile
@@ -5,16 +5,28 @@ ifeq ($(UNAME), Darwin)
else
endif
+OS:=$(shell uname -s)
+
+ifeq ($(JOBS),)
+ JOBS:=1
+ ifeq ($(OS),Linux)
+ JOBS:=$(shell grep -c ^processor /proc/cpuinfo)
+ endif
+ ifeq ($(OS),Darwin)
+ JOBS:=$(shell sysctl -n hw.ncpu)
+ endif
+endif
+
all: mapnik
install:
- @python scons/scons.py --config=cache --implicit-cache --max-drift=1 install
+ @python scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1 install
mapnik:
- @python scons/scons.py --config=cache --implicit-cache --max-drift=1
+ @python scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1
clean:
- @python scons/scons.py -c --config=cache --implicit-cache --max-drift=1
+ @python scons/scons.py -j$(JOBS) -c --config=cache --implicit-cache --max-drift=1
@if test -e ".sconsign.dblite"; then rm ".sconsign.dblite"; fi
@if test -e "config.log"; then rm "config.log"; fi
@if test -e ".sconf_temp/"; then rm -r ".sconf_temp/"; fi
@@ -34,7 +46,7 @@ rebuild:
make uninstall && make clean && time make && make install
uninstall:
- @python scons/scons.py --config=cache --implicit-cache --max-drift=1 uninstall
+ @python scons/scons.py -j$(JOBS) --config=cache --implicit-cache --max-drift=1 uninstall
test:
@ ./run_tests
@@ -42,6 +54,7 @@ test:
test-local:
@echo "*** Boostrapping local test environment..."
@export ${LINK_FIX}=`pwd`/src:${${LINK_FIX}} && \
+ export PATH=`pwd`/utils/mapnik-config/:${PATH} && \
export PYTHONPATH=`pwd`/bindings/python/:${PYTHONPATH} && \
export MAPNIK_FONT_DIRECTORY=`pwd`/fonts/dejavu-fonts-ttf-2.33/ttf/ && \
export MAPNIK_INPUT_PLUGINS_DIRECTORY=`pwd`/plugins/input/ && \
@@ -55,7 +68,7 @@ check: test-local
demo:
@echo "*** Running rundemo.cpp…"
- cd demo/c++; ./rundemo `mapnik-config --prefix`/lib/mapnik
+ cd demo/c++; ./rundemo `mapnik-config --prefix`
pep8:
# https://gist.github.com/1903033
diff --git a/README.md b/README.md
index 835152ff2..7ddca1790 100644
--- a/README.md
+++ b/README.md
@@ -27,4 +27,4 @@ See [INSTALL.md](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) for in
# License
-Mapnik software is free and is released under LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information.
+Mapnik software is free and is released under LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information.
diff --git a/SConstruct b/SConstruct
index ad51f5f9e..40b9ff277 100644
--- a/SConstruct
+++ b/SConstruct
@@ -22,6 +22,7 @@ import sys
import re
import platform
from glob import glob
+from copy import copy
from subprocess import Popen, PIPE
from SCons.SConf import SetCacheMode
import pickle
@@ -35,6 +36,12 @@ except:
LIBDIR_SCHEMA_DEFAULT='lib'
severities = ['debug', 'warn', 'error', 'none']
+DEFAULT_CC = "gcc"
+DEFAULT_CXX = "g++"
+if sys.platform == 'darwin':
+ DEFAULT_CC = "clang"
+ DEFAULT_CXX = "clang++"
+
py3 = None
# local file to hold custom user configuration variables
@@ -55,30 +62,29 @@ DEFAULT_LINK_PRIORITY = ['internal','other','frameworks','user','system']
pretty_dep_names = {
- 'ociei':'Oracle database library | configure with OCCI_LIBS & OCCI_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki//OCCI',
+ 'ociei':'Oracle database library | configure with OCCI_LIBS & OCCI_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/OCCI',
'gdal':'GDAL C++ library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki/GDAL',
- 'ogr':'OGR-enabled GDAL C++ Library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki//OGR',
- 'geos_c':'GEOS Simple Geometry Specification C Library | configured with GEOS_LIB & GEOS_INCLUDE | more info: https://github.com/mapnik/mapnik/wiki//GEOS',
+ 'ogr':'OGR-enabled GDAL C++ Library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki/OGR',
'cairo':'Cairo C library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'pycairo':'Python bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'proj':'Proj.4 C Projections library | configure with PROJ_LIBS & PROJ_INCLUDES | more info: http://trac.osgeo.org/proj/',
- 'pg':'Postgres C Library required for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki//PostGIS',
- 'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki//SQLite',
+ 'pg':'Postgres C Library required for PostGIS plugin | configure with pg_config program | more info: https://github.com/mapnik/mapnik/wiki/PostGIS',
+ 'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/SQLite',
'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES',
'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES',
'png':'PNG C library | configure with PNG_LIBS & PNG_INCLUDES',
+ 'webp':'WEBP C library | configure with WEBP_LIBS & WEBP_INCLUDES',
'icuuc':'ICU C++ library | configure with ICU_LIBS & ICU_INCLUDES or use ICU_LIB_NAME to specify custom lib name | more info: http://site.icu-project.org/',
- 'ltdl':'GNU Libtool | more info: http://www.gnu.org/software/libtool',
'z':'Z compression library | more info: http://www.zlib.net/',
'm':'Basic math library, part of C++ stlib',
'pkg-config':'pkg-config tool | more info: http://pkg-config.freedesktop.org',
'pg_config':'pg_config program | try setting PG_CONFIG SCons option',
'xml2-config':'xml2-config program | try setting XML2_CONFIG SCons option',
+ 'libxml2':'libxml2 library | try setting XML2_CONFIG SCons option to point to location of xml2-config program',
'gdal-config':'gdal-config program | try setting GDAL_CONFIG SCons option',
- 'geos-config':'geos-config program | try setting GEOS_CONFIG SCons option',
'freetype-config':'freetype-config program | try setting FREETYPE_CONFIG SCons option',
- 'osm':'more info: https://github.com/mapnik/mapnik/wiki//OsmPlugin',
- 'curl':'libcurl is required for the "osm" plugin - more info: https://github.com/mapnik/mapnik/wiki//OsmPlugin',
+ 'osm':'more info: https://github.com/mapnik/mapnik/wiki/OsmPlugin',
+ 'curl':'libcurl is required for the "osm" plugin - more info: https://github.com/mapnik/mapnik/wiki/OsmPlugin',
'boost_regex_icu':'libboost_regex built with optional ICU unicode support is needed for unicode regex support in mapnik.',
'sqlite_rtree':'The SQLite plugin requires libsqlite3 built with RTREE support (-DSQLITE_ENABLE_RTREE=1)',
'pgsql2sqlite_rtree':'The pgsql2sqlite program requires libsqlite3 built with RTREE support (-DSQLITE_ENABLE_RTREE=1)'
@@ -91,22 +97,20 @@ PLUGINS = { # plugins with external dependencies
'postgis': {'default':True,'path':None,'inc':'libpq-fe.h','lib':'pq','lang':'C'},
'gdal': {'default':True,'path':None,'inc':'gdal_priv.h','lib':'gdal','lang':'C++'},
'ogr': {'default':True,'path':None,'inc':'ogrsf_frmts.h','lib':'gdal','lang':'C++'},
- 'geos': {'default':False,'path':None,'inc':'geos_c.h','lib':'geos_c','lang':'C'},
# configured with custom paths, hence 'path': PREFIX/INCLUDES/LIBS
'occi': {'default':False,'path':'OCCI','inc':'occi.h','lib':'ociei','lang':'C++'},
'sqlite': {'default':True,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'},
'rasterlite': {'default':False,'path':'RASTERLITE','inc':['sqlite3.h','rasterlite.h'],'lib':'rasterlite','lang':'C'},
# todo: osm plugin does also depend on libxml2 (but there is a separate check for that)
- 'osm': {'default':True,'path':None,'inc':'curl/curl.h','lib':'curl','lang':'C'},
+ 'osm': {'default':False,'path':None,'inc':'curl/curl.h','lib':'curl','lang':'C'},
# plugins without external dependencies requiring CheckLibWithHeader...
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'csv': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'geojson': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
- 'kismet': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
- 'python': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
+ 'python': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
}
@@ -170,10 +174,14 @@ def shortest_name(libs):
name = lib
return name
+def rm_path(item,set,_env):
+ for i in _env[set]:
+ if item in i:
+ _env[set].remove(i)
def sort_paths(items,priority):
"""Sort paths such that compiling and linking will globally prefer custom or local libs
- over system libraries by fixing up the order libs are passed to gcc and the linker.
+ over system libraries by fixing up the order libs are passed to the compiler and the linker.
Ideally preference could be by-target instead of global, but our SCons implementation
is not currently utilizing different SCons build env()'s as we should.
@@ -243,7 +251,7 @@ def pretty_dep(dep):
if pretty:
return '%s (%s)' % (dep,pretty)
elif 'boost' in dep:
- return '%s (%s)' % (dep,'more info see: https://github.com/mapnik/mapnik/wiki//MapnikInstallation & http://www.boost.org')
+ return '%s (%s)' % (dep,'more info see: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation & http://www.boost.org')
return dep
@@ -258,14 +266,15 @@ opts = Variables()
opts.AddVariables(
# Compiler options
- ('CXX', 'The C++ compiler to use to compile mapnik (defaults to g++).', 'g++'),
- ('CC', 'The C compiler used for configure checks of C libs (defaults to gcc).', 'gcc'),
+ ('CXX', 'The C++ compiler to use to compile mapnik', DEFAULT_CXX),
+ ('CC', 'The C compiler used for configure checks of C libs.', DEFAULT_CC),
('CUSTOM_CXXFLAGS', 'Custom C++ flags, e.g. -I if you have headers in a nonstandard directory ', ''),
+ ('CUSTOM_DEFINES', 'Custom Compiler DEFINES, e.g. -DENABLE_THIS', ''),
('CUSTOM_CFLAGS', 'Custom C flags, e.g. -I if you have headers in a nonstandard directory (only used for configure checks)', ''),
('CUSTOM_LDFLAGS', 'Custom linker flags, e.g. -L if you have libraries in a nonstandard directory ', ''),
EnumVariable('LINKING', "Set library format for libmapnik",'shared', ['shared','static']),
EnumVariable('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']),
- EnumVariable('OPTIMIZATION','Set g++ optimization level','3', ['0','1','2','3','4','s']),
+ EnumVariable('OPTIMIZATION','Set compiler optimization level','3', ['0','1','2','3','4','s']),
# Note: setting DEBUG=True will override any custom OPTIMIZATION level
BoolVariable('DEBUG', 'Compile a debug version of Mapnik', 'False'),
BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'),
@@ -273,6 +282,7 @@ opts.AddVariables(
('WARNING_CXXFLAGS', 'Compiler flags you can set to reduce warning levels which are placed after -Wall.', ''),
# SCons build behavior options
+ ('HOST', 'Set the target host for cross compiling"', ''),
('CONFIG', "The path to the python file in which to save user configuration options. Currently : '%s'" % SCONS_LOCAL_CONFIG,SCONS_LOCAL_CONFIG),
BoolVariable('USE_CONFIG', "Use SCons user '%s' file (will also write variables after successful configuration)", 'True'),
# http://www.scons.org/wiki/GoFastButton
@@ -305,10 +315,8 @@ opts.AddVariables(
('XML2_CONFIG', 'The path to the xml2-config executable.', 'xml2-config'),
PathVariable('ICU_INCLUDES', 'Search path for ICU include files', '/usr/include', PathVariable.PathAccept),
PathVariable('ICU_LIBS','Search path for ICU include files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
- ('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc',
-PathVariable.PathAccept),
- PathVariable('LTDL_INCLUDES', 'Search path for libltdl (part of libtool) include files', '/usr/include', PathVariable.PathAccept),
- PathVariable('LTDL_LIBS','Search path for libltdl (ltdl.h) library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
+ ('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc', PathVariable.PathAccept),
+
BoolVariable('PNG', 'Build Mapnik with PNG read and write support', 'True'),
PathVariable('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include', PathVariable.PathAccept),
PathVariable('PNG_LIBS','Search path for libpng library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
@@ -318,6 +326,9 @@ PathVariable.PathAccept),
BoolVariable('TIFF', 'Build Mapnik with TIFF read and write support', 'True'),
PathVariable('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include', PathVariable.PathAccept),
PathVariable('TIFF_LIBS', 'Search path for libtiff library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
+ BoolVariable('WEBP', 'Build Mapnik with WEBP read', 'True'),
+ PathVariable('WEBP_INCLUDES', 'Search path for libwebp include files', '/usr/include', PathVariable.PathAccept),
+ PathVariable('WEBP_LIBS','Search path for libwebp library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
BoolVariable('PROJ', 'Build Mapnik with proj4 support to enable transformations between many different projections', 'True'),
PathVariable('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/include', PathVariable.PathAccept),
PathVariable('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
@@ -325,13 +336,12 @@ PathVariable.PathAccept),
# Variables affecting rendering back-ends
- BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'),
-
+ BoolVariable('GRID_RENDERER', 'build support for native grid renderer', 'True'),
BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'),
BoolVariable('CPP_TESTS', 'Compile the C++ tests', 'True'),
+ BoolVariable('BENCHMARK', 'Compile the C++ benchmark scripts', 'False'),
# Variables for optional dependencies
- ('GEOS_CONFIG', 'The path to the geos-config executable.', 'geos-config'),
# Note: cairo and and pycairo are optional but configured automatically through pkg-config
# Therefore, we use a single boolean for whether to attempt to build cairo support.
BoolVariable('CAIRO', 'Attempt to build with Cairo rendering support', 'True'),
@@ -349,7 +359,10 @@ PathVariable.PathAccept),
# Variables for logging and statistics
BoolVariable('ENABLE_LOG', 'Enable logging, which is enabled by default when building in *debug*', 'False'),
BoolVariable('ENABLE_STATS', 'Enable global statistics during map processing', 'False'),
- ('DEFAULT_LOG_SEVERITY', 'The default severity of the logger (eg. ' + ', '.join(severities), 'error'),
+ ('DEFAULT_LOG_SEVERITY', 'The default severity of the logger (eg. ' + ', '.join(severities) + ')', 'error'),
+
+ # Plugin linking
+ EnumVariable('PLUGIN_LINKING', "Set plugin linking with libmapnik", 'shared', ['shared','static']),
# Other variables
BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'),
@@ -366,6 +379,8 @@ PathVariable.PathAccept),
('JOBS', 'Set the number of parallel compilations', "1", lambda key, value, env: int(value), int),
BoolVariable('DEMO', 'Compile demo c++ application', 'True'),
BoolVariable('PGSQL2SQLITE', 'Compile and install a utility to convert postgres tables to sqlite', 'False'),
+ BoolVariable('SHAPEINDEX', 'Compile and install a utility to generate shapefile indexes in the custom format (.index) Mapnik supports', 'True'),
+ BoolVariable('SVG2PNG', 'Compile and install a utility to generate render an svg file to a png on the command line', 'False'),
BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'),
BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'),
BoolVariable('BIGINT', 'Compile support for 64-bit integers in mapnik::value', 'True'),
@@ -386,6 +401,7 @@ pickle_store = [# Scons internal variables
'LIBS',
'LINKFLAGS',
'CUSTOM_LDFLAGS', # user submitted
+ 'CUSTOM_DEFINES', # user submitted
'CUSTOM_CXXFLAGS', # user submitted
'CUSTOM_CFLAGS', # user submitted
'MAPNIK_LIB_NAME',
@@ -395,6 +411,7 @@ pickle_store = [# Scons internal variables
'PLUGINS',
'ABI_VERSION',
'MAPNIK_VERSION_STRING',
+ 'MAPNIK_VERSION',
'PLATFORM',
'BOOST_ABI',
'BOOST_APPEND',
@@ -426,14 +443,17 @@ pickle_store = [# Scons internal variables
'MAPNIK_LIB_BASE_DEST',
'EXTRA_FREETYPE_LIBS',
'LIBMAPNIK_CPPATHS',
+ 'LIBMAPNIK_DEFINES',
'LIBMAPNIK_CXXFLAGS',
'CAIRO_LIBPATHS',
- 'CAIRO_LINKFLAGS',
+ 'CAIRO_ALL_LIBS',
'CAIRO_CPPPATHS',
+ 'GRID_RENDERER',
'SVG_RENDERER',
'SQLITE_LINKFLAGS',
'BOOST_LIB_VERSION_FROM_HEADER',
- 'BIGINT'
+ 'BIGINT',
+ 'HOST'
]
# Add all other user configurable options to pickle pickle_store
@@ -454,7 +474,7 @@ HELP_REQUESTED = False
if ('-h' in command_line_args) or ('--help' in command_line_args):
HELP_REQUESTED = True
-if ('-c' in command_line_args) or ('--clean' in command_line_args):
+if ('install' not in command_line_args) and ('-c' in command_line_args) or ('--clean' in command_line_args):
HELP_REQUESTED = True
if 'configure' in command_line_args and not HELP_REQUESTED:
@@ -546,7 +566,7 @@ def parse_config(context, config, checks='--libs --cflags'):
env = context.env
tool = config.lower().replace('_','-')
toolname = tool
- if config in ('GDAL_CONFIG','GEOS_CONFIG'):
+ if config in ('GDAL_CONFIG'):
toolname += ' %s' % checks
context.Message( 'Checking for %s... ' % toolname)
cmd = '%s %s' % (env[config],checks)
@@ -575,7 +595,7 @@ def parse_config(context, config, checks='--libs --cflags'):
ret = False
print ' (xml2-config not found!)'
if not parsed:
- if config in ('GDAL_CONFIG','GEOS_CONFIG'):
+ if config in ('GDAL_CONFIG'):
# optional deps...
env['SKIPPED_DEPS'].append(tool)
conf.rollback_option(config)
@@ -657,15 +677,16 @@ def update_linux_project_files():
]
def iterate_dirs(headers_content, source_content, d):
- for root, subFolders, files in os.walk(d):
- for f in files:
- if f.endswith(".h") or f.endswith(".hpp"):
- headers_content.append(" ../%s \\" % os.path.join(root, f))
- if f.endswith(".cpp") or f.endswith(".c"):
- source_content.append(" ../%s \\" % os.path.join(root, f))
- for sd in subFolders:
- headers_content, source_content = \
- iterate_dirs(headers_content, source_content, sd)
+ if not "uninstall-" in d:
+ for root, subFolders, files in os.walk(d):
+ for f in files:
+ if f.endswith(".h") or f.endswith(".hpp"):
+ headers_content.append(" ../%s \\" % os.path.join(root, f))
+ if f.endswith(".cpp") or f.endswith(".c"):
+ source_content.append(" ../%s \\" % os.path.join(root, f))
+ for sd in subFolders:
+ headers_content, source_content = \
+ iterate_dirs(headers_content, source_content, os.path.join(root, sd))
return headers_content, source_content
for d in directories:
@@ -722,25 +743,23 @@ def FindBoost(context, prefixes, thread_flag):
msg = str()
if BOOST_LIB_DIR:
- msg += '\n *libs found: %s' % BOOST_LIB_DIR
+ msg += '\nFound boost libs: %s' % BOOST_LIB_DIR
env['BOOST_LIBS'] = BOOST_LIB_DIR
else:
env['BOOST_LIBS'] = '/usr/' + env['LIBDIR_SCHEMA']
- msg += '\n *using default boost lib dir: %s' % env['BOOST_LIBS']
+ msg += '\nUsing default boost lib dir: %s' % env['BOOST_LIBS']
if BOOST_INCLUDE_DIR:
- msg += '\n *headers found: %s' % BOOST_INCLUDE_DIR
+ msg += '\nFound boost headers: %s' % BOOST_INCLUDE_DIR
env['BOOST_INCLUDES'] = BOOST_INCLUDE_DIR
else:
env['BOOST_INCLUDES'] = '/usr/include'
- msg += '\n *using default boost include dir: %s' % env['BOOST_INCLUDES']
+ msg += '\nUsing default boost include dir: %s' % env['BOOST_INCLUDES']
if not env['BOOST_TOOLKIT'] and not env['BOOST_ABI'] and not env['BOOST_VERSION']:
if BOOST_APPEND:
- msg += '\n *lib naming extension found: %s' % BOOST_APPEND
+ msg += '\nFound boost lib name extension: %s' % BOOST_APPEND
env['BOOST_APPEND'] = BOOST_APPEND
- else:
- msg += '\n *no lib naming extension found'
else:
# Creating BOOST_APPEND according to the Boost library naming order,
# which goes ---. See:
@@ -755,7 +774,7 @@ def FindBoost(context, prefixes, thread_flag):
# Boost libraries.
if len(append_params) > 1:
env['BOOST_APPEND'] = '-'.join(append_params)
- msg += '\n *using boost lib naming: %s' % env['BOOST_APPEND']
+ msg += '\nFound boost lib name extension: %s' % env['BOOST_APPEND']
env.AppendUnique(CPPPATH = os.path.realpath(env['BOOST_INCLUDES']))
env.AppendUnique(LIBPATH = os.path.realpath(env['BOOST_LIBS']))
@@ -792,6 +811,32 @@ int main()
context.Result(ret)
return ret
+def CheckCairoHasFreetype(context, silent=False):
+ if not silent:
+ context.Message('Checking for cairo freetype font support ... ')
+ context.env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS']))
+
+ ret = context.TryRun("""
+
+#include
+
+int main()
+{
+ #ifdef CAIRO_HAS_FT_FONT
+ return 0;
+ #else
+ return 1;
+ #endif
+}
+
+""", '.cpp')[0]
+ if silent:
+ context.did_show_result=1
+ context.Result(ret)
+ for item in env['CAIRO_CPPPATHS']:
+ rm_path(item,'CPPPATH',context.env)
+ return ret
+
def GetBoostLibVersion(context):
ret = context.TryRun("""
@@ -862,8 +907,7 @@ int main()
def boost_regex_has_icu(context):
if env['RUNTIME_LINK'] == 'static':
- context.env.Append(LIBS='icui18n')
- context.env.Append(LIBS='icudata')
+ context.env.AppendUnique(LIBS='icudata')
ret = context.TryRun("""
#include
@@ -890,7 +934,7 @@ int main()
return True
return False
-def sqlite_has_rtree(context):
+def sqlite_has_rtree(context, silent=False):
""" check an sqlite3 install has rtree support.
PRAGMA compile_options;
@@ -927,7 +971,10 @@ int main()
}
""", '.c')
- context.Message('Checking if SQLite supports RTREE... ')
+ if not silent:
+ context.Message('Checking if SQLite supports RTREE... ')
+ if silent:
+ context.did_show_result=1
context.Result(ret[0])
if ret[0]:
return True
@@ -939,6 +986,7 @@ conf_tests = { 'prioritize_paths' : prioritize_paths,
'CheckPKGVersion' : CheckPKGVersion,
'FindBoost' : FindBoost,
'CheckBoost' : CheckBoost,
+ 'CheckCairoHasFreetype' : CheckCairoHasFreetype,
'GetBoostLibVersion' : GetBoostLibVersion,
'GetMapnikLibVersion' : GetMapnikLibVersion,
'parse_config' : parse_config,
@@ -1000,12 +1048,14 @@ if not preconfigured:
env['SKIPPED_DEPS'] = []
env['HAS_CAIRO'] = False
env['CAIRO_LIBPATHS'] = []
- env['CAIRO_LINKFLAGS'] = []
+ env['CAIRO_ALL_LIBS'] = []
env['CAIRO_CPPPATHS'] = []
env['HAS_PYCAIRO'] = False
env['HAS_LIBXML2'] = False
env['LIBMAPNIK_LIBS'] = []
+ env['LIBMAPNIK_LINKFLAGS'] = []
env['LIBMAPNIK_CPPATHS'] = []
+ env['LIBMAPNIK_DEFINES'] = []
env['LIBMAPNIK_CXXFLAGS'] = []
env['PLUGINS'] = PLUGINS
env['EXTRA_FREETYPE_LIBS'] = []
@@ -1065,6 +1115,7 @@ if not preconfigured:
env['LIBPATH'] = ['#src']
# set any custom cxxflags and ldflags to come first
+ env.Append(CPPDEFINES = env['CUSTOM_DEFINES'])
env.Append(CXXFLAGS = env['CUSTOM_CXXFLAGS'])
env.Append(CFLAGS = env['CUSTOM_CFLAGS'])
env.Append(LINKFLAGS = env['CUSTOM_LDFLAGS'])
@@ -1081,7 +1132,7 @@ if not preconfigured:
SOLARIS = env['PLATFORM'] == 'SunOS'
env['SUNCC'] = SOLARIS and env['CXX'].startswith('CC')
- # If the Sun Studio C++ compiler (`CC`) is used instead of GCC.
+ # If the Sun Studio C++ compiler (`CC`) is used instead of gcc.
if env['SUNCC']:
env['CC'] = 'cc'
# To be compatible w/Boost everything needs to be compiled
@@ -1098,15 +1149,15 @@ if not preconfigured:
# http://www.opensource.apple.com/tarballs/ICU/
# then copy the headers to a location that mapnik will find
if 'core' in env['ICU_LIB_NAME']:
- env.Append(CXXFLAGS = '-DU_HIDE_DRAFT_API')
- env.Append(CXXFLAGS = '-DUDISABLE_RENAMING')
+ env.Append(CPPDEFINES = '-DU_HIDE_DRAFT_API')
+ env.Append(CPPDEFINES = '-DUDISABLE_RENAMING')
if os.path.exists(env['ICU_LIB_NAME']):
#-sICU_LINK=" -L/usr/lib -licucore
env['ICU_LIB_NAME'] = os.path.basename(env['ICU_LIB_NAME']).replace('.dylib','').replace('lib','')
# Adding the required prerequisite library directories to the include path for
# compiling and the library path for linking, respectively.
- for required in ('ICU', 'SQLITE', 'LTDL'):
+ for required in ('ICU', 'SQLITE'):
inc_path = env['%s_INCLUDES' % required]
lib_path = env['%s_LIBS' % required]
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@@ -1128,16 +1179,18 @@ if not preconfigured:
# https://github.com/mapnik/mapnik/issues/913
if conf.parse_config('XML2_CONFIG',checks='--cflags'):
env['HAS_LIBXML2'] = True
+ else:
+ env['MISSING_DEPS'].append('libxml2')
- LIBSHEADERS = [
+ REQUIRED_LIBSHEADERS = [
['z', 'zlib.h', True,'C'],
- ['ltdl', 'ltdl.h', True,'C'],
[env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'],
]
+ OPTIONAL_LIBSHEADERS = []
+
if env['JPEG']:
- env.Append(CXXFLAGS = '-DHAVE_JPEG')
- LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], True,'C'])
+ OPTIONAL_LIBSHEADERS.append(['jpeg', ['stdio.h', 'jpeglib.h'], False,'C','-DHAVE_JPEG'])
inc_path = env['%s_INCLUDES' % 'JPEG']
lib_path = env['%s_LIBS' % 'JPEG']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@@ -1146,8 +1199,7 @@ if not preconfigured:
env['SKIPPED_DEPS'].extend(['jpeg'])
if env['PROJ']:
- env.Append(CXXFLAGS = '-DMAPNIK_USE_PROJ4')
- LIBSHEADERS.append(['proj', 'proj_api.h', True,'C'])
+ OPTIONAL_LIBSHEADERS.append(['proj', 'proj_api.h', False,'C','-DMAPNIK_USE_PROJ4'])
inc_path = env['%s_INCLUDES' % 'PROJ']
lib_path = env['%s_LIBS' % 'PROJ']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@@ -1156,8 +1208,7 @@ if not preconfigured:
env['SKIPPED_DEPS'].extend(['proj'])
if env['PNG']:
- env.Append(CXXFLAGS = '-DHAVE_PNG')
- LIBSHEADERS.append(['png', 'png.h', True,'C'])
+ OPTIONAL_LIBSHEADERS.append(['png', 'png.h', False,'C','-DHAVE_PNG'])
inc_path = env['%s_INCLUDES' % 'PNG']
lib_path = env['%s_LIBS' % 'PNG']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@@ -1165,9 +1216,17 @@ if not preconfigured:
else:
env['SKIPPED_DEPS'].extend(['png'])
+ if env['WEBP']:
+ OPTIONAL_LIBSHEADERS.append(['webp', 'webp/decode.h', False,'C','-DHAVE_WEBP'])
+ inc_path = env['%s_INCLUDES' % 'WEBP']
+ lib_path = env['%s_LIBS' % 'WEBP']
+ env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
+ env.AppendUnique(LIBPATH = os.path.realpath(lib_path))
+ else:
+ env['SKIPPED_DEPS'].extend(['webp'])
+
if env['TIFF']:
- env.Append(CXXFLAGS = '-DHAVE_TIFF')
- LIBSHEADERS.append(['tiff', 'tiff.h', True,'C'])
+ OPTIONAL_LIBSHEADERS.append(['tiff', 'tiff.h', False,'C','-DHAVE_TIFF'])
inc_path = env['%s_INCLUDES' % 'TIFF']
lib_path = env['%s_LIBS' % 'TIFF']
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@@ -1177,24 +1236,26 @@ if not preconfigured:
# if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
if env['PRIORITIZE_LINKING']:
- conf.prioritize_paths(silent=False)
+ conf.prioritize_paths(silent=True)
- for libname, headers, required, lang in LIBSHEADERS:
- if not conf.CheckLibWithHeader(libname, headers, lang):
- if required:
- color_print(1, 'Could not find required header or shared library for %s' % libname)
- env['MISSING_DEPS'].append(libname)
- else:
- color_print(4, 'Could not find optional header or shared library for %s' % libname)
- env['SKIPPED_DEPS'].append(libname)
+ if not env['HOST']:
+ for libname, headers, required, lang in REQUIRED_LIBSHEADERS:
+ if not conf.CheckLibWithHeader(libname, headers, lang):
+ if required:
+ color_print(1, 'Could not find required header or shared library for %s' % libname)
+ env['MISSING_DEPS'].append(libname)
+ else:
+ color_print(4, 'Could not find optional header or shared library for %s' % libname)
+ env['SKIPPED_DEPS'].append(libname)
- if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
- if not conf.icu_at_least_four_two():
- # expression_string.cpp and map.cpp use fromUTF* function only available in >= ICU 4.2
- env['MISSING_DEPS'].append(env['ICU_LIB_NAME'])
+ if not env['HOST']:
+ if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
+ if not conf.icu_at_least_four_two():
+ # expression_string.cpp and map.cpp use fromUTF* function only available in >= ICU 4.2
+ env['MISSING_DEPS'].append(env['ICU_LIB_NAME'])
if env['BIGINT']:
- env.Append(CXXFLAGS = '-DBIGINT')
+ env.Append(CPPDEFINES = '-DBIGINT')
if env['THREADING'] == 'multi':
thread_flag = thread_suffix
@@ -1203,137 +1264,172 @@ if not preconfigured:
conf.FindBoost(BOOST_SEARCH_PREFIXES,thread_flag)
- env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion()
+ has_boost_devel = True
+ if not env['HOST']:
+ if not conf.CheckHeader(header='boost/version.hpp',language='C++'):
+ env['MISSING_DEPS'].append('boost development headers')
+ has_boost_devel = False
- # The other required boost headers.
- BOOST_LIBSHEADERS = [
- ['system', 'boost/system/system_error.hpp', True],
- ['filesystem', 'boost/filesystem/operations.hpp', True],
- ['regex', 'boost/regex.hpp', True],
- ['program_options', 'boost/program_options.hpp', False]
- ]
+ if has_boost_devel:
+ if not env['HOST']:
+ env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion()
- if env['THREADING'] == 'multi':
- BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True])
- # on solaris the configure checks for boost_thread
- # require the -pthreads flag to be able to check for
- # threading support, so we add as a global library instead
- # of attaching to cxxflags after configure
- if env['PLATFORM'] == 'SunOS':
- env.Append(CXXFLAGS = '-pthreads')
+ # The other required boost headers.
+ BOOST_LIBSHEADERS = [
+ ['system', 'boost/system/system_error.hpp', True],
+ ['filesystem', 'boost/filesystem/operations.hpp', True],
+ ['regex', 'boost/regex.hpp', True],
+ ['program_options', 'boost/program_options.hpp', False]
+ ]
- # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
- if env['PRIORITIZE_LINKING']:
- conf.prioritize_paths()
+ if env['THREADING'] == 'multi':
+ BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True])
+ # on solaris the configure checks for boost_thread
+ # require the -pthreads flag to be able to check for
+ # threading support, so we add as a global library instead
+ # of attaching to cxxflags after configure
+ if env['PLATFORM'] == 'SunOS':
+ env.Append(CXXFLAGS = '-pthreads')
- # if the user is not setting custom boost configuration
- # enforce boost version greater than or equal to BOOST_MIN_VERSION
- if not conf.CheckBoost(BOOST_MIN_VERSION):
- color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
- color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION)
- if not env['BOOST_VERSION']:
- env['MISSING_DEPS'].append('boost version >=%s' % BOOST_MIN_VERSION)
- else:
- color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
+ # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests
+ if env['PRIORITIZE_LINKING']:
+ conf.prioritize_paths(silent=True)
- for count, libinfo in enumerate(BOOST_LIBSHEADERS):
- if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'):
- if libinfo[2]:
- color_print(1,'Could not find required header or shared library for boost %s' % libinfo[0])
- env['MISSING_DEPS'].append('boost ' + libinfo[0])
+ if not env['HOST']:
+ # if the user is not setting custom boost configuration
+ # enforce boost version greater than or equal to BOOST_MIN_VERSION
+ if not conf.CheckBoost(BOOST_MIN_VERSION):
+ color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
+ color_print(1,'Boost version %s or greater is required' % BOOST_MIN_VERSION)
+ if not env['BOOST_VERSION']:
+ env['MISSING_DEPS'].append('boost version >= %s' % BOOST_MIN_VERSION)
else:
- color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0])
- env['SKIPPED_DEPS'].append('boost ' + libinfo[0])
+ color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
- if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
+ if not env['HOST']:
+ for count, libinfo in enumerate(BOOST_LIBSHEADERS):
+ if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'):
+ if libinfo[2]:
+ color_print(1,'Could not find required header or shared library for boost %s' % libinfo[0])
+ env['MISSING_DEPS'].append('boost ' + libinfo[0])
+ else:
+ color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0])
+ env['SKIPPED_DEPS'].append('boost ' + libinfo[0])
+
+ if not env['HOST'] and env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
# http://lists.boost.org/Archives/boost/2009/03/150076.php
+ # we need libicui18n if using static boost libraries, so it is
+ # important to try this check with the library linked
+ env.AppendUnique(LIBS='icui18n')
if conf.boost_regex_has_icu():
# TODO - should avoid having this be globally defined...
- env.Append(CXXFLAGS = '-DBOOST_REGEX_HAS_ICU')
+ env.Append(CPPDEFINES = '-DBOOST_REGEX_HAS_ICU')
else:
env['SKIPPED_DEPS'].append('boost_regex_icu')
+ if not env['HOST']:
+ for libname, headers, required, lang, define in OPTIONAL_LIBSHEADERS:
+ if not conf.CheckLibWithHeader(libname, headers, lang):
+ if required:
+ color_print(1, 'Could not find required header or shared library for %s' % libname)
+ env['MISSING_DEPS'].append(libname)
+ else:
+ color_print(4, 'Could not find optional header or shared library for %s' % libname)
+ env['SKIPPED_DEPS'].append(libname)
+ else:
+ env.Append(CPPDEFINES = define)
+ else:
+ env.Append(CPPDEFINES = define)
+
env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])]
+ SQLITE_HAS_RTREE = None
+ if env['HOST']:
+ SQLITE_HAS_RTREE = True
+
+ CHECK_PKG_CONFIG = conf.CheckPKGConfig('0.15.0')
+
if len(env['REQUESTED_PLUGINS']):
- color_print(4,'Checking for requested plugins dependencies...')
- for plugin in env['REQUESTED_PLUGINS']:
- details = env['PLUGINS'][plugin]
- if plugin == 'gdal':
- if conf.parse_config('GDAL_CONFIG',checks='--libs'):
- conf.parse_config('GDAL_CONFIG',checks='--cflags')
- libname = conf.get_pkg_lib('GDAL_CONFIG','gdal')
- if libname:
- details['lib'] = libname
- elif plugin == 'postgis':
- conf.parse_pg_config('PG_CONFIG')
- elif plugin == 'ogr':
- if conf.ogr_enabled():
- if not 'gdal' in env['REQUESTED_PLUGINS']:
- conf.parse_config('GDAL_CONFIG',checks='--libs')
+ if env['HOST']:
+ for plugin in env['REQUESTED_PLUGINS']:
+ details = env['PLUGINS'][plugin]
+ if details['lib']:
+ env.AppendUnique(LIBS=details['lib'])
+ else:
+ color_print(4,'Checking for requested plugins dependencies...')
+ for plugin in env['REQUESTED_PLUGINS']:
+ details = env['PLUGINS'][plugin]
+ if plugin == 'gdal':
+ if conf.parse_config('GDAL_CONFIG',checks='--libs'):
conf.parse_config('GDAL_CONFIG',checks='--cflags')
- libname = conf.get_pkg_lib('GDAL_CONFIG','ogr')
- if libname:
- details['lib'] = libname
- elif plugin == 'geos':
- if conf.parse_config('GEOS_CONFIG',checks='--ldflags --cflags'):
- lgeos_c = env['PLUGINS']['geos']['lib']
- env.Append(LIBS = lgeos_c)
+ libname = conf.get_pkg_lib('GDAL_CONFIG','gdal')
+ if libname:
+ details['lib'] = libname
+ elif plugin == 'postgis':
+ conf.parse_pg_config('PG_CONFIG')
+ elif plugin == 'ogr':
+ if conf.ogr_enabled():
+ if not 'gdal' in env['REQUESTED_PLUGINS']:
+ conf.parse_config('GDAL_CONFIG',checks='--libs')
+ conf.parse_config('GDAL_CONFIG',checks='--cflags')
+ libname = conf.get_pkg_lib('GDAL_CONFIG','ogr')
+ if libname:
+ details['lib'] = libname
+ elif details['path'] and details['lib'] and details['inc']:
+ backup = env.Clone().Dictionary()
+ # Note, the 'delete_existing' keyword makes sure that these paths are prepended
+ # to the beginning of the path list even if they already exist
+ incpath = env['%s_INCLUDES' % details['path']]
+ libpath = env['%s_LIBS' % details['path']]
+ env.PrependUnique(CPPPATH = os.path.realpath(incpath),delete_existing=True)
+ env.PrependUnique(LIBPATH = os.path.realpath(libpath),delete_existing=True)
+ if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
+ env.Replace(**backup)
+ env['SKIPPED_DEPS'].append(details['lib'])
+ if plugin == 'sqlite':
+ SQLITE_HAS_RTREE = conf.sqlite_has_rtree()
+ sqlite_backup = env.Clone().Dictionary()
+ # if statically linking, on linux we likely
+ # need to link sqlite to pthreads and dl
+ if env['RUNTIME_LINK'] == 'static':
+ if CHECK_PKG_CONFIG and conf.CheckPKG('sqlite3'):
+ sqlite_env = env.Clone()
+ try:
+ sqlite_env.ParseConfig('pkg-config --static --libs sqlite3')
+ for lib in sqlite_env['LIBS']:
+ if not lib in env['LIBS']:
+ env["SQLITE_LINKFLAGS"].append(lib)
+ env.Append(LIBS=lib)
+ except OSError,e:
+ pass
+ if SQLITE_HAS_RTREE is None:
+ SQLITE_HAS_RTREE = conf.sqlite_has_rtree()
+ if not SQLITE_HAS_RTREE:
+ env.Replace(**sqlite_backup)
+ if details['lib'] in env['LIBS']:
+ env['LIBS'].remove(details['lib'])
+ env['SKIPPED_DEPS'].append('sqlite_rtree')
+ else:
+ env.Replace(**sqlite_backup)
+ elif details['lib'] and details['inc']:
+ if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
+ env['SKIPPED_DEPS'].append(details['lib'])
- elif details['path'] and details['lib'] and details['inc']:
- backup = env.Clone().Dictionary()
- # Note, the 'delete_existing' keyword makes sure that these paths are prepended
- # to the beginning of the path list even if they already exist
- incpath = env['%s_INCLUDES' % details['path']]
- libpath = env['%s_LIBS' % details['path']]
- env.PrependUnique(CPPPATH = os.path.realpath(incpath),delete_existing=True)
- env.PrependUnique(LIBPATH = os.path.realpath(libpath),delete_existing=True)
- if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
- env.Replace(**backup)
- env['SKIPPED_DEPS'].append(details['lib'])
- if plugin == 'sqlite':
- sqlite_backup = env.Clone().Dictionary()
+ # re-append the local paths for mapnik sources to the beginning of the list
+ # to make sure they come before any plugins that were 'prepended'
+ env.PrependUnique(CPPPATH = '#include', delete_existing=True)
+ env.PrependUnique(CPPPATH = '#', delete_existing=True)
+ env.PrependUnique(LIBPATH = '#src', delete_existing=True)
- # if statically linking, on linux we likely
- # need to link sqlite to pthreads and dl
- if env['RUNTIME_LINK'] == 'static':
- if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('sqlite3'):
- sqlite_env = env.Clone()
- try:
- sqlite_env.ParseConfig('pkg-config --static --libs sqlite3')
- for lib in sqlite_env['LIBS']:
- if not lib in env['LIBS']:
- env["SQLITE_LINKFLAGS"].append(lib)
- env.Append(LIBS=lib)
- except OSError,e:
- pass
-
- if not conf.sqlite_has_rtree():
- env.Replace(**sqlite_backup)
- if details['lib'] in env['LIBS']:
- env['LIBS'].remove(details['lib'])
- env['SKIPPED_DEPS'].append('sqlite_rtree')
- else:
- env.Replace(**sqlite_backup)
-
- elif details['lib'] and details['inc']:
- if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
- env['SKIPPED_DEPS'].append(details['lib'])
-
- # re-append the local paths for mapnik sources to the beginning of the list
- # to make sure they come before any plugins that were 'prepended'
- env.PrependUnique(CPPPATH = '#include', delete_existing=True)
- env.PrependUnique(CPPPATH = '#', delete_existing=True)
- env.PrependUnique(LIBPATH = '#src', delete_existing=True)
-
- if env['PGSQL2SQLITE']:
- if 'sqlite3' not in env['LIBS']:
- env.AppendUnique(LIBS='sqlite3')
- env.AppendUnique(CPPPATH = os.path.realpath(env['SQLITE_INCLUDES']))
- env.AppendUnique(LIBPATH = os.path.realpath(env['SQLITE_LIBS']))
- if not conf.sqlite_has_rtree():
- env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree')
- env['PGSQL2SQLITE'] = False
+ if not env['HOST']:
+ if env['PGSQL2SQLITE']:
+ if 'sqlite3' not in env['LIBS']:
+ env.AppendUnique(LIBS='sqlite3')
+ env.AppendUnique(CPPPATH = os.path.realpath(env['SQLITE_INCLUDES']))
+ env.AppendUnique(LIBPATH = os.path.realpath(env['SQLITE_LIBS']))
+ if not SQLITE_HAS_RTREE:
+ env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree')
+ env['PGSQL2SQLITE'] = False
# we rely on an internal, patched copy of agg with critical fixes
# prepend to make sure we link locally
@@ -1362,15 +1458,15 @@ if not preconfigured:
#os.path.join(c_inc,'include/libpng'),
]
)
- env["CAIRO_LINKFLAGS"] = ['cairo']
+ env["CAIRO_ALL_LIBS"] = ['cairo']
if env['RUNTIME_LINK'] == 'static':
- env["CAIRO_LINKFLAGS"].extend(
- ['pixman-1','expat','fontconfig','iconv']
+ env["CAIRO_ALL_LIBS"].extend(
+ ['pixman-1','expat','fontconfig']
)
# todo - run actual checkLib?
env['HAS_CAIRO'] = True
else:
- if not conf.CheckPKGConfig('0.15.0'):
+ if not CHECK_PKG_CONFIG:
env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('pkg-config')
env['SKIPPED_DEPS'].append('cairo')
@@ -1387,7 +1483,7 @@ if not preconfigured:
cairo_env.ParseConfig(cmd)
for lib in cairo_env['LIBS']:
if not lib in env['LIBS']:
- env["CAIRO_LINKFLAGS"].append(lib)
+ env["CAIRO_ALL_LIBS"].append(lib)
for lpath in cairo_env['LIBPATH']:
if not lpath in env['LIBPATH']:
env["CAIRO_LIBPATHS"].append(lpath)
@@ -1404,6 +1500,11 @@ if not preconfigured:
else:
color_print(4,'Not building with cairo support, pass CAIRO=True to enable')
+ if not env['HOST'] and env['HAS_CAIRO']:
+ if not conf.CheckCairoHasFreetype():
+ env['SKIPPED_DEPS'].append('cairo')
+ env['HAS_CAIRO'] = False
+
if 'python' in env['BINDINGS'] or 'python' in env['REQUESTED_PLUGINS']:
if not os.access(env['PYTHON'], os.X_OK):
color_print(1,"Cannot run python interpreter at '%s', make sure that you have the permissions to execute it." % env['PYTHON'])
@@ -1466,17 +1567,18 @@ if not preconfigured:
else:
env['PYTHON_IS_64BIT'] = False
- if 'python' in env['BINDINGS']:
+ if has_boost_devel and 'python' in env['BINDINGS']:
if py3 and env['BOOST_PYTHON_LIB'] == 'boost_python':
env['BOOST_PYTHON_LIB'] = 'boost_python3%s' % env['BOOST_APPEND']
elif env['BOOST_PYTHON_LIB'] == 'boost_python':
env['BOOST_PYTHON_LIB'] = 'boost_python%s' % env['BOOST_APPEND']
- if not conf.CheckHeader(header='boost/python/detail/config.hpp',language='C++'):
- color_print(1,'Could not find required header files for boost python')
- env['MISSING_DEPS'].append('boost python')
+ if not env['HOST']:
+ if not conf.CheckHeader(header='boost/python/detail/config.hpp',language='C++'):
+ color_print(1,'Could not find required header files for boost python')
+ env['MISSING_DEPS'].append('boost python')
if env['CAIRO']:
- if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('pycairo'):
+ if CHECK_PKG_CONFIG and conf.CheckPKG('pycairo'):
env['HAS_PYCAIRO'] = True
else:
env['SKIPPED_DEPS'].extend(['pycairo'])
@@ -1498,7 +1600,7 @@ if not preconfigured:
color_print(4," $ sudo python scons/scons.py install")
color_print(4,"\nTo view available path variables:\n $ python scons/scons.py --help or -h")
color_print(4,'\nTo view overall SCons help options:\n $ python scons/scons.py --help-options or -H\n')
- color_print(4,'More info: https://github.com/mapnik/mapnik/wiki//MapnikInstallation')
+ color_print(4,'More info: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation')
if not HELP_REQUESTED:
Exit(1)
else:
@@ -1518,43 +1620,41 @@ if not preconfigured:
color_print(4,"Did not use user config file, no custom path variables will be saved...")
if env['SKIPPED_DEPS']:
- color_print(3,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']]))
+ color_print(4,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']]))
print
# fetch the mapnik version header in order to set the
# ABI version used to build libmapnik.so on linux in src/build.py
- abi = conf.GetMapnikLibVersion()
- abi_fallback = "2.2.0-pre"
+ abi = None
+ abi_fallback = "3.0.0-pre"
+ if not env['HOST']:
+ abi = conf.GetMapnikLibVersion()
if not abi:
- color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback)
+ if not env['HOST']:
+ color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback)
abi = abi_fallback
- env['ABI_VERSION'] = abi.replace('-pre','').split('.')
+ abi_no_pre = abi.replace('-pre','').split('.')
+ env['ABI_VERSION'] = abi_no_pre
env['MAPNIK_VERSION_STRING'] = abi
+ env['MAPNIK_VERSION'] = str(int(abi_no_pre[0])*100000+int(abi_no_pre[1])*100+int(abi_no_pre[2]))
- # Common C++ flags.
+ # Common DEFINES.
+ env.Append(CPPDEFINES = '-D%s' % env['PLATFORM'].upper())
if env['THREADING'] == 'multi':
- common_cxx_flags = '-D%s -DMAPNIK_THREADSAFE ' % env['PLATFORM'].upper()
- else :
- common_cxx_flags = '-D%s ' % env['PLATFORM'].upper()
+ env.Append(CPPDEFINES = '-DMAPNIK_THREADSAFE')
# Mac OSX (Darwin) special settings
if env['PLATFORM'] == 'Darwin':
pthread = ''
- # Getting the macintosh version number, sticking as a compiler macro
- # for Leopard -- needed because different workarounds are needed than
- # for Tiger.
- # this was used for fribidi - not longer needed
- # but will retain logic for future use
- #if platform.mac_ver()[0].startswith('10.5'):
- # common_cxx_flags += '-DOSX_LEOPARD '
else:
pthread = '-pthread'
# Common debugging flags.
# http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html
- debug_flags = '-g -fno-omit-frame-pointer -DDEBUG -DMAPNIK_DEBUG'
- ndebug_flags = '-DNDEBUG'
+ debug_flags = ['-g', '-fno-omit-frame-pointer']
+ debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG']
+ ndebug_defines = ['-DNDEBUG']
# Enable logging in debug mode (always) and release mode (when specified)
if env['DEFAULT_LOG_SEVERITY']:
@@ -1569,42 +1669,48 @@ if not preconfigured:
color_print(1,"No logger severity specified, available options are %s." % severities_list)
Exit(1)
- log_enabled = ' -DMAPNIK_LOG -DMAPNIK_DEFAULT_LOG_SEVERITY=%d' % log_severity
+ log_enabled = ['-DMAPNIK_LOG', '-DMAPNIK_DEFAULT_LOG_SEVERITY=%d' % log_severity]
if env['DEBUG']:
- debug_flags += log_enabled
+ debug_defines += log_enabled
else:
if env['ENABLE_LOG']:
- ndebug_flags += log_enabled
+ ndebug_defines += log_enabled
# Enable statistics reporting
if env['ENABLE_STATS']:
- debug_flags += ' -DMAPNIK_STATS'
- ndebug_flags += ' -DMAPNIK_STATS'
+ debug_defines.append('-DMAPNIK_STATS')
+ ndebug_defines.append('-DMAPNIK_STATS')
# Add rdynamic to allow using statics between application and plugins
# http://stackoverflow.com/questions/8623657/multiple-instances-of-singleton-across-shared-libraries-on-linux
if env['PLATFORM'] != 'Darwin' and env['CXX'] == 'g++':
env.MergeFlags('-rdynamic')
- # Customizing the C++ compiler flags depending on:
- # (1) the C++ compiler used; and
- # (2) whether debug binaries are requested.
- if env['SUNCC']:
- if env['DEBUG']:
- env.Append(CXXFLAGS = common_cxx_flags + debug_flags)
- else:
- env.Append(CXXFLAGS = common_cxx_flags + '-O %s' % ndebug_flags)
+ if env['DEBUG']:
+ env.Append(CXXFLAGS = debug_flags)
+ env.Append(CPPDEFINES = debug_defines)
else:
- # Common flags for GCC.
- gcc_cxx_flags = '-ansi -Wall %s %s -ftemplate-depth-300 %s' % (env['WARNING_CXXFLAGS'], pthread, common_cxx_flags)
+ env.Append(CPPDEFINES = ndebug_defines)
+
+ if not env['SUNCC']:
+
+ # Common flags for CXX compiler.
+ common_cxx_flags = '-ansi -Wall %s %s -ftemplate-depth-300 ' % (env['WARNING_CXXFLAGS'], pthread)
+
+ # https://github.com/mapnik/mapnik/issues/1835
+ if sys.platform == 'darwin' and env['CXX'] == 'g++':
+ common_cxx_flags += '-fpermissive '
+
if env['DEBUG']:
- env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline %s' % debug_flags)
+ env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline')
else:
- env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts %s' % (env['OPTIMIZATION'],ndebug_flags))
+ # TODO - add back -fvisibility-inlines-hidden
+ # https://github.com/mapnik/mapnik/issues/1863
+ env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION']))
if env['DEBUG_UNDEFINED']:
- env.Append(CXXFLAGS = '-fcatch-undefined-behavior -ftrapv -fwrapv')
+ env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv')
if 'python' in env['BINDINGS'] or 'python' in env['REQUESTED_PLUGINS']:
majver, minver = env['PYTHON_VERSION'].split('.')
@@ -1631,7 +1737,7 @@ if not preconfigured:
# if requested, sort LIBPATH and CPPPATH one last time before saving...
if env['PRIORITIZE_LINKING']:
- conf.prioritize_paths()
+ conf.prioritize_paths(silent=True)
# finish config stage and pickle results
env = conf.Finish()
@@ -1689,15 +1795,11 @@ if not HELP_REQUESTED:
p = env['PATH_REMOVE']
if p in env['ENV']['PATH']:
env['ENV']['PATH'].replace(p,'')
- def rm_path(set):
- for i in env[set]:
- if p in i:
- env[set].remove(i)
- rm_path('LIBPATH')
- rm_path('CPPPATH')
- rm_path('CXXFLAGS')
- rm_path('CAIRO_LIBPATHS')
- rm_path('CAIRO_CPPPATHS')
+ rm_path(p,'LIBPATH',env)
+ rm_path(p,'CPPPATH',env)
+ rm_path(p,'CXXFLAGS',env)
+ rm_path(p,'CAIRO_LIBPATHS',env)
+ rm_path(p,'CAIRO_CPPPATHS',env)
if env['PATH_REPLACE']:
searches,replace = env['PATH_REPLACE'].split(':')
@@ -1720,21 +1822,9 @@ if not HELP_REQUESTED:
Export('env')
plugin_base = env.Clone()
- # for this to work you need:
- # if __GNUC__ >= 4
- # define MAPNIK_EXP __attribute__ ((visibility ("default")))
- #plugin_base.Append(CXXFLAGS='-fvisibility=hidden')
- #plugin_base.Append(CXXFLAGS='-fvisibility-inlines-hidden')
Export('plugin_base')
- # clear the '_CPPDEFFLAGS' variable
- # for unknown reasons this variable puts -DNone
- # in the g++ args prompting unnecessary recompiles
- env['_CPPDEFFLAGS'] = None
- plugin_base['_CPPDEFFLAGS'] = None
-
-
if env['FAST']:
# caching is 'auto' by default in SCons
# But let's also cache implicit deps...
@@ -1761,58 +1851,69 @@ if not HELP_REQUESTED:
# Build the requested and able-to-be-compiled input plug-ins
GDAL_BUILT = False
OGR_BUILT = False
- for plugin in env['REQUESTED_PLUGINS']:
- details = env['PLUGINS'][plugin]
- if details['lib'] in env['LIBS']:
- SConscript('plugins/input/%s/build.py' % plugin)
- if plugin == 'ogr': OGR_BUILT = True
- if plugin == 'gdal': GDAL_BUILT = True
- if plugin == 'ogr' or plugin == 'gdal':
- if GDAL_BUILT and OGR_BUILT:
- env['LIBS'].remove(details['lib'])
- else:
- env['LIBS'].remove(details['lib'])
- elif not details['lib']:
- # build internal shape and raster plugins
- SConscript('plugins/input/%s/build.py' % plugin)
- else:
- color_print(1,"Notice: dependencies not met for plugin '%s', not building..." % plugin)
- # also clear out locally built target
+ for plugin in env['PLUGINS']:
+ if env['PLUGIN_LINKING'] == 'static' or plugin not in env['REQUESTED_PLUGINS']:
if os.path.exists('plugins/input/%s.input' % plugin):
os.unlink('plugins/input/%s.input' % plugin)
+ elif plugin in env['REQUESTED_PLUGINS']:
+ details = env['PLUGINS'][plugin]
+ if details['lib'] in env['LIBS']:
+ if env['PLUGIN_LINKING'] == 'shared':
+ SConscript('plugins/input/%s/build.py' % plugin)
+ if plugin == 'ogr': OGR_BUILT = True
+ if plugin == 'gdal': GDAL_BUILT = True
+ if plugin == 'ogr' or plugin == 'gdal':
+ if GDAL_BUILT and OGR_BUILT:
+ env['LIBS'].remove(details['lib'])
+ else:
+ env['LIBS'].remove(details['lib'])
+ elif not details['lib']:
+ if env['PLUGIN_LINKING'] == 'shared':
+ # build internal datasource input plugins
+ SConscript('plugins/input/%s/build.py' % plugin)
+ else:
+ color_print(1,"Notice: dependencies not met for plugin '%s', not building..." % plugin)
+ if os.path.exists('plugins/input/%s.input' % plugin):
+ os.unlink('plugins/input/%s.input' % plugin)
create_uninstall_target(env, env['MAPNIK_LIB_DIR_DEST'], False)
create_uninstall_target(env, env['MAPNIK_INPUT_PLUGINS_DEST'] , False)
- # before installing plugins, wipe out any previously
- # installed plugins that we are no longer building
if 'install' in COMMAND_LINE_TARGETS:
+ # if statically linking plugins still make sure
+ # to create the dynamic plugins directory
+ if env['PLUGIN_LINKING'] == 'static':
+ if not os.path.exists(env['MAPNIK_INPUT_PLUGINS_DEST']):
+ os.makedirs(env['MAPNIK_INPUT_PLUGINS_DEST'])
+ # before installing plugins, wipe out any previously
+ # installed plugins that we are no longer building
for plugin in PLUGINS.keys():
- if plugin not in env['REQUESTED_PLUGINS']:
- plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'%s.input' % plugin)
- if os.path.exists(plugin_path):
- color_print(3,"Notice: removing out of date plugin: '%s'" % plugin_path)
+ plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'%s.input' % plugin)
+ if os.path.exists(plugin_path):
+ if plugin not in env['REQUESTED_PLUGINS'] or env['PLUGIN_LINKING'] == 'static':
+ color_print(4,"Notice: removing out of date plugin: '%s'" % plugin_path)
os.unlink(plugin_path)
# Build the c++ rundemo app if requested
- if env['DEMO']:
- SConscript('demo/c++/build.py')
+ if not env['HOST']:
+ if env['DEMO']:
+ SConscript('demo/c++/build.py')
# Build shapeindex and remove its dependency from the LIBS
- if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
- SConscript('utils/shapeindex/build.py')
-
- # Build the pgsql2psqlite app if requested
- if env['PGSQL2SQLITE']:
- SConscript('utils/pgsql2sqlite/build.py')
-
- SConscript('utils/svg2png/build.py')
-
- # devtools not ready for public
- #SConscript('utils/ogrindex/build.py')
- env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
- else :
- color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available")
+ if not env['HOST']:
+ if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
+ if env['SHAPEINDEX']:
+ SConscript('utils/shapeindex/build.py')
+ # Build the pgsql2psqlite app if requested
+ if env['PGSQL2SQLITE']:
+ SConscript('utils/pgsql2sqlite/build.py')
+ if env['SVG2PNG']:
+ SConscript('utils/svg2png/build.py')
+ # devtools not ready for public
+ #SConscript('utils/ogrindex/build.py')
+ env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
+ else :
+ color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available")
# Build the Python bindings
if 'python' in env['BINDINGS']:
@@ -1828,13 +1929,13 @@ if not HELP_REQUESTED:
SConscript('fonts/build.py')
# build C++ tests
- if env['CPP_TESTS']:
- SConscript('tests/cpp_tests/build.py')
+ SConscript('tests/cpp_tests/build.py')
- if env['SVG_RENDERER']:
- SConscript('tests/cpp_tests/svg_renderer_tests/build.py')
+ if env['CPP_TESTS'] and env['SVG_RENDERER']:
+ SConscript('tests/cpp_tests/svg_renderer_tests/build.py')
- SConscript('benchmark/build.py')
+ if env['BENCHMARK']:
+ SConscript('benchmark/build.py')
# install pkg-config script and mapnik-config script
SConscript('utils/mapnik-config/build.py')
@@ -1845,11 +1946,14 @@ if not HELP_REQUESTED:
# if requested, build the sample input plugins
if env['SAMPLE_INPUT_PLUGINS']:
SConscript('plugins/input/templates/helloworld/build.py')
- elif 'install' in COMMAND_LINE_TARGETS:
- plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'hello.input')
- if os.path.exists(plugin_path):
- color_print(3,"Notice: removing out of date plugin: '%s'" % plugin_path)
- os.unlink(plugin_path)
+ else:
+ if 'install' in COMMAND_LINE_TARGETS:
+ plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'hello.input')
+ if os.path.exists(plugin_path):
+ color_print(4,"Notice: removing out of date plugin: '%s'" % plugin_path)
+ os.unlink(plugin_path)
+ if os.path.exists('plugins/input/templates/hello.input'):
+ os.unlink('plugins/input/templates/hello.input')
# update linux project files
if env['PLATFORM'] == 'Linux':
diff --git a/benchmark/build.py b/benchmark/build.py
index 4dc448854..5a7db1f4e 100644
--- a/benchmark/build.py
+++ b/benchmark/build.py
@@ -10,12 +10,16 @@ test_env['LIBS'] = copy(env['LIBMAPNIK_LIBS'])
test_env.AppendUnique(LIBS='mapnik')
#test_env.AppendUnique(LIBS='sqlite3')
test_env.AppendUnique(CXXFLAGS='-g')
+linkflags = copy(env['CUSTOM_LDFLAGS'])
+linkflags
+if env['PLATFORM'] == 'Darwin':
+ linkflags += ' -F/ -framework CoreFoundation'
for cpp_test in glob.glob('run*.cpp'):
name = cpp_test.replace('.cpp','')
source_files = [cpp_test]
test_env_local = test_env.Clone()
- test_program = test_env_local.Program(name, source=source_files, LINKFLAGS=env['CUSTOM_LDFLAGS'])
+ test_program = test_env_local.Program(name, source=source_files, LINKFLAGS=linkflags)
Depends(test_program, env.subst('../src/%s' % env['MAPNIK_LIB_NAME']))
# build locally if installing
if 'install' in COMMAND_LINE_TARGETS:
diff --git a/benchmark/data/polygon.wkt b/benchmark/data/polygon.wkt
new file mode 100644
index 000000000..2fe5b480a
--- /dev/null
+++ b/benchmark/data/polygon.wkt
@@ -0,0 +1 @@
+MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))
\ No newline at end of file
diff --git a/benchmark/run.cpp b/benchmark/run.cpp
index daead8897..6173f6758 100644
--- a/benchmark/run.cpp
+++ b/benchmark/run.cpp
@@ -12,6 +12,8 @@
#include
#include
#include
+#include
+
// boost
#include
@@ -35,44 +37,56 @@ typedef process_cpu_clock clock_type;
typedef clock_type::duration dur;
template
-void benchmark(T test, std::string const& name)
+void benchmark(T & test_runner, std::string const& name)
{
try {
bool should_run_test = true;
- if (!test_set.empty()) {
+ if (!test_set.empty())
+ {
should_run_test = test_set.find(test_num) != test_set.end();
}
- if (should_run_test || dry_run) {
- if (!test.validate()) {
+ if (should_run_test || dry_run)
+ {
+ if (!test_runner.validate())
+ {
std::clog << "test did not validate: " << name << "\n";
//throw std::runtime_error(std::string("test did not validate: ") + name);
}
- if (dry_run) {
- std::clog << test_num << ") " << (test.threads_ ? "threaded -> ": "")
+ if (dry_run)
+ {
+ std::clog << test_num << ") " << (test_runner.threads_ ? "threaded -> ": "")
<< name << "\n";
- } else {
+ }
+ else
+ {
process_cpu_clock::time_point start;
dur elapsed;
- if (test.threads_ > 0) {
+ if (test_runner.threads_ > 0)
+ {
boost::thread_group tg;
- for (unsigned i=0;i ": "")
+ std::clog << test_num << ") " << (test_runner.threads_ ? "threaded -> ": "")
<< name << ": "
<< boost::chrono::duration_cast(elapsed) << "\n";
}
}
- } catch (std::exception const& ex) {
+ }
+ catch (std::exception const& ex)
+ {
std::clog << "test runner did not complete: " << ex.what() << "\n";
}
test_num++;
@@ -252,7 +266,7 @@ struct test5
s.resize(s.capacity());
while (true)
{
- size_t n2 = static_cast(snprintf(&s[0], s.size()+1, "%g", val_));
+ size_t n2 = static_cast(snprintf(&s[0], s.size()+1, "%g", val));
if (n2 <= s.size())
{
s.resize(n2);
@@ -380,13 +394,15 @@ struct test8
bool validate()
{
- mapnik::expression_grammar expr_grammar(transcoder("utf-8"));
- mapnik::expression_ptr expr = mapnik::parse_expression(expr_,expr_grammar);
- return mapnik::to_expression_string(*expr) == expr_;
+ transcoder tr("utf-8");
+ mapnik::expression_grammar expr_grammar(tr);
+ mapnik::expression_ptr expr = mapnik::parse_expression(expr_,expr_grammar);
+ return mapnik::to_expression_string(*expr) == expr_;
}
void operator()()
{
- mapnik::expression_grammar expr_grammar(transcoder("utf-8"));
+ transcoder tr("utf-8");
+ mapnik::expression_grammar expr_grammar(tr);
for (unsigned i=0;i
+#include "agg_conv_clipper.h"
+#include "agg_path_storage.h"
+#include
+
+struct test11
+{
+ unsigned iter_;
+ unsigned threads_;
+ std::string wkt_in_;
+ mapnik::box2d extent_;
+ typedef agg::conv_clipper poly_clipper;
+ test11(unsigned iterations,
+ unsigned threads,
+ std::string wkt_in,
+ mapnik::box2d const& extent)
+ : iter_(iterations),
+ threads_(threads),
+ wkt_in_(wkt_in),
+ extent_(extent) {
+
+ }
+
+ bool validate()
+ {
+ return true;
+ }
+ void operator()()
+ {
+ boost::ptr_vector paths;
+ if (!mapnik::from_wkt(wkt_in_, paths))
+ {
+ throw std::runtime_error("Failed to parse WKT");
+ }
+ agg::path_storage ps;
+ ps.move_to(extent_.minx(), extent_.miny());
+ ps.line_to(extent_.minx(), extent_.maxy());
+ ps.line_to(extent_.maxx(), extent_.maxy());
+ ps.line_to(extent_.maxx(), extent_.miny());
+ ps.close_polygon();
+ for (unsigned i=0;i
+
+struct test12
+{
+ unsigned iter_;
+ unsigned threads_;
+ std::string wkt_in_;
+
+ mapnik::box2d extent_;
+ typedef mapnik::polygon_clipper poly_clipper;
+ test12(unsigned iterations,
+ unsigned threads,
+ std::string wkt_in,
+ mapnik::box2d const& extent)
+ : iter_(iterations),
+ threads_(threads),
+ wkt_in_(wkt_in),
+ extent_(extent)
+ {
+ }
+
+ bool validate()
+ {
+ return true;
+ }
+ void operator()()
+ {
+ boost::ptr_vector paths;
+ if (!mapnik::from_wkt(wkt_in_, paths))
+ {
+ throw std::runtime_error("Failed to parse WKT");
+ }
+ for (unsigned i=0;i
+#include
+struct test13
+{
+ unsigned iter_;
+ unsigned threads_;
+
+ test13(unsigned iterations,
+ unsigned threads)
+ : iter_(iterations),
+ threads_(threads)
+ {}
+
+ bool validate()
+ {
+ return true;
+ }
+
+ void operator()()
+ {
+ mapnik::freetype_engine engine;
+ unsigned long count = 0;
+ for (unsigned i=0;i 0) {
@@ -720,6 +872,42 @@ int main( int argc, char** argv)
benchmark(runner,"rule caching using heap allocation");
}
+ {
+ std::string filename_("benchmark/data/polygon.wkt");
+ std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
+ if (!in.is_open())
+ throw std::runtime_error("could not open: '" + filename_ + "'");
+ std::string wkt_in( (std::istreambuf_iterator(in) ),
+ (std::istreambuf_iterator()) );
+ mapnik::box2d clipping_box(0,0,40,40);
+
+ test11 runner(100000,10,wkt_in,clipping_box);
+ benchmark(runner,"clipping polygon with agg_conv_clipper");
+ }
+
+ {
+
+ std::string filename_("benchmark/data/polygon.wkt");
+ std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
+ if (!in.is_open())
+ throw std::runtime_error("could not open: '" + filename_ + "'");
+ std::string wkt_in( (std::istreambuf_iterator(in) ),
+ (std::istreambuf_iterator()) );
+ mapnik::box2d clipping_box(0,0,40,40);
+
+ test12 runner(100000,10,wkt_in,clipping_box);
+ benchmark(runner,"clipping polygon with mapnik::polygon_clipper");
+ }
+
+ {
+ bool success = mapnik::freetype_engine::register_fonts("./fonts", true);
+ if (!success) {
+ std::clog << "warning, did not register any new fonts!\n";
+ }
+ unsigned face_count = mapnik::freetype_engine::face_names().size();
+ test13 runner(1000,10);
+ benchmark(runner, (boost::format("font_engihe: created %ld faces in ") % (face_count * 1000 * 10)).str());
+ }
std::cout << "...benchmark done\n";
return 0;
}
diff --git a/bindings/python/build.py b/bindings/python/build.py
index a16bb4533..7526ea48d 100644
--- a/bindings/python/build.py
+++ b/bindings/python/build.py
@@ -1,7 +1,7 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
-# Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
+# Copyright (C) 2013 Artem Pavlenko
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -43,20 +43,23 @@ prefix = env['PREFIX']
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
-libraries = ['mapnik',env['BOOST_PYTHON_LIB']]
+py_env = env.Clone()
+py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
+
+py_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
+
+py_env['LIBS'] = ['mapnik',env['BOOST_PYTHON_LIB']]
+
+link_all_libs = env['LINKING'] == 'static' or env['RUNTIME_LINK'] == 'static' or (env['PLATFORM'] == 'Darwin' and not env['PYTHON_DYNAMIC_LOOKUP'])
+
+if link_all_libs:
+ py_env.AppendUnique(LIBS=env['LIBMAPNIK_LIBS'])
+
+if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
+ py_env.AppendUnique(LIBS='rt')
# TODO - do solaris/fedora need direct linking too?
if env['PLATFORM'] == 'Darwin':
- if not env['PYTHON_DYNAMIC_LOOKUP']:
- if env['PNG']:
- libraries.append('png')
- if env['JPEG']:
- libraries.append('jpeg')
- libraries.append(env['ICU_LIB_NAME'])
- libraries.append('boost_regex%s' % env['BOOST_APPEND'])
- if env['THREADING'] == 'multi':
- libraries.append('boost_thread%s' % env['BOOST_APPEND'])
-
##### Python linking on OS X is tricky ###
# Confounding problems are:
# 1) likelyhood of multiple python installs of the same major.minor version
@@ -96,7 +99,6 @@ if env['PLATFORM'] == 'Darwin':
else:
# should we fall back to -lpython here?
python_link_flag = '-F/ -framework Python'
-
# if we are not linking to a framework then use the *nix standard approach
else:
# TODO - do we need to pass -L/?
@@ -147,9 +149,6 @@ except: pass
# install the shared object beside the module directory
sources = glob.glob('*.cpp')
-py_env = env.Clone()
-py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
-
if 'install' in COMMAND_LINE_TARGETS:
# install the core mapnik python files, including '__init__.py'
init_files = glob.glob('mapnik/*.py')
@@ -175,16 +174,16 @@ if 'install' in COMMAND_LINE_TARGETS:
if 'uninstall' not in COMMAND_LINE_TARGETS:
if env['HAS_CAIRO']:
py_env.Append(CPPPATH = env['CAIRO_CPPPATHS'])
- py_env.Append(CXXFLAGS = '-DHAVE_CAIRO')
- if env['PLATFORM'] == 'Darwin':
- py_env.Append(LIBS=env['CAIRO_LINKFLAGS'])
+ py_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
+ if link_all_libs:
+ py_env.Append(LIBS=env['CAIRO_ALL_LIBS'])
if env['HAS_PYCAIRO']:
py_env.ParseConfig('pkg-config --cflags pycairo')
- py_env.Append(CXXFLAGS = '-DHAVE_PYCAIRO')
+ py_env.Append(CPPDEFINES = '-DHAVE_PYCAIRO')
-libraries.append('boost_thread%s' % env['BOOST_APPEND'])
-_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LIBS=libraries, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
+py_env.AppendUnique(LIBS = 'boost_thread%s' % env['BOOST_APPEND'])
+_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
Depends(_mapnik, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py
index eca8c89b8..9fc06d96b 100644
--- a/bindings/python/mapnik/__init__.py
+++ b/bindings/python/mapnik/__init__.py
@@ -340,6 +340,53 @@ def Shapefile(**keywords):
keywords['type'] = 'shape'
return CreateDatasource(keywords)
+def CSV(**keywords):
+ """Create a CSV Datasource.
+
+ Required keyword arguments:
+ file -- path to csv
+
+ Optional keyword arguments:
+ inline -- inline CSV string (if provided 'file' argument will be ignored and non-needed)
+ base -- path prefix (default None)
+ encoding -- file encoding (default 'utf-8')
+ row_limit -- integer limit of rows to return (default: 0)
+ strict -- throw an error if an invalid row is encountered
+ escape -- The escape character to use for parsing data
+ quote -- The quote character to use for parsing data
+ separator -- The separator character to use for parsing data
+ headers -- A comma separated list of header names that can be set to add headers to data that lacks them
+ filesize_max -- The maximum filesize in MB that will be accepted
+
+ >>> from mapnik import CSV
+ >>> csv = CSV(file='test.csv')
+
+ >>> from mapnik import CSV
+ >>> csv = CSV(inline='''wkt,Name\n"POINT (120.15 48.47)","Winthrop, WA"''')
+
+ For more information see https://github.com/mapnik/mapnik/wiki/CSV-Plugin
+
+ """
+ keywords['type'] = 'csv'
+ return CreateDatasource(keywords)
+
+def GeoJSON(**keywords):
+ """Create a GeoJSON Datasource.
+
+ Required keyword arguments:
+ file -- path to json
+
+ Optional keyword arguments:
+ encoding -- file encoding (default 'utf-8')
+ base -- path prefix (default None)
+
+ >>> from mapnik import GeoJSON
+ >>> geojson = GeoJSON(file='test.json')
+
+ """
+ keywords['type'] = 'geojson'
+ return CreateDatasource(keywords)
+
def PostGIS(**keywords):
"""Create a PostGIS Datasource.
@@ -558,44 +605,6 @@ def Osm(**keywords):
keywords['type'] = 'osm'
return CreateDatasource(keywords)
-def Kismet(**keywords):
- """Create a Kismet Datasource.
-
- Required keyword arguments:
- host -- kismet hostname
- port -- kismet port
-
- Optional keyword arguments:
- encoding -- file encoding (default 'utf-8')
- extent -- manually specified data extent (comma delimited string, default None)
-
- >>> from mapnik import Kismet, Layer
- >>> datasource = Kismet(host='localhost',port=2501,extent='-179,-85,179,85')
- >>> lyr = Layer('Kismet Server Layer')
- >>> lyr.datasource = datasource
-
- """
- keywords['type'] = 'kismet'
- return CreateDatasource(keywords)
-
-def Geos(**keywords):
- """Create a GEOS Vector Datasource.
-
- Required keyword arguments:
- wkt -- inline WKT text of the geometry
-
- Optional keyword arguments:
- extent -- manually specified data extent (comma delimited string, default None)
-
- >>> from mapnik import Geos, Layer
- >>> datasource = Geos(wkt='MULTIPOINT(100 100, 50 50, 0 0)')
- >>> lyr = Layer('GEOS Layer from WKT string')
- >>> lyr.datasource = datasource
-
- """
- keywords['type'] = 'geos'
- return CreateDatasource(keywords)
-
def Python(**keywords):
"""Create a Python Datasource.
diff --git a/bindings/python/mapnik_datasource.cpp b/bindings/python/mapnik_datasource.cpp
index 6da2cb0fd..85e2ff721 100644
--- a/bindings/python/mapnik_datasource.cpp
+++ b/bindings/python/mapnik_datasource.cpp
@@ -48,14 +48,30 @@ namespace
{
//user-friendly wrapper that uses Python dictionary
using namespace boost::python;
-boost::shared_ptr create_datasource(const dict& d)
+boost::shared_ptr create_datasource(dict const& d)
{
mapnik::parameters params;
boost::python::list keys=d.keys();
- for (int i=0; i(keys[i]);
object obj = d[key];
+ if (PyUnicode_Check(obj.ptr()))
+ {
+ PyObject* temp = PyUnicode_AsUTF8String(obj.ptr());
+ if (temp)
+ {
+#if PY_VERSION_HEX >= 0x03000000
+ char* c_str = PyBytes_AsString(temp);
+#else
+ char* c_str = PyString_AsString(temp);
+#endif
+ params[key] = std::string(c_str);
+ Py_DecRef(temp);
+ }
+ continue;
+ }
+
extract ex0(obj);
extract ex1(obj);
extract ex2(obj);
@@ -138,6 +154,9 @@ boost::python::list field_types(boost::shared_ptr const& ds)
return fld_types;
}}
+mapnik::parameters const& (mapnik::datasource::*params_const)() const = &mapnik::datasource::params;
+
+
void export_datasource()
{
using namespace boost::python;
@@ -164,7 +183,7 @@ void export_datasource()
.def("fields",&fields)
.def("field_types",&field_types)
.def("features_at_point",&datasource::features_at_point, (arg("coord"),arg("tolerance")=0))
- .def("params",&datasource::params,return_value_policy(),
+ .def("params",make_function(params_const,return_value_policy()),
"The configuration parameters of the data source. "
"These vary depending on the type of data source.")
;
diff --git a/bindings/python/mapnik_debug_symbolizer.cpp b/bindings/python/mapnik_debug_symbolizer.cpp
new file mode 100644
index 000000000..6b255967f
--- /dev/null
+++ b/bindings/python/mapnik_debug_symbolizer.cpp
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ *
+ * This file is part of Mapnik (c++ mapping toolkit)
+ *
+ * Copyright (C) 2013 Artem Pavlenko
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *****************************************************************************/
+
+#include
+#include "mapnik_enumeration.hpp"
+#include
+
+void export_debug_symbolizer()
+{
+ using namespace boost::python;
+
+ mapnik::enumeration_("debug_symbolizer_mode")
+ .value("COLLISION",mapnik::DEBUG_SYM_MODE_COLLISION)
+ .value("VERTEX",mapnik::DEBUG_SYM_MODE_VERTEX)
+ ;
+
+ class_("DebugSymbolizer",
+ init<>("Default debug Symbolizer"))
+ .add_property("mode",
+ &mapnik::debug_symbolizer::get_mode,
+ &mapnik::debug_symbolizer::set_mode)
+ ;
+}
diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp
index d3bd8b1dd..caf4d2525 100644
--- a/bindings/python/mapnik_expression.cpp
+++ b/bindings/python/mapnik_expression.cpp
@@ -34,8 +34,6 @@
#include
#include
-
-using mapnik::Feature;
using mapnik::expression_ptr;
using mapnik::parse_expression;
using mapnik::to_expression_string;
@@ -53,15 +51,15 @@ std::string expression_to_string_(mapnik::expr_node const& expr)
return mapnik::to_expression_string(expr);
}
-mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::Feature const& f)
+mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::feature_impl const& f)
{
// will be auto-converted to proper python type by `mapnik_value_to_python`
- return boost::apply_visitor(mapnik::evaluate(f),expr);
+ return boost::apply_visitor(mapnik::evaluate(f),expr);
}
-bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::Feature const& f)
+bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::feature_impl const& f)
{
- return boost::apply_visitor(mapnik::evaluate(f),expr).to_bool();
+ return boost::apply_visitor(mapnik::evaluate(f),expr).to_bool();
}
// path expression
@@ -75,7 +73,7 @@ std::string path_to_string_(mapnik::path_expression const& expr)
return mapnik::path_processor_type::to_string(expr);
}
-std::string path_evaluate_(mapnik::path_expression const& expr, mapnik::Feature const& f)
+std::string path_evaluate_(mapnik::path_expression const& expr, mapnik::feature_impl const& f)
{
return mapnik::path_processor_type::evaluate(expr, f);
}
diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp
index 0c7e6745e..19b3b4aa2 100644
--- a/bindings/python/mapnik_feature.cpp
+++ b/bindings/python/mapnik_feature.cpp
@@ -30,7 +30,6 @@
#include
#include
-
// mapnik
#include
#include
@@ -39,30 +38,33 @@
#include
#include
+// stl
+#include
+
namespace {
-using mapnik::Feature;
using mapnik::geometry_utils;
using mapnik::from_wkt;
using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;
-mapnik::geometry_type const& (mapnik::Feature::*get_geometry_by_const_ref)(unsigned) const = &mapnik::Feature::get_geometry;
-boost::ptr_vector const& (mapnik::Feature::*get_paths_by_const_ref)() const = &mapnik::Feature::paths;
+mapnik::geometry_type const& (mapnik::feature_impl::*get_geometry_by_const_ref)(unsigned) const = &mapnik::feature_impl::get_geometry;
+boost::ptr_vector const& (mapnik::feature_impl::*get_paths_by_const_ref)() const = &mapnik::feature_impl::paths;
-void feature_add_geometries_from_wkb(Feature &feature, std::string wkb)
+void feature_add_geometries_from_wkb(mapnik::feature_impl &feature, std::string wkb)
{
- geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
+ bool result = geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
+ if (!result) throw std::runtime_error("Failed to parse WKB");
}
-void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)
+void feature_add_geometries_from_wkt(mapnik::feature_impl &feature, std::string wkt)
{
bool result = mapnik::from_wkt(wkt, feature.paths());
if (!result) throw std::runtime_error("Failed to parse WKT");
}
-std::string feature_to_geojson(Feature const& feature)
+std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
std::string json;
mapnik::json::feature_generator g;
@@ -73,22 +75,22 @@ std::string feature_to_geojson(Feature const& feature)
return json;
}
-mapnik::value __getitem__(Feature const& feature, std::string const& name)
+mapnik::value __getitem__(mapnik::feature_impl const& feature, std::string const& name)
{
return feature.get(name);
}
-mapnik::value __getitem2__(Feature const& feature, std::size_t index)
+mapnik::value __getitem2__(mapnik::feature_impl const& feature, std::size_t index)
{
return feature.get(index);
}
-void __setitem__(Feature & feature, std::string const& name, mapnik::value const& val)
+void __setitem__(mapnik::feature_impl & feature, std::string const& name, mapnik::value const& val)
{
feature.put_new(name,val);
}
-boost::python::dict attributes(Feature const& f)
+boost::python::dict attributes(mapnik::feature_impl const& f)
{
boost::python::dict attributes;
feature_kv_iterator itr = f.begin();
@@ -191,7 +193,6 @@ struct value_null_from_python
void export_feature()
{
using namespace boost::python;
- using mapnik::Feature;
// Python to mapnik::value converters
// NOTE: order matters here. For example value_null must be listed before
@@ -211,25 +212,25 @@ void export_feature()
.def("push", &context_type::push)
;
- class_,
+ class_,
boost::noncopyable>("Feature",init("Default ctor."))
- .def("id",&Feature::id)
- .def("__str__",&Feature::to_string)
+ .def("id",&mapnik::feature_impl::id)
+ .def("__str__",&mapnik::feature_impl::to_string)
.def("add_geometries_from_wkb", &feature_add_geometries_from_wkb)
.def("add_geometries_from_wkt", &feature_add_geometries_from_wkt)
- .def("add_geometry", &Feature::add_geometry)
- .def("num_geometries",&Feature::num_geometries)
+ .def("add_geometry", &mapnik::feature_impl::add_geometry)
+ .def("num_geometries",&mapnik::feature_impl::num_geometries)
.def("get_geometry", make_function(get_geometry_by_const_ref,return_value_policy()))
.def("geometries",make_function(get_paths_by_const_ref,return_value_policy()))
- .def("envelope", &Feature::envelope)
- .def("has_key", &Feature::has_key)
+ .def("envelope", &mapnik::feature_impl::envelope)
+ .def("has_key", &mapnik::feature_impl::has_key)
.add_property("attributes",&attributes)
.def("__setitem__",&__setitem__)
.def("__contains__",&__getitem__)
.def("__getitem__",&__getitem__)
.def("__getitem__",&__getitem2__)
- .def("__len__", &Feature::size)
- .def("context",&Feature::context)
+ .def("__len__", &mapnik::feature_impl::size)
+ .def("context",&mapnik::feature_impl::context)
.def("to_geojson",&feature_to_geojson)
;
}
diff --git a/bindings/python/mapnik_featureset.cpp b/bindings/python/mapnik_featureset.cpp
index 3148d116e..c1f7eecd4 100644
--- a/bindings/python/mapnik_featureset.cpp
+++ b/bindings/python/mapnik_featureset.cpp
@@ -65,10 +65,7 @@ inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr)
void export_featureset()
{
using namespace boost::python;
- using mapnik::Feature;
- using mapnik::Featureset;
-
- class_,
+ class_,
boost::noncopyable>("Featureset",no_init)
.def("__iter__",pass_through)
.def("next",next)
diff --git a/bindings/python/mapnik_geometry.cpp b/bindings/python/mapnik_geometry.cpp
index 61a2b5b1b..7d1a0d5f0 100644
--- a/bindings/python/mapnik_geometry.cpp
+++ b/bindings/python/mapnik_geometry.cpp
@@ -43,6 +43,9 @@
#include
#endif
+// stl
+#include
+
namespace {
using mapnik::from_wkt;
diff --git a/bindings/python/mapnik_grid.cpp b/bindings/python/mapnik_grid.cpp
index 1118d3b4b..09b21ee3d 100644
--- a/bindings/python/mapnik_grid.cpp
+++ b/bindings/python/mapnik_grid.cpp
@@ -20,6 +20,8 @@
*
*****************************************************************************/
+#if defined(GRID_RENDERER)
+
// boost
#include
#include
@@ -80,3 +82,5 @@ void export_grid()
;
}
+
+#endif
diff --git a/bindings/python/mapnik_grid_view.cpp b/bindings/python/mapnik_grid_view.cpp
index aa29dda78..5e9d2745f 100644
--- a/bindings/python/mapnik_grid_view.cpp
+++ b/bindings/python/mapnik_grid_view.cpp
@@ -20,6 +20,8 @@
*
*****************************************************************************/
+#if defined(GRID_RENDERER)
+
// boost
#include
#include
@@ -49,3 +51,5 @@ void export_grid_view()
)
;
}
+
+#endif
diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp
index 9c7c1fd1e..5b3db5e9e 100644
--- a/bindings/python/mapnik_image.cpp
+++ b/bindings/python/mapnik_image.cpp
@@ -107,6 +107,28 @@ bool painted(mapnik::image_32 const& im)
return im.painted();
}
+bool is_solid(mapnik::image_32 const& im)
+{
+ if (im.width() > 0 && im.height() > 0)
+ {
+ mapnik::image_data_32 const & data = im.data();
+ mapnik::image_data_32::pixel_type const* first_row = data.getRow(0);
+ mapnik::image_data_32::pixel_type const first_pixel = first_row[0];
+ for (unsigned y = 0; y < im.height(); ++y)
+ {
+ mapnik::image_data_32::pixel_type const * row = data.getRow(y);
+ for (unsigned x = 0; x < im.width(); ++x)
+ {
+ if (first_pixel != row[x])
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
unsigned get_pixel(mapnik::image_32 const& im, int x, int y)
{
if (x < static_cast(im.width()) && y < static_cast(im.height()))
@@ -142,6 +164,36 @@ boost::shared_ptr open_from_file(std::string const& filename)
throw mapnik::image_reader_exception("Unsupported image format:" + filename);
}
+boost::shared_ptr fromstring(std::string const& str)
+{
+ std::auto_ptr reader(get_image_reader(str.c_str(),str.size()));
+ if (reader.get())
+ {
+ boost::shared_ptr image_ptr = boost::make_shared(reader->width(),reader->height());
+ reader->read(0,0,image_ptr->data());
+ return image_ptr;
+ }
+ throw mapnik::image_reader_exception("Failed to load image from buffer" );
+}
+
+boost::shared_ptr frombuffer(PyObject * obj)
+{
+ void const* buffer=0;
+ Py_ssize_t buffer_len;
+ if (PyObject_AsReadBuffer(obj, &buffer, &buffer_len) == 0)
+ {
+ std::auto_ptr reader(get_image_reader(reinterpret_cast(buffer),buffer_len));
+ if (reader.get())
+ {
+ boost::shared_ptr image_ptr = boost::make_shared(reader->width(),reader->height());
+ reader->read(0,0,image_ptr->data());
+ return image_ptr;
+ }
+ }
+ throw mapnik::image_reader_exception("Failed to load image from buffer" );
+}
+
+
void blend (image_32 & im, unsigned x, unsigned y, image_32 const& im2, float opacity)
{
im.set_rectangle_alpha2(im2.data(),x,y,opacity);
@@ -206,6 +258,7 @@ void export_image()
.def("height",&image_32::height)
.def("view",&image_32::get_view)
.def("painted",&painted)
+ .def("is_solid",&is_solid)
.add_property("background",make_function
(&image_32::get_background,return_value_policy()),
&image_32::set_background, "The background color of the image.")
@@ -219,6 +272,7 @@ void export_image()
arg("mode")=mapnik::src_over,
arg("opacity")=1.0f
))
+ .def("premultiplied",&image_32::premultiplied)
.def("premultiply",&image_32::premultiply)
.def("demultiply",&image_32::demultiply)
.def("set_pixel",&set_pixel)
@@ -234,6 +288,10 @@ void export_image()
.def("save", &save_to_file3)
.def("open",open_from_file)
.staticmethod("open")
+ .def("frombuffer",&frombuffer)
+ .staticmethod("frombuffer")
+ .def("fromstring",&fromstring)
+ .staticmethod("fromstring")
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
.def("from_cairo",&from_cairo)
.staticmethod("from_cairo")
diff --git a/bindings/python/mapnik_image_view.cpp b/bindings/python/mapnik_image_view.cpp
index 18a0831b6..63bb61578 100644
--- a/bindings/python/mapnik_image_view.cpp
+++ b/bindings/python/mapnik_image_view.cpp
@@ -76,6 +76,27 @@ PyObject* view_tostring3(image_view const & view, std::string con
(s.data(),s.size());
}
+bool is_solid(image_view const& view)
+{
+ if (view.width() > 0 && view.height() > 0)
+ {
+ mapnik::image_view::pixel_type const* first_row = view.getRow(0);
+ mapnik::image_view::pixel_type const first_pixel = first_row[0];
+ for (unsigned y = 0; y < view.height(); ++y)
+ {
+ mapnik::image_view::pixel_type const * row = view.getRow(y);
+ for (unsigned x = 0; x < view.width(); ++x)
+ {
+ if (first_pixel != row[x])
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
void save_view1(image_view const& view,
std::string const& filename)
{
@@ -104,6 +125,7 @@ void export_image_view()
class_ >("ImageView","A view into an image.",no_init)
.def("width",&image_view::width)
.def("height",&image_view::height)
+ .def("is_solid",&is_solid)
.def("tostring",&view_tostring1)
.def("tostring",&view_tostring2)
.def("tostring",&view_tostring3)
diff --git a/bindings/python/mapnik_layer.cpp b/bindings/python/mapnik_layer.cpp
index f3584a0ac..4656a5217 100644
--- a/bindings/python/mapnik_layer.cpp
+++ b/bindings/python/mapnik_layer.cpp
@@ -117,10 +117,14 @@ void set_buffer_size(mapnik::layer & l, boost::optional const& buffer_size)
PyObject * get_buffer_size(mapnik::layer & l)
{
- boost::optional buffer_size = l.buffer_size();
+ boost::optional buffer_size = l.buffer_size();
if (buffer_size)
{
+#if PY_VERSION_HEX >= 0x03000000
+ return PyLong_FromLong(*buffer_size);
+#else
return PyInt_FromLong(*buffer_size);
+#endif
}
else
{
diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp
index eecedf6d6..37c4a50d8 100644
--- a/bindings/python/mapnik_map.cpp
+++ b/bindings/python/mapnik_map.cpp
@@ -91,17 +91,6 @@ mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x
return m.query_map_point(idx, x, y);
}
-// deepcopy
-/*
-mapnik::Map map_deepcopy(mapnik::Map & m, boost::python::dict memo)
-{
- // FIXME: ignore memo for now
- mapnik::Map result;
- mapnik::util::deepcopy(m, result);
- return result;
-}
-*/
-
void set_maximum_extent(mapnik::Map & m, boost::optional > const& box)
{
if (box)
@@ -116,10 +105,10 @@ void set_maximum_extent(mapnik::Map & m, boost::optional >
struct extract_style
{
- typedef mapnik::feature_type_style result_type;
+ typedef boost::python::tuple result_type;
result_type operator() (std::map::value_type const& val) const
{
- return val.second;
+ return boost::python::make_tuple(val.first,val.second);
}
};
@@ -155,7 +144,7 @@ void export_map()
class_("StyleRange")
.def("__iter__",
- range(&style_range::first, &style_range::second))
+ boost::python::range(&style_range::first, &style_range::second))
;
class_