diff --git a/.gitmodules b/.gitmodules index 4cca9a4a8..dfcbea536 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,4 +5,7 @@ [submodule "test/data-visual"] path = test/data-visual url = https://github.com/mapnik/test-data-visual.git - branch = master \ No newline at end of file + branch = master +[submodule "deps/mapbox/variant"] + path = deps/mapbox/variant + url = https://github.com/mapbox/variant.git diff --git a/.travis.yml b/.travis.yml index 656ac257a..c16bfa3a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,20 @@ language: cpp -sudo: false - git: depth: 10 - submodules: true + submodules: false env: global: + - CCACHE_TEMPDIR=/tmp/.ccache-temp + - CCACHE_COMPRESS=1 + - HEAVY_JOBS="2" + - PREFIX=/tmp/mapnik - secure: "N3a5nzzsgpuu45k8qWdYsHNxrSnqeAGLTOYpfYoAH7B94vuf7pa7XV1tQjXbxrnx2D6ryTdtUtyRKwy7zXbwXxGt4DpczWEo8f6DUd6+obAp3kdnXABg2Sj4oA7KMs0F0CmoADy0jdUZD5YyOJHu64LCIIgzEQ9q49PFMNbU3IE=" - secure: "iQYPNpMtejcgYeUkWZGIWz1msIco5qydJrhZTSCQOYahAQerdT7q5WZEpEo3G6IWOGgO1eo7GFuY8DvqQjw1+jC9b9mhkRNdo3LhGTKS9Gsbl5Q27k0rjlaFZmmQHrfPlQJwhfAIp+KLugHtQw5bCoLh+95E3j0F0DayF1tuJ3s=" + - secure: "F6ivqDNMBQQnrDGA9+7IX+GDswuIqQQd7YPJdQqa2Ked9jddAQDeJClb05ig3JlwfOlYLGZOd43ZX0pKuMtI2Gbkwz211agGP9S3YunwlRg8iWtJlO5kYFUdKCmJNhjg4icfkGELCgwXn+zuEWFSLpkPcjqAFKFlQrIJeAJJgKM=" addons: postgresql: "9.4" - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.5 - packages: - - clang-3.5 cache: directories: @@ -26,66 +23,86 @@ cache: matrix: include: - os: linux - compiler: clang - env: JOBS=8 MASON_PUBLISH=true + sudo: false + compiler: ": clang" + env: JOBS=8 MASON_PUBLISH=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" TRIGGER=true + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: [ 'libstdc++-5-dev', 'xutils'] - os: linux - compiler: gcc - env: JOBS=6 + sudo: false + compiler: ": clang-coverage" + env: JOBS=8 COVERAGE=true _CXX="ccache clang++-3.8 -Qunused-arguments" _CC="clang-3.8" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test'] + packages: ['libstdc++-5-dev', 'xutils' ] - os: osx - compiler: clang - env: JOBS=8 MASON_PUBLISH=true - - os: osx - compiler: clang - env: JOBS=8 COVERAGE=true + compiler: ": clang-osx" + # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions + osx_image: xcode7.3 # upgrades clang from 6 -> 7 + env: JOBS=4 MASON_PUBLISH=true _CXX="ccache clang++ -Qunused-arguments" before_install: + # workaround travis rvm bug + # http://superuser.com/questions/1044130/why-am-i-having-how-can-i-fix-this-error-shell-session-update-command-not-f + - | + if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then + rvm get head || true + fi + - if [[ ${_CXX:-false} != false ]]; then export CXX=${_CXX}; fi + - if [[ ${_CC:-false} != false ]]; then export CC=${_CC}; fi + - source scripts/travis-common.sh + - export PYTHONUSERBASE=$(pwd)/mason_packages/.link + - export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PYTHONUSERBASE}/bin:${PATH} - export COVERAGE=${COVERAGE:-false} - export MASON_PUBLISH=${MASON_PUBLISH:-false} + - export BENCH=${BENCH:-false} - if [[ ${TRAVIS_BRANCH} != 'master' ]]; then export MASON_PUBLISH=false; fi - if [[ ${TRAVIS_PULL_REQUEST} != 'false' ]]; then export MASON_PUBLISH=false; fi + - git_submodule_update --init --depth=10 install: - - if [[ $(uname -s) == 'Linux' ]]; then - export CXX="ccache clang++-3.5 -Qunused-arguments"; - export CC="ccache clang-3.5 -Qunused-arguments"; - export PYTHONPATH=$(pwd)/mason_packages/.link/lib/python2.7/site-packages; - else - brew rm postgis --force; - brew install postgis --force; - pg_ctl -w start -l postgres.log --pgdata /usr/local/var/postgres; - createuser -s postgres; - export PYTHONPATH=$(pwd)/mason_packages/.link/lib/python/site-packages; - fi - - psql -c 'create database template_postgis;' -U postgres; - - psql -c 'create extension postgis;' -d template_postgis -U postgres; - - if [[ ${COVERAGE} == true ]]; then - PYTHONUSERBASE=$(pwd)/mason_packages/.link pip install --user cpp-coveralls; + - on 'linux' export PYTHONPATH=${PYTHONUSERBASE}/lib/python2.7/site-packages + - on 'osx' export PYTHONPATH=${PYTHONUSERBASE}/lib/python/site-packages + - on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres + - on 'osx' rm -rf ${DATA_PATH} + - on 'osx' initdb ${DATA_PATH} -E utf8 + - on 'osx' pg_ctl -w start -l postgres.log --pgdata ${DATA_PATH}; + - on 'osx' cat postgres.log; + - on 'osx' createuser -s postgres + - psql -c 'create database template_postgis;' -U postgres + - psql -c 'create extension postgis;' -d template_postgis -U postgres + - enabled ${COVERAGE} pip install --user cpp-coveralls + +before_script: + - source bootstrap.sh + - | + if [[ $(uname -s) == 'Linux' ]]; then + mason install clang 3.8.0 + export PATH=$(mason prefix clang 3.8.0)/bin:${PATH} + which clang++ + export LLVM_COV="$(mason prefix clang 3.8.0)/bin/llvm-cov" fi + - ccache --version + - ccache -p || true + - ccache --show-stats || true + - commit_message_parse script: - - source bootstrap.sh - - if [[ ${COVERAGE} == true ]]; then - ./configure CUSTOM_LDFLAGS='--coverage' CUSTOM_CXXFLAGS='--coverage' CUSTOM_CFLAGS='--coverage' DEBUG=True; - elif [[ ${MASON_PUBLISH} == true ]]; then - export MASON_NAME=mapnik; - export MASON_VERSION=latest; - export MASON_LIB_FILE=lib/libmapnik-wkt.a; - source ./.mason/mason.sh; - ./configure PREFIX=${MASON_PREFIX} PATH_REPLACE='' MAPNIK_BUNDLED_SHARE_DIRECTORY=True RUNTIME_LINK='static'; - else - ./configure; - fi + - export SCONSFLAGS='--debug=time' + - configure BENCHMARK=${BENCH} + - cat config.log - make - - make test || TEST_RESULT=$? - - if [[ ${COVERAGE} == true ]]; then - ./mason_packages/.link/bin/cpp-coveralls --build-root . --gcov-options '\-lp' --exclude mason_packages --exclude .sconf_temp --exclude benchmark --exclude deps --exclude scons --exclude test --exclude demo --exclude docs --exclude fonts --exclude utils > /dev/null; - fi - - if [[ ${COVERAGE} != true ]]; then - make bench; - fi - - if [[ ${TEST_RESULT} != 0 ]]; then exit $TEST_RESULT ; fi; - - if [[ ${MASON_PUBLISH} == true ]]; then - ./mason_latest.sh build; - ./mason_latest.sh link; + - make test + - enabled ${COVERAGE} coverage + - enabled ${BENCH} make bench + +after_success: + - enabled ${TRIGGER} trigger_downstream + - if enabled ${MASON_PUBLISH}; then + source ./.mason/mason.sh && + ./mason_latest.sh build && ./mason_latest.sh publish; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index c6114f8e4..9840af1ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,83 @@ Developers: Please commit along with changes. For a complete change history, see the git log. +## 3.0.12 + +Released: xx-xx-xx + +(Packaged from xxxxxx) + +#### Summary + +- Ensured gdal.input is registered once (refs #3093 #3339 #3340) +- Fixed `mapnik::util::is_clockwise` implementation to use coordinates relative to the origin and avoid numeric precision issues +- `mapnik-index` is updated to fail on first error in input (csv) +- Added `guard` to `get_object_severity` method (ref #3322) +- Improved `hash` calculation for `mapnik::value` (ref #3406) +- AGG - made cover `unsigned` to avoid left shift of negative values (ref #3406) +- Fixed using `scale_factor` in `evaluate_transform(..)` +- Fixed line spacing logic by applying `scale factor` +- ~~Fixed `stringify_object/stringify_array` implementations by disabling white space skipping (ref #3419)~~ +- Added geojson unit test for property types/values +- JSON - added support for object and array type in `json_value` and update `stringifier` +- GDAL.input - fallback to using `overviews` if present (8e8482803bb435726534c3b686a56037b7d3e8ad) +- TopoJSON.input - improved and simplified grammer/parser implementation (https://github.com/mapnik/mapnik/pull/3429) +- GDAL.input - Added support for non-alpha mask band +- TopoJSON.input - fixed order of ellements limitation (ref #3434) +- Fixed stroke-width size not included in markers ellipse bounding box (ref #3445) +- Implemented `char_array_buffer` and removed `boost::iostreams` dependency (2e8c0d36c2237f2815d8004c1b96bad909056eb9) +- JSON.input - `extract_bounding_box_grammar` - make features optional (ref #3463) +- Ensure input plugins return `empty_featureset` rather than `nullptr` (feature_ptr()) +- Added support for quantising small (less than 3 pixel) images (ref #3466) +- Added support for natural logarithm function in expressions (ref #3475) +- Improved logic determining if certain compiler features are available e.g `inheriting constructors` (MSVC) +- GeoJSON - corrected quoting in `stringgifird` objects (ref #3491) + +## 3.0.11 + +Released: April 1, 2016 + +(Packaged from 8d9dc27) + +#### Summary + + - Raster scaling: fixed crash and clipping negative pixel values of floating point rasters (https://github.com/mapnik/mapnik/pull/3349) + - Restored support for unquoted strings in expressions (https://github.com/mapnik/mapnik/pull/3390) + - [TWKB](https://github.com/TWKB/) support via https://github.com/mapnik/mapnik/pull/3356 (#3355) + - Visual test runner can render SVG, PDF and Postscript with Cairo renderer (https://github.com/mapnik/mapnik/pull/3418) + - Scale factor is now applied also to `text-line-spacing` and transforms (https://github.com/mapnik/mapnik/pull/3416) + +## 3.0.10 + +Released: February 25, 2016 + +(Packaged from 5c0d496) + +#### Summary + + - The `shapeindex` command now has a `--index-parts` option. When used the index will be bigger + but will allow the Shapefile datasource to only parse polygon parts within the query bounds. + - WARNING: index files generated with this newer Mapnik are invalid for older versions of Mapnik. + - Any `.index` files accompanying a `.shp` must now be regenerated otherwise + it will be skipped. To avoid this problem you can delete the existing `.index` files, or ideally run `shapeindex` to recreate the `.index`. (https://github.com/mapnik/mapnik/pull/3300) + The trigger for this change was an optimization that required a new binary format for the shapefile indexes (https://github.com/mapnik/mapnik/pull/3217). + - Shapeindex - another fix for skipping `null` shapes (#3288) + - Fixed support for filter expressions starting with `not` (https://github.com/mapnik/mapnik/issues/3017) + - Ensure `mapped_memory_cache` acts as singleton across shared objects (#3306) + - Removed miniz support in PNG encoder (#3281) + - Added `-fvisibility=hidden -fvisibility-inlines-hidden` to default compiler flags + - Fixed parsing of SVG `PathElement` (https://github.com/mapnik/mapnik/issues/3225) + - JSON parsing now supports arbitrary (nested) attributes in `geometry` + - Support for rendering `dash-array` in SVGs + - SVG parser is now stricter (fails is all input is not parsable) (#3251) + - SVG parser now correctly handles optional separator `(,)` between multiple command parts + - Optimized parsing of `png` format string + - The `memory_datasource` now dynamically reports correct datasource type (vector or raster) + - Upgraded `mapbox::variant v1.1.0` + - Compare: https://github.com/mapnik/mapnik/compare/v3.0.9...v3.0.10 + + + ## 3.0.9 Released: November 26, 2015 @@ -18,12 +95,12 @@ Released: November 26, 2015 - Fixed mapnik.util.variant issue when compiling with gcc-5.x and SSO enabled by default (https://github.com/mapnik/mapnik/issues/3103) (via @nkovacs) - Fixed issue with complex scripts where some character sequences weren't rendered correctly (https://github.com/mapnik/mapnik/issues/3050) (via @jkroll20) - Revived postgis.input tests - - JSON: geometry grammar has been refactored and optimized to have expectation points + - JSON: geometry grammar has been re-factored and optimized to have expectation points - Filled missing specializations for value_bool in `mapnik::value` comparison operators - `mapnik.Image` - fixed copy semantics implementation for internal buffer - JSON parsing: unified error_handler across all grammars - Improved unit test coverage - - Raster scaling: fixed nodata handling, acurracy when working with small floats and clipping floats by \[0; 255\] (https://github.com/mapnik/mapnik/pull/3147) + - Raster scaling: fixed nodata handling, accuracy when working with small floats and clipping floats by \[0; 255\] (https://github.com/mapnik/mapnik/pull/3147) - Added [`code of conduct`](http://contributor-covenant.org) - GeoJSON plug-in is updated to skip feature with empty geometries - GeoJSON plug-in : ensure original order of features is preserved (fixed) (https://github.com/mapnik/mapnik/issues/3182) @@ -41,9 +118,9 @@ Released: October 23, 2015 - Renamed `SHAPE_MEMORY_MAPPED_FILE` define to `MAPNIK_MEMORY_MAPPED_FILE`. Pass `./configure MEMORY_MAPPED_FILE=True|False` to request support for memory mapped files across Mapnik plugins (currently shape, csv, and geojson). - - Unified `mapnik-index` utility supporing GeoJSON and CSV formats + - Unified `mapnik-index` utility supporting GeoJSON and CSV formats - Increased unit test coverage for GeoJSON and CSV plugins - - shape.input - refactor to support *.shx and improve handling various bogus shapefiles + - shape.input - re-factor to support *.shx and improve handling various bogus shapefiles - geojson.input - make JSON parser stricter + support single Feature/Geometry as well as FeatureCollection - maintain 'FT_LOAD_NO_HINTING' + support >= harfbuzz 1.0.5 - geojson.input - implement on-disk-index support @@ -109,7 +186,7 @@ Released: August 26, 2015 #### Summary -- CSV.input: plug-in has been refactored to minimise memory usage and to improve handling of larger input. +- CSV.input: plug-in has been re-factored to minimise memory usage and to improve handling of larger input. (NOTE: [large_csv](https://github.com/mapnik/mapnik/tree/large_csv) branch adds experimental trunsduction parser with deferred string initialisation) - CSV.input: added internal spatial index (boost::geometry::index::tree) for fast `bounding box` queries (https://github.com/mapnik/mapnik/pull/3010) - Fixed deadlock in recursive datasource registration via @zerebubuth (https://github.com/mapnik/mapnik/pull/3038) @@ -499,8 +576,8 @@ Summary: The 2.2.0 release is primarily a performance and stability release. The - Enabled default input plugin directory and fonts path to be set inherited from environment settings in python bindings to make it easier to run tests locally (#1594). New environment settings are: - - MAPNIK_INPUT_PLUGINS_DIRECTORY - - MAPNIK_FONT_DIRECTORY + - MAPNIK_INPUT_PLUGINS_DIRECTORY + - MAPNIK_FONT_DIRECTORY - Added support for controlling rendering behavior of markers on multi-geometries `marker-multi-policy` (#1555,#1573) @@ -892,7 +969,7 @@ Released January, 19 2010 - Gdal Plugin: Added support for Gdal overviews, enabling fast loading of > 1GB rasters (#54) - * Use the gdaladdo utility to add overviews to existing GDAL datasets + * Use the gdaladdo utility to add overviews to existing GDAL datasets - PostGIS: Added an optional `geometry_table` parameter. The `geometry_table` used by Mapnik to look up metadata in the geometry_columns and calculate extents (when the `geometry_field` and `srid` parameters @@ -917,23 +994,23 @@ Released January, 19 2010 complex queries that may aggregate geometries to be kept fast by allowing proper placement of the bbox query to be used by indexes. (#415) - * Pass the bbox token inside a subquery like: !bbox! + * Pass the bbox token inside a subquery like: !bbox! - * Valid Usages include: + * Valid Usages include: - - (Select ST_Union(geom) as geom from table where ST_Intersects(geometry,!bbox!)) as map - + + (Select ST_Union(geom) as geom from table where ST_Intersects(geometry,!bbox!)) as map + - - (Select * from table where geom && !bbox!) as map - + + (Select * from table where geom && !bbox!) as map + - PostGIS Plugin: Added `scale_denominator` substitution ability in sql query string (#415/#465) - * Pass the scale_denominator token inside a subquery like: !scale_denominator! + * Pass the scale_denominator token inside a subquery like: !scale_denominator! - * e.g. (Select * from table where field_value > !scale_denominator!) as map + * e.g. (Select * from table where field_value > !scale_denominator!) as map - PostGIS Plugin: Added support for quoted table names (r1454) (#393) @@ -965,14 +1042,14 @@ Released January, 19 2010 - TextSymbolizer: Large set of new attributes: `text_transform`, `line_spacing`, `character_spacing`, `wrap_character`, `wrap_before`, `horizontal_alignment`, `justify_alignment`, and `opacity`. - * More details at changesets: r1254 and r1341 + * More details at changesets: r1254 and r1341 - SheildSymbolizer: Added special new attributes: `unlock_image`, `VERTEX` placement, `no_text` and many attributes previously only supported in the TextSymbolizer: `allow_overlap`, `vertical_alignment`, `horizontal_alignment`, `justify_alignment`, `wrap_width`, `wrap_character`, `wrap_before`, `text_transform`, `line_spacing`, `character_spacing`, and `opacity`. - * More details at changeset r1341 + * More details at changeset r1341 - XML: Added support for using CDATA with libxml2 parser (r1364) @@ -1200,7 +1277,7 @@ Released April 1, 2009 - Plugins: Use memory mapped files for reading shape file (r628) -- Core: Use streams to write images (i/o refactor) (r628) (#15) +- Core: Use streams to write images (i/o re-factor) (r628) (#15) # Mapnik 0.5.1 diff --git a/INSTALL.md b/INSTALL.md index 0776a6f72..8992144b1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -2,6 +2,13 @@ Mapnik runs on Linux, OS X, Windows, and BSD systems. +First clone mapnik from github and initialize submodules + +```bash +git clone https://github.com/mapnik/mapnik.git +git submodule update --init +``` + To configure and build Mapnik do: ```bash @@ -35,7 +42,6 @@ NOTE: the above will not work on windows, rather see https://github.com/mapnik/m Then to run the tests locally (without needing to install): - git submodule update --init make test Install like: @@ -92,7 +98,7 @@ Additional optional dependencies: * PostgreSQL (for PostGIS plugin support) - libpq - PostreSQL libraries - pg_config - PostgreSQL installation capabilities - * libgdal - GDAL/OGR input (For gdal and ogr plugin support) + * libgdal - GDAL/OGR input (For gdal and ogr plugin support) (>= GDAL 2.0.2 for thread safety - https://github.com/mapnik/mapnik/issues/3339) * libsqlite3 - SQLite input (needs RTree support builtin) (sqlite plugin support) Instructions for installing many of these dependencies on diff --git a/Makefile b/Makefile index 3ff06a59c..fd3a2add4 100755 --- a/Makefile +++ b/Makefile @@ -7,6 +7,10 @@ ifeq ($(JOBS),) JOBS:=1 endif +ifeq ($(HEAVY_JOBS),) + HEAVY_JOBS:=1 +endif + all: mapnik install: @@ -20,7 +24,8 @@ release: git clone --depth 1 --branch v$${MAPNIK_VERSION} git@github.com:mapnik/mapnik.git $${TARBALL_NAME} && \ cd $${TARBALL_NAME} && \ git checkout "tags/v$${MAPNIK_VERSION}" && \ - git submodule update --depth 1 --init && \ + git submodule update --depth 100 --init && \ + rm -rf deps/mapbox/variant/.git && \ rm -rf test/data/.git && \ rm -rf test/data/.gitignore && \ rm -rf test/data-visual/.git && \ @@ -37,22 +42,28 @@ python: python bindings/python/test/visual.py -q src/json/libmapnik-json.a: - # we first build memory intensive files with -j1 - $(PYTHON) scons/scons.py -j1 \ + # we first build memory intensive files with -j$(HEAVY_JOBS) + $(PYTHON) scons/scons.py -j$(HEAVY_JOBS) \ --config=cache --implicit-cache --max-drift=1 \ - src/renderer_common/process_group_symbolizer.os \ + src/renderer_common/render_group_symbolizer.os \ + src/renderer_common/render_markers_symbolizer.os \ + src/renderer_common/render_thunk_extractor.os \ src/json/libmapnik-json.a \ src/wkt/libmapnik-wkt.a \ src/css_color_grammar.os \ src/expression_grammar.os \ src/transform_expression_grammar.os \ - src/image_filter_types.os \ - src/agg/process_markers_symbolizer.os \ - src/agg/process_group_symbolizer.os \ - src/grid/process_markers_symbolizer.os \ - src/grid/process_group_symbolizer.os \ - src/cairo/process_markers_symbolizer.os \ - src/cairo/process_group_symbolizer.os \ + src/image_filter_grammar.os \ + src/marker_helpers.os \ + src/svg/svg_transform_parser.os \ + src/agg/process_line_symbolizer.os \ + plugins/input/geojson/geojson_datasource.os \ + utils/mapnik-index/process_geojson_file.o \ + src/svg/svg_path_parser.os \ + src/svg/svg_parser.os \ + src/svg/svg_points_parser.os \ + src/svg/svg_transform_parser.os \ + mapnik: src/json/libmapnik-json.a # then install the rest with -j$(JOBS) @@ -70,6 +81,8 @@ clean: @find ./src/ -name "*.so" -exec rm {} \; @find ./ -name "*.o" -exec rm {} \; @find ./src/ -name "*.a" -exec rm {} \; + @find ./ -name "*.gcda" -exec rm {} \; + @find ./ -name "*.gcno" -exec rm {} \; distclean: if test -e "config.py"; then mv "config.py" "config.py.backup"; fi diff --git a/README.md b/README.md index 18268deb6..e99df9825 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ _/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/ _/ ``` -[![Build Status Linux](https://secure.travis-ci.org/mapnik/mapnik.png)](http://travis-ci.org/mapnik/mapnik) -[![Build status Windows](https://ci.appveyor.com/api/projects/status/hc9l7okdjtucfqqn?svg=true)](https://ci.appveyor.com/project/Mapbox/mapnik) +[![Build Status Linux](https://api.travis-ci.org/mapnik/mapnik.svg?branch=master)](http://travis-ci.org/mapnik/mapnik) +[![CircleCI](https://circleci.com/gh/mapnik/mapnik.svg?style=svg)](https://circleci.com/gh/mapnik/mapnik) +[![Build Status Windows](https://ci.appveyor.com/api/projects/status/hc9l7okdjtucfqqn?branch=master&svg=true)](https://ci.appveyor.com/project/Mapbox/mapnik) [![Coverage Status](https://coveralls.io/repos/mapnik/mapnik/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapnik/mapnik?branch=master) Mapnik is an open source toolkit for developing mapping applications. At the core is a C++ shared library providing algorithms and patterns for spatial data access and visualization. @@ -20,7 +21,7 @@ For further information see [http://mapnik.org](http://mapnik.org) and also our # Installation -See [INSTALL.md](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides. +See [INSTALL.md](INSTALL.md) for installation instructions and the [Install](https://github.com/mapnik/mapnik/wiki/Mapnik-Installation) page on the wiki for guides. # Code of Conduct @@ -28,4 +29,4 @@ Please note that this project is released with a [Contributor Code of Conduct](h # License -Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html_)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information. +Mapnik software is free and is released under the LGPL ([GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html)). Please see [COPYING](https://github.com/mapnik/mapnik/blob/master/COPYING) for more information. diff --git a/SConstruct b/SConstruct index b3c1a1903..6437b3b1d 100644 --- a/SConstruct +++ b/SConstruct @@ -294,7 +294,9 @@ opts.AddVariables( 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('COVERAGE', 'Compile a libmapnik and plugins with --coverage', 'False'), BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'), + BoolVariable('DEBUG_SANITIZE', 'Compile a version of Mapnik using clang/llvm address sanitation', 'False'), ListVariable('INPUT_PLUGINS','Input drivers to include',DEFAULT_PLUGINS,PLUGINS.keys()), ('WARNING_CXXFLAGS', 'Compiler flags you can set to reduce warning levels which are placed after -Wall.', ''), @@ -303,6 +305,7 @@ opts.AddVariables( ('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'), BoolVariable('NO_ATEXIT', 'Will prevent Singletons from being deleted atexit of main thread', 'False'), + BoolVariable('NO_DLCLOSE', 'Will prevent plugins from being unloaded', 'False'), # http://www.scons.org/wiki/GoFastButton # http://stackoverflow.com/questions/1318863/how-to-optimize-an-scons-script BoolVariable('FAST', "Make SCons faster at the cost of less precise dependency tracking", 'False'), @@ -317,7 +320,6 @@ opts.AddVariables( ('PATH_REMOVE', 'A path prefix to exclude from all known command and compile paths (create multiple excludes separated by :)', ''), ('PATH_REPLACE', 'Two path prefixes (divided with a :) to search/replace from all known command and compile paths', ''), ('MAPNIK_NAME', 'Name of library', 'mapnik'), - BoolVariable('MAPNIK_BUNDLED_SHARE_DIRECTORY', 'For portable packaging: instruct mapnik-config to report relative paths to bundled GDAL_DATA, PROJ_LIB, and ICU_DATA','False'), # Boost variables # default is '/usr/include', see FindBoost method below @@ -703,11 +705,7 @@ def FindBoost(context, prefixes, thread_flag): BOOST_INCLUDE_DIR = None BOOST_APPEND = None env['BOOST_APPEND'] = str() - - if env['THREADING'] == 'multi': - search_lib = 'libboost_thread' - else: - search_lib = 'libboost_filesystem' + search_lib = 'libboost_filesystem' # note: must call normpath to strip trailing slash otherwise dirname # does not remove 'lib' and 'include' @@ -1139,6 +1137,9 @@ if not preconfigured: else: mode = 'release mode' + if env['COVERAGE']: + mode += ' (with coverage)' + env['PLATFORM'] = platform.uname()[0] color_print(4,"Configuring on %s in *%s*..." % (env['PLATFORM'],mode)) @@ -1355,7 +1356,7 @@ if not preconfigured: # test for C++11 support, which is required if not env['HOST'] and not conf.supports_cxx11(): - color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler to at least g++ 4.7 (ideally 4.8)") + color_print(1,"C++ compiler does not support C++11 standard (-std=c++11), which is required. Please upgrade your compiler") Exit(1) if not env['HOST']: @@ -1407,15 +1408,6 @@ if not preconfigured: ['program_options', 'boost/program_options.hpp', False] ] - if env['THREADING'] == 'multi': - BOOST_LIBSHEADERS.append(['thread', 'boost/thread/mutex.hpp', True]) - # on solaris the configure checks for boost_thread - # require the -pthreads flag to be able to check for - # threading support, so we add as a global library instead - # of attaching to cxxflags after configure - if env['PLATFORM'] == 'SunOS': - env.Append(CXXFLAGS = '-pthreads') - # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests if env['PRIORITIZE_LINKING']: conf.prioritize_paths(silent=True) @@ -1447,12 +1439,13 @@ if not preconfigured: # just turn it off like this, but seems the only available work- # around. See https://svn.boost.org/trac/boost/ticket/6779 for more # details. - boost_version = [int(x) for x in env.get('BOOST_LIB_VERSION_FROM_HEADER').split('_')] - if not conf.CheckBoostScopedEnum(): - if boost_version < [1, 51]: - env.Append(CXXFLAGS = '-DBOOST_NO_SCOPED_ENUMS') - elif boost_version < [1, 57]: - env.Append(CXXFLAGS = '-DBOOST_NO_CXX11_SCOPED_ENUMS') + if not env['HOST']: + boost_version = [int(x) for x in env.get('BOOST_LIB_VERSION_FROM_HEADER').split('_')] + if not conf.CheckBoostScopedEnum(): + if boost_version < [1, 51]: + env.Append(CXXFLAGS = '-DBOOST_NO_SCOPED_ENUMS') + elif boost_version < [1, 57]: + env.Append(CXXFLAGS = '-DBOOST_NO_CXX11_SCOPED_ENUMS') if not env['HOST'] and env['ICU_LIB_NAME'] not in env['MISSING_DEPS']: # http://lists.boost.org/Archives/boost/2009/03/150076.php @@ -1605,6 +1598,7 @@ if not preconfigured: # prepend to make sure we link locally env.Prepend(CPPPATH = '#deps/agg/include') env.Prepend(LIBPATH = '#deps/agg') + env.Prepend(CPPPATH = '#deps/mapbox/variant/include') # prepend deps dir for auxillary headers env.Prepend(CPPPATH = '#deps') @@ -1630,7 +1624,7 @@ if not preconfigured: env["CAIRO_ALL_LIBS"] = ['cairo'] if env['RUNTIME_LINK'] == 'static': env["CAIRO_ALL_LIBS"].extend( - ['pixman-1','expat'] + ['pixman-1'] ) # todo - run actual checkLib? env['HAS_CAIRO'] = True @@ -1727,6 +1721,9 @@ if not preconfigured: if env['NO_ATEXIT']: env.Append(CPPDEFINES = '-DMAPNIK_NO_ATEXIT') + if env['NO_DLCLOSE'] or env['COVERAGE']: + env.Append(CPPDEFINES = '-DMAPNIK_NO_DLCLOSE') + # Mac OSX (Darwin) special settings if env['PLATFORM'] == 'Darwin': pthread = '' @@ -1786,20 +1783,24 @@ if not preconfigured: # Common flags for g++/clang++ CXX compiler. # TODO: clean up code more to make -Wextra -Wsign-compare -Wsign-conversion -Wconversion viable - common_cxx_flags = '-Wall %s %s -ftemplate-depth-300 -Wsign-compare -Wshadow ' % (env['WARNING_CXXFLAGS'], pthread) + # -Wfloat-equal -Wold-style-cast -Wexit-time-destructors -Wglobal-constructors -Wreserved-id-macro -Wheader-hygiene -Wmissing-noreturn + common_cxx_flags = '-fvisibility=hidden -fvisibility-inlines-hidden -Wall %s %s -ftemplate-depth-300 -Wsign-compare -Wshadow ' % (env['WARNING_CXXFLAGS'], pthread) if 'clang++' in env['CXX']: - common_cxx_flags += ' -Wno-unsequenced ' + common_cxx_flags += ' -Wno-unsequenced -Wtautological-compare -Wheader-hygiene ' if env['DEBUG']: env.Append(CXXFLAGS = common_cxx_flags + '-O0') else: - # TODO - add back -fvisibility-inlines-hidden - # https://github.com/mapnik/mapnik/issues/1863 env.Append(CXXFLAGS = common_cxx_flags + '-O%s' % (env['OPTIMIZATION'])) if env['DEBUG_UNDEFINED']: env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv') + if env['DEBUG_SANITIZE']: + env.Append(CXXFLAGS = ['-fsanitize=address']) + env.Append(LINKFLAGS = ['-fsanitize=address']) + + # if requested, sort LIBPATH and CPPPATH one last time before saving... if env['PRIORITIZE_LINKING']: conf.prioritize_paths(silent=True) @@ -1888,6 +1889,10 @@ if not HELP_REQUESTED: plugin_base = env.Clone() + if env['COVERAGE']: + plugin_base.Append(LINKFLAGS='--coverage') + plugin_base.Append(CXXFLAGS='--coverage') + Export('plugin_base') if env['FAST']: diff --git a/appveyor.yml b/appveyor.yml index 6566a9ab5..34ddc3b6a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ environment: msvs_toolset: 14 - BOOST_VERSION: 59 + BOOST_VERSION: 60 FASTBUILD: 1 matrix: - platform: x64 @@ -8,11 +8,24 @@ environment: os: Visual Studio 2015 -shallow_clone: true +#shallow_clone: true +# limit clone to latest 5 commits +clone_depth: 5 + +services: + - postgresql94 #if changing this, also change PATH below install: + - SET PGUSER=postgres + - SET PGPASSWORD=Password12! + - SET PATH=C:\Program Files\PostgreSQL\9.4\bin\;%PATH% + +build_script: - scripts\build-appveyor.bat +after_build: + - 7z a mapnik-visual-images.zip C:\tmp\mapnik-visual-images + artifacts: - path: mapnik-gyp\msbuild-summary.txt name: msbuild-summary.txt @@ -20,7 +33,8 @@ artifacts: name: msbuild-errors.txt - path: mapnik-gyp\msbuild-warnings.txt name: msbuild-warnings.txt + - path: mapnik-visual-images.zip + name: mapnik-visual-images.zip -build: off test: off deploy: off diff --git a/benchmark/bench_framework.hpp b/benchmark/bench_framework.hpp index 52088e4e1..a3de4fdd9 100644 --- a/benchmark/bench_framework.hpp +++ b/benchmark/bench_framework.hpp @@ -1,7 +1,8 @@ -#ifndef __MAPNIK_BENCH_FRAMEWORK_HPP__ -#define __MAPNIK_BENCH_FRAMEWORK_HPP__ +#ifndef MAPNIK_BENCH_FRAMEWORK_HPP +#define MAPNIK_BENCH_FRAMEWORK_HPP // mapnik +#include #include #include #include @@ -9,7 +10,8 @@ // stl #include -#include +#include // log10, round +#include // snprintf #include #include #include @@ -18,6 +20,12 @@ namespace benchmark { +template +using milliseconds = std::chrono::duration; + +template +using seconds = std::chrono::duration; + class test_case { protected: @@ -38,26 +46,78 @@ public: { return iterations_; } + mapnik::parameters const& params() const + { + return params_; + } virtual bool validate() const = 0; virtual bool operator()() const = 0; - virtual ~test_case() {} }; -void handle_args(int argc, char** argv, mapnik::parameters & params) +// gathers --long-option values in 'params'; +// returns the index of the first non-option argument, +// or negated index of an ill-formed option argument +inline int parse_args(int argc, char** argv, mapnik::parameters & params) { - if (argc > 0) { - for (int i=1;i("log")) { + if (*severity == "debug") + mapnik::logger::set_severity(mapnik::logger::debug); + else if (*severity == "warn") + mapnik::logger::set_severity(mapnik::logger::warn); + else if (*severity == "error") + mapnik::logger::set_severity(mapnik::logger::error); + else if (*severity == "none") + mapnik::logger::set_severity(mapnik::logger::none); + else + std::clog << "ignoring option --log='" << *severity + << "' (allowed values are: debug, warn, error, none)\n"; + } +} + +inline int handle_args(int argc, char** argv, mapnik::parameters & params) +{ + int res = parse_args(argc, argv, params); + handle_common_args(params); + return res; } #define BENCHMARK(test_class,name) \ @@ -80,6 +140,29 @@ void handle_args(int argc, char** argv, mapnik::parameters & params) } \ } \ +struct big_number_fmt +{ + int w; + double v; + const char* u; + + big_number_fmt(int width, double value, int base = 1000) + : w(width), v(value), u("") + { + static const char* suffixes = "\0\0k\0M\0G\0T\0P\0E\0Z\0Y\0\0"; + u = suffixes; + + while (v > 1 && std::log10(std::round(v)) >= width && u[2]) + { + v /= base; + u += 2; + } + + // adjust width for proper alignment without suffix + w += (u == suffixes); + } +}; + template int run(T const& test_runner, std::string const& name) { @@ -88,52 +171,120 @@ int run(T const& test_runner, std::string const& name) if (!test_runner.validate()) { std::clog << "test did not validate: " << name << "\n"; - return -1; + return 1; } // run test once before timing // if it returns false then we'll abort timing - if (test_runner()) + if (!test_runner()) { - std::chrono::high_resolution_clock::time_point start; - std::chrono::high_resolution_clock::duration elapsed; - std::stringstream s; - s << name << ":" - << std::setw(45 - (int)s.tellp()) << std::right - << " t:" << test_runner.threads() - << " i:" << test_runner.iterations(); - if (test_runner.threads() > 0) + return 2; + } + + std::chrono::high_resolution_clock::time_point start; + std::chrono::high_resolution_clock::duration elapsed; + auto opt_min_duration = test_runner.params().template get("min-duration", 0.0); + std::chrono::duration min_seconds(*opt_min_duration); + auto min_duration = std::chrono::duration_cast(min_seconds); + auto num_iters = test_runner.iterations(); + auto num_threads = test_runner.threads(); + auto total_iters = 0; + + if (num_threads > 0) + { + std::mutex mtx_ready; + std::unique_lock lock_ready(mtx_ready); + + auto stub = [&](T const& test_copy) { - using thread_group = std::vector >; - using value_type = thread_group::value_type; - thread_group tg; - for (std::size_t i=0;ijoinable()) t->join();}); - elapsed = std::chrono::high_resolution_clock::now() - start; + // workers will wait on this mutex until the main thread + // constructs all of them and starts measuring time + std::unique_lock my_lock(mtx_ready); + my_lock.unlock(); + test_copy(); + }; + + std::vector tg; + tg.reserve(num_threads); + for (auto i = num_threads; i-- > 0; ) + { + tg.emplace_back(stub, test_runner); } - else + start = std::chrono::high_resolution_clock::now(); + lock_ready.unlock(); + // wait for all workers to finish + for (auto & t : tg) { - start = std::chrono::high_resolution_clock::now(); + if (t.joinable()) + t.join(); + } + elapsed = std::chrono::high_resolution_clock::now() - start; + // this is actually per-thread count, not total, but I think + // reporting average 'iters/thread/second' is more useful + // than 'iters/second' multiplied by the number of threads + total_iters += num_iters; + } + else + { + start = std::chrono::high_resolution_clock::now(); + do { test_runner(); elapsed = std::chrono::high_resolution_clock::now() - start; - } - s << std::setw(65 - (int)s.tellp()) << std::right - << std::chrono::duration_cast(elapsed).count() << " milliseconds\n"; - std::clog << s.str(); + total_iters += num_iters; + } while (elapsed < min_duration); } + + char msg[200]; + double dur_total = milliseconds(elapsed).count(); + auto elapsed_nonzero = std::max(elapsed, decltype(elapsed){1}); + big_number_fmt itersf(4, total_iters); + big_number_fmt ips(5, total_iters / seconds(elapsed_nonzero).count()); + + std::snprintf(msg, sizeof(msg), + "%-43s %3zu threads %*.0f%s iters %6.0f milliseconds %*.0f%s i/s\n", + name.c_str(), + num_threads, + itersf.w, itersf.v, itersf.u, + dur_total, + ips.w, ips.v, ips.u + ); + std::clog << msg; return 0; } catch (std::exception const& ex) { std::clog << "test runner did not complete: " << ex.what() << "\n"; - return -1; + return 4; } - return 0; } +struct sequencer +{ + sequencer(int argc, char** argv) + : exit_code_(0) + { + benchmark::handle_args(argc, argv, params_); + } + + int done() const + { + return exit_code_; + } + + template + sequencer & run(std::string const& name, Args && ...args) + { + // Test instance lifetime is confined to this function + Test test_runner(params_, std::forward(args)...); + // any failing test run will make exit code non-zero + exit_code_ |= benchmark::run(test_runner, name); + return *this; // allow chaining calls + } + +protected: + mapnik::parameters params_; + int exit_code_; +}; + } -#endif // __MAPNIK_BENCH_FRAMEWORK_HPP__ +#endif // MAPNIK_BENCH_FRAMEWORK_HPP diff --git a/benchmark/compare_images.hpp b/benchmark/compare_images.hpp index fb0e4ac95..ff90e01a0 100644 --- a/benchmark/compare_images.hpp +++ b/benchmark/compare_images.hpp @@ -1,11 +1,10 @@ -#ifndef __MAPNIK_COMPARE_IMAGES_HPP__ -#define __MAPNIK_COMPARE_IMAGES_HPP__ +#ifndef MAPNIK_COMPARE_IMAGES_HPP +#define MAPNIK_COMPARE_IMAGES_HPP #include #include #include -using namespace mapnik; namespace benchmark { @@ -23,15 +22,15 @@ namespace benchmark { throw mapnik::image_reader_exception("Failed to load: " + src_fn); } - const image_any desc_any = reader1->read(0,0,reader1->width(), reader1->height()); - const image_any src_any = reader2->read(0,0,reader2->width(), reader2->height()); + const mapnik::image_any desc_any = reader1->read(0,0,reader1->width(), reader1->height()); + const mapnik::image_any src_any = reader2->read(0,0,reader2->width(), reader2->height()); - image_rgba8 const& dest = util::get(desc_any); - image_rgba8 const& src = util::get(src_any); + mapnik::image_rgba8 const& dest = mapnik::util::get(desc_any); + mapnik::image_rgba8 const& src = mapnik::util::get(src_any); return compare(dest, src, 0, true) == 0; } } -#endif // __MAPNIK_COMPARE_IMAGES_HPP__ +#endif // MAPNIK_COMPARE_IMAGES_HPP diff --git a/benchmark/run b/benchmark/run index 00285b2ba..6a8fdd938 100755 --- a/benchmark/run +++ b/benchmark/run @@ -6,8 +6,14 @@ source ./localize.sh BASE=./benchmark/out function run { - ${BASE}/$1 --threads 0 --iterations $3; - ${BASE}/$1 --threads $2 --iterations $(expr $3 / $2); + local runner="$BASE/$1 --log=none" + local threads="$2" + local iters="$3" + shift 3 + $runner --threads 0 --iterations $iters "$@" + if test $threads -gt 0; then + $runner --threads $threads --iterations $((iters/threads)) "$@" + fi } run test_getline 30 10000000 #run test_array_allocation 20 100000 @@ -23,6 +29,8 @@ run test_face_ptr_creation 10 1000 run test_font_registration 10 100 run test_offset_converter 10 1000 +# commented since this is really slow on travis +: ' ./benchmark/out/test_rendering \ --name "text rendering" \ --map benchmark/data/roads.xml \ @@ -31,6 +39,7 @@ run test_offset_converter 10 1000 --height 600 \ --iterations 20 \ --threads 10 +' ./benchmark/out/test_rendering \ --name "gdal tiff rendering" \ diff --git a/benchmark/test_array_allocation.cpp b/benchmark/test_array_allocation.cpp index fda9bb6ab..186c1620e 100644 --- a/benchmark/test_array_allocation.cpp +++ b/benchmark/test_array_allocation.cpp @@ -231,33 +231,6 @@ public: } }; -class test3d : public benchmark::test_case -{ -public: - uint32_t size_; - std::vector array_; - test3d(mapnik::parameters const& params) - : test_case(params), - size_(*params.get("size",256*256)), - array_(size_,0) { } - bool validate() const - { - return true; - } - bool operator()() const - { - for (std::size_t i=0;i data(size_); - for (std::size_t i=0;i("calloc") + .run("malloc/memcpy") + .run("malloc/memset") + .run("operator new/std::fill") + .run("operator new/memcpy") + .run("vector(N)") + .run("vector/resize") + .run("vector/assign") + .run("deque(N)") + .run("std::string range") + .run("std::string &[0]") + .run("valarray") #if BOOST_VERSION >= 105400 - { - test7 test_runner(params); - return_value = return_value | run(test_runner,"static_vector"); - } + .run("static_vector") #endif - return return_value; + .done(); } diff --git a/benchmark/test_getline.cpp b/benchmark/test_getline.cpp index 1791b06cf..ed21c0421 100644 --- a/benchmark/test_getline.cpp +++ b/benchmark/test_getline.cpp @@ -1,7 +1,7 @@ #include "bench_framework.hpp" -#include -#include -#include "../plugins/input/csv/csv_utils.hpp" +#include "../plugins/input/csv/csv_getline.hpp" + + class test : public benchmark::test_case { diff --git a/benchmark/test_numeric_cast_vs_static_cast.cpp b/benchmark/test_numeric_cast_vs_static_cast.cpp index 8ea6e6be1..9e14bf31e 100644 --- a/benchmark/test_numeric_cast_vs_static_cast.cpp +++ b/benchmark/test_numeric_cast_vs_static_cast.cpp @@ -73,16 +73,8 @@ public: int main(int argc, char** argv) { - mapnik::parameters params; - benchmark::handle_args(argc,argv,params); - int return_value = 0; - { - test_static test_runner(params); - return_value = return_value | run(test_runner,"static_cast"); - } - { - test_numeric test_runner(params); - return_value = return_value | run(test_runner,"numeric_cast"); - } - return return_value; + return benchmark::sequencer(argc, argv) + .run("static_cast") + .run("numeric_cast") + .done(); } diff --git a/benchmark/test_png_encoding1.cpp b/benchmark/test_png_encoding1.cpp index 55d3f18af..ec98f2884 100644 --- a/benchmark/test_png_encoding1.cpp +++ b/benchmark/test_png_encoding1.cpp @@ -19,8 +19,8 @@ public: out.clear(); out = mapnik::save_to_string(im_,"png8:m=h:z=1"); } + return true; } - return true; }; BENCHMARK(test,"encoding blank png") diff --git a/benchmark/test_png_encoding2.cpp b/benchmark/test_png_encoding2.cpp index 640050c0d..910a9ac95 100644 --- a/benchmark/test_png_encoding2.cpp +++ b/benchmark/test_png_encoding2.cpp @@ -30,8 +30,8 @@ public: out.clear(); out = mapnik::save_to_string(*im_,"png8:m=h:z=1"); } + return true; } - return true; }; BENCHMARK(test,"encoding multicolor png") diff --git a/benchmark/test_polygon_clipping_rendering.cpp b/benchmark/test_polygon_clipping_rendering.cpp index ab23459c4..758505d9d 100644 --- a/benchmark/test_polygon_clipping_rendering.cpp +++ b/benchmark/test_polygon_clipping_rendering.cpp @@ -51,30 +51,10 @@ int main(int argc, char** argv) mapnik::box2d z1(-20037508.3428,-8317435.0606,20037508.3428,18399242.7298); // bbox for 16/10491/22911.png mapnik::box2d z16(-13622912.929097254,6026906.8062295765,-13621689.93664469,6028129.79868214); - int return_value = 0; - { - test test_runner(params, - "benchmark/data/polygon_rendering_clip.xml", - z1); - return_value = return_value | run(test_runner,"polygon clip render z1"); - } - { - test test_runner(params, - "benchmark/data/polygon_rendering_no_clip.xml", - z1); - return_value = return_value | run(test_runner,"polygon noclip render z1"); - } - { - test test_runner(params, - "benchmark/data/polygon_rendering_clip.xml", - z16); - return_value = return_value | run(test_runner,"polygon clip render z16"); - } - { - test test_runner(params, - "benchmark/data/polygon_rendering_no_clip.xml", - z16); - return_value = return_value | run(test_runner,"polygon noclip render z16"); - } - return return_value; + return benchmark::sequencer(argc, argv) + .run("polygon clip render z1", "benchmark/data/polygon_rendering_clip.xml", z1) + .run("polygon noclip render z1", "benchmark/data/polygon_rendering_no_clip.xml", z1) + .run("polygon clip render z16", "benchmark/data/polygon_rendering_clip.xml", z16) + .run("polygon noclip render z16", "benchmark/data/polygon_rendering_no_clip.xml", z16) + .done(); } diff --git a/benchmark/test_proj_transform1.cpp b/benchmark/test_proj_transform1.cpp index 451c51ae1..37f4b0c4c 100644 --- a/benchmark/test_proj_transform1.cpp +++ b/benchmark/test_proj_transform1.cpp @@ -59,42 +59,16 @@ public: // echo -180 -60 | cs2cs -f "%.10f" +init=epsg:4326 +to +init=epsg:3857 int main(int argc, char** argv) { - mapnik::parameters params; - benchmark::handle_args(argc,argv,params); mapnik::box2d from(-180,-80,180,80); mapnik::box2d to(-20037508.3427892476,-15538711.0963092316,20037508.3427892476,15538711.0963092316); std::string from_str("+init=epsg:4326"); std::string to_str("+init=epsg:3857"); std::string from_str2("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); std::string to_str2("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"); - int return_value = 0; - test test_runner(params, - from_str, - to_str, - from, - to, - true); - return_value = return_value | run(test_runner,"lonlat->merc epsg"); - test test_runner2(params, - from_str2, - to_str2, - from, - to, - true); - return_value = return_value | run(test_runner2,"lonlat->merc literal"); - test test_runner3(params, - to_str, - from_str, - to, - from, - true); - return_value = return_value | run(test_runner3,"merc->lonlat epsg"); - test test_runner4(params, - to_str2, - from_str2, - to, - from, - true); - return_value = return_value | run(test_runner4,"merc->lonlat literal"); - return return_value; + return benchmark::sequencer(argc, argv) + .run("lonlat->merc epsg", from_str, to_str, from, to, true) + .run("lonlat->merc literal", from_str2, to_str2, from, to, true) + .run("merc->lonlat epsg", to_str, from_str, to, from, true) + .run("merc->lonlat literal", to_str2, from_str2, to, from, true) + .done(); } diff --git a/bootstrap.sh b/bootstrap.sh index b148139bd..113d60f8c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash -#set -eu +set -eu +set -o pipefail : ' @@ -10,67 +11,75 @@ todo - shrink icu data ' +MASON_VERSION="7ed8931" + function setup_mason() { if [[ ! -d ./.mason ]]; then - git clone --depth 1 https://github.com/mapbox/mason.git ./.mason + git clone https://github.com/mapbox/mason.git ./.mason + (cd ./.mason && git checkout ${MASON_VERSION}) else echo "Updating to latest mason" - (cd ./.mason && git pull) + (cd ./.mason && git fetch && git checkout ${MASON_VERSION}) fi - export MASON_DIR=$(pwd)/.mason export PATH=$(pwd)/.mason:$PATH export CXX=${CXX:-clang++} export CC=${CC:-clang} } -if [[ $(uname -s) == 'Darwin' ]]; then - FIND_PATTERN="\/Users\/travis\/build\/mapbox\/mason" -else - FIND_PATTERN="\/home\/travis\/build\/mapbox\/mason" -fi - -REPLACE="$(pwd)" -REPLACE=${REPLACE////\\/} - function install() { MASON_PLATFORM_ID=$(mason env MASON_PLATFORM_ID) if [[ ! -d ./mason_packages/${MASON_PLATFORM_ID}/${1}/${2} ]]; then mason install $1 $2 - mason link $1 $2 - if [[ $3 ]]; then - LA_FILE=$(${MASON_DIR:-~/.mason}/mason prefix $1 $2)/lib/$3.la + if [[ ${3:-false} != false ]]; then + LA_FILE=$(mason prefix $1 $2)/lib/$3.la if [[ -f ${LA_FILE} ]]; then - perl -i -p -e "s/${FIND_PATTERN}/${REPLACE}/g;" ${LA_FILE} + perl -i -p -e 's:\Q$ENV{HOME}/build/mapbox/mason\E:$ENV{PWD}:g' ${LA_FILE} else echo "$LA_FILE not found" fi fi fi + mason link $1 $2 } ICU_VERSION="55.1" function install_mason_deps() { - install gdal 1.11.2 libgdal & - install boost 1.59.0 & - install boost_liball 1.59.0 & - install freetype 2.6 libfreetype & - install harfbuzz 0.9.40 libharfbuzz & + FAIL=0 + install ccache 3.2.4 & install jpeg_turbo 1.4.0 libjpeg & - install libpng 1.6.17 libpng & - install webp 0.4.2 libwebp & + install libpng 1.6.20 libpng & + install libtiff 4.0.4beta libtiff & + install libpq 9.4.1 & + install sqlite 3.8.8.3 libsqlite3 & + install expat 2.1.0 libexpat & install icu ${ICU_VERSION} & install proj 4.8.0 libproj & - install libtiff 4.0.4beta libtiff & - install libpq 9.4.0 & - install sqlite 3.8.8.1 libsqlite3 & - install expat 2.1.0 libexpat & install pixman 0.32.6 libpixman-1 & install cairo 1.14.2 libcairo & install protobuf 2.6.1 & - wait # technically protobuf is not a mapnik core dep, but installing # here by default helps make mapnik-vector-tile builds easier + install webp 0.5.0 libwebp & + install gdal 1.11.2 libgdal & + install boost 1.61.0 & + install boost_libsystem 1.61.0 & + install boost_libfilesystem 1.61.0 & + install boost_libprogram_options 1.61.0 & + install boost_libregex_icu 1.61.0 & + # technically boost thread and python are not a core dep, but installing + # here by default helps make python-mapnik builds easier + install boost_libthread 1.61.0 & + install boost_libpython 1.61.0 & + install freetype 2.6 libfreetype & + install harfbuzz 0.9.41 libharfbuzz & + for job in $(jobs -p) + do + wait $job || let "FAIL+=1" + done + if [[ "$FAIL" != "0" ]]; then + exit ${FAIL} + fi } MASON_LINKED_ABS=$(pwd)/mason_packages/.link @@ -80,22 +89,15 @@ export CPLUS_INCLUDE_PATH="${MASON_LINKED_ABS}/include" export LIBRARY_PATH="${MASON_LINKED_ABS}/lib" function make_config() { - if [[ $(uname -s) == 'Darwin' ]]; then - local PATH_REPLACE="/Users/travis/build/mapbox/mason/mason_packages:./mason_packages" - else - local PATH_REPLACE="/home/travis/build/mapbox/mason/mason_packages:./mason_packages" - fi - echo " CXX = '$CXX' CC = '$CC' -CUSTOM_CXXFLAGS = '-fvisibility=hidden -fvisibility-inlines-hidden -DU_CHARSET_IS_UTF8=1' RUNTIME_LINK = 'static' INPUT_PLUGINS = 'all' PATH = '${MASON_LINKED_REL}/bin' PKG_CONFIG_PATH = '${MASON_LINKED_REL}/lib/pkgconfig' PATH_REMOVE = '/usr:/usr/local' -PATH_REPLACE = '${PATH_REPLACE}' +PATH_REPLACE = '$HOME/build/mapbox/mason/mason_packages:./mason_packages' BOOST_INCLUDES = '${MASON_LINKED_REL}/include' BOOST_LIBS = '${MASON_LINKED_REL}/lib' ICU_INCLUDES = '${MASON_LINKED_REL}/include' @@ -126,8 +128,7 @@ CPP_TESTS = True PGSQL2SQLITE = True XMLPARSER = 'ptree' SVG2PNG = True -SAMPLE_INPUT_PLUGINS = True -" > ./config.py +" } # NOTE: the `mapnik-settings.env` is used by test/run (which is run by `make test`) @@ -141,7 +142,7 @@ function setup_runtime_settings() { function main() { setup_mason install_mason_deps - make_config + make_config > ./config.py setup_runtime_settings echo "Ready, now run:" echo "" @@ -149,3 +150,8 @@ function main() { } main + +# allow sourcing of script without +# causing the terminal to bail on error +set +eu +set +o pipefail diff --git a/circle.yml b/circle.yml new file mode 100644 index 000000000..435cd077b --- /dev/null +++ b/circle.yml @@ -0,0 +1,45 @@ +machine: + xcode: + version: 7.3 + environment: + XCODE_SCHEME: "no" + XCODE_WORKSPACE: "no" + JOBS: 8 + CCACHE_TEMPDIR: /tmp/.ccache-temp + CCACHE_COMPRESS: 1 + LLVM_VERSION: 3.8 + pre: + - echo "here" + post: + - echo "there" + +checkout: + post: + - git submodule update --init + +dependencies: + cache_directories: + - "~/.ccache" + - "~/.apt-cache" + pre: + # https://discuss.circleci.com/t/add-ability-to-cache-apt-get-programs/598/3 + - sudo rm -rf /var/cache/apt/archives && sudo ln -s ~/.apt-cache /var/cache/apt/archives && mkdir -p ~/.apt-cache/partial + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + override: + - sudo apt-get update -y + - sudo apt-get install -y libstdc++-5-dev xutils + +database: + pre: + - ./bootstrap.sh + - ./.mason/mason install clang ${LLVM_VERSION}.0 + - ./.mason/mason link clang ${LLVM_VERSION}.0 + - ./configure CC="$(pwd)/mason_packages/.link/bin/clang-${LLVM_VERSION}" CXX="$(pwd)/mason_packages/.link/bin/ccache $(pwd)/mason_packages/.link/bin/clang++-${LLVM_VERSION} -Qunused-arguments" + - make + override: + - psql -c 'create database template_postgis;' + - psql -c 'create extension postgis;' -d template_postgis + +test: + override: + - make test diff --git a/demo/c++/README.md b/demo/c++/README.md index daa4198c1..548508ee0 100644 --- a/demo/c++/README.md +++ b/demo/c++/README.md @@ -52,11 +52,11 @@ If you do not have svn installed you can grab gyp from: Simply type: - make + make Then to run do: - ./rundemo `mapnik-config --prefix` + ./rundemo `mapnik-config --prefix` On OS X you can also create an xcode project: diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index c07bd5c31..c20c288cf 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -55,7 +55,7 @@ int main ( int, char** ) try { std::cout << " running demo ... \n"; datasource_cache::instance().register_datasources("plugins/input/"); - freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.34/ttf/DejaVuSans.ttf"); + freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf"); Map m(800,600); m.set_background(parse_color("white")); @@ -230,7 +230,7 @@ int main ( int, char** ) parameters p; p["type"]="shape"; p["file"]="demo/data/boundaries"; - p["encoding"]="latin1"; + p["encoding"]="utf8"; layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance().create(p)); @@ -295,7 +295,7 @@ int main ( int, char** ) parameters p; p["type"]="shape"; p["file"]="demo/data/popplaces"; - p["encoding"] = "latin1"; + p["encoding"] = "utf8"; layer lyr("Populated Places"); lyr.set_srs(srs_lcc); lyr.set_datasource(datasource_cache::instance().create(p)); diff --git a/demo/data/boundaries.dbf b/demo/data/boundaries.dbf index aeed23561..04d2ed661 100644 Binary files a/demo/data/boundaries.dbf and b/demo/data/boundaries.dbf differ diff --git a/demo/data/boundaries.prj b/demo/data/boundaries.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/boundaries.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/boundaries.sbx b/demo/data/boundaries.sbx deleted file mode 100644 index c66e6e334..000000000 Binary files a/demo/data/boundaries.sbx and /dev/null differ diff --git a/demo/data/boundaries_l.dbf b/demo/data/boundaries_l.dbf index e6bc20c98..44d4ca8e1 100644 Binary files a/demo/data/boundaries_l.dbf and b/demo/data/boundaries_l.dbf differ diff --git a/demo/data/boundaries_l.prj b/demo/data/boundaries_l.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/boundaries_l.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/boundaries_l.sbx b/demo/data/boundaries_l.sbx deleted file mode 100644 index e609d80c5..000000000 Binary files a/demo/data/boundaries_l.sbx and /dev/null differ diff --git a/demo/data/ontdrainage.dbf b/demo/data/ontdrainage.dbf index 33d8004b6..819265027 100644 Binary files a/demo/data/ontdrainage.dbf and b/demo/data/ontdrainage.dbf differ diff --git a/demo/data/ontdrainage.prj b/demo/data/ontdrainage.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/ontdrainage.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/ontdrainage.sbx b/demo/data/ontdrainage.sbx deleted file mode 100644 index 3739c6198..000000000 Binary files a/demo/data/ontdrainage.sbx and /dev/null differ diff --git a/demo/data/popplaces.dbf b/demo/data/popplaces.dbf index 408968e85..d385b6f1d 100644 Binary files a/demo/data/popplaces.dbf and b/demo/data/popplaces.dbf differ diff --git a/demo/data/popplaces.prj b/demo/data/popplaces.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/popplaces.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/popplaces.sbx b/demo/data/popplaces.sbx deleted file mode 100644 index c02888185..000000000 Binary files a/demo/data/popplaces.sbx and /dev/null differ diff --git a/demo/data/qcdrainage.dbf b/demo/data/qcdrainage.dbf index 95ce20f20..04fcf8541 100644 Binary files a/demo/data/qcdrainage.dbf and b/demo/data/qcdrainage.dbf differ diff --git a/demo/data/qcdrainage.prj b/demo/data/qcdrainage.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/qcdrainage.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/qcdrainage.sbx b/demo/data/qcdrainage.sbx deleted file mode 100644 index c73534e78..000000000 Binary files a/demo/data/qcdrainage.sbx and /dev/null differ diff --git a/demo/data/roads.dbf b/demo/data/roads.dbf index 73c1db9dd..709f88182 100644 Binary files a/demo/data/roads.dbf and b/demo/data/roads.dbf differ diff --git a/demo/data/roads.prj b/demo/data/roads.prj deleted file mode 100644 index 21aa9c392..000000000 --- a/demo/data/roads.prj +++ /dev/null @@ -1 +0,0 @@ -PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/demo/data/roads.sbx b/demo/data/roads.sbx deleted file mode 100644 index b804cb3b2..000000000 Binary files a/demo/data/roads.sbx and /dev/null differ diff --git a/demo/python/rundemo.py b/demo/python/rundemo.py index 7e6c42c40..910d846a5 100755 --- a/demo/python/rundemo.py +++ b/demo/python/rundemo.py @@ -18,7 +18,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from __future__ import print_function import sys from os import path diff --git a/demo/viewer/about_dialog.cpp b/demo/viewer/about_dialog.cpp index 06f0a966e..2a37349ee 100644 --- a/demo/viewer/about_dialog.cpp +++ b/demo/viewer/about_dialog.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/about_dialog.hpp b/demo/viewer/about_dialog.hpp index 670567112..160dcc857 100644 --- a/demo/viewer/about_dialog.hpp +++ b/demo/viewer/about_dialog.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/info_dialog.cpp b/demo/viewer/info_dialog.cpp index 304abf8f3..b25002025 100644 --- a/demo/viewer/info_dialog.cpp +++ b/demo/viewer/info_dialog.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/info_dialog.hpp b/demo/viewer/info_dialog.hpp index dde4c6661..c4b887f18 100644 --- a/demo/viewer/info_dialog.hpp +++ b/demo/viewer/info_dialog.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layer_info_dialog.cpp b/demo/viewer/layer_info_dialog.cpp index 23de7e824..f7e983d35 100644 --- a/demo/viewer/layer_info_dialog.cpp +++ b/demo/viewer/layer_info_dialog.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layer_info_dialog.hpp b/demo/viewer/layer_info_dialog.hpp index efac7822f..370551e01 100644 --- a/demo/viewer/layer_info_dialog.hpp +++ b/demo/viewer/layer_info_dialog.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layerdelegate.cpp b/demo/viewer/layerdelegate.cpp index 13a1135e1..5e4331793 100644 --- a/demo/viewer/layerdelegate.cpp +++ b/demo/viewer/layerdelegate.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layerdelegate.hpp b/demo/viewer/layerdelegate.hpp index 941621d2f..92a57a75e 100644 --- a/demo/viewer/layerdelegate.hpp +++ b/demo/viewer/layerdelegate.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LAYER_DELEGATE_HPP diff --git a/demo/viewer/layerlistmodel.cpp b/demo/viewer/layerlistmodel.cpp index 6a4b0bbfa..f2ad085ef 100644 --- a/demo/viewer/layerlistmodel.cpp +++ b/demo/viewer/layerlistmodel.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layerlistmodel.hpp b/demo/viewer/layerlistmodel.hpp index ab838c782..d69133315 100644 --- a/demo/viewer/layerlistmodel.hpp +++ b/demo/viewer/layerlistmodel.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layerwidget.cpp b/demo/viewer/layerwidget.cpp index 58b88a29a..d392150fb 100644 --- a/demo/viewer/layerwidget.cpp +++ b/demo/viewer/layerwidget.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/layerwidget.hpp b/demo/viewer/layerwidget.hpp index f458ee94f..e75ee7db2 100644 --- a/demo/viewer/layerwidget.hpp +++ b/demo/viewer/layerwidget.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/main.cpp b/demo/viewer/main.cpp index e80619772..d8f06d25a 100644 --- a/demo/viewer/main.cpp +++ b/demo/viewer/main.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/mainwindow.cpp b/demo/viewer/mainwindow.cpp index 9e9a34dd4..939028ab5 100644 --- a/demo/viewer/mainwindow.cpp +++ b/demo/viewer/mainwindow.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/mainwindow.hpp b/demo/viewer/mainwindow.hpp index 260968c8f..ebfc2c59a 100644 --- a/demo/viewer/mainwindow.hpp +++ b/demo/viewer/mainwindow.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index 04ce9c768..9b2c5278d 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/mapwidget.hpp b/demo/viewer/mapwidget.hpp index cc7964b5e..e65908fcf 100644 --- a/demo/viewer/mapwidget.hpp +++ b/demo/viewer/mapwidget.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/styles_model.cpp b/demo/viewer/styles_model.cpp index d2b2f708e..d7b68ba0e 100644 --- a/demo/viewer/styles_model.cpp +++ b/demo/viewer/styles_model.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/demo/viewer/styles_model.hpp b/demo/viewer/styles_model.hpp index b6ead4bfc..a21885915 100644 --- a/demo/viewer/styles_model.hpp +++ b/demo/viewer/styles_model.hpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/deps/agg/include/agg_array.h b/deps/agg/include/agg_array.h index 80e02c205..d07e46b0b 100644 --- a/deps/agg/include/agg_array.h +++ b/deps/agg/include/agg_array.h @@ -27,8 +27,8 @@ namespace agg { public: typedef T value_type; - pod_array_adaptor(T* array, unsigned size) : - m_array(array), m_size(size) {} + pod_array_adaptor(T* array, unsigned _size) : + m_array(array), m_size(_size) {} unsigned size() const { return m_size; } const T& operator [] (unsigned i) const { return m_array[i]; } @@ -87,7 +87,7 @@ namespace agg void clear() { m_size = 0; } void add(const T& v) { m_array[m_size++] = v; } void push_back(const T& v) { m_array[m_size++] = v; } - void inc_size(unsigned size) { m_size += size; } + void inc_size(unsigned _size) { m_size += _size; } unsigned size() const { return m_size; } const T& operator [] (unsigned i) const { return m_array[i]; } @@ -112,9 +112,9 @@ namespace agg ~pod_array() { pod_allocator::deallocate(m_array, m_size); } pod_array() : m_array(0), m_size(0) {} - pod_array(unsigned size) : - m_array(pod_allocator::allocate(size)), - m_size(size) + pod_array(unsigned _size) : + m_array(pod_allocator::allocate(_size)), + m_size(_size) {} pod_array(const self_type& v) : @@ -124,12 +124,12 @@ namespace agg memcpy(m_array, v.m_array, sizeof(T) * m_size); } - void resize(unsigned size) + void resize(unsigned _size) { - if(size != m_size) + if(_size != m_size) { pod_allocator::deallocate(m_array, m_size); - m_array = pod_allocator::allocate(m_size = size); + m_array = pod_allocator::allocate(m_size = _size); } } const self_type& operator = (const self_type& v) @@ -191,7 +191,7 @@ namespace agg void add(const T& v) { m_array[m_size++] = v; } void push_back(const T& v) { m_array[m_size++] = v; } void insert_at(unsigned pos, const T& val); - void inc_size(unsigned size) { m_size += size; } + void inc_size(unsigned _size) { m_size += _size; } unsigned size() const { return m_size; } unsigned byte_size() const { return m_size * sizeof(T); } void serialize(int8u* ptr) const; @@ -230,10 +230,10 @@ namespace agg //------------------------------------------------------------------------ template - void pod_vector::allocate(unsigned size, unsigned extra_tail) + void pod_vector::allocate(unsigned _size, unsigned extra_tail) { - capacity(size, extra_tail); - m_size = size; + capacity(_size, extra_tail); + m_size = _size; } @@ -245,10 +245,10 @@ namespace agg { if(new_size > m_capacity) { - T* data = pod_allocator::allocate(new_size); - memcpy(data, m_array, m_size * sizeof(T)); + T* _data = pod_allocator::allocate(new_size); + memcpy(_data, m_array, m_size * sizeof(T)); pod_allocator::deallocate(m_array, m_capacity); - m_array = data; + m_array = _data; } } else @@ -289,11 +289,11 @@ namespace agg //------------------------------------------------------------------------ template - void pod_vector::deserialize(const int8u* data, unsigned byte_size) + void pod_vector::deserialize(const int8u* _data, unsigned _byte_size) { - byte_size /= sizeof(T); - allocate(byte_size); - if(byte_size) memcpy(m_array, data, byte_size * sizeof(T)); + _byte_size /= sizeof(T); + allocate(_byte_size); + if(_byte_size) memcpy(m_array, _data, _byte_size * sizeof(T)); } //------------------------------------------------------------------------ @@ -371,9 +371,9 @@ namespace agg } } - void cut_at(unsigned size) + void cut_at(unsigned _size) { - if(size < m_size) m_size = size; + if(_size < m_size) m_size = _size; } unsigned size() const { return m_size; } @@ -529,11 +529,11 @@ namespace agg //------------------------------------------------------------------------ template - void pod_bvector::free_tail(unsigned size) + void pod_bvector::free_tail(unsigned _size) { - if(size < m_size) + if(_size < m_size) { - unsigned nb = (size + block_mask) >> block_shift; + unsigned nb = (_size + block_mask) >> block_shift; while(m_num_blocks > nb) { pod_allocator::deallocate(m_blocks[--m_num_blocks], block_size); @@ -544,7 +544,7 @@ namespace agg m_blocks = 0; m_max_blocks = 0; } - m_size = size; + m_size = _size; } } @@ -728,16 +728,16 @@ namespace agg //------------------------------------------------------------------------ template - void pod_bvector::deserialize(const int8u* data, unsigned byte_size) + void pod_bvector::deserialize(const int8u* _data, unsigned _byte_size) { remove_all(); - byte_size /= sizeof(T); - for(unsigned i = 0; i < byte_size; ++i) + _byte_size /= sizeof(T); + for(unsigned i = 0; i < _byte_size; ++i) { T* ptr = data_ptr(); - memcpy(ptr, data, sizeof(T)); + memcpy(ptr, _data, sizeof(T)); ++m_size; - data += sizeof(T); + _data += sizeof(T); } } @@ -746,27 +746,27 @@ namespace agg //------------------------------------------------------------------------ template void pod_bvector::deserialize(unsigned start, const T& empty_val, - const int8u* data, unsigned byte_size) + const int8u* _data, unsigned _byte_size) { while(m_size < start) { add(empty_val); } - byte_size /= sizeof(T); - for(unsigned i = 0; i < byte_size; ++i) + _byte_size /= sizeof(T); + for(unsigned i = 0; i < _byte_size; ++i) { if(start + i < m_size) { - memcpy(&((*this)[start + i]), data, sizeof(T)); + memcpy(&((*this)[start + i]), _data, sizeof(T)); } else { T* ptr = data_ptr(); - memcpy(ptr, data, sizeof(T)); + memcpy(ptr, _data, sizeof(T)); ++m_size; } - data += sizeof(T); + _data += sizeof(T); } } @@ -1087,8 +1087,8 @@ namespace agg public: typedef typename Array::value_type value_type; - range_adaptor(Array& array, unsigned start, unsigned size) : - m_array(array), m_start(start), m_size(size) + range_adaptor(Array& array, unsigned start, unsigned _size) : + m_array(array), m_start(start), m_size(_size) {} unsigned size() const { return m_size; } diff --git a/deps/agg/include/agg_conv_clip_polygon.h b/deps/agg/include/agg_conv_clip_polygon.h index 79aceedf3..a7e28db87 100644 --- a/deps/agg/include/agg_conv_clip_polygon.h +++ b/deps/agg/include/agg_conv_clip_polygon.h @@ -42,9 +42,9 @@ namespace agg conv_clip_polygon(VertexSource& vs) : conv_adaptor_vpgen(vs) {} - void clip_box(double x1, double y1, double x2, double y2) + void clip_box(double _x1, double _y1, double _x2, double _y2) { - base_type::vpgen().clip_box(x1, y1, x2, y2); + base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); } double x1() const { return base_type::vpgen().x1(); } diff --git a/deps/agg/include/agg_conv_clip_polyline.h b/deps/agg/include/agg_conv_clip_polyline.h index 8bad5964f..8aa34c9d9 100644 --- a/deps/agg/include/agg_conv_clip_polyline.h +++ b/deps/agg/include/agg_conv_clip_polyline.h @@ -42,9 +42,9 @@ namespace agg conv_clip_polyline(VertexSource& vs) : conv_adaptor_vpgen(vs) {} - void clip_box(double x1, double y1, double x2, double y2) + void clip_box(double _x1, double _y1, double _x2, double _y2) { - base_type::vpgen().clip_box(x1, y1, x2, y2); + base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); } double x1() const { return base_type::vpgen().x1(); } diff --git a/deps/agg/include/agg_rasterizer_cells_aa.h b/deps/agg/include/agg_rasterizer_cells_aa.h old mode 100755 new mode 100644 diff --git a/deps/agg/include/agg_rasterizer_compound_aa.h b/deps/agg/include/agg_rasterizer_compound_aa.h old mode 100755 new mode 100644 diff --git a/deps/agg/include/agg_rasterizer_scanline_aa.h b/deps/agg/include/agg_rasterizer_scanline_aa.h index 77bc41bc7..b2d4e3e12 100644 --- a/deps/agg/include/agg_rasterizer_scanline_aa.h +++ b/deps/agg/include/agg_rasterizer_scanline_aa.h @@ -2,15 +2,15 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // -// The author gratefully acknowleges the support of David Turner, -// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details. // //---------------------------------------------------------------------------- @@ -19,12 +19,12 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Adaptation for 32-bit screen coordinates has been sponsored by +// Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. -// +// //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED #define AGG_RASTERIZER_SCANLINE_AA_INCLUDED @@ -39,8 +39,8 @@ namespace agg //-----------------------------------------------------------------cell_aa - // A pixel cell. There're no constructors defined and it was done - // intentionally in order to avoid extra overhead when allocating an + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an // array of cells. struct cell_aa { @@ -67,10 +67,10 @@ namespace agg //==================================================rasterizer_scanline_aa - // Polygon rasterizer that is used to render filled polygons with - // high-quality Anti-Aliasing. Internally, by default, the class uses - // integer coordinates in format 24.8, i.e. 24 bits for integer part - // and 8 bits for fractional - see poly_subpixel_shift. This class can be + // Polygon rasterizer that is used to render filled polygons with + // high-quality Anti-Aliasing. Internally, by default, the class uses + // integer coordinates in format 24.8, i.e. 24 bits for integer part + // and 8 bits for fractional - see poly_subpixel_shift. This class can be // used in the following way: // // 1. filling_rule(filling_rule_e ft) - optional. @@ -79,20 +79,20 @@ namespace agg // // 3. reset() // - // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create + // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create // more than one contour, but each contour must consist of at least 3 // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); // is the absolute minimum of vertices that define a triangle. // The algorithm does not check either the number of vertices nor - // coincidence of their coordinates, but in the worst case it just + // coincidence of their coordinates, but in the worst case it just // won't draw anything. - // The orger of the vertices (clockwise or counterclockwise) + // The orger of the vertices (clockwise or counterclockwise) // is important when using the non-zero filling rule (fill_non_zero). // In this case the vertex order of all the contours must be the same // if you want your intersecting polygons to be without "holes". - // You actually can use different vertices order. If the contours do not - // intersect each other the order is not important anyway. If they do, - // contours with the same vertex order will be rendered without "holes" + // You actually can use different vertices order. If the contours do not + // intersect each other the order is not important anyway. If they do, + // contours with the same vertex order will be rendered without "holes" // while the intersecting contours with different orders will have "holes". // // filling_rule() and gamma() can be called anytime before "sweeping". @@ -122,7 +122,7 @@ namespace agg }; //-------------------------------------------------------------------- - rasterizer_scanline_aa() : + rasterizer_scanline_aa() : m_outline(), m_clipper(), m_filling_rule(fill_non_zero), @@ -136,8 +136,8 @@ namespace agg } //-------------------------------------------------------------------- - template - rasterizer_scanline_aa(const GammaF& gamma_function) : + template + rasterizer_scanline_aa(const GammaF& gamma_function) : m_outline(), m_clipper(m_outline), m_filling_rule(fill_non_zero), @@ -150,7 +150,7 @@ namespace agg } //-------------------------------------------------------------------- - void reset(); + void reset(); void reset_clipping(); void clip_box(double x1, double y1, double x2, double y2); void filling_rule(filling_rule_e filling_rule); @@ -158,7 +158,7 @@ namespace agg //-------------------------------------------------------------------- template void gamma(const GammaF& gamma_function) - { + { int i; for(i = 0; i < aa_scale; i++) { @@ -167,9 +167,9 @@ namespace agg } //-------------------------------------------------------------------- - unsigned apply_gamma(unsigned cover) const - { - return m_gamma[cover]; + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; } //-------------------------------------------------------------------- @@ -198,7 +198,7 @@ namespace agg add_vertex(x, y, cmd); } } - + //-------------------------------------------------------------------- int min_x() const { return m_outline.min_x(); } int min_y() const { return m_outline.min_y(); } @@ -237,7 +237,7 @@ namespace agg sl.reset_spans(); unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); - int cover = 0; + unsigned cover = 0; while(num_cells) { @@ -276,7 +276,7 @@ namespace agg } } } - + if(sl.num_spans()) break; ++m_scan_y; } @@ -294,7 +294,7 @@ namespace agg //-------------------------------------------------------------------- // Disable copying rasterizer_scanline_aa(const rasterizer_scanline_aa&); - const rasterizer_scanline_aa& + const rasterizer_scanline_aa& operator = (const rasterizer_scanline_aa&); private: @@ -321,32 +321,32 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::reset() - { - m_outline.reset(); + template + void rasterizer_scanline_aa::reset() + { + m_outline.reset(); m_status = status_initial; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) - { - m_filling_rule = filling_rule; + template + void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::clip_box(double x1, double y1, + template + void rasterizer_scanline_aa::clip_box(double x1, double y1, double x2, double y2) { reset(); - m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), conv_type::upscale(x2), conv_type::upscale(y2)); } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::reset_clipping() { reset(); @@ -354,7 +354,7 @@ namespace agg } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::close_polygon() { if(m_status == status_line_to) @@ -365,56 +365,56 @@ namespace agg } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::move_to(int x, int y) { if(m_outline.sorted()) reset(); if(m_auto_close) close_polygon(); - m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_clipper.move_to(m_start_x = conv_type::downscale(x), m_start_y = conv_type::downscale(y)); m_status = status_move_to; } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::line_to(int x, int y) { - m_clipper.line_to(m_outline, - conv_type::downscale(x), + m_clipper.line_to(m_outline, + conv_type::downscale(x), conv_type::downscale(y)); m_status = status_line_to; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to_d(double x, double y) - { + template + void rasterizer_scanline_aa::move_to_d(double x, double y) + { if(m_outline.sorted()) reset(); if(m_auto_close) close_polygon(); - m_clipper.move_to(m_start_x = conv_type::upscale(x), - m_start_y = conv_type::upscale(y)); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); m_status = status_move_to; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to_d(double x, double y) - { - m_clipper.line_to(m_outline, - conv_type::upscale(x), - conv_type::upscale(y)); + template + void rasterizer_scanline_aa::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); m_status = status_line_to; } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::add_vertex(double x, double y, unsigned cmd) { - if(is_move_to(cmd)) + if(is_move_to(cmd)) { move_to_d(x, y); } - else + else if(is_vertex(cmd)) { line_to_d(x, y); @@ -427,32 +427,32 @@ namespace agg } //------------------------------------------------------------------------ - template + template void rasterizer_scanline_aa::edge(int x1, int y1, int x2, int y2) { if(m_outline.sorted()) reset(); m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); - m_clipper.line_to(m_outline, - conv_type::downscale(x2), + m_clipper.line_to(m_outline, + conv_type::downscale(x2), conv_type::downscale(y2)); m_status = status_move_to; } - - //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::edge_d(double x1, double y1, - double x2, double y2) - { - if(m_outline.sorted()) reset(); - m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); - m_clipper.line_to(m_outline, - conv_type::upscale(x2), - conv_type::upscale(y2)); - m_status = status_move_to; - } //------------------------------------------------------------------------ - template + template + void rasterizer_scanline_aa::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template void rasterizer_scanline_aa::sort() { if(m_auto_close) close_polygon(); @@ -460,12 +460,12 @@ namespace agg } //------------------------------------------------------------------------ - template + template AGG_INLINE bool rasterizer_scanline_aa::rewind_scanlines() { if(m_auto_close) close_polygon(); m_outline.sort_cells(); - if(m_outline.total_cells() == 0) + if(m_outline.total_cells() == 0) { return false; } @@ -475,14 +475,14 @@ namespace agg //------------------------------------------------------------------------ - template + template AGG_INLINE bool rasterizer_scanline_aa::navigate_scanline(int y) { if(m_auto_close) close_polygon(); m_outline.sort_cells(); - if(m_outline.total_cells() == 0 || - y < m_outline.min_y() || - y > m_outline.max_y()) + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) { return false; } @@ -491,7 +491,7 @@ namespace agg } //------------------------------------------------------------------------ - template + template bool rasterizer_scanline_aa::hit_test(int tx, int ty) { if(!navigate_scanline(ty)) return false; @@ -507,4 +507,3 @@ namespace agg #endif - diff --git a/deps/agg/include/agg_vcgen_dash.h b/deps/agg/include/agg_vcgen_dash.h index c87dce4c8..f531013ba 100644 --- a/deps/agg/include/agg_vcgen_dash.h +++ b/deps/agg/include/agg_vcgen_dash.h @@ -2,8 +2,8 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // @@ -21,6 +21,7 @@ #include "agg_basics.h" #include "agg_vertex_sequence.h" +#include namespace agg { @@ -29,7 +30,7 @@ namespace agg // // See Implementation agg_vcgen_dash.cpp // - class vcgen_dash + class MAPNIK_DECL vcgen_dash { enum max_dashes_e { diff --git a/deps/mapbox/variant b/deps/mapbox/variant new file mode 160000 index 000000000..aaddee927 --- /dev/null +++ b/deps/mapbox/variant @@ -0,0 +1 @@ +Subproject commit aaddee9270e3956cee98cdd7d04aea848d69f5f0 diff --git a/deps/mapnik/build.py b/deps/mapnik/build.py index 32afe1189..76529fbda 100644 --- a/deps/mapnik/build.py +++ b/deps/mapnik/build.py @@ -4,14 +4,15 @@ from glob import glob Import('env') subdirs = { - 'sparsehash':'sparsehash', - 'sparsehash/internal':'sparsehash/internal', - '../agg/include':'agg', + './sparsehash':{'dir':'sparsehash','glob':'*'}, + './sparsehash/internal':{'dir':'sparsehash/internal','glob':'*'}, + '../agg/include':{'dir':'agg','glob':'agg*'}, + '../mapbox/variant/include':{'dir':'mapbox','glob':'*/*.hpp'} } if 'install' in COMMAND_LINE_TARGETS: for k,v in subdirs.items(): - pathdir = os.path.join(k,'*') + pathdir = os.path.join(k,v['glob']) includes = glob(pathdir) - inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/'+v) + inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/'+v['dir']) env.Alias(target='install', source=env.Install(inc_target, includes)) diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-ExtraLight.ttf b/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-ExtraLight.ttf deleted file mode 100644 index 9c6cf9f91..000000000 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-ExtraLight.ttf and /dev/null differ diff --git a/fonts/dejavu-fonts-ttf-2.35/AUTHORS b/fonts/dejavu-fonts-ttf-2.37/AUTHORS similarity index 91% rename from fonts/dejavu-fonts-ttf-2.35/AUTHORS rename to fonts/dejavu-fonts-ttf-2.37/AUTHORS index 3be64a987..55c2bc990 100644 --- a/fonts/dejavu-fonts-ttf-2.35/AUTHORS +++ b/fonts/dejavu-fonts-ttf-2.37/AUTHORS @@ -21,7 +21,7 @@ James Cloos James Crippen John Karp Keenan Pepper -Lars Naesbye Christensen +Lars Næsbye Christensen Lior Halphon MaEr Mashrab Kuvatov @@ -33,6 +33,7 @@ Misu Moldovan Nguyen Thai Ngoc Duy Nicolas Mailhot Norayr Chilingarian +Olleg Samoylov Ognyan Kulev Ondrej Koala Vacha Peter Cernak @@ -53,4 +54,4 @@ Vasek Stodulka Wesley Transue Yoshiki Ohshima -$Id: AUTHORS 2593 2015-05-17 07:47:39Z ben_laenen $ +$Id$ diff --git a/fonts/dejavu-fonts-ttf-2.35/BUGS b/fonts/dejavu-fonts-ttf-2.37/BUGS similarity index 57% rename from fonts/dejavu-fonts-ttf-2.35/BUGS rename to fonts/dejavu-fonts-ttf-2.37/BUGS index 49b36de55..43d1c9401 100644 --- a/fonts/dejavu-fonts-ttf-2.35/BUGS +++ b/fonts/dejavu-fonts-ttf-2.37/BUGS @@ -1,3 +1,3 @@ See http://dejavu.sourceforge.net/wiki/index.php/Bugs -$Id: BUGS 80 2004-11-13 13:12:02Z src $ +$Id$ diff --git a/fonts/dejavu-fonts-ttf-2.35/LICENSE b/fonts/dejavu-fonts-ttf-2.37/LICENSE similarity index 54% rename from fonts/dejavu-fonts-ttf-2.35/LICENSE rename to fonts/dejavu-fonts-ttf-2.37/LICENSE index 254e2cc42..df52c1709 100644 --- a/fonts/dejavu-fonts-ttf-2.35/LICENSE +++ b/fonts/dejavu-fonts-ttf-2.37/LICENSE @@ -1,6 +1,7 @@ Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + Bitstream Vera Fonts Copyright ------------------------------ @@ -46,7 +47,7 @@ Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot -org. +org. Arev Fonts Copyright ------------------------------ @@ -96,4 +97,91 @@ dealings in this Font Software without prior written authorization from Tavmjong Bah. For further information, contact: tavmjong @ free . fr. -$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ +TeX Gyre DJV Math +----------------- +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. + +Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski +(on behalf of TeX users groups) are in public domain. + +Letters imported from Euler Fraktur from AMSfonts are (c) American +Mathematical Society (see below). +Bitstream Vera Fonts Copyright +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera +is a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license (“Fonts”) and associated +documentation +files (the “Font Software”), to reproduce and distribute the Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, +and/or sell copies of the Font Software, and to permit persons to whom +the Font Software is furnished to do so, subject to the following +conditions: + +The above copyright and trademark notices and this permission notice +shall be +included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional +glyphs or characters may be added to the Fonts, only if the fonts are +renamed +to names not containing either the words “Bitstream” or the word “Vera”. + +This License becomes null and void to the extent applicable to Fonts or +Font Software +that has been modified and is distributed under the “Bitstream Vera” +names. + +The Font Software may be sold as part of a larger software package but +no copy +of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN +ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR +INABILITY TO USE +THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. +Except as contained in this notice, the names of GNOME, the GNOME +Foundation, +and Bitstream Inc., shall not be used in advertising or otherwise to promote +the sale, use or other dealings in this Font Software without prior written +authorization from the GNOME Foundation or Bitstream Inc., respectively. +For further information, contact: fonts at gnome dot org. + +AMSFonts (v. 2.2) copyright + +The PostScript Type 1 implementation of the AMSFonts produced by and +previously distributed by Blue Sky Research and Y&Y, Inc. are now freely +available for general use. This has been accomplished through the +cooperation +of a consortium of scientific publishers with Blue Sky Research and Y&Y. +Members of this consortium include: + +Elsevier Science IBM Corporation Society for Industrial and Applied +Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) + +In order to assure the authenticity of these fonts, copyright will be +held by +the American Mathematical Society. This is not meant to restrict in any way +the legitimate use of the fonts, such as (but not limited to) electronic +distribution of documents containing these fonts, inclusion of these fonts +into other public domain or commercial font collections or computer +applications, use of the outline data to create derivative fonts and/or +faces, etc. However, the AMS does require that the AMS copyright notice be +removed from any derivative versions of the fonts which have been altered in +any way. In addition, to ensure the fidelity of TeX documents using Computer +Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, +has requested that any alterations which yield different font metrics be +given a different name. + +$Id$ diff --git a/fonts/dejavu-fonts-ttf-2.35/NEWS b/fonts/dejavu-fonts-ttf-2.37/NEWS similarity index 93% rename from fonts/dejavu-fonts-ttf-2.35/NEWS rename to fonts/dejavu-fonts-ttf-2.37/NEWS index 78654ed98..2a2ee3708 100644 --- a/fonts/dejavu-fonts-ttf-2.35/NEWS +++ b/fonts/dejavu-fonts-ttf-2.37/NEWS @@ -1,3 +1,29 @@ +Changes from 2.35 to 2.36 + +* Fix issue with empty glyphs in condensed typefaces in the released source files. + +Changes from 2.35 to 2.36 + +* Math: added DejaVu Math Tex Gyre by B. Jackowski, P. Strzelczyk and + P. Pianowski (on behalf of TeX users groups) +* Sans: removed dot of U+06BA in all forms +* Sans: fixed position of three dots of U+06BD in init and medi forms (by + Denis Jacquerye) +* Sans: corrected direction of contours in U+05E7 (by Lior Halphon) +* Sans: added U+1F643 (by Olleg Samoylov) +* Serif: moved up U+0360-0361 (by Gee Fung Sit 薛至峰) +* Serif: increased spacing of Roman numerals U+2161-2163, U+2165-2168, + U+216A-216B (by Gee Fung Sit 薛至峰) +* Serif: fixed anchor position of U+00E6 (by Gee Fung Sit 薛至峰) +* Sans: fixed vertical position of U+20BA (by Gee Fung Sit 薛至峰) +* Sans, Serif: fixed glyph height of Block Elements (by Gee Fung Sit 薛至峰) +* Sans, Serif: added U+A698-A699 (by Gee Fung Sit 薛至峰) +* Sans, Mono, Serif: added U+037F (by Gee Fung Sit 薛至峰) +* Mono: added U+0376-0377, U+037B-037D (by Gee Fung Sit 薛至峰) +* Serif: removed duplicate point from U+1D05 (by Gee Fung Sit 薛至峰) +* Mono: added U+20BA, U+20BD (by Gee Fung Sit 薛至峰) +* Sans: added moon symbols U+1F311-1F318 (by Ben Laenen) + Changes from 2.34 to 2.35 * Sans, SansMono, Serif: added U+0E3F, U+A7F8-U+A7F9 (by Gee Fung Sit 薛至峰) @@ -51,7 +77,7 @@ Changes from 2.34 to 2.35 U+234E-U+234F, U+2351, U+2355-U+2356, U+235D, U+2361-U+2362, U+2366-U+2367, U+236A, U+2371-U+2372 (by Sami Tarazi) * Serif: added U+20BA (by Gee Fung Sit 薛至峰) -* Sans, Serif: added U+20BD (by Gee Fung Sit 薛至峰) +* Sans, Serif: added U+20BD (by Gee Fung Sit 薛至峰) Changes from 2.33 to 2.34 @@ -82,7 +108,7 @@ Changes from 2.33 to 2.34 * Sans: adjusted ogonek reference in U+0172, U+01EA, U+01EB (by Denis Jacquerye) * Sans: added anchors to U+0104, U+0105 (by Denis Jacquerye) -* Sans: added U+1F600, U+1F611, U+1F615, U+1F617, U+1F619, U+1F61B, U+1F61F, +* Sans: added U+1F600, U+1F611, U+1F615, U+1F617, U+1F619, U+1F61B, U+1F61F, U+1F626-U+1F627, U+1F62E-U+1F62F, U+1F634 (by Gee Fung Sit 薛至峰) * Sans: replaced U+27A1 with mirror image of U+2B05 for consistency (by Gee Fung Sit 薛至峰) @@ -114,46 +140,46 @@ Changes from 2.33 to 2.34 Changes from 2.32 to 2.33 -* added Old Italic block to Sans (by MaEr) -* added U+051E, U+051F to Sans (by MaEr) +* added Old Italic block to Sans (by MaEr) +* added U+051E, U+051F to Sans (by MaEr) * added U+01BA, U+0372-U+0373, U+0376-U+0377, U+03CF, U+1D00-U+1D01, U+1D03-U+1D07, U+1D0A-U+1D13, U+1D15, U+1D18-U+1D1C, U+1D20-U+1D2B, U+1D2F, U+1D3D, U+1D5C-U+1D61, U+1D66-U+1D6B, U+1DB8, U+1E9C-U+1E9D, U+1EFA-U+1EFB, U+2C60-U+2C61, U+2C63, U+A726-U+A73C, U+A73E-U+A73F, U+A746-U+A747, U+A74A-U+A74B, U+A74E+U+A74F, U+A768-U+A769, U+A77B-U+A77C, - U+A780-U+A787, U+A790-U+A791, U+A7FA-U+A7FF to Serif (by Gee Fung Sit 薛至峰) -* added alternate forms to U+014A and U+01B7 in Serif (by Gee Fung Sit 薛至峰) + U+A780-U+A787, U+A790-U+A791, U+A7FA-U+A7FF to Serif (by Gee Fung Sit 薛至峰) +* added alternate forms to U+014A and U+01B7 in Serif (by Gee Fung Sit 薛至峰) * typographical improvements to U+0166-U+0167, U+0197, U+01B5-U+01B6, U+01BB, U+0222-U+0223, U+023D, U+0250-U+0252, U+026E, U+0274, U+028F, U+029F, U+02A3-U+02A5, U+02AB, U+03FE-U+03FF, U+1D02, U+1D14, U+1D1D-U+1D1F, U+1D3B, - U+1D43-U+1D46, U+1D59, U+1D9B, U+2C71, U+2C73 in Serif (by Gee Fung Sit 薛至峰) + U+1D43-U+1D46, U+1D59, U+1D9B, U+2C71, U+2C73 in Serif (by Gee Fung Sit 薛至峰) * fixed bugs #31762 and #34700 plus other small fixes (wrong direction, - duplicate points, etc.) for Sans and Serif (by Gee Fung Sit 薛至峰) -* added U+204B to Mono (by Gee Fung Sit 薛至峰) -* added U+26E2 to Sans (by Gee Fung Sit 薛至峰) -* added Playing Cards block (U+1F0A0-U+1F0DF) to Sans (by Gee Fung Sit 薛至峰) + duplicate points, etc.) for Sans and Serif (by Gee Fung Sit 薛至峰) +* added U+204B to Mono (by Gee Fung Sit 薛至峰) +* added U+26E2 to Sans (by Gee Fung Sit 薛至峰) +* added Playing Cards block (U+1F0A0-U+1F0DF) to Sans (by Gee Fung Sit 薛至峰) * emoticons in Sans: replace U+2639-U+263B with better versions, add U+1F601-U+1F610, U+1F612-U+1F614, U+1F616, U+1F618, U+1F61A, U+1F61C-U+1F61E, U+1F620-U+1F624, U+1F625, U+1F628-U+1F62B, U+1F62D, U+1F630-U+1F633, - U+1F635-U+1F640 (by Ben Laenen and Denis Jacquerye) -* added U+A78E, U+A790-U+A791 to Sans and Mono (by Denis Jacquerye) -* added U+A7FA to Sans (by Denis Jacquerye) + U+1F635-U+1F640 (by Ben Laenen and Denis Jacquerye) +* added U+A78E, U+A790-U+A791 to Sans and Mono (by Denis Jacquerye) +* added U+A7FA to Sans (by Denis Jacquerye) * subscripts: added U+2095-U+209C to Sans, Serif and Mono, adjusted - U+1D49-U+1D4A in Sans and Mono (by Denis Jacquerye) -* added U+0243 to Mono (by Denis Jacquerye) + U+1D49-U+1D4A in Sans and Mono (by Denis Jacquerye) +* added U+0243 to Mono (by Denis Jacquerye) * adjusted U+0307 to match dot of i, replaced dotaccent U+02D9 with U+0307 in -most dependencies in Sans (by Denis Jacquerye) -* adjusted anchors of f and added them to long s in Sans (by Denis Jacquerye) -* added anchors to precomposed dependencies of D and d (by Denis Jacquerye) +most dependencies in Sans (by Denis Jacquerye) +* adjusted anchors of f and added them to long s in Sans (by Denis Jacquerye) +* added anchors to precomposed dependencies of D and d (by Denis Jacquerye) * added debug glyphs U+F002 and U+F003 which will show current point size (by - Ben Laenen) -* use correct version for Serbian italic be (by Eugeniy Meshcheryakov) -* added pictograms U+1F42D-U+1F42E, U+1F431, U+1F435 (by Denis Jacquerye) -* improved Hebrew in Sans (by Lior Halphon) + Ben Laenen) +* use correct version for Serbian italic be (by Eugeniy Meshcheryakov) +* added pictograms U+1F42D-U+1F42E, U+1F431, U+1F435 (by Denis Jacquerye) +* improved Hebrew in Sans (by Lior Halphon) * improved Armenian in Sans, and added Armenian in Serif and Mono (by Rouben - Hakobian (Tarumian), Aleksey Chalabyan and Norayr Chilingarian) + Hakobian (Tarumian), Aleksey Chalabyan and Norayr Chilingarian) * remove "locl" feature for Romanian for S/T/s/t with cedilla/comma accent (by - Ben Laenen) + Ben Laenen) * replace wrong "dflt" script tag in Mono with "DFLT" (by Ben Laenen) Changes from 2.31 to 2.32 @@ -210,26 +236,26 @@ Changes from 2.30 to 2.31 U+06AA-U+06AE, U+06B0-U+06B4, U+06B6-U+06B9, U+06BB-U+06BE and their contextual forms to Sans (by MihailJP) * added U+A78D LATIN CAPITAL LETTER TURNED H for coming Unicode 6.0 (by Denis - Jacquerye) + Jacquerye) Changes from 2.29 to 2.30 -* added U+0462-U+0463 to Mono (by Denis Jacquerye) -* corrected U+1E53 in Serif (by Gee Fung Sit) -* added U+1E4C-U+1E4D to Mono and Serif (by Gee Fung Sit) -* added U+1E78-U+1E79 to Mono (by Gee Fung Sit) +* added U+0462-U+0463 to Mono (by Denis Jacquerye) +* corrected U+1E53 in Serif (by Gee Fung Sit) +* added U+1E4C-U+1E4D to Mono and Serif (by Gee Fung Sit) +* added U+1E78-U+1E79 to Mono (by Gee Fung Sit) * fixed missing diacritics in Latin Extended Additional in Sans ExtraLight - (moved stacked diacritics out of PUA in the process) (by Gee Fung Sit) -* fixed anchors on U+1E78 in Serif (by Gee Fung Sit) -* added U+1DC4-U+1DC9 to Serif (by Denis Jacquerye) -* renamed above-mark to above-mark in Serif-Italic (by Denis Jacquerye) + (moved stacked diacritics out of PUA in the process) (by Gee Fung Sit) +* fixed anchors on U+1E78 in Serif (by Gee Fung Sit) +* added U+1DC4-U+1DC9 to Serif (by Denis Jacquerye) +* renamed above-mark to above-mark in Serif-Italic (by Denis Jacquerye) * added U+1DC4-U+1DC9 to context class for dotless substitution (by Denis - Jacquerye) -* changed Doubleacute to Doublegrave in Sans ExtraLight (by Gee Fung Sit) -* removed redundant reference in U+01FB in Sans Oblique (by Gee Fung Sit) -* added U+A726-U+A727 to Mono (Denis Jacquerye) + Jacquerye) +* changed Doubleacute to Doublegrave in Sans ExtraLight (by Gee Fung Sit) +* removed redundant reference in U+01FB in Sans Oblique (by Gee Fung Sit) +* added U+A726-U+A727 to Mono (Denis Jacquerye) * changed U+04BE and U+04BF according to recommedations of Sasha Ankwab in Sans - (by Andrey V. Panov) + (by Andrey V. Panov) * remove "Symbol Charset" from set of codepages in Sans (by Eugeniy Meshcheryakov) @@ -249,7 +275,7 @@ Changes from 2.28 to 2.29 * Remove 'cmap' mappings for U+066E, U+066F, U+067C, U+067D, U+0681, U+0682, U+0685, U+0692, U+06A1, U+06B5, U+06BA, U+06C6, U+06CE, and U+06D5 in Sans Mono (bug 20323) (by Roozbeh Pournader) -* add half brackets (U+2E22 - U+2E25, by Steve Tinney) +* add half brackets (U+2E22 - U+2E25, by Steve Tinney) Changes from 2.27 to 2.28 @@ -319,7 +345,7 @@ Changes from 2.26 to 2.27 * rounded U+2C77 at the bottom in Serif (by Gee Fung Sit) * added joining behavior for tone letters (U+02E5-U+02E9) in Sans (bug #15669) (by Gee Fung Sit) -* fixed outline of y.alt in Sans Regular (by Denis Jacquerye) +* fixed outline of y.alt in Sans Regular (by Denis Jacquerye) * changed references of U+1D5A8, U+1D5C5, U+1D5DC, U+1D5F9, U+1D610, U+1D62D, U+1D644 and U+1D661 to stylistic alternates to have a better distinction (by Gee Fung Sit) @@ -333,41 +359,41 @@ Changes from 2.26 to 2.27 Changes from 2.25 to 2.26 -- added glyphs for Cyrillic-B to Sans (by Wesley Transue) -- added U+0370-U+0371 to Sans (by Wesley Transue) +- added glyphs for Cyrillic-B to Sans (by Wesley Transue) +- added U+0370-U+0371 to Sans (by Wesley Transue) - added U+019C, U+01A2-U+01A3, U+01A6, U+01E4-U+01E5, U+024C-U+024D, U+0285, U+0290, U+02A0, U+0370-U+0371, U+03F1, U+03FC to Sans ExtraLight (by Wesley - Transue) + Transue) - added U+20A0-U+20A5, U+20A7-U+20B3, U+2105, U+210D, U+210F, U+2115, U+2117, U+2119-U+211A, U+211D, U+2124, U+212E, U+2200-U+2204 to Mono (by Heikki - Lindroos) -- added U+01BA and U+01BF to Mono (by Heikki Lindroos) -- merged OpenType "aalt" feature in Latin in Sans (by Denis Jacquerye) -- added alternative shape for y in Sans (by Denis Jacquerye) -- added saltillo (U+A78B-U+A78C) to all faces (by James Cloos) + Lindroos) +- added U+01BA and U+01BF to Mono (by Heikki Lindroos) +- merged OpenType "aalt" feature in Latin in Sans (by Denis Jacquerye) +- added alternative shape for y in Sans (by Denis Jacquerye) +- added saltillo (U+A78B-U+A78C) to all faces (by James Cloos) - changed U+047C-U+047D to references instead of outlines in Sans (by Wesley - Transue) -- added Latin letter tresillo U+A72A-U+A72B to Sans (by Wesley Transue) -- added U+A734-U+A737 to Sans (by Wesley Transue) -- added U+2053 to Serif and fixed it bug:9425 in Sans (by Gee Fung Sit) -- removed problematic hints for U+0423 bug:10025 (by Gee Fung Sit) -- added U+27C5-U+27C6 bug:10255 to all faces (by Gee Fung Sit) -- fixed width of U+2016 in Sans Oblique (by Gee Fung Sit) + Transue) +- added Latin letter tresillo U+A72A-U+A72B to Sans (by Wesley Transue) +- added U+A734-U+A737 to Sans (by Wesley Transue) +- added U+2053 to Serif and fixed it bug:9425 in Sans (by Gee Fung Sit) +- removed problematic hints for U+0423 bug:10025 (by Gee Fung Sit) +- added U+27C5-U+27C6 bug:10255 to all faces (by Gee Fung Sit) +- fixed width of U+2016 in Sans Oblique (by Gee Fung Sit) - added U+2016, U+2032-U+2038, U+2042, U+2045-U+2046, U+204B-U+204F, - U+2051-U+2052, U+2057 to Serif (by Gee Fung Sit) -- made U+2140 bigger to match other n-ary operators (by Gee Fung Sit) -- added U+0606-U+0607, U+0609-U+060A to Sans (by Gee Fung Sit) -- added U+221B-U+221C to Mono (by Gee Fung Sit) -- small adjustments to U+221B-U+221C in Sans and Serif (by Gee Fung Sit) -- update U+04B4-U+04B5 in Serif (by Andrey V. Panov) -- increased max-storage value from maxp table to 153 (by Andrey V. Panov) + U+2051-U+2052, U+2057 to Serif (by Gee Fung Sit) +- made U+2140 bigger to match other n-ary operators (by Gee Fung Sit) +- added U+0606-U+0607, U+0609-U+060A to Sans (by Gee Fung Sit) +- added U+221B-U+221C to Mono (by Gee Fung Sit) +- small adjustments to U+221B-U+221C in Sans and Serif (by Gee Fung Sit) +- update U+04B4-U+04B5 in Serif (by Andrey V. Panov) +- increased max-storage value from maxp table to 153 (by Andrey V. Panov) - added U+0472-U+0473, U+0510-U+0511, U+051A-U+051D, U+0606-U+0607, U+0609-U+060A, U+1E26-U+1E27, U+1E54-U+1E55, U+1E7C-U+1E7D, U+1E8C-U+1E8D, U+1E90-U+1E91, U+1E97-U+1E99, U+1E9F, U+1EAC-U+1EAD, U+1EB6-U+1EB7, U+1EC6-U+1EC7, U+1ED8-U+1EDD, U+1EE0-U+1EE3, U+1EE8-U+1EEB, U+1EEE-U+1EF1 to - Mono (by Gee Fung Sit) + Mono (by Gee Fung Sit) - added locl rules for S/T cedilla for Romanian and Moldavian so they get - rendered as S/T with comma accent (see Redhat bug #455981) (by Ben Laenen) + rendered as S/T with comma accent (see Redhat bug #455981) (by Ben Laenen) - removed ligature rule from Armenian U+0587 bug:16113 (by Gee Fung Sit) Changes from 2.24 to 2.25 @@ -395,33 +421,33 @@ Changes from 2.24 to 2.25 - added a bunch of glyphs+small corrections to Sans Light (by Gee Fung Sit) - added U+0496, U+0497, U+04B0, U+04B1 (by Andrey V. Panov) - updated U+0493, U+049B, U+04B3, U+04B7, U+04F7 (by Andrey V. Panov) -- further improvements in extended Cyrillic (by Andrey V. Panov) +- further improvements in extended Cyrillic (by Andrey V. Panov) Changes from 2.23 to 2.24 -- instructions for U+05C0 ׀, U+05C3 ׃, U+05F3 ׳, and U+05F4 ״ in DejaVu +- instructions for U+05C0 ׀, U+05C3 ׃, U+05F3 ׳, and U+05F4 ״ in DejaVu Sans. (by Wesley Transue) - instructions for U+2116 in Sans (by Andrey V. Panov) -- Unicode 5.1 update: moved U+F208 to U+2C6D, U+F25F to U+2C71, added - U+2C6E-U+2C6F, U+2C72-U+2C73, updated outline of U+2C71 in Sans. (by +- Unicode 5.1 update: moved U+F208 to U+2C6D, U+F25F to U+2C71, added + U+2C6E-U+2C6F, U+2C72-U+2C73, updated outline of U+2C71 in Sans. (by Denis Jacquerye) - updated and instructed U+0401 in Sans (by Andrey V. Panov) -- fixed the bug in Sans faces where U+02EC ˬ faced the wrong direction. +- fixed the bug in Sans faces where U+02EC ˬ faced the wrong direction. Also, added a few more glyph instructions. (by Wesley Transue) -- removed OS2Sub and OS2Strike that weren't intentional in Sans +- removed OS2Sub and OS2Strike that weren't intentional in Sans ExtraLight. (by Denis Jacquerye) -- updated instructions for U+401, U+44F in Serif Book. (by Andrey V. +- updated instructions for U+401, U+44F in Serif Book. (by Andrey V. Panov) -- instructions for U+02C4 ˄, U+02C5 ˅, U+03D8 Ϙ, U+03D9 ϙ, U+0494 Ҕ, and +- instructions for U+02C4 ˄, U+02C5 ˅, U+03D8 Ϙ, U+03D9 ϙ, U+0494 Ҕ, and U+0495 ҕ in Sans Book. (by Wesley Transue) -- instructions for U+01A6 Ʀ, U+0238 ȸ, U+0239 ȹ, U+02EC ˬ, and U+05C6 ׆ +- instructions for U+01A6 Ʀ, U+0238 ȸ, U+0239 ȹ, U+02EC ˬ, and U+05C6 ׆ in Sans Book. (by Wesley Transue) -- DejaVuSans.sfd DejaVuSerif.sfd: updated instructions for U+447 and +- DejaVuSans.sfd DejaVuSerif.sfd: updated instructions for U+447 and U+451 using code generated with xgridfit (by Andrey V. Panov) -- instructions for a few glyphs in the Latin Extended-B Block, Greek +- instructions for a few glyphs in the Latin Extended-B Block, Greek Block, Cyrillic Block, and N'Ko block. (by Wesley Transue) -- updated sfdnormalize.pl, and SFD files to new SFD format with empty - lines. (by Denis Jacquerye) +- updated sfdnormalize.pl, and SFD files to new SFD format with empty + lines. (by Denis Jacquerye) Changes from 2.22 to 2.23 @@ -436,7 +462,7 @@ Changes from 2.22 to 2.23 Wesley Transue) - added mathematical alphanumeric symbols to all styles (by Max Berger) - added Unicode 5.1 U+2E18 as U+2E18.u51 (not yet usable) to Sans (by Roozbeh - Pournader) + Pournader) - dereferenced all glyphs with mixed references and outlines (by Denis Jacquerye) - removed non-zero width from U+0344 in Sans (by Denis Jacquerye) @@ -519,7 +545,7 @@ Changes from 2.19 to 2.20 Changes from 2.18 to 2.19 -- fixed misplaced symbols (U+2325,2326) in Sans Oblique (by John Karp) +- fixed misplaced symbols (U+2325,2326) in Sans Oblique (by John Karp) - added Mark to Base anchors: 'cedilla' for combining cedilla and 'above-legacy' for stacking above precomposed glyphs (just a,e,i,o,u with macron for now) in Sans (by Denis Jacquerye). @@ -599,25 +625,25 @@ Changes from 2.15 to 2.16 - adjusted dot and dieresis below and above in Serif fonts (by Denis Jacquerye) - added U+1E1C-U+1E1D to Serif fonts (by Denis Jacquerye) - added U+22BE, U+22BF (by Wesley Transue) -- added U+2324; modified U+2325: more standard proportions, and matches U+2324 - and U+2387; added U+2387 : flipped U+2325 with standard arrowhead +- added U+2324; modified U+2325: more standard proportions, and matches U+2324 + and U+2387; added U+2387 : flipped U+2325 with standard arrowhead (by John Karp) - added Lao digits U+0ED0-0ED7, U+0ED9 (by Remy Oudompheng) -- added to Mono in Arabic block : U+060C, U+0615, U+061B, U+061F, - U+0621-U+063A, U+0640-0655, U+065A, U+0660-066F, U+0674, U+0679-0687, U+0691, - U+0692, U+0698, U+06A1, U+06A4, U+06A9, U+06AF, U+06B5, U+06BA, U+06BE, +- added to Mono in Arabic block : U+060C, U+0615, U+061B, U+061F, + U+0621-U+063A, U+0640-0655, U+065A, U+0660-066F, U+0674, U+0679-0687, U+0691, + U+0692, U+0698, U+06A1, U+06A4, U+06A9, U+06AF, U+06B5, U+06BA, U+06BE, U+06C6, U+06CC, U+06CE, U+06D5, U+06F0-06F9 (by Remy Oudompheng) -- added to Mono in Arabic Presentations Forms-A : U+FB52-FB81, U+FB8A-FB95, +- added to Mono in Arabic Presentations Forms-A : U+FB52-FB81, U+FB8A-FB95, U+FB9E, U+FB9F, U+FBAA-FBAD, U+FBE8, U+FBE9, U+FBFC-FBFF (by Remy Oudompheng) -- added to Mono in Arabic Presentations Forms-B : U+FE70-FE74, U+FE76-FEFC, +- added to Mono in Arabic Presentations Forms-B : U+FE70-FE74, U+FE76-FEFC, U+FEFF (by Remy Oudompheng) -- added U+05BA, U+05BE, U+05F3, U+05F4, U+FB1E, U+FB21-U+FB28, U+FB4F to Sans +- added U+05BA, U+05BE, U+05F3, U+05F4, U+FB1E, U+FB21-U+FB28, U+FB4F to Sans (by Eugeniy Meshcheryakov) - added U+2102 to Mono (by Eugeniy Meshcheryakov) - added U+2983-U+2984 to Sans (by Gee Fung Sit) - added U+2A2F to Sans, Serif and Mono (by Gee Fung Sit) - added U+2373-2375, U+237A to Sans (by John Karp) -- converted kern pairs to kern classes with Tavmjong Bah's scripts +- converted kern pairs to kern classes with Tavmjong Bah's scripts (by Denis Jacquerye) - set ScriptLang of kerning classes to just latn because of Pango bug (by Denis Jacquerye) @@ -629,7 +655,7 @@ Changes from 2.15 to 2.16 (by Denis Jacquerye) - added bearings to en dash U+2013, em dash U+2014 and figure dash U+2012 by making dashes shorter, preserving character width (by Denis Jacquerye) -- reduced U+031C, U+0325 (ring below), U+0339 to be entirely visible; +- reduced U+031C, U+0325 (ring below), U+0339 to be entirely visible; added instructions in Sans Book; changed U+1e00-U+1e01 to use new ring below (by Denis Jacquerye) - adjusted circumflex below on U+1E12-U+1E13, U+1E18-U+1E19, U+1E3C-U+1E3D, @@ -662,96 +688,96 @@ Changes from 2.14 to 2.15 Changes from 2.13 to 2.14 - added Philippine peso glyph U+20B1 (by Clayborne Arevalo) -- made U+2012 have the same width as digits, according to Unicode 5.0, +- made U+2012 have the same width as digits, according to Unicode 5.0, page 206 (by Roozbeh Pournader) -- made all of the "above" combining characters remove the dot of "i", - "j", etc (Soft_Dotted characters), according to Unicode 5.0, +- made all of the "above" combining characters remove the dot of "i", + "j", etc (Soft_Dotted characters), according to Unicode 5.0, page 228 (by Roozbeh Pournader) -- made U+012F, U+03F3, U+0456, U+0458, U+1E2D, and U+1ECB (all fonts - except Mono), U+0249, U+2148, and U+2149 (Sans and Sans Condensed), - U+0268 (Sans ExtraLight, Serif and Serif Condensed), and U+029D (Serif - and Serif Condensed) respect the Soft_Dotted property (by Roozbeh +- made U+012F, U+03F3, U+0456, U+0458, U+1E2D, and U+1ECB (all fonts + except Mono), U+0249, U+2148, and U+2149 (Sans and Sans Condensed), + U+0268 (Sans ExtraLight, Serif and Serif Condensed), and U+029D (Serif + and Serif Condensed) respect the Soft_Dotted property (by Roozbeh Pournader) - added U+223E, U+223F, U+2240, U+22C2, U+22C3 to Sans (by Remy Oudompheng) - added U+203D to Serif (by Gee Fung Sit) -- added zero-width glyphs for U+2061-U+2063 to Sans and Serif (by Gee +- added zero-width glyphs for U+2061-U+2063 to Sans and Serif (by Gee Fung Sit) -- changed isolated forms of Arabic waw (U+0648, U+0624 and U+06C6) (bug #9432) +- changed isolated forms of Arabic waw (U+0648, U+0624 and U+06C6) (bug #9432) (by Ben Laenen) -- added Lao consonants U+0E81, U+0E82, U+0E84, U+0E87, U+0E88, U+0E8A, - U+0E8D, U+0E94-0E97, U+0E99-0E9F, U+0EA1-0EA3, U+0EA5, U+0EA7, U+0EAA, +- added Lao consonants U+0E81, U+0E82, U+0E84, U+0E87, U+0E88, U+0E8A, + U+0E8D, U+0E94-0E97, U+0E99-0E9F, U+0EA1-0EA3, U+0EA5, U+0EA7, U+0EAA, U+0EAB, U+0EAD-0EAF to Sans Mono (by Remy Oudompheng) -- added U+0200-U+0217, U+0226-U+0229, U+02F3, U+1E00-U+1E07, - U+1E0A-U+1E0B, U+1E18-U+1E1F, U+1E22-U+1E23, U+1E28-U+1E2D, - U+1E3A-U+1E3B, U+1E40, U+1E48-U+1E49, U+1E56, U+1E58-U+1E59, - U+1E5E-U+1E5F, U+1E60, U+1E68-U+1E6B, U+1E6E-U+1E6F, U+1E72-U+1E77, - U+1E86-U+1E8B, U+1E92-U+1E96, U+1EA0-U+1EA1, U+1EF4-U+1EF5 to Mono +- added U+0200-U+0217, U+0226-U+0229, U+02F3, U+1E00-U+1E07, + U+1E0A-U+1E0B, U+1E18-U+1E1F, U+1E22-U+1E23, U+1E28-U+1E2D, + U+1E3A-U+1E3B, U+1E40, U+1E48-U+1E49, U+1E56, U+1E58-U+1E59, + U+1E5E-U+1E5F, U+1E60, U+1E68-U+1E6B, U+1E6E-U+1E6F, U+1E72-U+1E77, + U+1E86-U+1E8B, U+1E92-U+1E96, U+1EA0-U+1EA1, U+1EF4-U+1EF5 to Mono (by Ben Laenen) -- renamed uppercase variants of diacritics (macron, breve, double grave, - double acute, inverted breve, dot above) to "uni03XX.case" in Mono +- renamed uppercase variants of diacritics (macron, breve, double grave, + double acute, inverted breve, dot above) to "uni03XX.case" in Mono (by Ben Laenen) -- moved uppercase variants of diacritics up in Mono so they properly +- moved uppercase variants of diacritics up in Mono so they properly vertically align on capitals (by Ben Laenen) -- precomposed glyphs with macron, breve, double grave, double acute, - inverted breve, dot above, macron below, breve below, inverted breve - below, dot below, cedilla, caron below, circumflex below, diaeresis - below, tilde below now reference to combining diacritics instead of +- precomposed glyphs with macron, breve, double grave, double acute, + inverted breve, dot above, macron below, breve below, inverted breve + below, dot below, cedilla, caron below, circumflex below, diaeresis + below, tilde below now reference to combining diacritics instead of space modifiers in Mono (by Ben Laenen) -- made ring below (U+0325), and half rings below (U+031C and U+0339) +- made ring below (U+0325), and half rings below (U+031C and U+0339) smaller in Mono (by Ben Laenen) - added U+205F to all fonts (by Roozbeh Pournader) - added U+035E-U+035F to Sans (by Roozbeh Pournader) -- added empty glyphs for U+034F, U+202A-U+202E, U+2060, U+206A-206F, +- added empty glyphs for U+034F, U+202A-U+202E, U+2060, U+206A-206F, U+FE00-U+FE0F to non-Mono fonts (by Roozbeh Pournader) -- added U+2101, U+2107-U+2108, U+210B, U+210C, U+2110, U+2112, U+211B, - U+211F, U+2123, U+2125, U+2128-U+2129, U+212C-U+212D, U+212F, - U+2130-U+2131, U+2133, U+2136-U+213A, U+2141-U+2144, U+2B00-U+2B11, +- added U+2101, U+2107-U+2108, U+210B, U+210C, U+2110, U+2112, U+211B, + U+211F, U+2123, U+2125, U+2128-U+2129, U+212C-U+212D, U+212F, + U+2130-U+2131, U+2133, U+2136-U+213A, U+2141-U+2144, U+2B00-U+2B11, U+2B20-U+2B23 to Sans (by John Karp) - reshaped omega (U+03C9) in Mono (by Ben Laenen) -- added U+2205, U+22C6, U+2300-U+2301, U+2303-U+2306, U+230C-U+230F, - U+2312-U+2315, U+231C-U+231F, U+2335, U+2337-U+233E, U+2341-U+2344, - U+2347-U+2348, U+234B-U+234D, U+2349-U+2350, U+2352-U+2354, - U+2357-U+2359, U+235A-U+235C, U+235E-U+2360, U+2363-U+2365, - U+2368-U+2369, U+236B-U+2370, U+2373-U+237A, U+2380-U+2383, +- added U+2205, U+22C6, U+2300-U+2301, U+2303-U+2306, U+230C-U+230F, + U+2312-U+2315, U+231C-U+231F, U+2335, U+2337-U+233E, U+2341-U+2344, + U+2347-U+2348, U+234B-U+234D, U+2349-U+2350, U+2352-U+2354, + U+2357-U+2359, U+235A-U+235C, U+235E-U+2360, U+2363-U+2365, + U+2368-U+2369, U+236B-U+2370, U+2373-U+237A, U+2380-U+2383, U+2388-U+238B, U+2395 in Mono (by Ben Laenen) Changes from 2.12 to 2.13 -- adjusted U+0198B, U+01B3-U+01B4 in Sans, hinted U+01B4 in Sans Book +- adjusted U+0198B, U+01B3-U+01B4 in Sans, hinted U+01B4 in Sans Book (by Denis Jacquerye) -- added U+27F0-U+27FF, U+2906-U+2907, U+290A-U+290B, U+2940-U+2941 to Sans +- added U+27F0-U+27FF, U+2906-U+2907, U+290A-U+290B, U+2940-U+2941 to Sans (by Denis Jacquerye) -- added U+01E6-U+01E9, U+01EE-U+01EF, U+01F4-U+01F5, U+01FC-U+01FF, +- added U+01E6-U+01E9, U+01EE-U+01EF, U+01F4-U+01F5, U+01FC-U+01FF, U+021E-U+021F, U+0245, U+02BD, U+02C9, U+1E9B, U+2045-U+2046, U+2213, U+22C5, U+22EF to Sans Mono (by Roozbeh Pournader) - added U+04FA-U+04FD to Sans (by Michael Everson) -- removed U+2329 and U+232A because of their CJK properties, added U+27E8 +- removed U+2329 and U+232A because of their CJK properties, added U+27E8 and U+27E9 in their stead, fixing part of bug #9038 (by Roozbeh Pournader) -- corrected and improvised U+0466-U+0469, U+046E-U+0471, U+047C-U+047D, U+0482, - U+0484-U+0486, U+0492-U+0493, U+04B0-U+04B1, U+050C-U+050D, and U+204A +- corrected and improvised U+0466-U+0469, U+046E-U+0471, U+047C-U+047D, U+0482, + U+0484-U+0486, U+0492-U+0493, U+04B0-U+04B1, U+050C-U+050D, and U+204A in Sans (by Michael Everson) -- added instructions for U+0402, U+0409, U+040A, U+040B, U+044D, U+040F, +- added instructions for U+0402, U+0409, U+040A, U+040B, U+044D, U+040F, U+0452, U+0459-U+045B, U+045F to Sans Book (by Eugeniy Meshcheryakov) -- made italic shape for U+431, U+432, U+437, U+43B, U+43C, U+43D, U+444, U+447, - U+44D, U+44F, U+459, U+45A in SerifOblique and SerifBoldOblique +- made italic shape for U+431, U+432, U+437, U+43B, U+43C, U+43D, U+444, U+447, + U+44D, U+44F, U+459, U+45A in SerifOblique and SerifBoldOblique (by Andrey V. Panov) -- modified U+024C to match glyph in Unicode chart, fixing bug #9039 +- modified U+024C to match glyph in Unicode chart, fixing bug #9039 (by Denis Jacquerye) -- made some canonically equivalent characters share the same glyph: - U+02B9 = U+0374, U+0343 = U+0313, and U+0387 = U+00B7 also adjusting U+02BA +- made some canonically equivalent characters share the same glyph: + U+02B9 = U+0374, U+0343 = U+0313, and U+0387 = U+00B7 also adjusting U+02BA to look like double U+02B9, fixing parts of bug #9038 (by Roozbeh Pournader) -- changed shapes for U+0478 and U+0479 in Sans to those in the Unicode charts, - based on a recent decision by Unicode Technical Committee to only use +- changed shapes for U+0478 and U+0479 in Sans to those in the Unicode charts, + based on a recent decision by Unicode Technical Committee to only use the digraph form (by Michael Everson) -- adjusted width of NBSP U+00A0 and NNBSP U+202F, fixing bug #8401 +- adjusted width of NBSP U+00A0 and NNBSP U+202F, fixing bug #8401 (by Denis Jacquerye) -- fixed several contours to not intersect, use horizontal or vertical tangents, +- fixed several contours to not intersect, use horizontal or vertical tangents, use integer coordinates, etc (by Roozbeh Pournader and Denis Jacquerye) -- added U+1402, U+1430, U+144D, U+146C, U+148A, U+14A4, U+14C1, U+14D4, U+14EE, +- added U+1402, U+1430, U+144D, U+146C, U+148A, U+14A4, U+14C1, U+14D4, U+14EE, U+1527, U+1545, U+157E, U+158E, U+15AF to Sans (by Eugeniy Meshcheryakov) - enlarged width of U+459 and U+45A in Serif (by Andrey V. Panov) - made traditional shape for U+452, U+45B (by Andrey V. Panov) -- added euro sign U+20AC to Sans ExtraLight, making fontconfig recognize +- added euro sign U+20AC to Sans ExtraLight, making fontconfig recognize the font as supporting English (by Denis Jacquerye) Changes from 2.11 to 2.12 @@ -820,47 +846,47 @@ Changes from 2.10 to 2.11 Changes from 2.9 to 2.10: -- added U+0242, U+024A-U+024B, U+024E-U+024F, U+037C-U+037D, U+0E3F, - U+1D2C-U+1D2E, U+1D30-U+1D42, U+1D5D-U+1D6A, U+1D78, U+1DB8, - U+2090-U+2094, U+20D0-U+20D1, U+2C60-U+2C66, U+2C6B-U+2C6C, U+2C74 and +- added U+0242, U+024A-U+024B, U+024E-U+024F, U+037C-U+037D, U+0E3F, + U+1D2C-U+1D2E, U+1D30-U+1D42, U+1D5D-U+1D6A, U+1D78, U+1DB8, + U+2090-U+2094, U+20D0-U+20D1, U+2C60-U+2C66, U+2C6B-U+2C6C, U+2C74 and U+FB29 to Sans (by Gee Fung Sit) -- added Lao glyphs : U+0E81-0E82, U+E084, U+0E87-0E88, U+0E8A, U+0E8D, - U+0E94-0E97, U+0E99-0E9F, U+0EA1-0EA3, U+0EA5, U+0EA7, U+0EAA-0EAB, - U+0EAD-0EB9, U+0EBB-0EBD, U+0EC0-0EC4, U+0EC6, U+0EC8-0ECD, U+0EDC-0EDD +- added Lao glyphs : U+0E81-0E82, U+E084, U+0E87-0E88, U+0E8A, U+0E8D, + U+0E94-0E97, U+0E99-0E9F, U+0EA1-0EA3, U+0EA5, U+0EA7, U+0EAA-0EAB, + U+0EAD-0EB9, U+0EBB-0EBD, U+0EC0-0EC4, U+0EC6, U+0EC8-0ECD, U+0EDC-0EDD (by Remy Oudompheng) - fixed U+0193 not showing in Windows (bug #7897) (by Ben Laenen) - changes to U+222B-222D in Sans Mono (by Remy Oudompheng) -- ported the three remaining currency symbols from Arev (U+20B0, - U+20B2-U+20B3), and replaced one (U+20AF) in Sans (by Lars Naesbye +- ported the three remaining currency symbols from Arev (U+20B0, + U+20B2-U+20B3), and replaced one (U+20AF) in Sans (by Lars Naesbye Christensen) - corrected U+20A5 in Sans (by Gee Fung Sit) -- merged Double-Struck Letters from Arev: U+2102, U+210D, U+2115, +- merged Double-Struck Letters from Arev: U+2102, U+210D, U+2115, U+2119-U+211A, U+2124, U+213C-U+2140 (by Gee Fung Sit) -- added U+2308-U+230B and U+2329-U+232A to Sans Mono and Serif faces, - fixed incorrect direction of U+2329 in Sans faces, and improved - U+2308-U+230B in Sans faces per Ben Laenen's suggestions (by David +- added U+2308-U+230B and U+2329-U+232A to Sans Mono and Serif faces, + fixed incorrect direction of U+2329 in Sans faces, and improved + U+2308-U+230B in Sans faces per Ben Laenen's suggestions (by David Lawrence Ramsey) - added U+06D5 and final form of it (needed for Kurdish) (by Ben Laenen) -- added two special glyphs U+F000 and U+F001 in Sans Book that show the +- added two special glyphs U+F000 and U+F001 in Sans Book that show the current ppem size (horizontal and vertical) (by Ben Laenen) -- added U+2318 and U+2325 to Sans Mono faces, based on the Sans versions +- added U+2318 and U+2325 to Sans Mono faces, based on the Sans versions (by David Lawrence Ramsey) -- added U+2B14-U+2B1A to all faces except Sans ExtraLight (by David +- added U+2B14-U+2B1A to all faces except Sans ExtraLight (by David Lawrence Ramsey) -- respaced all Geometric Shapes characters in Serif faces to match those - in Sans faces again, respaced U+23CF in Sans, Sans ExtraLight, and - Serif faces to match U+25A0 (or Sans in Sans ExtraLight's case) again, - and respaced U+2B12-U+2B13 in Sans and Serif faces to match U+25A1 +- respaced all Geometric Shapes characters in Serif faces to match those + in Sans faces again, respaced U+23CF in Sans, Sans ExtraLight, and + Serif faces to match U+25A0 (or Sans in Sans ExtraLight's case) again, + and respaced U+2B12-U+2B13 in Sans and Serif faces to match U+25A1 again (by David Lawrence Ramsey) -- corrected width of Modifier Small Letters U+1D43-1D5B in Sans Oblique +- corrected width of Modifier Small Letters U+1D43-1D5B in Sans Oblique and U+1D9B-U+1DBF in Sans Oblique and Sans Bold Oblique (by Gee Fung Sit) -- added a bunch of glyphs to Sans ExtraLight (see SVN for details) (by +- added a bunch of glyphs to Sans ExtraLight (see SVN for details) (by Gee Fung Sit) -- adjusted Cyrillic descenders in Sans ExtraLight to sync with Sans (by +- adjusted Cyrillic descenders in Sans ExtraLight to sync with Sans (by Gee Fung Sit) - added U+0242, U+0245 to Serif (by Gee Fung Sit) -- replaced the SHPIX routines which gave them bad spacing at certain - sizes in FreeType for A, V, Z, v and z in Sans Bold (by Ben Laenen) +- replaced the SHPIX routines which gave them bad spacing at certain + sizes in FreeType for A, V, Z, v and z in Sans Bold (by Ben Laenen) Changes from 2.8 to 2.9: @@ -1097,7 +1123,7 @@ Changes from 2.3 to 2.4: - added DejaVu Sans Extra Light (by Denis Jacquerye) - Adjusted underline position for (hopefully) improved legibility in Sans, Serif, Mono (Tim May) -- added auto-generated DejaVu LGC (by Stepan Roh) +- added auto-generated DejaVu LGC (by Stepan Roh) Changes from 2.2 to 2.3: @@ -1159,7 +1185,7 @@ Changes from 2.2 to 2.3: - added U+0181, U+0187-U+0188, U+018A, U+018D, U+018F, U+0191, U+0193, U+0195-U+019F, U+01A4-01A5, U+01AC-01AD, U+01B5-U+01B6, U+1BB, U+01F6, U+01D7-U+01DC, U+0238-U+0239, U+0241 to Mono (by Denis Jacquerye) -- added to Mono and Serif (by Denis Jacquerye) +- added to Mono and Serif (by Denis Jacquerye) Changes from 2.1 to 2.2: @@ -1203,7 +1229,7 @@ Changes from 2.1 to 2.2: - completed basic Greek alphabet: added U+0374-U+0375, U+037A, U+037E, U+0384-U+038A, U+038C, U+038E-U+0390, U+03AC-U+03BF, U+03C1-U+03CE (by Ben Laenen) -- added U+2070 and U+2074-U+2079 (by Mederic Boquien) +- added U+2070 and U+2074-U+2079 (by Mederic Boquien) Changes from 2.0 to 2.1: @@ -1238,7 +1264,7 @@ Changes from 2.0 to 2.1: Lawrence Ramsey) - new logo (by Gee Fung Sit) - added U+0180, U+018E, U+201F, U+2024, U+2025, U+203D, U+2200, U+2203, - U+2213, U+222C, U+222D, U+2263 to Sans (by Gee Fung Sit) + U+2213, U+222C, U+222D, U+2263 to Sans (by Gee Fung Sit) Changes from 1.15 to 2.0: @@ -1426,4 +1452,4 @@ Changes from 0.9 to 0.9.1: - proper caron shape for dcaron and tcaron - minor visual changes -$Id: NEWS 2594 2015-05-17 07:54:48Z ben_laenen $ +$Id$ diff --git a/fonts/dejavu-fonts-ttf-2.35/README b/fonts/dejavu-fonts-ttf-2.37/README.md similarity index 86% rename from fonts/dejavu-fonts-ttf-2.35/README rename to fonts/dejavu-fonts-ttf-2.37/README.md index 8cbc7bf60..43148d7c7 100644 --- a/fonts/dejavu-fonts-ttf-2.35/README +++ b/fonts/dejavu-fonts-ttf-2.37/README.md @@ -1,4 +1,6 @@ -DejaVu fonts 2.35 (c)2004-2015 DejaVu fonts team +[![Build Status](https://travis-ci.org/dejavu-fonts/dejavu-fonts.svg)](https://travis-ci.org/dejavu-fonts/dejavu-fonts) + +DejaVu fonts 2.37 (c)2004-2016 DejaVu fonts team ------------------------------------------------ The DejaVu fonts are a font family based on the Bitstream Vera Fonts @@ -31,6 +33,7 @@ DejaVu Serif Condensed (experimental) DejaVu Serif Condensed Bold (experimental) DejaVu Serif Condensed Bold Italic (experimental) DejaVu Serif Condensed Italic (experimental) +DejaVu Math TeX Gyre All fonts are also available as derivative called DejaVu LGC with support only for Latin, Greek and Cyrillic scripts. @@ -56,4 +59,9 @@ U+213C-U+2140, U+2295-U+2298, U+2308-U+230B, U+26A2-U+26B1, U+2701-U+2704, U+2706-U+2709, U+270C-U+274B, U+2758-U+275A, U+2761-U+2775, U+2780-U+2794, U+2798-U+27AF, U+27B1-U+27BE, U+FB05-U+FB06 -$Id: README 2595 2015-05-17 07:57:27Z ben_laenen $ +DejaVu Math TeX Gyre +-------------------- +TeX Gyre DJV Math by B. Jackowski, P. Strzelczyk and P. Pianowski +(on behalf of TeX users groups). + +$Id$ diff --git a/fonts/dejavu-fonts-ttf-2.35/fontconfig/20-unhint-small-dejavu-sans-mono.conf b/fonts/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans-mono.conf similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/fontconfig/20-unhint-small-dejavu-sans-mono.conf rename to fonts/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans-mono.conf diff --git a/fonts/dejavu-fonts-ttf-2.35/fontconfig/20-unhint-small-dejavu-sans.conf b/fonts/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans.conf similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/fontconfig/20-unhint-small-dejavu-sans.conf rename to fonts/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans.conf diff --git a/fonts/dejavu-fonts-ttf-2.35/fontconfig/20-unhint-small-dejavu-serif.conf b/fonts/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-serif.conf similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/fontconfig/20-unhint-small-dejavu-serif.conf rename to fonts/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-serif.conf diff --git a/fonts/dejavu-fonts-ttf-2.35/fontconfig/57-dejavu-sans-mono.conf b/fonts/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans-mono.conf similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/fontconfig/57-dejavu-sans-mono.conf rename to fonts/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans-mono.conf diff --git a/fonts/dejavu-fonts-ttf-2.35/fontconfig/57-dejavu-sans.conf b/fonts/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans.conf similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/fontconfig/57-dejavu-sans.conf rename to fonts/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans.conf diff --git a/fonts/dejavu-fonts-ttf-2.35/fontconfig/57-dejavu-serif.conf b/fonts/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-serif.conf similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/fontconfig/57-dejavu-serif.conf rename to fonts/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-serif.conf diff --git a/fonts/dejavu-fonts-ttf-2.35/langcover.txt b/fonts/dejavu-fonts-ttf-2.37/langcover.txt similarity index 100% rename from fonts/dejavu-fonts-ttf-2.35/langcover.txt rename to fonts/dejavu-fonts-ttf-2.37/langcover.txt diff --git a/fonts/dejavu-fonts-ttf-2.35/status.txt b/fonts/dejavu-fonts-ttf-2.37/status.txt similarity index 93% rename from fonts/dejavu-fonts-ttf-2.35/status.txt rename to fonts/dejavu-fonts-ttf-2.37/status.txt index 515ac7a7c..8b78cf38b 100644 --- a/fonts/dejavu-fonts-ttf-2.35/status.txt +++ b/fonts/dejavu-fonts-ttf-2.37/status.txt @@ -1,5 +1,5 @@ This is the status file for DejaVu fonts -($Id: status.txt 2538 2013-08-25 16:02:56Z moyogo $) +($Id$) original = present in original Bitstream Vera 1.10 = added in DejaVu fonts @@ -211,7 +211,7 @@ U+010c Ccaron original U+010d ccaron original U+010e Dcaron 1.0 U+010f dcaron 1.0 -U+0110 Dcroat 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+0110 Dcroat 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+0111 dcroat original U+0112 Emacron 1.5 U+0113 emacron 1.5 @@ -769,7 +769,7 @@ U+0349 uni0349 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+034a uni034A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+034b uni034B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+034c uni034C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+034d uni034D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+034d uni034D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+034e uni034E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+034f uni034F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+0351 uni0351 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -791,13 +791,14 @@ U+0372 uni0372 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+0373 uni0373 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+0374 uni0374 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+0375 uni0375 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0376 uni0376 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0377 uni0377 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) +U+0376 uni0376 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+0377 uni0377 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+037a uni037A 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+037b uni037B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+037c uni037C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+037d uni037D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) +U+037b uni037B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+037c uni037C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+037d uni037D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+037e uni037E 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+037f uni037F 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+0384 tonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+0385 dieresistonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+0386 Alphatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) @@ -809,29 +810,29 @@ U+038c Omicrontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+038e Upsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+038f Omegatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+0390 iotadieresistonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0391 Alpha 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0392 Beta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0393 Gamma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0394 uni0394 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0395 Epsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0396 Zeta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0397 Eta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0398 Theta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0399 Iota 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+039a Kappa 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+039b Lambda 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+039c Mu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+039d Nu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+039e Xi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+039f Omicron 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a0 Pi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a1 Rho 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a3 Sigma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a4 Tau 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a5 Upsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a6 Phi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a7 Chi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03a8 Psi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+0391 Alpha 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0392 Beta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0393 Gamma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0394 uni0394 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0395 Epsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0396 Zeta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0397 Eta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0398 Theta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+0399 Iota 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+039a Kappa 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+039b Lambda 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+039c Mu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+039d Nu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+039e Xi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+039f Omicron 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a0 Pi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a1 Rho 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a3 Sigma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a4 Tau 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a5 Upsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a6 Phi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a7 Chi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03a8 Psi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+03a9 Omega original U+03aa Iotadieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03ab Upsilondieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) @@ -840,31 +841,31 @@ U+03ad epsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+03ae etatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03af iotatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03b0 upsilondieresistonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b1 alpha 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b2 beta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b3 gamma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b4 delta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b5 epsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b6 zeta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b7 eta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b8 theta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b9 iota 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ba kappa 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03bb lambda 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03bc uni03BC 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03bd nu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03be xi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03bf omicron 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+03b1 alpha 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b2 beta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b3 gamma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b4 delta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b5 epsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b6 zeta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b7 eta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b8 theta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03b9 iota 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03ba kappa 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03bb lambda 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03bc uni03BC 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03bd nu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03be xi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03bf omicron 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+03c0 pi original -U+03c1 rho 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c2 sigma1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c3 sigma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c4 tau 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c5 upsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c6 phi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c7 chi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c8 psi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03c9 omega 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+03c1 rho 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c2 sigma1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c3 sigma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c4 tau 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c5 upsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c6 phi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c7 chi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c8 psi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03c9 omega 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+03ca iotadieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03cb upsilondieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03cc omicrontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) @@ -872,12 +873,12 @@ U+03cd upsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+03ce omegatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03cf uni03CF 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+03d0 uni03D0 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d1 theta1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) +U+03d1 theta1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+03d2 Upsilon1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) U+03d3 uni03D3 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) U+03d4 uni03D4 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d5 phi1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.18 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03d6 omega1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) +U+03d5 phi1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.18 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03d6 omega1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) 2.36 (Math TeX Gyre Regular) U+03d7 uni03D7 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) U+03d8 uni03D8 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) U+03d9 uni03D9 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) @@ -903,12 +904,12 @@ U+03ec uni03EC 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+03ed uni03ED 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+03ee uni03EE 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+03ef uni03EF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03f0 uni03F0 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03f1 uni03F1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) +U+03f0 uni03F0 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03f1 uni03F1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) 2.36 (Math TeX Gyre Regular) U+03f2 uni03F2 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03f3 uni03F3 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f4 uni03F4 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f5 uni03F5 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+03f4 uni03F4 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+03f5 uni03F5 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+03f6 uni03F6 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03f7 uni03F7 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+03f8 uni03F8 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) @@ -1572,7 +1573,7 @@ U+07f5 uni07F5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condense U+07f8 uni07F8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) U+07f9 uni07F9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) U+07fa uni07FA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0e3f uni0E3F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.35 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) +U+0e3f uni0E3F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.35 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) U+0e81 uni0E81 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+0e82 uni0E82 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+0e84 uni0E84 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) @@ -2473,96 +2474,96 @@ U+1e9c uni1E9C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+1e9d uni1E9D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+1e9e uni1E9E 2.28 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.32 (Sans ExtraLight) U+1e9f uni1E9F 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1ea0 uni1EA0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ea1 uni1EA1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ea2 uni1EA2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ea3 uni1EA3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ea4 uni1EA4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ea5 uni1EA5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ea6 uni1EA6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ea7 uni1EA7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ea8 uni1EA8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ea9 uni1EA9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eaa uni1EAA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eab uni1EAB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eac uni1EAC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1ead uni1EAD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1eae uni1EAE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1eaf uni1EAF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1eb0 uni1EB0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1eb1 uni1EB1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1eb2 uni1EB2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1eb3 uni1EB3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1eb4 uni1EB4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1eb5 uni1EB5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1eb6 uni1EB6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1eb7 uni1EB7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+1ea0 uni1EA0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ea1 uni1EA1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ea2 uni1EA2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ea3 uni1EA3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ea4 uni1EA4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ea5 uni1EA5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ea6 uni1EA6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ea7 uni1EA7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ea8 uni1EA8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ea9 uni1EA9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eaa uni1EAA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eab uni1EAB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eac uni1EAC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1ead uni1EAD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1eae uni1EAE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eaf uni1EAF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb0 uni1EB0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb1 uni1EB1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb2 uni1EB2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb3 uni1EB3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb4 uni1EB4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb5 uni1EB5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1eb6 uni1EB6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1eb7 uni1EB7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+1eb8 uni1EB8 2.2 U+1eb9 uni1EB9 2.2 -U+1eba uni1EBA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ebb uni1EBB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ebc uni1EBC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ebd uni1EBD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ebe uni1EBE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ebf uni1EBF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec0 uni1EC0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec1 uni1EC1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec2 uni1EC2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec3 uni1EC3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec4 uni1EC4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec5 uni1EC5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ec6 uni1EC6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1ec7 uni1EC7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1ec8 uni1EC8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ec9 uni1EC9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) +U+1eba uni1EBA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ebb uni1EBB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ebc uni1EBC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ebd uni1EBD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ebe uni1EBE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ebf uni1EBF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec0 uni1EC0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec1 uni1EC1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec2 uni1EC2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec3 uni1EC3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec4 uni1EC4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec5 uni1EC5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ec6 uni1EC6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1ec7 uni1EC7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1ec8 uni1EC8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ec9 uni1EC9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+1eca uni1ECA 2.2 U+1ecb uni1ECB 2.2 U+1ecc uni1ECC 2.2 U+1ecd uni1ECD 2.2 -U+1ece uni1ECE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ecf uni1ECF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ed0 uni1ED0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed1 uni1ED1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed2 uni1ED2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed3 uni1ED3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed4 uni1ED4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed5 uni1ED5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed6 uni1ED6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed7 uni1ED7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ed8 uni1ED8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1ed9 uni1ED9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1eda uni1EDA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1edb uni1EDB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1edc uni1EDC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1edd uni1EDD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ede uni1EDE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1edf uni1EDF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ee0 uni1EE0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ee1 uni1EE1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ee2 uni1EE2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ee3 uni1EE3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) +U+1ece uni1ECE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ecf uni1ECF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ed0 uni1ED0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed1 uni1ED1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed2 uni1ED2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed3 uni1ED3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed4 uni1ED4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed5 uni1ED5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed6 uni1ED6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed7 uni1ED7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ed8 uni1ED8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1ed9 uni1ED9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1eda uni1EDA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1edb uni1EDB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1edc uni1EDC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1edd uni1EDD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ede uni1EDE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1edf uni1EDF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ee0 uni1EE0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ee1 uni1EE1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ee2 uni1EE2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ee3 uni1EE3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) U+1ee4 uni1EE4 2.2 U+1ee5 uni1EE5 2.2 -U+1ee6 uni1EE6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ee7 uni1EE7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ee8 uni1EE8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ee9 uni1EE9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eea uni1EEA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eeb uni1EEB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eec uni1EEC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eed uni1EED 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eee uni1EEE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1eef uni1EEF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ef0 uni1EF0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1ef1 uni1EF1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) +U+1ee6 uni1EE6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ee7 uni1EE7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ee8 uni1EE8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ee9 uni1EE9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eea uni1EEA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eeb uni1EEB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eec uni1EEC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eed uni1EED 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eee uni1EEE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1eef uni1EEF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ef0 uni1EF0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+1ef1 uni1EF1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) U+1ef2 Ygrave 1.2 U+1ef3 ygrave 1.2 -U+1ef4 uni1EF4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ef5 uni1EF5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ef6 uni1EF6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ef7 uni1EF7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ef8 uni1EF8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ef9 uni1EF9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) +U+1ef4 uni1EF4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ef5 uni1EF5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ef6 uni1EF6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ef7 uni1EF7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ef8 uni1EF8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+1ef9 uni1EF9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+1efa uni1EFA 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+1efb uni1EFB 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+1f00 uni1F00 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) @@ -2798,20 +2799,20 @@ U+1ffb uni1FFB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+1ffc uni1FFC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) U+1ffd uni1FFD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) U+1ffe uni1FFE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+2000 uni2000 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2001 uni2001 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2002 uni2002 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2003 uni2003 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2004 uni2004 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2005 uni2005 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2006 uni2006 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2007 uni2007 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2008 uni2008 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2009 uni2009 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+200a uni200A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+200b uni200B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+200c uni200C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+200d uni200D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) +U+2000 uni2000 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2001 uni2001 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2002 uni2002 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2003 uni2003 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2004 uni2004 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2005 uni2005 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2006 uni2006 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2007 uni2007 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2008 uni2008 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2009 uni2009 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+200a uni200A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+200b uni200B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+200c uni200C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+200d uni200D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+200e uni200E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) U+200f uni200F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) U+2010 uni2010 1.5 @@ -2820,7 +2821,7 @@ U+2012 figuredash 1.5 U+2013 endash original U+2014 emdash original U+2015 uni2015 1.5 -U+2016 uni2016 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2016 uni2016 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2017 underscoredbl 2.3 U+2018 quoteleft original U+2019 quoteright original @@ -2845,28 +2846,28 @@ U+202b uni202B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+202c uni202C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+202d uni202D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+202e uni202E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+202f uni202F 2.11 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.23 (Serif Italic Condensed) +U+202f uni202F 2.11 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2030 perthousand original U+2031 uni2031 2.1 -U+2032 minute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2033 second 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2034 uni2034 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2035 uni2035 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2036 uni2036 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2037 uni2037 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) +U+2032 minute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+2033 second 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+2034 uni2034 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+2035 uni2035 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+2036 uni2036 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+2037 uni2037 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) U+2038 uni2038 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+2039 guilsinglleft original U+203a guilsinglright original -U+203b uni203B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) +U+203b uni203B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+203c exclamdbl 2.0 -U+203d uni203D 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.11 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.14 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+203d uni203D 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.11 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.14 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+203e uni203E 2.3 U+203f uni203F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2040 uni2040 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) U+2041 uni2041 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2042 uni2042 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+2043 uni2043 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2044 fraction 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) +U+2044 fraction 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) U+2045 uni2045 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+2046 uni2046 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+2047 uni2047 2.0 @@ -2880,12 +2881,12 @@ U+204e uni204E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+204f uni204F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+2050 uni2050 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) U+2051 uni2051 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2052 uni2052 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) +U+2052 uni2052 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) U+2053 uni2053 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+2054 uni2054 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) U+2055 uni2055 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2056 uni2056 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2057 uni2057 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) +U+2057 uni2057 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) U+2058 uni2058 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2059 uni2059 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+205a uni205A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -2894,11 +2895,11 @@ U+205c uni205C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+205d uni205D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+205e uni205E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+205f uni205F 2.14 -U+2060 uni2060 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2061 uni2061 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2062 uni2062 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2063 uni2063 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2064 uni2064 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) +U+2060 uni2060 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2061 uni2061 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2062 uni2062 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2063 uni2063 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2064 uni2064 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) U+206a uni206A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+206b uni206B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+206c uni206C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -2948,111 +2949,132 @@ U+209a uni209A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+209b uni209B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+209c uni209C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+20a0 uni20A0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a1 colonmonetary 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20a1 colonmonetary 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+20a2 uni20A2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20a3 franc 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a4 lira 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20a4 lira 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+20a5 uni20A5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20a6 uni20A6 2.3 U+20a7 peseta 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20a8 uni20A8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a9 uni20A9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20a9 uni20A9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+20aa uni20AA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20ab dong 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20ab dong 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+20ac Euro original U+20ad uni20AD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20ae uni20AE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20af uni20AF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20b0 uni20B0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20b1 uni20B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+20b2 uni20B2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20b1 uni20B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+20b2 uni20B2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+20b3 uni20B3 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+20b4 uni20B4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+20b5 uni20B5 2.2 U+20b8 uni20B8 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+20b9 uni20B9 2.32 -U+20ba uni20BA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+20bd uni20BD 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+20d0 uni20D0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+20d1 uni20D1 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+20d6 uni20D6 2.8 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+20d7 uni20D7 2.8 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+20db uni20DB 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+20dc uni20DC 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+20e1 uni20E1 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+20ba uni20BA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20bd uni20BD 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+20d0 uni20D0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+20d1 uni20D1 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+20d2 uni20D2 2.36 (Math TeX Gyre Regular) +U+20d3 uni20D3 2.36 (Math TeX Gyre Regular) +U+20d4 uni20D4 2.36 (Math TeX Gyre Regular) +U+20d5 uni20D5 2.36 (Math TeX Gyre Regular) +U+20d6 uni20D6 2.8 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+20d7 uni20D7 2.8 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+20d8 uni20D8 2.36 (Math TeX Gyre Regular) +U+20db uni20DB 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+20dc uni20DC 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+20dd uni20DD 2.36 (Math TeX Gyre Regular) +U+20de uni20DE 2.36 (Math TeX Gyre Regular) +U+20df uni20DF 2.36 (Math TeX Gyre Regular) +U+20e1 uni20E1 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+20e4 uni20E4 2.36 (Math TeX Gyre Regular) +U+20e5 uni20E5 2.36 (Math TeX Gyre Regular) +U+20e6 uni20E6 2.36 (Math TeX Gyre Regular) +U+20e8 uni20E8 2.36 (Math TeX Gyre Regular) +U+20e9 uni20E9 2.36 (Math TeX Gyre Regular) +U+20ea uni20EA 2.36 (Math TeX Gyre Regular) +U+20eb uni20EB 2.36 (Math TeX Gyre Regular) +U+20ec uni20EC 2.36 (Math TeX Gyre Regular) +U+20ed uni20ED 2.36 (Math TeX Gyre Regular) +U+20ee uni20EE 2.36 (Math TeX Gyre Regular) +U+20ef uni20EF 2.36 (Math TeX Gyre Regular) +U+20f0 uni20F0 2.36 (Math TeX Gyre Regular) U+2100 uni2100 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2101 uni2101 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2102 uni2102 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.16 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Condensed) -U+2103 uni2103 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2102 uni2102 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.16 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+2103 uni2103 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2104 uni2104 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2105 uni2105 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2106 uni2106 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2107 uni2107 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2107 uni2107 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2108 uni2108 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2109 uni2109 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+210b uni210B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+210c uni210C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+210d uni210D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+210e uni210E 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+210f uni210F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.28 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2110 uni2110 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2111 Ifraktur 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2112 uni2112 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2113 uni2113 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2109 uni2109 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+210a uni210A 2.36 (Math TeX Gyre Regular) +U+210b uni210B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+210c uni210C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+210d uni210D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+210e uni210E 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) 2.36 (Math TeX Gyre Regular) +U+210f uni210F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.28 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+2110 uni2110 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2111 Ifraktur 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2112 uni2112 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2113 uni2113 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2114 uni2114 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2115 uni2115 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2116 uni2116 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2117 uni2117 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2118 weierstrass 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2119 uni2119 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+211a uni211A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+211b uni211B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+211c Rfraktur 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+211d uni211D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+211e prescription 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2115 uni2115 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2116 uni2116 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2117 uni2117 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2118 weierstrass 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2119 uni2119 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+211a uni211A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+211b uni211B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+211c Rfraktur 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+211d uni211D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+211e prescription 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+211f uni211F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2120 uni2120 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2120 uni2120 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2121 uni2121 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2122 trademark original U+2123 uni2123 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2124 uni2124 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2124 uni2124 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2125 uni2125 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2126 uni2126 2.2 -U+2127 uni2127 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2128 uni2128 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2127 uni2127 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2128 uni2128 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2129 uni2129 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+212a uni212A 2.2 U+212b uni212B 2.2 -U+212c uni212C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+212d uni212D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+212e estimated 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+212f uni212F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2130 uni2130 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2131 uni2131 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+212c uni212C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+212d uni212D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+212e estimated 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+212f uni212F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2130 uni2130 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2131 uni2131 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2132 uni2132 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2133 uni2133 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2134 uni2134 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2135 aleph 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2136 uni2136 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2137 uni2137 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2138 uni2138 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2133 uni2133 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2134 uni2134 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2135 aleph 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2136 uni2136 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2137 uni2137 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2138 uni2138 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2139 uni2139 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+213a uni213A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+213b uni213B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+213c uni213C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+213d uni213D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+213e uni213E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+213f uni213F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+2140 uni2140 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) +U+213c uni213C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+213d uni213D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+213e uni213E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+213f uni213F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+2140 uni2140 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) U+2141 uni2141 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) U+2142 uni2142 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) U+2143 uni2143 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) U+2144 uni2144 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) -U+2145 uni2145 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+2146 uni2146 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+2147 uni2147 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) -U+2148 uni2148 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2149 uni2149 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) +U+2145 uni2145 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+2146 uni2146 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+2147 uni2147 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+2148 uni2148 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2149 uni2149 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) U+214b uni214B 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+214e uni214E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+2150 uni2150 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) @@ -3110,84 +3132,84 @@ U+2183 uni2183 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+2184 uni2184 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2185 uni2185 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+2189 uni2189 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2190 arrowleft 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2191 arrowup 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2192 arrowright 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2193 arrowdown 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2194 arrowboth 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2195 arrowupdn 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2196 uni2196 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2197 uni2197 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2198 uni2198 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2199 uni2199 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+219a uni219A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+219b uni219B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2190 arrowleft 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2191 arrowup 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2192 arrowright 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2193 arrowdown 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2194 arrowboth 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2195 arrowupdn 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2196 uni2196 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2197 uni2197 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2198 uni2198 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2199 uni2199 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+219a uni219A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+219b uni219B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+219c uni219C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+219d uni219D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+219e uni219E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+219f uni219F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a0 uni21A0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a1 uni21A1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a2 uni21A2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a3 uni21A3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a4 uni21A4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a5 uni21A5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a6 uni21A6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a7 uni21A7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+219e uni219E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+219f uni219F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a0 uni21A0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a1 uni21A1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a2 uni21A2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a3 uni21A3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a4 uni21A4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a5 uni21A5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a6 uni21A6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21a7 uni21A7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21a8 arrowupdnbse 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a9 uni21A9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21aa uni21AA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ab uni21AB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ac uni21AC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ad uni21AD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ae uni21AE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+21a9 uni21A9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21aa uni21AA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21ab uni21AB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21ac uni21AC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21ad uni21AD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21ae uni21AE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21af uni21AF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b0 uni21B0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b1 uni21B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b2 uni21B2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b3 uni21B3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b4 uni21B4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b5 carriagereturn 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b6 uni21B6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b7 uni21B7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+21b0 uni21B0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b1 uni21B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b2 uni21B2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b3 uni21B3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b4 uni21B4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b5 carriagereturn 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b6 uni21B6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21b7 uni21B7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21b8 uni21B8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21b9 uni21B9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ba uni21BA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21bb uni21BB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21bc uni21BC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21bd uni21BD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21be uni21BE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21bf uni21BF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c0 uni21C0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c1 uni21C1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c2 uni21C2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c3 uni21C3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c4 uni21C4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c5 uni21C5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c6 uni21C6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c7 uni21C7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c8 uni21C8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21c9 uni21C9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ca uni21CA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21cb uni21CB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21cc uni21CC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21cd uni21CD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ce uni21CE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21cf uni21CF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d0 arrowdblleft 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d1 arrowdblup 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d2 arrowdblright 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d3 arrowdbldown 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d4 arrowdblboth 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d5 uni21D5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d6 uni21D6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d7 uni21D7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d8 uni21D8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21d9 uni21D9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21da uni21DA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21db uni21DB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21dc uni21DC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21dd uni21DD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+21ba uni21BA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21bb uni21BB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21bc uni21BC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21bd uni21BD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21be uni21BE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21bf uni21BF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c0 uni21C0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c1 uni21C1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c2 uni21C2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c3 uni21C3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c4 uni21C4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c5 uni21C5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c6 uni21C6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c7 uni21C7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c8 uni21C8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21c9 uni21C9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21ca uni21CA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21cb uni21CB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21cc uni21CC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21cd uni21CD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21ce uni21CE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21cf uni21CF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d0 arrowdblleft 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d1 arrowdblup 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d2 arrowdblright 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d3 arrowdbldown 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d4 arrowdblboth 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d5 uni21D5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d6 uni21D6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d7 uni21D7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d8 uni21D8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21d9 uni21D9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21da uni21DA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21db uni21DB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21dc uni21DC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21dd uni21DD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21de uni21DE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21df uni21DF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21e0 uni21E0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -3196,10 +3218,10 @@ U+21e2 uni21E2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+21e3 uni21E3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21e4 uni21E4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21e5 uni21E5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e6 uni21E6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e7 uni21E7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e8 uni21E8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e9 uni21E9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+21e6 uni21E6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21e7 uni21E7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21e8 uni21E8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21e9 uni21E9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21ea uni21EA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21eb uni21EB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21ec uni21EC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -3209,10 +3231,10 @@ U+21ef uni21EF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+21f0 uni21F0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21f1 uni21F1 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21f2 uni21F2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f3 uni21F3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+21f3 uni21F3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21f4 uni21F4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f5 uni21F5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f6 uni21F6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+21f5 uni21F5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+21f6 uni21F6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+21f7 uni21F7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21f8 uni21F8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21f9 uni21F9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -3222,31 +3244,31 @@ U+21fc uni21FC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+21fd uni21FD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21fe uni21FE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+21ff uni21FF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2200 universal 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2201 uni2201 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2200 universal 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2201 uni2201 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2202 partialdiff original -U+2203 existential 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2204 uni2204 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2205 emptyset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2203 existential 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2204 uni2204 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2205 emptyset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2206 Delta original U+2207 gradient 2.1 -U+2208 element 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2209 notelement 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+220a uni220A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+220b suchthat 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+220c uni220C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+220d uni220D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+220e uni220E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2208 element 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2209 notelement 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+220a uni220A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+220b suchthat 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+220c uni220C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+220d uni220D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+220e uni220E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+220f product original -U+2210 uni2210 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2210 uni2210 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2211 summation original U+2212 minus original -U+2213 uni2213 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2214 uni2214 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2213 uni2213 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2214 uni2214 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2215 uni2215 original -U+2216 uni2216 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2217 asteriskmath 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2218 uni2218 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2216 uni2216 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2217 asteriskmath 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2218 uni2218 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2219 uni2219 original U+221a radical original U+221b uni221B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) @@ -3255,215 +3277,215 @@ U+221d proportional 2.1 U+221e infinity original U+221f orthogonal 2.1 U+2220 angle 2.3 -U+2221 uni2221 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2222 uni2222 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2223 uni2223 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2224 uni2224 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2225 uni2225 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2226 uni2226 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2221 uni2221 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2222 uni2222 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2223 uni2223 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2224 uni2224 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2225 uni2225 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2226 uni2226 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2227 logicaland 2.1 U+2228 logicalor 2.1 U+2229 intersection 2.1 U+222a union 2.1 U+222b integral original -U+222c uni222C 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+222d uni222D 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+222e uni222E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+222f uni222F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2230 uni2230 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2231 uni2231 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2232 uni2232 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2233 uni2233 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2234 therefore 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2235 uni2235 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2236 uni2236 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2237 uni2237 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2238 uni2238 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2239 uni2239 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+223a uni223A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+223b uni223B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+223c similar 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+223d uni223D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+223e uni223E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+223f uni223F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2240 uni2240 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2241 uni2241 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2242 uni2242 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2243 uni2243 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2244 uni2244 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2245 congruent 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2246 uni2246 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2247 uni2247 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) +U+222c uni222C 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+222d uni222D 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+222e uni222E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+222f uni222F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2230 uni2230 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2231 uni2231 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2232 uni2232 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2233 uni2233 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2234 therefore 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2235 uni2235 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2236 uni2236 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2237 uni2237 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2238 uni2238 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2239 uni2239 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+223a uni223A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+223b uni223B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+223c similar 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+223d uni223D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+223e uni223E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+223f uni223F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2240 uni2240 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2241 uni2241 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2242 uni2242 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2243 uni2243 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2244 uni2244 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2245 congruent 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2246 uni2246 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2247 uni2247 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2248 approxequal original -U+2249 uni2249 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+224a uni224A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+224b uni224B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+224c uni224C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+224d uni224D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+224e uni224E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+224f uni224F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2250 uni2250 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2251 uni2251 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2252 uni2252 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2253 uni2253 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2254 uni2254 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2255 uni2255 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2256 uni2256 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2257 uni2257 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2258 uni2258 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2259 uni2259 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+225a uni225A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+225b uni225B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+225c uni225C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+225d uni225D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+225e uni225E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+225f uni225F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) +U+2249 uni2249 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+224a uni224A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+224b uni224B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+224c uni224C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+224d uni224D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+224e uni224E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+224f uni224F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2250 uni2250 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2251 uni2251 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2252 uni2252 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2253 uni2253 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2254 uni2254 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2255 uni2255 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2256 uni2256 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2257 uni2257 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2258 uni2258 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2259 uni2259 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+225a uni225A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+225b uni225B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+225c uni225C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+225d uni225D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+225e uni225E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+225f uni225F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2260 notequal original U+2261 equivalence 2.1 -U+2262 uni2262 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2263 uni2263 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2262 uni2262 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2263 uni2263 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2264 lessequal original U+2265 greaterequal original -U+2266 uni2266 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2267 uni2267 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2268 uni2268 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2269 uni2269 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+226a uni226A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+226b uni226B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+226c uni226C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+226d uni226D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+226e uni226E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+226f uni226F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2270 uni2270 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2271 uni2271 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2272 uni2272 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2273 uni2273 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2274 uni2274 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2275 uni2275 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2276 uni2276 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2277 uni2277 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2278 uni2278 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2279 uni2279 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+227a uni227A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+227b uni227B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+227c uni227C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+227d uni227D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+227e uni227E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+227f uni227F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2280 uni2280 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2281 uni2281 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2282 propersubset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2283 propersuperset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2284 notsubset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2285 uni2285 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2286 reflexsubset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2287 reflexsuperset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2288 uni2288 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2289 uni2289 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+228a uni228A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+228b uni228B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+228c uni228C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+228d uni228D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+228e uni228E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+228f uni228F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2290 uni2290 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2291 uni2291 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2292 uni2292 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2293 uni2293 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2294 uni2294 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2295 circleplus 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2296 uni2296 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2297 circlemultiply 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2298 uni2298 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2299 uni2299 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+229a uni229A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+229b uni229B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+229c uni229C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+229d uni229D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+229e uni229E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+229f uni229F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22a0 uni22A0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22a1 uni22A1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22a2 uni22A2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22a3 uni22A3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22a4 uni22A4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22a5 perpendicular 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22a6 uni22A6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22a7 uni22A7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22a8 uni22A8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22a9 uni22A9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22aa uni22AA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22ab uni22AB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22ac uni22AC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22ad uni22AD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22ae uni22AE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22af uni22AF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2266 uni2266 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2267 uni2267 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2268 uni2268 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2269 uni2269 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+226a uni226A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+226b uni226B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+226c uni226C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+226d uni226D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+226e uni226E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+226f uni226F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2270 uni2270 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2271 uni2271 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2272 uni2272 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2273 uni2273 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2274 uni2274 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2275 uni2275 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2276 uni2276 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2277 uni2277 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2278 uni2278 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2279 uni2279 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+227a uni227A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+227b uni227B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+227c uni227C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+227d uni227D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+227e uni227E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+227f uni227F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2280 uni2280 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2281 uni2281 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2282 propersubset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2283 propersuperset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2284 notsubset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2285 uni2285 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2286 reflexsubset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2287 reflexsuperset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2288 uni2288 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2289 uni2289 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+228a uni228A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+228b uni228B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+228c uni228C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+228d uni228D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+228e uni228E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+228f uni228F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2290 uni2290 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2291 uni2291 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2292 uni2292 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2293 uni2293 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2294 uni2294 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2295 circleplus 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2296 uni2296 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2297 circlemultiply 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2298 uni2298 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2299 uni2299 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+229a uni229A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+229b uni229B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+229c uni229C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+229d uni229D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+229e uni229E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+229f uni229F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22a0 uni22A0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22a1 uni22A1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22a2 uni22A2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22a3 uni22A3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22a4 uni22A4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22a5 perpendicular 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22a6 uni22A6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22a7 uni22A7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22a8 uni22A8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22a9 uni22A9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22aa uni22AA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22ab uni22AB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22ac uni22AC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22ad uni22AD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22ae uni22AE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22af uni22AF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+22b0 uni22B0 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+22b1 uni22B1 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22b2 uni22B2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22b3 uni22B3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22b4 uni22B4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22b5 uni22B5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22b6 uni22B6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22b7 uni22B7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22b8 uni22B8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22b9 uni22B9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ba uni22BA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22bb uni22BB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22bc uni22BC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22bd uni22BD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22be uni22BE 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+22bf uni22BF 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+22c0 uni22C0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22c1 uni22C1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22c2 uni22C2 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22c3 uni22C3 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22c4 uni22C4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+22c5 dotmath 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+22c6 uni22C6 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22c7 uni22C7 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22c8 uni22C8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22c9 uni22C9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ca uni22CA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22cb uni22CB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22cc uni22CC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22cd uni22CD 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+22ce uni22CE 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22cf uni22CF 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22d0 uni22D0 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22d1 uni22D1 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+22d2 uni22D2 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22d3 uni22D3 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+22b2 uni22B2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22b3 uni22B3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22b4 uni22B4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22b5 uni22B5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22b6 uni22B6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22b7 uni22B7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22b8 uni22B8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22b9 uni22B9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ba uni22BA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22bb uni22BB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22bc uni22BC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22bd uni22BD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22be uni22BE 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+22bf uni22BF 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+22c0 uni22C0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22c1 uni22C1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22c2 uni22C2 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22c3 uni22C3 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22c4 uni22C4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+22c5 dotmath 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+22c6 uni22C6 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22c7 uni22C7 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22c8 uni22C8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22c9 uni22C9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ca uni22CA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22cb uni22CB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22cc uni22CC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22cd uni22CD 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+22ce uni22CE 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22cf uni22CF 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22d0 uni22D0 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22d1 uni22D1 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+22d2 uni22D2 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22d3 uni22D3 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+22d4 uni22D4 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22d5 uni22D5 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22d6 uni22D6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22d7 uni22D7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22d8 uni22D8 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+22d9 uni22D9 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+22da uni22DA 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+22db uni22DB 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+22dc uni22DC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22dd uni22DD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22de uni22DE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22df uni22DF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e0 uni22E0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e1 uni22E1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e2 uni22E2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e3 uni22E3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e4 uni22E4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e5 uni22E5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e6 uni22E6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e7 uni22E7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e8 uni22E8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22e9 uni22E9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+22ea uni22EA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22eb uni22EB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ec uni22EC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ed uni22ED 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ee uni22EE 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ef uni22EF 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f0 uni22F0 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f1 uni22F1 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+22d5 uni22D5 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22d6 uni22D6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22d7 uni22D7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22d8 uni22D8 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+22d9 uni22D9 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+22da uni22DA 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+22db uni22DB 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+22dc uni22DC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22dd uni22DD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22de uni22DE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22df uni22DF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e0 uni22E0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e1 uni22E1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e2 uni22E2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e3 uni22E3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e4 uni22E4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e5 uni22E5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e6 uni22E6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e7 uni22E7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e8 uni22E8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22e9 uni22E9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ea uni22EA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22eb uni22EB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ec uni22EC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ed uni22ED 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ee uni22EE 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22ef uni22EF 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22f0 uni22F0 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+22f1 uni22F1 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+22f2 uni22F2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+22f3 uni22F3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+22f4 uni22F4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -3478,18 +3500,18 @@ U+22fc uni22FC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+22fd uni22FD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+22fe uni22FE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+22ff uni22FF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2300 uni2300 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) +U+2300 uni2300 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) U+2301 uni2301 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+2302 house 1.14 U+2303 uni2303 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+2304 uni2304 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2305 uni2305 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2306 uni2306 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2305 uni2305 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+2306 uni2306 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2307 uni2307 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2308 uni2308 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2309 uni2309 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+230a uni230A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+230b uni230B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) +U+2308 uni2308 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2309 uni2309 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+230a uni230A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+230b uni230B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+230c uni230C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+230d uni230D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+230e uni230E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) @@ -3502,19 +3524,21 @@ U+2314 uni2314 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Obli U+2315 uni2315 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2318 uni2318 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) U+2319 uni2319 1.14 -U+231c uni231C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+231d uni231D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+231e uni231E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+231f uni231F 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) +U+231c uni231C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+231d uni231D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+231e uni231E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+231f uni231F 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) U+2320 integraltp 2.3 U+2321 integralbt 2.3 +U+2322 uni2322 2.36 (Math TeX Gyre Regular) +U+2323 uni2323 2.36 (Math TeX Gyre Regular) U+2324 uni2324 2.16 (Sans, Sans Bold, Sans Bold Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique) 2.19 (Sans Condensed Oblique, Sans Oblique) U+2325 uni2325 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) U+2326 uni2326 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+2327 uni2327 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+2328 uni2328 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2329 angleleft 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) -U+232a angleright 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) +U+2329 angleleft 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+232a angleright 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) U+232b uni232B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+232c uni232C 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+2335 uni2335 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) @@ -3599,33 +3623,44 @@ U+238a uni238A 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Obli U+238b uni238B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2394 uni2394 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+2395 uni2395 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+239b uni239B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+239c uni239C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+239d uni239D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+239e uni239E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+239f uni239F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a0 uni23A0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a1 uni23A1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a2 uni23A2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a3 uni23A3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a4 uni23A4 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a5 uni23A5 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a6 uni23A6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a7 uni23A7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a8 uni23A8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23a9 uni23A9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23aa uni23AA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23ab uni23AB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23ac uni23AC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+23ad uni23AD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) +U+239b uni239B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+239c uni239C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+239d uni239D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+239e uni239E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+239f uni239F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a0 uni23A0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a1 uni23A1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a2 uni23A2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a3 uni23A3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a4 uni23A4 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a5 uni23A5 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a6 uni23A6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a7 uni23A7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a8 uni23A8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23a9 uni23A9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23aa uni23AA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23ab uni23AB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23ac uni23AC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) +U+23ad uni23AD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) U+23ae uni23AE 2.3 -U+23b7 uni23B7 2.35 (Serif, Serif Condensed) +U+23b2 uni23B2 2.36 (Math TeX Gyre Regular) +U+23b3 uni23B3 2.36 (Math TeX Gyre Regular) +U+23b4 uni23B4 2.36 (Math TeX Gyre Regular) +U+23b5 uni23B5 2.36 (Math TeX Gyre Regular) +U+23b7 uni23B7 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) U+23ce uni23CE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) U+23cf uni23CF 2.3 +U+23d0 uni23D0 2.36 (Math TeX Gyre Regular) +U+23dc uni23DC 2.36 (Math TeX Gyre Regular) +U+23dd uni23DD 2.36 (Math TeX Gyre Regular) +U+23de uni23DE 2.36 (Math TeX Gyre Regular) +U+23df uni23DF 2.36 (Math TeX Gyre Regular) +U+23e0 uni23E0 2.36 (Math TeX Gyre Regular) +U+23e1 uni23E1 2.36 (Math TeX Gyre Regular) U+23e3 uni23E3 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+23e5 uni23E5 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+23e8 uni23E8 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2422 uni2422 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2422 uni2422 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2423 uni2423 1.6 U+2460 uni2460 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2461 uni2461 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -3637,9 +3672,9 @@ U+2466 uni2466 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+2467 uni2467 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2468 uni2468 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2469 uni2469 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2500 SF100000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2500 SF100000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2501 uni2501 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2502 SF110000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2502 SF110000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2503 uni2503 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2504 uni2504 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2505 uni2505 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) @@ -3649,23 +3684,23 @@ U+2508 uni2508 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans U+2509 uni2509 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+250a uni250A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+250b uni250B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+250c SF010000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+250c SF010000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+250d uni250D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+250e uni250E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+250f uni250F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2510 SF030000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2510 SF030000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2511 uni2511 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2512 uni2512 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2513 uni2513 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2514 SF020000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2514 SF020000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2515 uni2515 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2516 uni2516 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2517 uni2517 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2518 SF040000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2518 SF040000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2519 uni2519 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+251a uni251A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+251b uni251B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+251c SF080000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+251c SF080000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+251d uni251D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+251e uni251E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+251f uni251F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) @@ -3673,7 +3708,7 @@ U+2520 uni2520 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans U+2521 uni2521 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2522 uni2522 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2523 uni2523 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2524 SF090000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2524 SF090000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2525 uni2525 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2526 uni2526 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2527 uni2527 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) @@ -3681,7 +3716,7 @@ U+2528 uni2528 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans U+2529 uni2529 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+252a uni252A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+252b uni252B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+252c SF060000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+252c SF060000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+252d uni252D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+252e uni252E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+252f uni252F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) @@ -3689,7 +3724,7 @@ U+2530 uni2530 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans U+2531 uni2531 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2532 uni2532 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2533 uni2533 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2534 SF070000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+2534 SF070000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+2535 uni2535 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2536 uni2536 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+2537 uni2537 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) @@ -3697,7 +3732,7 @@ U+2538 uni2538 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans U+2539 uni2539 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+253a uni253A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+253b uni253B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+253c SF050000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) +U+253c SF050000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) U+253d uni253D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+253e uni253E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) U+253f uni253F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) @@ -3989,22 +4024,22 @@ U+265c uni265C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+265d uni265D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+265e uni265E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+265f uni265F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2660 spade 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2661 uni2661 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2662 uni2662 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2663 club 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2664 uni2664 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2665 heart 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2666 diamond 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2667 uni2667 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2660 spade 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2661 uni2661 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2662 uni2662 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2663 club 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2664 uni2664 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2665 heart 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2666 diamond 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2667 uni2667 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2668 uni2668 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+2669 uni2669 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266a musicalnote 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+266a musicalnote 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+266b musicalnotedbl 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+266c uni266C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266d uni266D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266e uni266E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266f uni266F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+266d uni266D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+266e uni266E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+266f uni266F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2670 uni2670 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+2671 uni2671 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+2672 uni2672 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) @@ -4065,8 +4100,8 @@ U+26a9 uni26A9 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Obliq U+26aa uni26AA 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+26ab uni26AB 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+26ac uni26AC 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26ad uni26AD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26ae uni26AE 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) +U+26ad uni26AD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) +U+26ae uni26AE 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) U+26af uni26AF 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) U+26b0 uni26B0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+26b1 uni26B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) @@ -4097,7 +4132,7 @@ U+270f uni270F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+2710 uni2710 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+2711 uni2711 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+2712 uni2712 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2713 uni2713 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) +U+2713 uni2713 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) 2.36 (Math TeX Gyre Regular) U+2714 uni2714 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+2715 uni2715 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+2716 uni2716 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) @@ -4110,7 +4145,7 @@ U+271c uni271C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+271d uni271D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+271e uni271E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+271f uni271F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2720 uni2720 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) +U+2720 uni2720 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) 2.36 (Math TeX Gyre Regular) U+2721 uni2721 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+2722 uni2722 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) U+2723 uni2723 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) @@ -4227,7 +4262,7 @@ U+279d uni279D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+279e uni279E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+279f uni279F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+27a0 uni27A0 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a1 uni27A1 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+27a1 uni27A1 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+27a2 uni27A2 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+27a3 uni27A3 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+27a4 uni27A4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) @@ -4257,33 +4292,44 @@ U+27bc uni27BC 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+27bd uni27BD 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+27be uni27BE 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) U+27bf uni27BF 2.7 (Sans Mono Bold) -U+27c2 uni27C2 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+27c2 uni27C2 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+27c5 uni27C5 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) U+27c6 uni27C6 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+27dc uni27DC 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+27d8 uni27D8 2.36 (Math TeX Gyre Regular) +U+27d9 uni27D9 2.36 (Math TeX Gyre Regular) +U+27da uni27DA 2.36 (Math TeX Gyre Regular) +U+27db uni27DB 2.36 (Math TeX Gyre Regular) +U+27dc uni27DC 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27dd uni27DD 2.36 (Math TeX Gyre Regular) +U+27de uni27DE 2.36 (Math TeX Gyre Regular) U+27e0 uni27E0 2.3 -U+27e6 uni27E6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+27e7 uni27E7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+27e8 uni27E8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27e9 uni27E9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27ea uni27EA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+27eb uni27EB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+27e1 uni27E1 2.36 (Math TeX Gyre Regular) +U+27e2 uni27E2 2.36 (Math TeX Gyre Regular) +U+27e3 uni27E3 2.36 (Math TeX Gyre Regular) +U+27e6 uni27E6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27e7 uni27E7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27e8 uni27E8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27e9 uni27E9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27ea uni27EA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27eb uni27EB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27ee uni27EE 2.36 (Math TeX Gyre Regular) +U+27ef uni27EF 2.36 (Math TeX Gyre Regular) U+27f0 uni27F0 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+27f1 uni27F1 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+27f2 uni27F2 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+27f3 uni27F3 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f4 uni27F4 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f5 uni27F5 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+27f6 uni27F6 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+27f7 uni27F7 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+27f8 uni27F8 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f9 uni27F9 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27fa uni27FA 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27fb uni27FB 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27fc uni27FC 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27fd uni27FD 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27fe uni27FE 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27ff uni27FF 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+27f4 uni27F4 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27f5 uni27F5 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27f6 uni27F6 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27f7 uni27F7 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+27f8 uni27F8 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27f9 uni27F9 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27fa uni27FA 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27fb uni27FB 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27fc uni27FC 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27fd uni27FD 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27fe uni27FE 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+27ff uni27FF 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2800 uni2800 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2801 uni2801 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2802 uni2802 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -4546,8 +4592,8 @@ U+2902 uni2902 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Co U+2903 uni2903 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2904 uni2904 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2905 uni2905 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2906 uni2906 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2907 uni2907 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2906 uni2906 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2907 uni2907 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2908 uni2908 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2909 uni2909 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+290a uni290A 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -4685,15 +4731,20 @@ U+29d5 uni29D5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+29eb uni29EB 2.2 U+29fa uni29FA 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) U+29fb uni29FB 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2a00 uni2A00 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2a01 uni2A01 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a02 uni2A02 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a0c uni2A0C 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+2a00 uni2A00 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2a01 uni2A01 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a02 uni2A02 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a03 uni2A03 2.36 (Math TeX Gyre Regular) +U+2a04 uni2A04 2.36 (Math TeX Gyre Regular) +U+2a05 uni2A05 2.36 (Math TeX Gyre Regular) +U+2a06 uni2A06 2.36 (Math TeX Gyre Regular) +U+2a09 uni2A09 2.36 (Math TeX Gyre Regular) +U+2a0c uni2A0C 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2a0d uni2A0D 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2a0e uni2A0E 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2a0f uni2A0F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a10 uni2A10 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a11 uni2A11 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2a11 uni2A11 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2a12 uni2A12 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a13 uni2A13 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a14 uni2A14 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -4705,25 +4756,26 @@ U+2a19 uni2A19 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+2a1a uni2A1A 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a1b uni2A1B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a1c uni2A1C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a2f uni2A2F 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) +U+2a2f uni2A2F 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2a3f uni2A3F 2.36 (Math TeX Gyre Regular) U+2a6a uni2A6A 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+2a6b uni2A6B 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2a7d uni2A7D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a7e uni2A7E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2a7d uni2A7D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a7e uni2A7E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2a7f uni2A7F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a80 uni2A80 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a81 uni2A81 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a82 uni2A82 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a83 uni2A83 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a84 uni2A84 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a85 uni2A85 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a86 uni2A86 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a87 uni2A87 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a88 uni2A88 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a89 uni2A89 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a8a uni2A8A 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a8b uni2A8B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a8c uni2A8C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2a85 uni2A85 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a86 uni2A86 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a87 uni2A87 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a88 uni2A88 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a89 uni2A89 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a8a uni2A8A 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a8b uni2A8B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a8c uni2A8C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2a8d uni2A8D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a8e uni2A8E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a8f uni2A8F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -4732,8 +4784,8 @@ U+2a91 uni2A91 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+2a92 uni2A92 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a93 uni2A93 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a94 uni2A94 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a95 uni2A95 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a96 uni2A96 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2a95 uni2A95 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2a96 uni2A96 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2a97 uni2A97 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a98 uni2A98 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2a99 uni2A99 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -4745,8 +4797,8 @@ U+2a9e uni2A9E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Conden U+2a9f uni2A9F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2aa0 uni2AA0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2aae uni2AAE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2aaf uni2AAF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab0 uni2AB0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+2aaf uni2AAF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+2ab0 uni2AB0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) U+2ab1 uni2AB1 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2ab2 uni2AB2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2ab3 uni2AB3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -4763,16 +4815,16 @@ U+2b00 uni2B00 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+2b01 uni2B01 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2b02 uni2B02 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2b03 uni2B03 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b04 uni2B04 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b05 uni2B05 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b06 uni2B06 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b07 uni2B07 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2b04 uni2B04 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+2b05 uni2B05 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2b06 uni2B06 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2b07 uni2B07 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2b08 uni2B08 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2b09 uni2B09 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2b0a uni2B0A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) U+2b0b uni2B0B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b0c uni2B0C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b0d uni2B0D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) +U+2b0c uni2B0C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+2b0d uni2B0D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) U+2b0e uni2B0E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2b0f uni2B0F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+2b10 uni2B10 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -4785,13 +4837,15 @@ U+2b16 uni2B16 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, U+2b17 uni2B17 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) U+2b18 uni2B18 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) U+2b19 uni2B19 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b1a uni2B1A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) +U+2b1a uni2B1A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+2b1f uni2B1F 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) U+2b20 uni2B20 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2b21 uni2B21 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2b22 uni2B22 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2b23 uni2B23 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+2b24 uni2B24 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) +U+2b31 uni2B31 2.36 (Math TeX Gyre Regular) +U+2b33 uni2B33 2.36 (Math TeX Gyre Regular) U+2b53 uni2B53 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) U+2b54 uni2B54 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) U+2c60 uni2C60 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) @@ -4926,6 +4980,8 @@ U+2e23 uni2E23 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans U+2e24 uni2E24 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.30 (Sans Bold) 2.31 (Serif Condensed Italic) U+2e25 uni2E25 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.30 (Sans Bold) 2.31 (Serif Condensed Italic) U+2e2e uni2E2E 2.26 +U+3016 whitelenticularbracketleft 2.36 (Math TeX Gyre Regular) +U+3017 whitelenticularbracketright 2.36 (Math TeX Gyre Regular) U+4dc0 uni4DC0 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+4dc1 uni4DC1 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+4dc2 uni4DC2 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -5069,6 +5125,8 @@ U+a68c uniA68C 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Conde U+a68d uniA68D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) U+a694 uniA694 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) U+a695 uniA695 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) +U+a698 uniA698 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) +U+a699 uniA699 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) U+a708 uniA708 2.27 U+a709 uniA709 2.27 U+a70a uniA70A 2.27 @@ -5319,11 +5377,11 @@ U+f6c7 uniF6C7 2.11 (Serif Bold Italic, Serif Condensed Bold Italic U+f6c8 uniF6C8 2.11 (Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+f6d1 cyrBreve 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+f6d4 cyrbreve 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fb00 uniFB00 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+fb00 uniFB00 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+fb01 fi original U+fb02 fl original -U+fb03 uniFB03 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fb04 uniFB04 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) +U+fb03 uniFB03 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) +U+fb04 uniFB04 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) U+fb05 uniFB05 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+fb06 uniFB06 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+fb13 uniFB13 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -5650,7 +5708,7 @@ U+fef9 uniFEF9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed U+fefa uniFEFA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) U+fefb uniFEFB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) U+fefc uniFEFC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feff uniFEFF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) +U+feff uniFEFF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) 2.36 (Math TeX Gyre Regular) U+fff9 uniFFF9 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+fffa uniFFFA 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) U+fffb uniFFFB 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) @@ -5778,810 +5836,1002 @@ U+1d353 u1D353 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Cond U+1d354 u1D354 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1d355 u1D355 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1d356 u1D356 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d400 u1D400 2.23 (Serif Bold, Serif Condensed Bold) -U+1d401 u1D401 2.23 (Serif Bold, Serif Condensed Bold) -U+1d402 u1D402 2.23 (Serif Bold, Serif Condensed Bold) -U+1d403 u1D403 2.23 (Serif Bold, Serif Condensed Bold) -U+1d404 u1D404 2.23 (Serif Bold, Serif Condensed Bold) -U+1d405 u1D405 2.23 (Serif Bold, Serif Condensed Bold) -U+1d406 u1D406 2.23 (Serif Bold, Serif Condensed Bold) -U+1d407 u1D407 2.23 (Serif Bold, Serif Condensed Bold) -U+1d408 u1D408 2.23 (Serif Bold, Serif Condensed Bold) -U+1d409 u1D409 2.23 (Serif Bold, Serif Condensed Bold) -U+1d40a u1D40A 2.23 (Serif Bold, Serif Condensed Bold) -U+1d40b u1D40B 2.23 (Serif Bold, Serif Condensed Bold) -U+1d40c u1D40C 2.23 (Serif Bold, Serif Condensed Bold) -U+1d40d u1D40D 2.23 (Serif Bold, Serif Condensed Bold) -U+1d40e u1D40E 2.23 (Serif Bold, Serif Condensed Bold) -U+1d40f u1D40F 2.23 (Serif Bold, Serif Condensed Bold) -U+1d410 u1D410 2.23 (Serif Bold, Serif Condensed Bold) -U+1d411 u1D411 2.23 (Serif Bold, Serif Condensed Bold) -U+1d412 u1D412 2.23 (Serif Bold, Serif Condensed Bold) -U+1d413 u1D413 2.23 (Serif Bold, Serif Condensed Bold) -U+1d414 u1D414 2.23 (Serif Bold, Serif Condensed Bold) -U+1d415 u1D415 2.23 (Serif Bold, Serif Condensed Bold) -U+1d416 u1D416 2.23 (Serif Bold, Serif Condensed Bold) -U+1d417 u1D417 2.23 (Serif Bold, Serif Condensed Bold) -U+1d418 u1D418 2.23 (Serif Bold, Serif Condensed Bold) -U+1d419 u1D419 2.23 (Serif Bold, Serif Condensed Bold) -U+1d41a u1D41A 2.23 (Serif Bold, Serif Condensed Bold) -U+1d41b u1D41B 2.23 (Serif Bold, Serif Condensed Bold) -U+1d41c u1D41C 2.23 (Serif Bold, Serif Condensed Bold) -U+1d41d u1D41D 2.23 (Serif Bold, Serif Condensed Bold) -U+1d41e u1D41E 2.23 (Serif Bold, Serif Condensed Bold) -U+1d41f u1D41F 2.23 (Serif Bold, Serif Condensed Bold) -U+1d420 u1D420 2.23 (Serif Bold, Serif Condensed Bold) -U+1d421 u1D421 2.23 (Serif Bold, Serif Condensed Bold) -U+1d422 u1D422 2.23 (Serif Bold, Serif Condensed Bold) -U+1d423 u1D423 2.23 (Serif Bold, Serif Condensed Bold) -U+1d424 u1D424 2.23 (Serif Bold, Serif Condensed Bold) -U+1d425 u1D425 2.23 (Serif Bold, Serif Condensed Bold) -U+1d426 u1D426 2.23 (Serif Bold, Serif Condensed Bold) -U+1d427 u1D427 2.23 (Serif Bold, Serif Condensed Bold) -U+1d428 u1D428 2.23 (Serif Bold, Serif Condensed Bold) -U+1d429 u1D429 2.23 (Serif Bold, Serif Condensed Bold) -U+1d42a u1D42A 2.23 (Serif Bold, Serif Condensed Bold) -U+1d42b u1D42B 2.23 (Serif Bold, Serif Condensed Bold) -U+1d42c u1D42C 2.23 (Serif Bold, Serif Condensed Bold) -U+1d42d u1D42D 2.23 (Serif Bold, Serif Condensed Bold) -U+1d42e u1D42E 2.23 (Serif Bold, Serif Condensed Bold) -U+1d42f u1D42F 2.23 (Serif Bold, Serif Condensed Bold) -U+1d430 u1D430 2.23 (Serif Bold, Serif Condensed Bold) -U+1d431 u1D431 2.23 (Serif Bold, Serif Condensed Bold) -U+1d432 u1D432 2.23 (Serif Bold, Serif Condensed Bold) -U+1d433 u1D433 2.23 (Serif Bold, Serif Condensed Bold) -U+1d434 u1D434 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d435 u1D435 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d436 u1D436 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d437 u1D437 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d438 u1D438 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d439 u1D439 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d43a u1D43A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d43b u1D43B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d43c u1D43C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d43d u1D43D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d43e u1D43E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d43f u1D43F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d440 u1D440 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d441 u1D441 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d442 u1D442 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d443 u1D443 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d444 u1D444 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d445 u1D445 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d446 u1D446 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d447 u1D447 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d448 u1D448 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d449 u1D449 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d44a u1D44A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d44b u1D44B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d44c u1D44C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d44d u1D44D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d44e u1D44E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d44f u1D44F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d450 u1D450 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d451 u1D451 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d452 u1D452 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d453 u1D453 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d454 u1D454 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d456 u1D456 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d457 u1D457 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d458 u1D458 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d459 u1D459 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d45a u1D45A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d45b u1D45B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d45c u1D45C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d45d u1D45D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d45e u1D45E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d45f u1D45F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d460 u1D460 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d461 u1D461 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d462 u1D462 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d463 u1D463 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d464 u1D464 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d465 u1D465 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d466 u1D466 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d467 u1D467 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d468 u1D468 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d469 u1D469 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d46a u1D46A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d46b u1D46B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d46c u1D46C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d46d u1D46D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d46e u1D46E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d46f u1D46F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d470 u1D470 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d471 u1D471 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d472 u1D472 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d473 u1D473 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d474 u1D474 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d475 u1D475 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d476 u1D476 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d477 u1D477 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d478 u1D478 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d479 u1D479 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d47a u1D47A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d47b u1D47B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d47c u1D47C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d47d u1D47D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d47e u1D47E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d47f u1D47F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d480 u1D480 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d481 u1D481 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d482 u1D482 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d483 u1D483 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d484 u1D484 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d485 u1D485 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d486 u1D486 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d487 u1D487 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d488 u1D488 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d489 u1D489 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d48a u1D48A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d48b u1D48B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d48c u1D48C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d48d u1D48D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d48e u1D48E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d48f u1D48F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d490 u1D490 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d491 u1D491 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d492 u1D492 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d493 u1D493 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d494 u1D494 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d495 u1D495 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d496 u1D496 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d497 u1D497 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d498 u1D498 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d499 u1D499 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d49a u1D49A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d49b u1D49B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d538 u1D538 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d539 u1D539 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d53b u1D53B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d53c u1D53C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d53d u1D53D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d53e u1D53E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d540 u1D540 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d541 u1D541 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d542 u1D542 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d543 u1D543 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d544 u1D544 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d546 u1D546 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d54a u1D54A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d54b u1D54B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d54c u1D54C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d54d u1D54D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d54e u1D54E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d54f u1D54F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d550 u1D550 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d552 u1D552 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d553 u1D553 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d554 u1D554 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d555 u1D555 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d556 u1D556 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d557 u1D557 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d558 u1D558 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d559 u1D559 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d55a u1D55A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1d55b u1D55B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d55c u1D55C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d55d u1D55D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d55e u1D55E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d55f u1D55F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d560 u1D560 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d561 u1D561 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d562 u1D562 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d563 u1D563 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d564 u1D564 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d565 u1D565 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d566 u1D566 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d567 u1D567 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d568 u1D568 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d569 u1D569 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d56a u1D56A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d56b u1D56B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) -U+1d5a0 u1D5A0 2.23 (Sans, Sans Condensed) -U+1d5a1 u1D5A1 2.23 (Sans, Sans Condensed) -U+1d5a2 u1D5A2 2.23 (Sans, Sans Condensed) -U+1d5a3 u1D5A3 2.23 (Sans, Sans Condensed) -U+1d5a4 u1D5A4 2.23 (Sans, Sans Condensed) -U+1d5a5 u1D5A5 2.23 (Sans, Sans Condensed) -U+1d5a6 u1D5A6 2.23 (Sans, Sans Condensed) -U+1d5a7 u1D5A7 2.23 (Sans, Sans Condensed) -U+1d5a8 u1D5A8 2.23 (Sans, Sans Condensed) -U+1d5a9 u1D5A9 2.23 (Sans, Sans Condensed) -U+1d5aa u1D5AA 2.23 (Sans, Sans Condensed) -U+1d5ab u1D5AB 2.23 (Sans, Sans Condensed) -U+1d5ac u1D5AC 2.23 (Sans, Sans Condensed) -U+1d5ad u1D5AD 2.23 (Sans, Sans Condensed) -U+1d5ae u1D5AE 2.23 (Sans, Sans Condensed) -U+1d5af u1D5AF 2.23 (Sans, Sans Condensed) -U+1d5b0 u1D5B0 2.23 (Sans, Sans Condensed) -U+1d5b1 u1D5B1 2.23 (Sans, Sans Condensed) -U+1d5b2 u1D5B2 2.23 (Sans, Sans Condensed) -U+1d5b3 u1D5B3 2.23 (Sans, Sans Condensed) -U+1d5b4 u1D5B4 2.23 (Sans, Sans Condensed) -U+1d5b5 u1D5B5 2.23 (Sans, Sans Condensed) -U+1d5b6 u1D5B6 2.23 (Sans, Sans Condensed) -U+1d5b7 u1D5B7 2.23 (Sans, Sans Condensed) -U+1d5b8 u1D5B8 2.23 (Sans, Sans Condensed) -U+1d5b9 u1D5B9 2.23 (Sans, Sans Condensed) -U+1d5ba u1D5BA 2.23 (Sans, Sans Condensed) -U+1d5bb u1D5BB 2.23 (Sans, Sans Condensed) -U+1d5bc u1D5BC 2.23 (Sans, Sans Condensed) -U+1d5bd u1D5BD 2.23 (Sans, Sans Condensed) -U+1d5be u1D5BE 2.23 (Sans, Sans Condensed) -U+1d5bf u1D5BF 2.23 (Sans, Sans Condensed) -U+1d5c0 u1D5C0 2.23 (Sans, Sans Condensed) -U+1d5c1 u1D5C1 2.23 (Sans, Sans Condensed) -U+1d5c2 u1D5C2 2.23 (Sans, Sans Condensed) -U+1d5c3 u1D5C3 2.23 (Sans, Sans Condensed) -U+1d5c4 u1D5C4 2.23 (Sans, Sans Condensed) -U+1d5c5 u1D5C5 2.23 (Sans, Sans Condensed) -U+1d5c6 u1D5C6 2.23 (Sans, Sans Condensed) -U+1d5c7 u1D5C7 2.23 (Sans, Sans Condensed) -U+1d5c8 u1D5C8 2.23 (Sans, Sans Condensed) -U+1d5c9 u1D5C9 2.23 (Sans, Sans Condensed) -U+1d5ca u1D5CA 2.23 (Sans, Sans Condensed) -U+1d5cb u1D5CB 2.23 (Sans, Sans Condensed) -U+1d5cc u1D5CC 2.23 (Sans, Sans Condensed) -U+1d5cd u1D5CD 2.23 (Sans, Sans Condensed) -U+1d5ce u1D5CE 2.23 (Sans, Sans Condensed) -U+1d5cf u1D5CF 2.23 (Sans, Sans Condensed) -U+1d5d0 u1D5D0 2.23 (Sans, Sans Condensed) -U+1d5d1 u1D5D1 2.23 (Sans, Sans Condensed) -U+1d5d2 u1D5D2 2.23 (Sans, Sans Condensed) -U+1d5d3 u1D5D3 2.23 (Sans, Sans Condensed) -U+1d5d4 u1D5D4 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5d5 u1D5D5 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5d6 u1D5D6 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5d7 u1D5D7 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5d8 u1D5D8 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5d9 u1D5D9 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5da u1D5DA 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5db u1D5DB 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5dc u1D5DC 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5dd u1D5DD 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5de u1D5DE 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5df u1D5DF 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e0 u1D5E0 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e1 u1D5E1 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e2 u1D5E2 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e3 u1D5E3 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e4 u1D5E4 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e5 u1D5E5 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e6 u1D5E6 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e7 u1D5E7 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e8 u1D5E8 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5e9 u1D5E9 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5ea u1D5EA 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5eb u1D5EB 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5ec u1D5EC 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5ed u1D5ED 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5ee u1D5EE 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5ef u1D5EF 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f0 u1D5F0 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f1 u1D5F1 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f2 u1D5F2 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f3 u1D5F3 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f4 u1D5F4 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f5 u1D5F5 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f6 u1D5F6 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f7 u1D5F7 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f8 u1D5F8 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5f9 u1D5F9 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5fa u1D5FA 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5fb u1D5FB 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5fc u1D5FC 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5fd u1D5FD 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5fe u1D5FE 2.23 (Sans Bold, Sans Condensed Bold) -U+1d5ff u1D5FF 2.23 (Sans Bold, Sans Condensed Bold) -U+1d600 u1D600 2.23 (Sans Bold, Sans Condensed Bold) -U+1d601 u1D601 2.23 (Sans Bold, Sans Condensed Bold) -U+1d602 u1D602 2.23 (Sans Bold, Sans Condensed Bold) -U+1d603 u1D603 2.23 (Sans Bold, Sans Condensed Bold) -U+1d604 u1D604 2.23 (Sans Bold, Sans Condensed Bold) -U+1d605 u1D605 2.23 (Sans Bold, Sans Condensed Bold) -U+1d606 u1D606 2.23 (Sans Bold, Sans Condensed Bold) -U+1d607 u1D607 2.23 (Sans Bold, Sans Condensed Bold) -U+1d608 u1D608 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d609 u1D609 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d60a u1D60A 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d60b u1D60B 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d60c u1D60C 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d60d u1D60D 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d60e u1D60E 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d60f u1D60F 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d610 u1D610 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d611 u1D611 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d612 u1D612 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d613 u1D613 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d614 u1D614 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d615 u1D615 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d616 u1D616 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d617 u1D617 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d618 u1D618 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d619 u1D619 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d61a u1D61A 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d61b u1D61B 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d61c u1D61C 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d61d u1D61D 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d61e u1D61E 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d61f u1D61F 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d620 u1D620 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d621 u1D621 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d622 u1D622 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d623 u1D623 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d624 u1D624 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d625 u1D625 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d626 u1D626 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d627 u1D627 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d628 u1D628 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d629 u1D629 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d62a u1D62A 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d62b u1D62B 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d62c u1D62C 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d62d u1D62D 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d62e u1D62E 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d62f u1D62F 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d630 u1D630 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d631 u1D631 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d632 u1D632 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d633 u1D633 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d634 u1D634 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d635 u1D635 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d636 u1D636 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d637 u1D637 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d638 u1D638 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d639 u1D639 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d63a u1D63A 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d63b u1D63B 2.23 (Sans Condensed Oblique, Sans Oblique) -U+1d63c u1D63C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d63d u1D63D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d63e u1D63E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d63f u1D63F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d640 u1D640 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d641 u1D641 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d642 u1D642 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d643 u1D643 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d644 u1D644 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d645 u1D645 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d646 u1D646 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d647 u1D647 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d648 u1D648 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d649 u1D649 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d64a u1D64A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d64b u1D64B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d64c u1D64C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d64d u1D64D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d64e u1D64E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d64f u1D64F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d650 u1D650 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d651 u1D651 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d652 u1D652 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d653 u1D653 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d654 u1D654 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d655 u1D655 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d656 u1D656 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d657 u1D657 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d658 u1D658 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d659 u1D659 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d65a u1D65A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d65b u1D65B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d65c u1D65C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d65d u1D65D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d65e u1D65E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d65f u1D65F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d660 u1D660 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d661 u1D661 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d662 u1D662 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d663 u1D663 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d664 u1D664 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d665 u1D665 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d666 u1D666 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d667 u1D667 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d668 u1D668 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d669 u1D669 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d66a u1D66A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d66b u1D66B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d66c u1D66C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d66d u1D66D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d66e u1D66E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d66f u1D66F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d670 u1D670 2.23 (Sans Mono) -U+1d671 u1D671 2.23 (Sans Mono) -U+1d672 u1D672 2.23 (Sans Mono) -U+1d673 u1D673 2.23 (Sans Mono) -U+1d674 u1D674 2.23 (Sans Mono) -U+1d675 u1D675 2.23 (Sans Mono) -U+1d676 u1D676 2.23 (Sans Mono) -U+1d677 u1D677 2.23 (Sans Mono) -U+1d678 u1D678 2.23 (Sans Mono) -U+1d679 u1D679 2.23 (Sans Mono) -U+1d67a u1D67A 2.23 (Sans Mono) -U+1d67b u1D67B 2.23 (Sans Mono) -U+1d67c u1D67C 2.23 (Sans Mono) -U+1d67d u1D67D 2.23 (Sans Mono) -U+1d67e u1D67E 2.23 (Sans Mono) -U+1d67f u1D67F 2.23 (Sans Mono) -U+1d680 u1D680 2.23 (Sans Mono) -U+1d681 u1D681 2.23 (Sans Mono) -U+1d682 u1D682 2.23 (Sans Mono) -U+1d683 u1D683 2.23 (Sans Mono) -U+1d684 u1D684 2.23 (Sans Mono) -U+1d685 u1D685 2.23 (Sans Mono) -U+1d686 u1D686 2.23 (Sans Mono) -U+1d687 u1D687 2.23 (Sans Mono) -U+1d688 u1D688 2.23 (Sans Mono) -U+1d689 u1D689 2.23 (Sans Mono) -U+1d68a u1D68A 2.23 (Sans Mono) -U+1d68b u1D68B 2.23 (Sans Mono) -U+1d68c u1D68C 2.23 (Sans Mono) -U+1d68d u1D68D 2.23 (Sans Mono) -U+1d68e u1D68E 2.23 (Sans Mono) -U+1d68f u1D68F 2.23 (Sans Mono) -U+1d690 u1D690 2.23 (Sans Mono) -U+1d691 u1D691 2.23 (Sans Mono) -U+1d692 u1D692 2.23 (Sans Mono) -U+1d693 u1D693 2.23 (Sans Mono) -U+1d694 u1D694 2.23 (Sans Mono) -U+1d695 u1D695 2.23 (Sans Mono) -U+1d696 u1D696 2.23 (Sans Mono) -U+1d697 u1D697 2.23 (Sans Mono) -U+1d698 u1D698 2.23 (Sans Mono) -U+1d699 u1D699 2.23 (Sans Mono) -U+1d69a u1D69A 2.23 (Sans Mono) -U+1d69b u1D69B 2.23 (Sans Mono) -U+1d69c u1D69C 2.23 (Sans Mono) -U+1d69d u1D69D 2.23 (Sans Mono) -U+1d69e u1D69E 2.23 (Sans Mono) -U+1d69f u1D69F 2.23 (Sans Mono) -U+1d6a0 u1D6A0 2.23 (Sans Mono) -U+1d6a1 u1D6A1 2.23 (Sans Mono) -U+1d6a2 u1D6A2 2.23 (Sans Mono) -U+1d6a3 u1D6A3 2.23 (Sans Mono) -U+1d6a4 u1D6A4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d6a5 u1D6A5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) -U+1d6a8 u1D6A8 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6a9 u1D6A9 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6aa u1D6AA 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ab u1D6AB 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ac u1D6AC 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ad u1D6AD 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ae u1D6AE 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6af u1D6AF 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b0 u1D6B0 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b1 u1D6B1 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b2 u1D6B2 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b3 u1D6B3 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b4 u1D6B4 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b5 u1D6B5 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b6 u1D6B6 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b7 u1D6B7 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b8 u1D6B8 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6b9 u1D6B9 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ba u1D6BA 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6bb u1D6BB 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6bc u1D6BC 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6bd u1D6BD 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6be u1D6BE 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6bf u1D6BF 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c0 u1D6C0 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c1 u1D6C1 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c2 u1D6C2 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c3 u1D6C3 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c4 u1D6C4 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c5 u1D6C5 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c6 u1D6C6 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c7 u1D6C7 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c8 u1D6C8 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6c9 u1D6C9 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ca u1D6CA 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6cb u1D6CB 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6cc u1D6CC 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6cd u1D6CD 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6ce u1D6CE 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6cf u1D6CF 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d0 u1D6D0 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d1 u1D6D1 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d2 u1D6D2 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d3 u1D6D3 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d4 u1D6D4 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d5 u1D6D5 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d6 u1D6D6 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d7 u1D6D7 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d8 u1D6D8 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6d9 u1D6D9 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6da u1D6DA 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6db u1D6DB 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6dc u1D6DC 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6dd u1D6DD 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6de u1D6DE 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6df u1D6DF 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6e0 u1D6E0 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6e1 u1D6E1 2.23 (Serif Bold, Serif Condensed Bold) -U+1d6e2 u1D6E2 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e3 u1D6E3 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e4 u1D6E4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e5 u1D6E5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e6 u1D6E6 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e7 u1D6E7 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e8 u1D6E8 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6e9 u1D6E9 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6ea u1D6EA 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6eb u1D6EB 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6ec u1D6EC 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6ed u1D6ED 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6ee u1D6EE 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6ef u1D6EF 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f0 u1D6F0 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f1 u1D6F1 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f2 u1D6F2 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f3 u1D6F3 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f4 u1D6F4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f5 u1D6F5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f6 u1D6F6 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f7 u1D6F7 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f8 u1D6F8 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6f9 u1D6F9 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6fa u1D6FA 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6fb u1D6FB 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6fc u1D6FC 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6fd u1D6FD 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6fe u1D6FE 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d6ff u1D6FF 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d700 u1D700 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d701 u1D701 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d702 u1D702 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d703 u1D703 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d704 u1D704 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d705 u1D705 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d706 u1D706 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d707 u1D707 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d708 u1D708 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d709 u1D709 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d70a u1D70A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d70b u1D70B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d70c u1D70C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d70d u1D70D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d70e u1D70E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d70f u1D70F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d710 u1D710 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d711 u1D711 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d712 u1D712 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d713 u1D713 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d714 u1D714 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d715 u1D715 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d716 u1D716 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d717 u1D717 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d718 u1D718 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d719 u1D719 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d71a u1D71A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d71b u1D71B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1d71c u1D71C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d71d u1D71D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d71e u1D71E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d71f u1D71F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d720 u1D720 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d721 u1D721 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d722 u1D722 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d723 u1D723 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d724 u1D724 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d725 u1D725 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d726 u1D726 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d727 u1D727 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d728 u1D728 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d729 u1D729 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d72a u1D72A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d72b u1D72B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d72c u1D72C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d72d u1D72D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d72e u1D72E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d72f u1D72F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d730 u1D730 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d731 u1D731 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d732 u1D732 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d733 u1D733 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d734 u1D734 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d735 u1D735 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d736 u1D736 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d737 u1D737 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d738 u1D738 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d739 u1D739 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d73a u1D73A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d73b u1D73B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d73c u1D73C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d73d u1D73D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d73e u1D73E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d73f u1D73F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d740 u1D740 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d741 u1D741 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d742 u1D742 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d743 u1D743 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d744 u1D744 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d745 u1D745 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d746 u1D746 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d747 u1D747 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d748 u1D748 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d749 u1D749 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d74a u1D74A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d74b u1D74B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d74c u1D74C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d74d u1D74D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d74e u1D74E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d74f u1D74F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d750 u1D750 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d751 u1D751 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d752 u1D752 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d753 u1D753 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d754 u1D754 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d755 u1D755 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) -U+1d756 u1D756 2.23 (Sans Bold, Sans Condensed Bold) -U+1d757 u1D757 2.23 (Sans Bold, Sans Condensed Bold) -U+1d758 u1D758 2.23 (Sans Bold, Sans Condensed Bold) -U+1d759 u1D759 2.23 (Sans Bold, Sans Condensed Bold) -U+1d75a u1D75A 2.23 (Sans Bold, Sans Condensed Bold) -U+1d75b u1D75B 2.23 (Sans Bold, Sans Condensed Bold) -U+1d75c u1D75C 2.23 (Sans Bold, Sans Condensed Bold) -U+1d75d u1D75D 2.23 (Sans Bold, Sans Condensed Bold) -U+1d75e u1D75E 2.23 (Sans Bold, Sans Condensed Bold) -U+1d75f u1D75F 2.23 (Sans Bold, Sans Condensed Bold) -U+1d760 u1D760 2.23 (Sans Bold, Sans Condensed Bold) -U+1d761 u1D761 2.23 (Sans Bold, Sans Condensed Bold) -U+1d762 u1D762 2.23 (Sans Bold, Sans Condensed Bold) -U+1d763 u1D763 2.23 (Sans Bold, Sans Condensed Bold) -U+1d764 u1D764 2.23 (Sans Bold, Sans Condensed Bold) -U+1d765 u1D765 2.23 (Sans Bold, Sans Condensed Bold) -U+1d766 u1D766 2.23 (Sans Bold, Sans Condensed Bold) -U+1d767 u1D767 2.23 (Sans Bold, Sans Condensed Bold) -U+1d768 u1D768 2.23 (Sans Bold, Sans Condensed Bold) -U+1d769 u1D769 2.23 (Sans Bold, Sans Condensed Bold) -U+1d76a u1D76A 2.23 (Sans Bold, Sans Condensed Bold) -U+1d76b u1D76B 2.23 (Sans Bold, Sans Condensed Bold) -U+1d76c u1D76C 2.23 (Sans Bold, Sans Condensed Bold) -U+1d76d u1D76D 2.23 (Sans Bold, Sans Condensed Bold) -U+1d76e u1D76E 2.23 (Sans Bold, Sans Condensed Bold) -U+1d76f u1D76F 2.23 (Sans Bold, Sans Condensed Bold) -U+1d770 u1D770 2.23 (Sans Bold, Sans Condensed Bold) -U+1d771 u1D771 2.23 (Sans Bold, Sans Condensed Bold) -U+1d772 u1D772 2.23 (Sans Bold, Sans Condensed Bold) -U+1d773 u1D773 2.23 (Sans Bold, Sans Condensed Bold) -U+1d774 u1D774 2.23 (Sans Bold, Sans Condensed Bold) -U+1d775 u1D775 2.23 (Sans Bold, Sans Condensed Bold) -U+1d776 u1D776 2.23 (Sans Bold, Sans Condensed Bold) -U+1d777 u1D777 2.23 (Sans Bold, Sans Condensed Bold) -U+1d778 u1D778 2.23 (Sans Bold, Sans Condensed Bold) -U+1d779 u1D779 2.23 (Sans Bold, Sans Condensed Bold) -U+1d77a u1D77A 2.23 (Sans Bold, Sans Condensed Bold) -U+1d77b u1D77B 2.23 (Sans Bold, Sans Condensed Bold) -U+1d77c u1D77C 2.23 (Sans Bold, Sans Condensed Bold) -U+1d77d u1D77D 2.23 (Sans Bold, Sans Condensed Bold) -U+1d77e u1D77E 2.23 (Sans Bold, Sans Condensed Bold) -U+1d77f u1D77F 2.23 (Sans Bold, Sans Condensed Bold) -U+1d780 u1D780 2.23 (Sans Bold, Sans Condensed Bold) -U+1d781 u1D781 2.23 (Sans Bold, Sans Condensed Bold) -U+1d782 u1D782 2.23 (Sans Bold, Sans Condensed Bold) -U+1d783 u1D783 2.23 (Sans Bold, Sans Condensed Bold) -U+1d784 u1D784 2.23 (Sans Bold, Sans Condensed Bold) -U+1d785 u1D785 2.23 (Sans Bold, Sans Condensed Bold) -U+1d786 u1D786 2.23 (Sans Bold, Sans Condensed Bold) -U+1d787 u1D787 2.23 (Sans Bold, Sans Condensed Bold) -U+1d788 u1D788 2.23 (Sans Bold, Sans Condensed Bold) -U+1d789 u1D789 2.23 (Sans Bold, Sans Condensed Bold) -U+1d78a u1D78A 2.23 (Sans Bold, Sans Condensed Bold) -U+1d78b u1D78B 2.23 (Sans Bold, Sans Condensed Bold) -U+1d78c u1D78C 2.23 (Sans Bold, Sans Condensed Bold) -U+1d78d u1D78D 2.23 (Sans Bold, Sans Condensed Bold) -U+1d78e u1D78E 2.23 (Sans Bold, Sans Condensed Bold) -U+1d78f u1D78F 2.23 (Sans Bold, Sans Condensed Bold) -U+1d790 u1D790 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d791 u1D791 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d792 u1D792 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d793 u1D793 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d794 u1D794 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d795 u1D795 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d796 u1D796 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d797 u1D797 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d798 u1D798 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d799 u1D799 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d79a u1D79A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d79b u1D79B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d79c u1D79C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d79d u1D79D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d79e u1D79E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d79f u1D79F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a0 u1D7A0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a1 u1D7A1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a2 u1D7A2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a3 u1D7A3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a4 u1D7A4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a5 u1D7A5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a6 u1D7A6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a7 u1D7A7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a8 u1D7A8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7a9 u1D7A9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7aa u1D7AA 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7ab u1D7AB 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7ac u1D7AC 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7ad u1D7AD 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7ae u1D7AE 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7af u1D7AF 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b0 u1D7B0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b1 u1D7B1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b2 u1D7B2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b3 u1D7B3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b4 u1D7B4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b5 u1D7B5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b6 u1D7B6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b7 u1D7B7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b8 u1D7B8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7b9 u1D7B9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7ba u1D7BA 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7bb u1D7BB 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7bc u1D7BC 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7bd u1D7BD 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7be u1D7BE 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7bf u1D7BF 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c0 u1D7C0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c1 u1D7C1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c2 u1D7C2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c3 u1D7C3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c4 u1D7C4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c5 u1D7C5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c6 u1D7C6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c7 u1D7C7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c8 u1D7C8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+1d7c9 u1D7C9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) +U+1d400 u1D400 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d401 u1D401 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d402 u1D402 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d403 u1D403 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d404 u1D404 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d405 u1D405 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d406 u1D406 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d407 u1D407 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d408 u1D408 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d409 u1D409 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d40a u1D40A 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d40b u1D40B 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d40c u1D40C 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d40d u1D40D 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d40e u1D40E 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d40f u1D40F 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d410 u1D410 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d411 u1D411 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d412 u1D412 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d413 u1D413 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d414 u1D414 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d415 u1D415 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d416 u1D416 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d417 u1D417 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d418 u1D418 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d419 u1D419 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d41a u1D41A 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d41b u1D41B 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d41c u1D41C 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d41d u1D41D 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d41e u1D41E 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d41f u1D41F 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d420 u1D420 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d421 u1D421 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d422 u1D422 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d423 u1D423 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d424 u1D424 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d425 u1D425 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d426 u1D426 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d427 u1D427 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d428 u1D428 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d429 u1D429 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d42a u1D42A 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d42b u1D42B 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d42c u1D42C 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d42d u1D42D 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d42e u1D42E 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d42f u1D42F 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d430 u1D430 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d431 u1D431 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d432 u1D432 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d433 u1D433 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d434 u1D434 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d435 u1D435 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d436 u1D436 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d437 u1D437 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d438 u1D438 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d439 u1D439 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d43a u1D43A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d43b u1D43B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d43c u1D43C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d43d u1D43D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d43e u1D43E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d43f u1D43F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d440 u1D440 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d441 u1D441 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d442 u1D442 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d443 u1D443 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d444 u1D444 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d445 u1D445 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d446 u1D446 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d447 u1D447 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d448 u1D448 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d449 u1D449 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d44a u1D44A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d44b u1D44B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d44c u1D44C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d44d u1D44D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d44e u1D44E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d44f u1D44F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d450 u1D450 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d451 u1D451 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d452 u1D452 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d453 u1D453 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d454 u1D454 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d456 u1D456 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d457 u1D457 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d458 u1D458 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d459 u1D459 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d45a u1D45A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d45b u1D45B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d45c u1D45C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d45d u1D45D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d45e u1D45E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d45f u1D45F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d460 u1D460 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d461 u1D461 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d462 u1D462 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d463 u1D463 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d464 u1D464 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d465 u1D465 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d466 u1D466 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d467 u1D467 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d468 u1D468 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d469 u1D469 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d46a u1D46A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d46b u1D46B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d46c u1D46C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d46d u1D46D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d46e u1D46E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d46f u1D46F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d470 u1D470 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d471 u1D471 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d472 u1D472 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d473 u1D473 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d474 u1D474 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d475 u1D475 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d476 u1D476 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d477 u1D477 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d478 u1D478 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d479 u1D479 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d47a u1D47A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d47b u1D47B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d47c u1D47C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d47d u1D47D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d47e u1D47E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d47f u1D47F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d480 u1D480 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d481 u1D481 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d482 u1D482 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d483 u1D483 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d484 u1D484 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d485 u1D485 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d486 u1D486 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d487 u1D487 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d488 u1D488 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d489 u1D489 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d48a u1D48A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d48b u1D48B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d48c u1D48C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d48d u1D48D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d48e u1D48E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d48f u1D48F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d490 u1D490 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d491 u1D491 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d492 u1D492 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d493 u1D493 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d494 u1D494 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d495 u1D495 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d496 u1D496 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d497 u1D497 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d498 u1D498 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d499 u1D499 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d49a u1D49A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d49b u1D49B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d49c u1D49C 2.36 (Math TeX Gyre Regular) +U+1d49e u1D49E 2.36 (Math TeX Gyre Regular) +U+1d49f u1D49F 2.36 (Math TeX Gyre Regular) +U+1d4a2 u1D4A2 2.36 (Math TeX Gyre Regular) +U+1d4a5 u1D4A5 2.36 (Math TeX Gyre Regular) +U+1d4a6 u1D4A6 2.36 (Math TeX Gyre Regular) +U+1d4a9 u1D4A9 2.36 (Math TeX Gyre Regular) +U+1d4aa u1D4AA 2.36 (Math TeX Gyre Regular) +U+1d4ab u1D4AB 2.36 (Math TeX Gyre Regular) +U+1d4ac u1D4AC 2.36 (Math TeX Gyre Regular) +U+1d4ae u1D4AE 2.36 (Math TeX Gyre Regular) +U+1d4af u1D4AF 2.36 (Math TeX Gyre Regular) +U+1d4b0 u1D4B0 2.36 (Math TeX Gyre Regular) +U+1d4b1 u1D4B1 2.36 (Math TeX Gyre Regular) +U+1d4b2 u1D4B2 2.36 (Math TeX Gyre Regular) +U+1d4b3 u1D4B3 2.36 (Math TeX Gyre Regular) +U+1d4b4 u1D4B4 2.36 (Math TeX Gyre Regular) +U+1d4b5 u1D4B5 2.36 (Math TeX Gyre Regular) +U+1d4b6 u1D4B6 2.36 (Math TeX Gyre Regular) +U+1d4b7 u1D4B7 2.36 (Math TeX Gyre Regular) +U+1d4b8 u1D4B8 2.36 (Math TeX Gyre Regular) +U+1d4b9 u1D4B9 2.36 (Math TeX Gyre Regular) +U+1d4bb u1D4BB 2.36 (Math TeX Gyre Regular) +U+1d4bd u1D4BD 2.36 (Math TeX Gyre Regular) +U+1d4be u1D4BE 2.36 (Math TeX Gyre Regular) +U+1d4bf u1D4BF 2.36 (Math TeX Gyre Regular) +U+1d4c0 u1D4C0 2.36 (Math TeX Gyre Regular) +U+1d4c1 u1D4C1 2.36 (Math TeX Gyre Regular) +U+1d4c2 u1D4C2 2.36 (Math TeX Gyre Regular) +U+1d4c3 u1D4C3 2.36 (Math TeX Gyre Regular) +U+1d4c5 u1D4C5 2.36 (Math TeX Gyre Regular) +U+1d4c6 u1D4C6 2.36 (Math TeX Gyre Regular) +U+1d4c7 u1D4C7 2.36 (Math TeX Gyre Regular) +U+1d4c8 u1D4C8 2.36 (Math TeX Gyre Regular) +U+1d4c9 u1D4C9 2.36 (Math TeX Gyre Regular) +U+1d4ca u1D4CA 2.36 (Math TeX Gyre Regular) +U+1d4cb u1D4CB 2.36 (Math TeX Gyre Regular) +U+1d4cc u1D4CC 2.36 (Math TeX Gyre Regular) +U+1d4cd u1D4CD 2.36 (Math TeX Gyre Regular) +U+1d4ce u1D4CE 2.36 (Math TeX Gyre Regular) +U+1d4cf u1D4CF 2.36 (Math TeX Gyre Regular) +U+1d4d0 u1D4D0 2.36 (Math TeX Gyre Regular) +U+1d4d1 u1D4D1 2.36 (Math TeX Gyre Regular) +U+1d4d2 u1D4D2 2.36 (Math TeX Gyre Regular) +U+1d4d3 u1D4D3 2.36 (Math TeX Gyre Regular) +U+1d4d4 u1D4D4 2.36 (Math TeX Gyre Regular) +U+1d4d5 u1D4D5 2.36 (Math TeX Gyre Regular) +U+1d4d6 u1D4D6 2.36 (Math TeX Gyre Regular) +U+1d4d7 u1D4D7 2.36 (Math TeX Gyre Regular) +U+1d4d8 u1D4D8 2.36 (Math TeX Gyre Regular) +U+1d4d9 u1D4D9 2.36 (Math TeX Gyre Regular) +U+1d4da u1D4DA 2.36 (Math TeX Gyre Regular) +U+1d4db u1D4DB 2.36 (Math TeX Gyre Regular) +U+1d4dc u1D4DC 2.36 (Math TeX Gyre Regular) +U+1d4dd u1D4DD 2.36 (Math TeX Gyre Regular) +U+1d4de u1D4DE 2.36 (Math TeX Gyre Regular) +U+1d4df u1D4DF 2.36 (Math TeX Gyre Regular) +U+1d4e0 u1D4E0 2.36 (Math TeX Gyre Regular) +U+1d4e1 u1D4E1 2.36 (Math TeX Gyre Regular) +U+1d4e2 u1D4E2 2.36 (Math TeX Gyre Regular) +U+1d4e3 u1D4E3 2.36 (Math TeX Gyre Regular) +U+1d4e4 u1D4E4 2.36 (Math TeX Gyre Regular) +U+1d4e5 u1D4E5 2.36 (Math TeX Gyre Regular) +U+1d4e6 u1D4E6 2.36 (Math TeX Gyre Regular) +U+1d4e7 u1D4E7 2.36 (Math TeX Gyre Regular) +U+1d4e8 u1D4E8 2.36 (Math TeX Gyre Regular) +U+1d4e9 u1D4E9 2.36 (Math TeX Gyre Regular) +U+1d4ea u1D4EA 2.36 (Math TeX Gyre Regular) +U+1d4eb u1D4EB 2.36 (Math TeX Gyre Regular) +U+1d4ec u1D4EC 2.36 (Math TeX Gyre Regular) +U+1d4ed u1D4ED 2.36 (Math TeX Gyre Regular) +U+1d4ee u1D4EE 2.36 (Math TeX Gyre Regular) +U+1d4ef u1D4EF 2.36 (Math TeX Gyre Regular) +U+1d4f0 u1D4F0 2.36 (Math TeX Gyre Regular) +U+1d4f1 u1D4F1 2.36 (Math TeX Gyre Regular) +U+1d4f2 u1D4F2 2.36 (Math TeX Gyre Regular) +U+1d4f3 u1D4F3 2.36 (Math TeX Gyre Regular) +U+1d4f4 u1D4F4 2.36 (Math TeX Gyre Regular) +U+1d4f5 u1D4F5 2.36 (Math TeX Gyre Regular) +U+1d4f6 u1D4F6 2.36 (Math TeX Gyre Regular) +U+1d4f7 u1D4F7 2.36 (Math TeX Gyre Regular) +U+1d4f8 u1D4F8 2.36 (Math TeX Gyre Regular) +U+1d4f9 u1D4F9 2.36 (Math TeX Gyre Regular) +U+1d4fa u1D4FA 2.36 (Math TeX Gyre Regular) +U+1d4fb u1D4FB 2.36 (Math TeX Gyre Regular) +U+1d4fc u1D4FC 2.36 (Math TeX Gyre Regular) +U+1d4fd u1D4FD 2.36 (Math TeX Gyre Regular) +U+1d4fe u1D4FE 2.36 (Math TeX Gyre Regular) +U+1d4ff u1D4FF 2.36 (Math TeX Gyre Regular) +U+1d500 u1D500 2.36 (Math TeX Gyre Regular) +U+1d501 u1D501 2.36 (Math TeX Gyre Regular) +U+1d502 u1D502 2.36 (Math TeX Gyre Regular) +U+1d503 u1D503 2.36 (Math TeX Gyre Regular) +U+1d504 u1D504 2.36 (Math TeX Gyre Regular) +U+1d505 u1D505 2.36 (Math TeX Gyre Regular) +U+1d507 u1D507 2.36 (Math TeX Gyre Regular) +U+1d508 u1D508 2.36 (Math TeX Gyre Regular) +U+1d509 u1D509 2.36 (Math TeX Gyre Regular) +U+1d50a u1D50A 2.36 (Math TeX Gyre Regular) +U+1d50d u1D50D 2.36 (Math TeX Gyre Regular) +U+1d50e u1D50E 2.36 (Math TeX Gyre Regular) +U+1d50f u1D50F 2.36 (Math TeX Gyre Regular) +U+1d510 u1D510 2.36 (Math TeX Gyre Regular) +U+1d511 u1D511 2.36 (Math TeX Gyre Regular) +U+1d512 u1D512 2.36 (Math TeX Gyre Regular) +U+1d513 u1D513 2.36 (Math TeX Gyre Regular) +U+1d514 u1D514 2.36 (Math TeX Gyre Regular) +U+1d516 u1D516 2.36 (Math TeX Gyre Regular) +U+1d517 u1D517 2.36 (Math TeX Gyre Regular) +U+1d518 u1D518 2.36 (Math TeX Gyre Regular) +U+1d519 u1D519 2.36 (Math TeX Gyre Regular) +U+1d51a u1D51A 2.36 (Math TeX Gyre Regular) +U+1d51b u1D51B 2.36 (Math TeX Gyre Regular) +U+1d51c u1D51C 2.36 (Math TeX Gyre Regular) +U+1d51e u1D51E 2.36 (Math TeX Gyre Regular) +U+1d51f u1D51F 2.36 (Math TeX Gyre Regular) +U+1d520 u1D520 2.36 (Math TeX Gyre Regular) +U+1d521 u1D521 2.36 (Math TeX Gyre Regular) +U+1d522 u1D522 2.36 (Math TeX Gyre Regular) +U+1d523 u1D523 2.36 (Math TeX Gyre Regular) +U+1d524 u1D524 2.36 (Math TeX Gyre Regular) +U+1d525 u1D525 2.36 (Math TeX Gyre Regular) +U+1d526 u1D526 2.36 (Math TeX Gyre Regular) +U+1d527 u1D527 2.36 (Math TeX Gyre Regular) +U+1d528 u1D528 2.36 (Math TeX Gyre Regular) +U+1d529 u1D529 2.36 (Math TeX Gyre Regular) +U+1d52a u1D52A 2.36 (Math TeX Gyre Regular) +U+1d52b u1D52B 2.36 (Math TeX Gyre Regular) +U+1d52c u1D52C 2.36 (Math TeX Gyre Regular) +U+1d52d u1D52D 2.36 (Math TeX Gyre Regular) +U+1d52e u1D52E 2.36 (Math TeX Gyre Regular) +U+1d52f u1D52F 2.36 (Math TeX Gyre Regular) +U+1d530 u1D530 2.36 (Math TeX Gyre Regular) +U+1d531 u1D531 2.36 (Math TeX Gyre Regular) +U+1d532 u1D532 2.36 (Math TeX Gyre Regular) +U+1d533 u1D533 2.36 (Math TeX Gyre Regular) +U+1d534 u1D534 2.36 (Math TeX Gyre Regular) +U+1d535 u1D535 2.36 (Math TeX Gyre Regular) +U+1d536 u1D536 2.36 (Math TeX Gyre Regular) +U+1d537 u1D537 2.36 (Math TeX Gyre Regular) +U+1d538 u1D538 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d539 u1D539 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d53b u1D53B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d53c u1D53C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d53d u1D53D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d53e u1D53E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d540 u1D540 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d541 u1D541 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d542 u1D542 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d543 u1D543 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d544 u1D544 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d546 u1D546 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d54a u1D54A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d54b u1D54B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d54c u1D54C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d54d u1D54D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d54e u1D54E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d54f u1D54F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d550 u1D550 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d552 u1D552 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d553 u1D553 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d554 u1D554 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d555 u1D555 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d556 u1D556 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d557 u1D557 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d558 u1D558 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d559 u1D559 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d55a u1D55A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) +U+1d55b u1D55B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d55c u1D55C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d55d u1D55D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d55e u1D55E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d55f u1D55F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d560 u1D560 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d561 u1D561 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d562 u1D562 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d563 u1D563 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d564 u1D564 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d565 u1D565 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d566 u1D566 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d567 u1D567 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d568 u1D568 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d569 u1D569 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d56a u1D56A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d56b u1D56B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d56c u1D56C 2.36 (Math TeX Gyre Regular) +U+1d56d u1D56D 2.36 (Math TeX Gyre Regular) +U+1d56e u1D56E 2.36 (Math TeX Gyre Regular) +U+1d56f u1D56F 2.36 (Math TeX Gyre Regular) +U+1d570 u1D570 2.36 (Math TeX Gyre Regular) +U+1d571 u1D571 2.36 (Math TeX Gyre Regular) +U+1d572 u1D572 2.36 (Math TeX Gyre Regular) +U+1d573 u1D573 2.36 (Math TeX Gyre Regular) +U+1d574 u1D574 2.36 (Math TeX Gyre Regular) +U+1d575 u1D575 2.36 (Math TeX Gyre Regular) +U+1d576 u1D576 2.36 (Math TeX Gyre Regular) +U+1d577 u1D577 2.36 (Math TeX Gyre Regular) +U+1d578 u1D578 2.36 (Math TeX Gyre Regular) +U+1d579 u1D579 2.36 (Math TeX Gyre Regular) +U+1d57a u1D57A 2.36 (Math TeX Gyre Regular) +U+1d57b u1D57B 2.36 (Math TeX Gyre Regular) +U+1d57c u1D57C 2.36 (Math TeX Gyre Regular) +U+1d57d u1D57D 2.36 (Math TeX Gyre Regular) +U+1d57e u1D57E 2.36 (Math TeX Gyre Regular) +U+1d57f u1D57F 2.36 (Math TeX Gyre Regular) +U+1d580 u1D580 2.36 (Math TeX Gyre Regular) +U+1d581 u1D581 2.36 (Math TeX Gyre Regular) +U+1d582 u1D582 2.36 (Math TeX Gyre Regular) +U+1d583 u1D583 2.36 (Math TeX Gyre Regular) +U+1d584 u1D584 2.36 (Math TeX Gyre Regular) +U+1d585 u1D585 2.36 (Math TeX Gyre Regular) +U+1d586 u1D586 2.36 (Math TeX Gyre Regular) +U+1d587 u1D587 2.36 (Math TeX Gyre Regular) +U+1d588 u1D588 2.36 (Math TeX Gyre Regular) +U+1d589 u1D589 2.36 (Math TeX Gyre Regular) +U+1d58a u1D58A 2.36 (Math TeX Gyre Regular) +U+1d58b u1D58B 2.36 (Math TeX Gyre Regular) +U+1d58c u1D58C 2.36 (Math TeX Gyre Regular) +U+1d58d u1D58D 2.36 (Math TeX Gyre Regular) +U+1d58e u1D58E 2.36 (Math TeX Gyre Regular) +U+1d58f u1D58F 2.36 (Math TeX Gyre Regular) +U+1d590 u1D590 2.36 (Math TeX Gyre Regular) +U+1d591 u1D591 2.36 (Math TeX Gyre Regular) +U+1d592 u1D592 2.36 (Math TeX Gyre Regular) +U+1d593 u1D593 2.36 (Math TeX Gyre Regular) +U+1d594 u1D594 2.36 (Math TeX Gyre Regular) +U+1d595 u1D595 2.36 (Math TeX Gyre Regular) +U+1d596 u1D596 2.36 (Math TeX Gyre Regular) +U+1d597 u1D597 2.36 (Math TeX Gyre Regular) +U+1d598 u1D598 2.36 (Math TeX Gyre Regular) +U+1d599 u1D599 2.36 (Math TeX Gyre Regular) +U+1d59a u1D59A 2.36 (Math TeX Gyre Regular) +U+1d59b u1D59B 2.36 (Math TeX Gyre Regular) +U+1d59c u1D59C 2.36 (Math TeX Gyre Regular) +U+1d59d u1D59D 2.36 (Math TeX Gyre Regular) +U+1d59e u1D59E 2.36 (Math TeX Gyre Regular) +U+1d59f u1D59F 2.36 (Math TeX Gyre Regular) +U+1d5a0 u1D5A0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a1 u1D5A1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a2 u1D5A2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a3 u1D5A3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a4 u1D5A4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a5 u1D5A5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a6 u1D5A6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a7 u1D5A7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a8 u1D5A8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5a9 u1D5A9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5aa u1D5AA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ab u1D5AB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ac u1D5AC 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ad u1D5AD 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ae u1D5AE 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5af u1D5AF 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b0 u1D5B0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b1 u1D5B1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b2 u1D5B2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b3 u1D5B3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b4 u1D5B4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b5 u1D5B5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b6 u1D5B6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b7 u1D5B7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b8 u1D5B8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5b9 u1D5B9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ba u1D5BA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5bb u1D5BB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5bc u1D5BC 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5bd u1D5BD 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5be u1D5BE 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5bf u1D5BF 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c0 u1D5C0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c1 u1D5C1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c2 u1D5C2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c3 u1D5C3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c4 u1D5C4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c5 u1D5C5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c6 u1D5C6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c7 u1D5C7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c8 u1D5C8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5c9 u1D5C9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ca u1D5CA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5cb u1D5CB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5cc u1D5CC 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5cd u1D5CD 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5ce u1D5CE 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5cf u1D5CF 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5d0 u1D5D0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5d1 u1D5D1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5d2 u1D5D2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5d3 u1D5D3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d5d4 u1D5D4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5d5 u1D5D5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5d6 u1D5D6 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5d7 u1D5D7 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5d8 u1D5D8 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5d9 u1D5D9 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5da u1D5DA 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5db u1D5DB 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5dc u1D5DC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5dd u1D5DD 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5de u1D5DE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5df u1D5DF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e0 u1D5E0 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e1 u1D5E1 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e2 u1D5E2 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e3 u1D5E3 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e4 u1D5E4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e5 u1D5E5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e6 u1D5E6 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e7 u1D5E7 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e8 u1D5E8 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5e9 u1D5E9 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5ea u1D5EA 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5eb u1D5EB 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5ec u1D5EC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5ed u1D5ED 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5ee u1D5EE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5ef u1D5EF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f0 u1D5F0 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f1 u1D5F1 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f2 u1D5F2 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f3 u1D5F3 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f4 u1D5F4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f5 u1D5F5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f6 u1D5F6 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f7 u1D5F7 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f8 u1D5F8 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5f9 u1D5F9 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5fa u1D5FA 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5fb u1D5FB 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5fc u1D5FC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5fd u1D5FD 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5fe u1D5FE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d5ff u1D5FF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d600 u1D600 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d601 u1D601 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d602 u1D602 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d603 u1D603 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d604 u1D604 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d605 u1D605 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d606 u1D606 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d607 u1D607 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d608 u1D608 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d609 u1D609 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d60a u1D60A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d60b u1D60B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d60c u1D60C 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d60d u1D60D 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d60e u1D60E 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d60f u1D60F 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d610 u1D610 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d611 u1D611 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d612 u1D612 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d613 u1D613 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d614 u1D614 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d615 u1D615 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d616 u1D616 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d617 u1D617 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d618 u1D618 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d619 u1D619 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d61a u1D61A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d61b u1D61B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d61c u1D61C 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d61d u1D61D 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d61e u1D61E 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d61f u1D61F 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d620 u1D620 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d621 u1D621 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d622 u1D622 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d623 u1D623 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d624 u1D624 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d625 u1D625 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d626 u1D626 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d627 u1D627 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d628 u1D628 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d629 u1D629 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d62a u1D62A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d62b u1D62B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d62c u1D62C 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d62d u1D62D 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d62e u1D62E 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d62f u1D62F 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d630 u1D630 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d631 u1D631 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d632 u1D632 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d633 u1D633 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d634 u1D634 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d635 u1D635 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d636 u1D636 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d637 u1D637 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d638 u1D638 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d639 u1D639 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d63a u1D63A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d63b u1D63B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) +U+1d63c u1D63C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d63d u1D63D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d63e u1D63E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d63f u1D63F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d640 u1D640 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d641 u1D641 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d642 u1D642 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d643 u1D643 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d644 u1D644 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d645 u1D645 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d646 u1D646 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d647 u1D647 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d648 u1D648 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d649 u1D649 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d64a u1D64A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d64b u1D64B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d64c u1D64C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d64d u1D64D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d64e u1D64E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d64f u1D64F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d650 u1D650 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d651 u1D651 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d652 u1D652 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d653 u1D653 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d654 u1D654 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d655 u1D655 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d656 u1D656 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d657 u1D657 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d658 u1D658 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d659 u1D659 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d65a u1D65A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d65b u1D65B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d65c u1D65C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d65d u1D65D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d65e u1D65E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d65f u1D65F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d660 u1D660 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d661 u1D661 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d662 u1D662 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d663 u1D663 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d664 u1D664 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d665 u1D665 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d666 u1D666 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d667 u1D667 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d668 u1D668 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d669 u1D669 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d66a u1D66A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d66b u1D66B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d66c u1D66C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d66d u1D66D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d66e u1D66E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d66f u1D66F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d670 u1D670 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d671 u1D671 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d672 u1D672 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d673 u1D673 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d674 u1D674 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d675 u1D675 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d676 u1D676 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d677 u1D677 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d678 u1D678 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d679 u1D679 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d67a u1D67A 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d67b u1D67B 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d67c u1D67C 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d67d u1D67D 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d67e u1D67E 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d67f u1D67F 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d680 u1D680 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d681 u1D681 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d682 u1D682 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d683 u1D683 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d684 u1D684 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d685 u1D685 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d686 u1D686 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d687 u1D687 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d688 u1D688 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d689 u1D689 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d68a u1D68A 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d68b u1D68B 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d68c u1D68C 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d68d u1D68D 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d68e u1D68E 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d68f u1D68F 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d690 u1D690 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d691 u1D691 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d692 u1D692 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d693 u1D693 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d694 u1D694 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d695 u1D695 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d696 u1D696 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d697 u1D697 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d698 u1D698 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d699 u1D699 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d69a u1D69A 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d69b u1D69B 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d69c u1D69C 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d69d u1D69D 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d69e u1D69E 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d69f u1D69F 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d6a0 u1D6A0 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d6a1 u1D6A1 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d6a2 u1D6A2 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d6a3 u1D6A3 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d6a4 u1D6A4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d6a5 u1D6A5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) +U+1d6a8 u1D6A8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6a9 u1D6A9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6aa u1D6AA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ab u1D6AB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ac u1D6AC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ad u1D6AD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ae u1D6AE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6af u1D6AF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b0 u1D6B0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b1 u1D6B1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b2 u1D6B2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b3 u1D6B3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b4 u1D6B4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b5 u1D6B5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b6 u1D6B6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b7 u1D6B7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b8 u1D6B8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6b9 u1D6B9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ba u1D6BA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6bb u1D6BB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6bc u1D6BC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6bd u1D6BD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6be u1D6BE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6bf u1D6BF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c0 u1D6C0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c1 u1D6C1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c2 u1D6C2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c3 u1D6C3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c4 u1D6C4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c5 u1D6C5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c6 u1D6C6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c7 u1D6C7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c8 u1D6C8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6c9 u1D6C9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ca u1D6CA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6cb u1D6CB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6cc u1D6CC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6cd u1D6CD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6ce u1D6CE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6cf u1D6CF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d0 u1D6D0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d1 u1D6D1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d2 u1D6D2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d3 u1D6D3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d4 u1D6D4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d5 u1D6D5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d6 u1D6D6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d7 u1D6D7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d8 u1D6D8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6d9 u1D6D9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6da u1D6DA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6db u1D6DB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6dc u1D6DC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6dd u1D6DD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6de u1D6DE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6df u1D6DF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6e0 u1D6E0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6e1 u1D6E1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d6e2 u1D6E2 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e3 u1D6E3 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e4 u1D6E4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e5 u1D6E5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e6 u1D6E6 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e7 u1D6E7 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e8 u1D6E8 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6e9 u1D6E9 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6ea u1D6EA 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6eb u1D6EB 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6ec u1D6EC 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6ed u1D6ED 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6ee u1D6EE 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6ef u1D6EF 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f0 u1D6F0 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f1 u1D6F1 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f2 u1D6F2 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f3 u1D6F3 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f4 u1D6F4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f5 u1D6F5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f6 u1D6F6 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f7 u1D6F7 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f8 u1D6F8 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6f9 u1D6F9 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6fa u1D6FA 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6fb u1D6FB 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6fc u1D6FC 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6fd u1D6FD 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6fe u1D6FE 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d6ff u1D6FF 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d700 u1D700 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d701 u1D701 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d702 u1D702 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d703 u1D703 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d704 u1D704 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d705 u1D705 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d706 u1D706 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d707 u1D707 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d708 u1D708 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d709 u1D709 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d70a u1D70A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d70b u1D70B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d70c u1D70C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d70d u1D70D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d70e u1D70E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d70f u1D70F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d710 u1D710 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d711 u1D711 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d712 u1D712 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d713 u1D713 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d714 u1D714 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d715 u1D715 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d716 u1D716 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d717 u1D717 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d718 u1D718 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d719 u1D719 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d71a u1D71A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d71b u1D71B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) +U+1d71c u1D71C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d71d u1D71D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d71e u1D71E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d71f u1D71F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d720 u1D720 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d721 u1D721 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d722 u1D722 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d723 u1D723 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d724 u1D724 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d725 u1D725 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d726 u1D726 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d727 u1D727 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d728 u1D728 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d729 u1D729 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d72a u1D72A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d72b u1D72B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d72c u1D72C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d72d u1D72D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d72e u1D72E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d72f u1D72F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d730 u1D730 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d731 u1D731 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d732 u1D732 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d733 u1D733 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d734 u1D734 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d735 u1D735 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d736 u1D736 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d737 u1D737 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d738 u1D738 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d739 u1D739 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d73a u1D73A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d73b u1D73B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d73c u1D73C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d73d u1D73D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d73e u1D73E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d73f u1D73F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d740 u1D740 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d741 u1D741 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d742 u1D742 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d743 u1D743 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d744 u1D744 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d745 u1D745 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d746 u1D746 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d747 u1D747 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d748 u1D748 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d749 u1D749 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d74a u1D74A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d74b u1D74B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d74c u1D74C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d74d u1D74D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d74e u1D74E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d74f u1D74F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d750 u1D750 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d751 u1D751 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d752 u1D752 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d753 u1D753 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d754 u1D754 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d755 u1D755 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) +U+1d756 u1D756 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d757 u1D757 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d758 u1D758 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d759 u1D759 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d75a u1D75A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d75b u1D75B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d75c u1D75C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d75d u1D75D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d75e u1D75E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d75f u1D75F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d760 u1D760 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d761 u1D761 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d762 u1D762 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d763 u1D763 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d764 u1D764 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d765 u1D765 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d766 u1D766 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d767 u1D767 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d768 u1D768 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d769 u1D769 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d76a u1D76A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d76b u1D76B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d76c u1D76C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d76d u1D76D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d76e u1D76E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d76f u1D76F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d770 u1D770 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d771 u1D771 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d772 u1D772 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d773 u1D773 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d774 u1D774 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d775 u1D775 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d776 u1D776 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d777 u1D777 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d778 u1D778 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d779 u1D779 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d77a u1D77A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d77b u1D77B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d77c u1D77C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d77d u1D77D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d77e u1D77E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d77f u1D77F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d780 u1D780 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d781 u1D781 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d782 u1D782 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d783 u1D783 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d784 u1D784 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d785 u1D785 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d786 u1D786 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d787 u1D787 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d788 u1D788 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d789 u1D789 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d78a u1D78A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d78b u1D78B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d78c u1D78C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d78d u1D78D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d78e u1D78E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d78f u1D78F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d790 u1D790 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d791 u1D791 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d792 u1D792 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d793 u1D793 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d794 u1D794 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d795 u1D795 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d796 u1D796 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d797 u1D797 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d798 u1D798 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d799 u1D799 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d79a u1D79A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d79b u1D79B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d79c u1D79C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d79d u1D79D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d79e u1D79E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d79f u1D79F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a0 u1D7A0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a1 u1D7A1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a2 u1D7A2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a3 u1D7A3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a4 u1D7A4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a5 u1D7A5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a6 u1D7A6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a7 u1D7A7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a8 u1D7A8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7a9 u1D7A9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7aa u1D7AA 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7ab u1D7AB 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7ac u1D7AC 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7ad u1D7AD 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7ae u1D7AE 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7af u1D7AF 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b0 u1D7B0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b1 u1D7B1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b2 u1D7B2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b3 u1D7B3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b4 u1D7B4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b5 u1D7B5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b6 u1D7B6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b7 u1D7B7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b8 u1D7B8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7b9 u1D7B9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7ba u1D7BA 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7bb u1D7BB 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7bc u1D7BC 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7bd u1D7BD 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7be u1D7BE 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7bf u1D7BF 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c0 u1D7C0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c1 u1D7C1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c2 u1D7C2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c3 u1D7C3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c4 u1D7C4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c5 u1D7C5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c6 u1D7C6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c7 u1D7C7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c8 u1D7C8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) +U+1d7c9 u1D7C9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) U+1d7ca u1D7CA 2.23 (Serif Bold, Serif Condensed Bold) U+1d7cb u1D7CB 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7ce u1D7CE 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7cf u1D7CF 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d0 u1D7D0 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d1 u1D7D1 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d2 u1D7D2 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d3 u1D7D3 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d4 u1D7D4 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d5 u1D7D5 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d6 u1D7D6 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d7 u1D7D7 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7d8 u1D7D8 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7d9 u1D7D9 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7da u1D7DA 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7db u1D7DB 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7dc u1D7DC 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7dd u1D7DD 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7de u1D7DE 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7df u1D7DF 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7e0 u1D7E0 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7e1 u1D7E1 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+1d7e2 u1D7E2 2.23 (Sans, Sans Condensed) -U+1d7e3 u1D7E3 2.23 (Sans, Sans Condensed) -U+1d7e4 u1D7E4 2.23 (Sans, Sans Condensed) -U+1d7e5 u1D7E5 2.23 (Sans, Sans Condensed) -U+1d7e6 u1D7E6 2.23 (Sans, Sans Condensed) -U+1d7e7 u1D7E7 2.23 (Sans, Sans Condensed) -U+1d7e8 u1D7E8 2.23 (Sans, Sans Condensed) -U+1d7e9 u1D7E9 2.23 (Sans, Sans Condensed) -U+1d7ea u1D7EA 2.23 (Sans, Sans Condensed) -U+1d7eb u1D7EB 2.23 (Sans, Sans Condensed) -U+1d7ec u1D7EC 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7ed u1D7ED 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7ee u1D7EE 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7ef u1D7EF 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f0 u1D7F0 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f1 u1D7F1 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f2 u1D7F2 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f3 u1D7F3 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f4 u1D7F4 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f5 u1D7F5 2.23 (Sans Bold, Sans Condensed Bold) -U+1d7f6 u1D7F6 2.23 (Sans Mono) -U+1d7f7 u1D7F7 2.23 (Sans Mono) -U+1d7f8 u1D7F8 2.23 (Sans Mono) -U+1d7f9 u1D7F9 2.23 (Sans Mono) -U+1d7fa u1D7FA 2.23 (Sans Mono) -U+1d7fb u1D7FB 2.23 (Sans Mono) -U+1d7fc u1D7FC 2.23 (Sans Mono) -U+1d7fd u1D7FD 2.23 (Sans Mono) -U+1d7fe u1D7FE 2.23 (Sans Mono) -U+1d7ff u1D7FF 2.23 (Sans Mono) +U+1d7ce u1D7CE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7cf u1D7CF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d0 u1D7D0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d1 u1D7D1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d2 u1D7D2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d3 u1D7D3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d4 u1D7D4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d5 u1D7D5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d6 u1D7D6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d7 u1D7D7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d8 u1D7D8 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7d9 u1D7D9 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7da u1D7DA 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7db u1D7DB 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7dc u1D7DC 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7dd u1D7DD 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7de u1D7DE 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7df u1D7DF 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7e0 u1D7E0 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7e1 u1D7E1 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) +U+1d7e2 u1D7E2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e3 u1D7E3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e4 u1D7E4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e5 u1D7E5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e6 u1D7E6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e7 u1D7E7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e8 u1D7E8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7e9 u1D7E9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7ea u1D7EA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7eb u1D7EB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) +U+1d7ec u1D7EC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7ed u1D7ED 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7ee u1D7EE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7ef u1D7EF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f0 u1D7F0 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f1 u1D7F1 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f2 u1D7F2 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f3 u1D7F3 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f4 u1D7F4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f5 u1D7F5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) +U+1d7f6 u1D7F6 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7f7 u1D7F7 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7f8 u1D7F8 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7f9 u1D7F9 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7fa u1D7FA 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7fb u1D7FB 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7fc u1D7FC 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7fd u1D7FD 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7fe u1D7FE 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) +U+1d7ff u1D7FF 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) U+1ee00 u1EE00 2.35 (Sans, Sans Condensed) U+1ee01 u1EE01 2.35 (Sans, Sans Condensed) U+1ee02 u1EE02 2.35 (Sans, Sans Condensed) @@ -6815,6 +7065,14 @@ U+1f0dc u1F0DC 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Cond U+1f0dd u1F0DD 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f0de u1F0DE 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f0df u1F0DF 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f311 u1F311 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f312 u1F312 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f313 u1F313 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f314 u1F314 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f315 u1F315 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f316 u1F316 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f317 u1F317 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f318 u1F318 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f42d u1F42D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f42e u1F42E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f431 u1F431 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) @@ -6882,3 +7140,4 @@ U+1f63d u1F63D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Cond U+1f63e u1F63E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f63f u1F63F 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) U+1f640 u1F640 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) +U+1f643 u1F643 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) diff --git a/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuMathTeXGyre.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuMathTeXGyre.ttf new file mode 100644 index 000000000..8a24f0640 Binary files /dev/null and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuMathTeXGyre.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-Bold.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Bold.ttf similarity index 81% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-Bold.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Bold.ttf index 1f22f07c9..6d65fa7dc 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-Bold.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Bold.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-BoldOblique.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-BoldOblique.ttf similarity index 83% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-BoldOblique.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-BoldOblique.ttf index b8886cb5e..753f2d80b 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-BoldOblique.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-BoldOblique.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-ExtraLight.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-ExtraLight.ttf new file mode 100644 index 000000000..b09f32d7d Binary files /dev/null and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-ExtraLight.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-Oblique.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Oblique.ttf similarity index 83% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-Oblique.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Oblique.ttf index 300ea68b6..999bac771 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans-Oblique.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Oblique.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf similarity index 79% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf index 526721885..e5f7eecce 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-Bold.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Bold.ttf similarity index 79% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-Bold.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Bold.ttf index 9628230ef..22987c62d 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-Bold.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Bold.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-BoldOblique.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-BoldOblique.ttf similarity index 82% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-BoldOblique.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-BoldOblique.ttf index c499c5f37..f5fa0ca26 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-BoldOblique.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-BoldOblique.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-Oblique.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Oblique.ttf similarity index 82% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-Oblique.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Oblique.ttf index b4141d5d3..7fde90789 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed-Oblique.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Oblique.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed.ttf similarity index 76% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed.ttf index bbca09297..3259bc21a 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansCondensed.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-Bold.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Bold.ttf similarity index 83% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-Bold.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Bold.ttf index cbcdd31d6..8184ced8c 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-Bold.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Bold.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-BoldOblique.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-BoldOblique.ttf similarity index 85% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-BoldOblique.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-BoldOblique.ttf index da513440a..754dca732 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-BoldOblique.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-BoldOblique.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-Oblique.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Oblique.ttf similarity index 84% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-Oblique.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Oblique.ttf index 0185ce95a..4c858d401 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono-Oblique.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Oblique.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf similarity index 82% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf index 278cd7813..f5786022f 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSansMono.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-Bold.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Bold.ttf similarity index 78% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-Bold.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Bold.ttf index d683eb282..3bb755fa1 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-Bold.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Bold.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-BoldItalic.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-BoldItalic.ttf similarity index 80% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-BoldItalic.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-BoldItalic.ttf index b4831f765..a36dd4b70 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-BoldItalic.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-BoldItalic.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-Italic.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Italic.ttf similarity index 78% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-Italic.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Italic.ttf index 45b508b82..805daf222 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif-Italic.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Italic.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif.ttf similarity index 78% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif.ttf index 39dd3946d..0b803d206 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerif.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-Bold.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Bold.ttf similarity index 77% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-Bold.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Bold.ttf index 5a494804c..222bf134b 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-Bold.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Bold.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-BoldItalic.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-BoldItalic.ttf similarity index 79% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-BoldItalic.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-BoldItalic.ttf index d6572889d..e44663695 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-BoldItalic.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-BoldItalic.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-Italic.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Italic.ttf similarity index 79% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-Italic.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Italic.ttf index 0fbe02591..c529df31b 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed-Italic.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Italic.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed.ttf b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed.ttf similarity index 77% rename from fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed.ttf rename to fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed.ttf index f9e5e6890..d3959b322 100644 Binary files a/fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSerifCondensed.ttf and b/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed.ttf differ diff --git a/fonts/dejavu-fonts-ttf-2.35/unicover.txt b/fonts/dejavu-fonts-ttf-2.37/unicover.txt similarity index 81% rename from fonts/dejavu-fonts-ttf-2.35/unicover.txt rename to fonts/dejavu-fonts-ttf-2.37/unicover.txt index b7dc3c957..fc05f99b4 100644 --- a/fonts/dejavu-fonts-ttf-2.35/unicover.txt +++ b/fonts/dejavu-fonts-ttf-2.37/unicover.txt @@ -11,7 +11,7 @@ U+0180 Latin Extended-B 100% (208/208) 100% (208/208 U+0250 IPA Extensions 100% (96/96) 100% (96/96) 100% (96/96) U+02b0 Spacing Modifier Letters 78% (63/80) 73% (59/80) 62% (50/80) U+0300 Combining Diacritical Marks 83% (93/112) 61% (69/112) 59% (67/112) -U+0370 Greek and Coptic 99% (134/135) 88% (120/135) 81% (110/135) +U+0370 Greek and Coptic 100% (135/135) 89% (121/135) 85% (116/135) U+0400 Cyrillic 100% (256/256) 79% (204/256) 70% (180/256) U+0500 Cyrillic Supplement 79% (38/48) 20% (10/48) 12% (6/48) U+0530 Armenian 96% (86/89) 96% (86/89) 96% (86/89) @@ -23,16 +23,16 @@ U+0780 Thaana (0/50) (0/50) U+07c0 NKo 91% (54/59) (0/59) (0/59) U+0800 Samaritan (0/61) (0/61) (0/61) U+0840 Mandaic (0/29) (0/29) (0/29) -U+08a0 Arabic Extended-A (0/47) (0/47) (0/47) +U+08a0 Arabic Extended-A (0/73) (0/73) (0/73) U+0900 Devanagari (0/128) (0/128) (0/128) U+0980 Bengali (0/93) (0/93) (0/93) U+0a00 Gurmukhi (0/79) (0/79) (0/79) -U+0a80 Gujarati (0/84) (0/84) (0/84) +U+0a80 Gujarati (0/85) (0/85) (0/85) U+0b00 Oriya (0/90) (0/90) (0/90) U+0b80 Tamil (0/72) (0/72) (0/72) -U+0c00 Telugu (0/95) (0/95) (0/95) -U+0c80 Kannada (0/87) (0/87) (0/87) -U+0d00 Malayalam (0/99) (0/99) (0/99) +U+0c00 Telugu (0/96) (0/96) (0/96) +U+0c80 Kannada (0/88) (0/88) (0/88) +U+0d00 Malayalam (0/114) (0/114) (0/114) U+0d80 Sinhala (0/90) (0/90) (0/90) U+0e00 Thai 1% (1/87) 1% (1/87) 1% (1/87) U+0e80 Lao 97% (65/67) (0/67) 68% (46/67) @@ -42,7 +42,7 @@ U+10a0 Georgian 94% (83/88) 94% (83/88) U+1100 Hangul Jamo (0/256) (0/256) (0/256) U+1200 Ethiopic (0/358) (0/358) (0/358) U+1380 Ethiopic Supplement (0/26) (0/26) (0/26) -U+13a0 Cherokee (0/85) (0/85) (0/85) +U+13a0 Cherokee (0/92) (0/92) (0/92) U+1400 Unified Canadian Aboriginal Syllabics 63% (404/640) (0/640) (0/640) U+1680 Ogham 100% (29/29) (0/29) (0/29) U+16a0 Runic (0/89) (0/89) (0/89) @@ -65,22 +65,23 @@ U+1b80 Sundanese (0/64) (0/64) U+1bc0 Batak (0/56) (0/56) (0/56) U+1c00 Lepcha (0/74) (0/74) (0/74) U+1c50 Ol Chiki (0/48) (0/48) (0/48) +U+1c80 Cyrillic Extended-C (0/9) (0/9) (0/9) U+1cc0 Sundanese Supplement (0/8) (0/8) (0/8) U+1cd0 Vedic Extensions (0/41) (0/41) (0/41) U+1d00 Phonetic Extensions 82% (106/128) 89% (115/128) 48% (62/128) U+1d80 Phonetic Extensions Supplement 59% (38/64) 59% (38/64) 57% (37/64) -U+1dc0 Combining Diacritical Marks Supplement 10% (6/58) 10% (6/58) (0/58) +U+1dc0 Combining Diacritical Marks Supplement 10% (6/59) 10% (6/59) (0/59) U+1e00 Latin Extended Additional 98% (252/256) 98% (252/256) 71% (182/256) U+1f00 Greek Extended 100% (233/233) 100% (233/233) 100% (233/233) U+2000 General Punctuation 96% (107/111) 78% (87/111) 48% (54/111) U+2070 Superscripts and Subscripts 100% (42/42) 100% (42/42) 100% (42/42) -U+20a0 Currency Symbols 86% (26/30) 33% (10/30) 80% (24/30) +U+20a0 Currency Symbols 83% (26/31) 32% (10/31) 83% (26/31) U+20d0 Combining Diacritical Marks for Symbols 21% (7/33) (0/33) (0/33) U+2100 Letterlike Symbols 93% (75/80) 42% (34/80) 22% (18/80) -U+2150 Number Forms 94% (55/58) 94% (55/58) 27% (16/58) +U+2150 Number Forms 91% (55/60) 91% (55/60) 26% (16/60) U+2190 Arrows 100% (112/112) 100% (112/112) 100% (112/112) U+2200 Mathematical Operators 100% (256/256) 39% (101/256) 69% (178/256) -U+2300 Miscellaneous Technical 25% (65/251) 14% (36/251) 54% (136/251) +U+2300 Miscellaneous Technical 25% (65/255) 14% (36/255) 53% (136/255) U+2400 Control Pictures 5% (2/39) 2% (1/39) 2% (1/39) U+2440 Optical Character Recognition (0/11) (0/11) (0/11) U+2460 Enclosed Alphanumerics 6% (10/160) (0/160) (0/160) @@ -95,7 +96,7 @@ U+2800 Braille Patterns 100% (256/256) 100% (256/256 U+2900 Supplemental Arrows-B 4% (6/128) 100% (128/128) (0/128) U+2980 Miscellaneous Mathematical Symbols-B 10% (13/128) 0% (1/128) 5% (7/128) U+2a00 Supplemental Mathematical Operators 28% (74/256) 2% (6/256) 1% (4/256) -U+2b00 Miscellaneous Symbols and Arrows 17% (35/202) 13% (27/202) 8% (18/202) +U+2b00 Miscellaneous Symbols and Arrows 16% (35/206) 13% (27/206) 8% (18/206) U+2c00 Glagolitic (0/94) (0/94) (0/94) U+2c60 Latin Extended-C 96% (31/32) 84% (27/32) 43% (14/32) U+2c80 Coptic (0/123) (0/123) (0/123) @@ -103,7 +104,7 @@ U+2d00 Georgian Supplement 95% (38/40) 95% (38/40) U+2d30 Tifinagh 93% (55/59) (0/59) (0/59) U+2d80 Ethiopic Extended (0/79) (0/79) (0/79) U+2de0 Cyrillic Extended-A (0/32) (0/32) (0/32) -U+2e00 Supplemental Punctuation 10% (7/67) 10% (7/67) 10% (7/67) +U+2e00 Supplemental Punctuation 10% (7/69) 10% (7/69) 10% (7/69) U+2e80 CJK Radicals Supplement (0/115) (0/115) (0/115) U+2f00 Kangxi Radicals (0/214) (0/214) (0/214) U+2ff0 Ideographic Description Characters (0/12) (0/12) (0/12) @@ -125,15 +126,15 @@ U+a000 Yi Syllables (0/1165) (0/1165) U+a490 Yi Radicals (0/55) (0/55) (0/55) U+a4d0 Lisu 100% (48/48) (0/48) (0/48) U+a500 Vai (0/300) (0/300) (0/300) -U+a640 Cyrillic Extended-B 32% (31/95) 10% (10/95) (0/95) +U+a640 Cyrillic Extended-B 34% (33/96) 12% (12/96) (0/96) U+a6a0 Bamum (0/88) (0/88) (0/88) U+a700 Modifier Tone Letters 62% (20/32) 62% (20/32) 62% (20/32) -U+a720 Latin Extended-D 50% (77/152) 39% (60/152) 11% (17/152) +U+a720 Latin Extended-D 48% (77/160) 37% (60/160) 10% (17/160) U+a800 Syloti Nagri (0/44) (0/44) (0/44) U+a830 Common Indic Number Forms (0/10) (0/10) (0/10) U+a840 Phags-pa (0/56) (0/56) (0/56) -U+a880 Saurashtra (0/81) (0/81) (0/81) -U+a8e0 Devanagari Extended (0/28) (0/28) (0/28) +U+a880 Saurashtra (0/82) (0/82) (0/82) +U+a8e0 Devanagari Extended (0/30) (0/30) (0/30) U+a900 Kayah Li (0/48) (0/48) (0/48) U+a930 Rejang (0/37) (0/37) (0/37) U+a960 Hangul Jamo Extended-A (0/29) (0/29) (0/29) @@ -144,7 +145,8 @@ U+aa60 Myanmar Extended-A (0/32) (0/32) U+aa80 Tai Viet (0/72) (0/72) (0/72) U+aae0 Meetei Mayek Extensions (0/23) (0/23) (0/23) U+ab00 Ethiopic Extended-A (0/32) (0/32) (0/32) -U+ab30 Latin Extended-E (0/50) (0/50) (0/50) +U+ab30 Latin Extended-E (0/54) (0/54) (0/54) +U+ab70 Cherokee Supplement (0/80) (0/80) (0/80) U+abc0 Meetei Mayek (0/56) (0/56) (0/56) U+ac00 Hangul Syllables (0/0) (0/0) (0/0) U+d7b0 Hangul Jamo Extended-B (0/72) (0/72) (0/72) @@ -157,7 +159,7 @@ U+fb00 Alphabetic Presentation Forms 100% (58/58) 12% (7/58) U+fb50 Arabic Presentation Forms-A 17% (108/611) (0/611) 11% (72/611) U+fe00 Variation Selectors 100% (16/16) 100% (16/16) (0/16) U+fe10 Vertical Forms (0/10) (0/10) (0/10) -U+fe20 Combining Half Marks 28% (4/14) (0/14) (0/14) +U+fe20 Combining Half Marks 25% (4/16) (0/16) (0/16) U+fe30 CJK Compatibility Forms (0/32) (0/32) (0/32) U+fe50 Small Form Variants (0/26) (0/26) (0/26) U+fe70 Arabic Presentation Forms-B 100% (141/141) (0/141) 100% (141/141) @@ -166,7 +168,7 @@ U+fff0 Specials 100% (5/5) 100% (5/5) U+10000 Linear B Syllabary (0/88) (0/88) (0/88) U+10080 Linear B Ideograms (0/123) (0/123) (0/123) U+10100 Aegean Numbers (0/57) (0/57) (0/57) -U+10140 Ancient Greek Numbers (0/77) (0/77) (0/77) +U+10140 Ancient Greek Numbers (0/79) (0/79) (0/79) U+10190 Ancient Symbols (0/13) (0/13) (0/13) U+101d0 Phaistos Disc (0/46) (0/46) (0/46) U+10280 Lycian (0/29) (0/29) (0/29) @@ -180,6 +182,7 @@ U+103a0 Old Persian (0/50) (0/50) U+10400 Deseret (0/80) (0/80) (0/80) U+10450 Shavian (0/48) (0/48) (0/48) U+10480 Osmanya (0/40) (0/40) (0/40) +U+104b0 Osage (0/72) (0/72) (0/72) U+10500 Elbasan (0/40) (0/40) (0/40) U+10530 Caucasian Albanian (0/53) (0/53) (0/53) U+10600 Linear A (0/341) (0/341) (0/341) @@ -187,10 +190,11 @@ U+10800 Cypriot Syllabary (0/55) (0/55) U+10840 Imperial Aramaic (0/31) (0/31) (0/31) U+10860 Palmyrene (0/32) (0/32) (0/32) U+10880 Nabataean (0/40) (0/40) (0/40) +U+108e0 Hatran (0/26) (0/26) (0/26) U+10900 Phoenician (0/29) (0/29) (0/29) U+10920 Lydian (0/27) (0/27) (0/27) U+10980 Meroitic Hieroglyphs (0/32) (0/32) (0/32) -U+109a0 Meroitic Cursive (0/26) (0/26) (0/26) +U+109a0 Meroitic Cursive (0/90) (0/90) (0/90) U+10a00 Kharoshthi (0/65) (0/65) (0/65) U+10a60 Old South Arabian (0/32) (0/32) (0/32) U+10a80 Old North Arabian (0/32) (0/32) (0/32) @@ -200,57 +204,74 @@ U+10b40 Inscriptional Parthian (0/30) (0/30) U+10b60 Inscriptional Pahlavi (0/27) (0/27) (0/27) U+10b80 Psalter Pahlavi (0/29) (0/29) (0/29) U+10c00 Old Turkic (0/73) (0/73) (0/73) +U+10c80 Old Hungarian (0/108) (0/108) (0/108) U+10e60 Rumi Numeral Symbols (0/31) (0/31) (0/31) U+11000 Brahmi (0/109) (0/109) (0/109) U+11080 Kaithi (0/66) (0/66) (0/66) U+110d0 Sora Sompeng (0/35) (0/35) (0/35) U+11100 Chakma (0/67) (0/67) (0/67) U+11150 Mahajani (0/39) (0/39) (0/39) -U+11180 Sharada (0/85) (0/85) (0/85) +U+11180 Sharada (0/94) (0/94) (0/94) U+111e0 Sinhala Archaic Numbers (0/20) (0/20) (0/20) -U+11200 Khojki (0/61) (0/61) (0/61) +U+11200 Khojki (0/62) (0/62) (0/62) +U+11280 Multani (0/38) (0/38) (0/38) U+112b0 Khudawadi (0/69) (0/69) (0/69) -U+11300 Grantha (0/83) (0/83) (0/83) +U+11300 Grantha (0/85) (0/85) (0/85) +U+11400 Newa (0/92) (0/92) (0/92) U+11480 Tirhuta (0/82) (0/82) (0/82) -U+11580 Siddham (0/72) (0/72) (0/72) +U+11580 Siddham (0/92) (0/92) (0/92) U+11600 Modi (0/79) (0/79) (0/79) +U+11660 Mongolian Supplement (0/13) (0/13) (0/13) U+11680 Takri (0/66) (0/66) (0/66) +U+11700 Ahom (0/57) (0/57) (0/57) U+118a0 Warang Citi (0/84) (0/84) (0/84) U+11ac0 Pau Cin Hau (0/57) (0/57) (0/57) -U+12000 Cuneiform (0/921) (0/921) (0/921) +U+11c00 Bhaiksuki (0/97) (0/97) (0/97) +U+11c70 Marchen (0/68) (0/68) (0/68) +U+12000 Cuneiform (0/922) (0/922) (0/922) U+12400 Cuneiform Numbers and Punctuation (0/116) (0/116) (0/116) +U+12480 Early Dynastic Cuneiform (0/196) (0/196) (0/196) U+13000 Egyptian Hieroglyphs (0/1071) (0/1071) (0/1071) +U+14400 Anatolian Hieroglyphs (0/583) (0/583) (0/583) U+16800 Bamum Supplement (0/569) (0/569) (0/569) U+16a40 Mro (0/43) (0/43) (0/43) U+16ad0 Bassa Vah (0/36) (0/36) (0/36) U+16b00 Pahawh Hmong (0/127) (0/127) (0/127) U+16f00 Miao (0/133) (0/133) (0/133) +U+16fe0 Ideographic Symbols and Punctuation (0/1) (0/1) (0/1) +U+17000 Tangut (0/0) (0/0) (0/0) +U+18800 Tangut Components (0/755) (0/755) (0/755) U+1b000 Kana Supplement (0/2) (0/2) (0/2) U+1bc00 Duployan (0/143) (0/143) (0/143) U+1bca0 Shorthand Format Controls (0/4) (0/4) (0/4) U+1d000 Byzantine Musical Symbols (0/246) (0/246) (0/246) -U+1d100 Musical Symbols (0/220) (0/220) (0/220) +U+1d100 Musical Symbols (0/231) (0/231) (0/231) U+1d200 Ancient Greek Musical Notation (0/70) (0/70) (0/70) U+1d300 Tai Xuan Jing Symbols 100% (87/87) (0/87) (0/87) U+1d360 Counting Rod Numerals (0/18) (0/18) (0/18) U+1d400 Mathematical Alphanumeric Symbols 11% (117/996) 10% (108/996) 6% (63/996) +U+1d800 Sutton SignWriting (0/672) (0/672) (0/672) +U+1e000 Glagolitic Supplement (0/38) (0/38) (0/38) U+1e800 Mende Kikakui (0/213) (0/213) (0/213) +U+1e900 Adlam (0/87) (0/87) (0/87) U+1ee00 Arabic Mathematical Alphabetic Symbols 51% (74/143) (0/143) (0/143) U+1f000 Mahjong Tiles (0/44) (0/44) (0/44) U+1f030 Domino Tiles 100% (100/100) (0/100) (0/100) U+1f0a0 Playing Cards 71% (59/82) (0/82) (0/82) -U+1f100 Enclosed Alphanumeric Supplement (0/173) (0/173) (0/173) -U+1f200 Enclosed Ideographic Supplement (0/57) (0/57) (0/57) -U+1f300 Miscellaneous Symbols and Pictographs 0% (4/742) (0/742) (0/742) -U+1f600 Emoticons 80% (63/78) (0/78) (0/78) +U+1f100 Enclosed Alphanumeric Supplement (0/191) (0/191) (0/191) +U+1f200 Enclosed Ideographic Supplement (0/58) (0/58) (0/58) +U+1f300 Miscellaneous Symbols and Pictographs 1% (12/768) (0/768) (0/768) +U+1f600 Emoticons 80% (64/80) (0/80) (0/80) U+1f650 Ornamental Dingbats (0/48) (0/48) (0/48) -U+1f680 Transport and Map Symbols (0/97) (0/97) (0/97) +U+1f680 Transport and Map Symbols (0/103) (0/103) (0/103) U+1f700 Alchemical Symbols (0/116) (0/116) (0/116) U+1f780 Geometric Shapes Extended (0/85) (0/85) (0/85) U+1f800 Supplemental Arrows-C (0/148) (0/148) (0/148) +U+1f900 Supplemental Symbols and Pictographs (0/82) (0/82) (0/82) U+20000 CJK Unified Ideographs Extension B (0/0) (0/0) (0/0) U+2a700 CJK Unified Ideographs Extension C (0/0) (0/0) (0/0) U+2b740 CJK Unified Ideographs Extension D (0/0) (0/0) (0/0) +U+2b820 CJK Unified Ideographs Extension E (0/0) (0/0) (0/0) U+2f800 CJK Compatibility Ideographs Supplement (0/542) (0/542) (0/542) U+e0000 Tags (0/98) (0/98) (0/98) U+e0100 Variation Selectors Supplement (0/240) (0/240) (0/240) diff --git a/fonts/unifont-8.0.01.ttf b/fonts/unifont-9.0.01.ttf similarity index 96% rename from fonts/unifont-8.0.01.ttf rename to fonts/unifont-9.0.01.ttf index ec875c5a9..650b2d8c2 100644 Binary files a/fonts/unifont-8.0.01.ttf and b/fonts/unifont-9.0.01.ttf differ diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp index 139405cd9..ff87ce0ef 100644 --- a/include/mapnik/agg_helpers.hpp +++ b/include/mapnik/agg_helpers.hpp @@ -26,8 +26,10 @@ // mapnik #include -// agg +#pragma GCC diagnostic push +#include #include "agg_gamma_functions.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/agg_pattern_source.hpp b/include/mapnik/agg_pattern_source.hpp index a0000204f..42dd7f36f 100644 --- a/include/mapnik/agg_pattern_source.hpp +++ b/include/mapnik/agg_pattern_source.hpp @@ -27,8 +27,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_color_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/agg_rasterizer.hpp b/include/mapnik/agg_rasterizer.hpp index 51cf4cd5d..66da59fd6 100644 --- a/include/mapnik/agg_rasterizer.hpp +++ b/include/mapnik/agg_rasterizer.hpp @@ -26,8 +26,11 @@ // mapnik #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/agg_render_marker.hpp b/include/mapnik/agg_render_marker.hpp index 65e531cfd..283807a93 100644 --- a/include/mapnik/agg_render_marker.hpp +++ b/include/mapnik/agg_render_marker.hpp @@ -30,7 +30,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_color_rgba.h" #include "agg_renderer_base.h" #include "agg_renderer_scanline.h" @@ -43,6 +44,7 @@ #include "agg_pixfmt_rgba.h" #include "agg_span_image_filter_rgba.h" #include "agg_span_interpolator_linear.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/attribute.hpp b/include/mapnik/attribute.hpp index b0cf6839a..edfaebefc 100644 --- a/include/mapnik/attribute.hpp +++ b/include/mapnik/attribute.hpp @@ -36,8 +36,8 @@ namespace mapnik { struct attribute { std::string name_; - explicit attribute(std::string const& name) - : name_(name) {} + explicit attribute(std::string const& _name) + : name_(_name) {} template V const& value(F const& f) const diff --git a/include/mapnik/box2d.hpp b/include/mapnik/box2d.hpp index 4471c281c..267120111 100644 --- a/include/mapnik/box2d.hpp +++ b/include/mapnik/box2d.hpp @@ -27,8 +27,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // agg // forward declare so that apps using mapnik do not need agg headers @@ -38,9 +40,8 @@ struct trans_affine; namespace mapnik { -/*! - * A spatial envelope (i.e. bounding box) which also defines some basic operators. - */ +// A spatial envelope (i.e. bounding box) which also defines some basic operators. + template class MAPNIK_DECL box2d : boost::equality_comparable , boost::addable, @@ -48,7 +49,8 @@ template class MAPNIK_DECL box2d boost::multipliable2, T > > > > { public: - using box2d_type = box2d; + using value_type = T; + using box2d_type = box2d; private: T minx_; T miny_; @@ -63,12 +65,22 @@ private: swap(lhs.maxy_, rhs.maxy_); } public: + box2d(); box2d(T minx,T miny,T maxx,T maxy); box2d(coord const& c0, coord const& c1); box2d(box2d_type const& rhs); box2d(box2d_type const& rhs, agg::trans_affine const& tr); + // move box2d(box2d_type&& rhs); + // converting ctor + template + explicit box2d(box2d other) + : minx_(static_cast(other.minx())), + miny_(static_cast(other.miny())), + maxx_(static_cast(other.maxx())), + maxy_(static_cast(other.maxy())) + {} box2d_type& operator=(box2d_type other); T minx() const; T miny() const; @@ -97,6 +109,7 @@ public: void re_center(T cx,T cy); void re_center(coord const& c); void init(T x0,T y0,T x1,T y1); + void init(T x, T y); void clip(box2d_type const& other); void pad(T padding); bool from_string(std::string const& str); diff --git a/include/mapnik/box2d_impl.hpp b/include/mapnik/box2d_impl.hpp new file mode 100644 index 000000000..7f3e9d1e7 --- /dev/null +++ b/include/mapnik/box2d_impl.hpp @@ -0,0 +1,496 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include + +// stl +#include +#include +#include + +#include + +#pragma GCC diagnostic push +#include +#include +#include +#include +#pragma GCC diagnostic pop + +// agg +#include "agg_trans_affine.h" + +BOOST_FUSION_ADAPT_TPL_ADT( + (T), + (mapnik::box2d)(T), + (T, T, obj.minx(), obj.set_minx(mapnik::safe_cast(val))) + (T, T, obj.miny(), obj.set_miny(mapnik::safe_cast(val))) + (T, T, obj.maxx(), obj.set_maxx(mapnik::safe_cast(val))) + (T, T, obj.maxy(), obj.set_maxy(mapnik::safe_cast(val)))) + +namespace mapnik +{ +template +box2d::box2d() + :minx_( std::numeric_limits::max()), + miny_( std::numeric_limits::max()), + maxx_(-std::numeric_limits::max()), + maxy_(-std::numeric_limits::max()) {} + +template +box2d::box2d(T minx,T miny,T maxx,T maxy) +{ + init(minx,miny,maxx,maxy); +} + +template +box2d::box2d(coord const& c0, coord const& c1) +{ + init(c0.x,c0.y,c1.x,c1.y); +} + +template +box2d::box2d(box2d_type const& rhs) + : minx_(rhs.minx_), + miny_(rhs.miny_), + maxx_(rhs.maxx_), + maxy_(rhs.maxy_) {} + +template +box2d::box2d(box2d_type && rhs) + : minx_(std::move(rhs.minx_)), + miny_(std::move(rhs.miny_)), + maxx_(std::move(rhs.maxx_)), + maxy_(std::move(rhs.maxy_)) {} + +template +box2d& box2d::operator=(box2d_type other) +{ + swap(*this, other); + return *this; +} + +template +box2d::box2d(box2d_type const& rhs, agg::trans_affine const& tr) +{ + double x0 = rhs.minx_, y0 = rhs.miny_; + double x1 = rhs.maxx_, y1 = rhs.miny_; + double x2 = rhs.maxx_, y2 = rhs.maxy_; + double x3 = rhs.minx_, y3 = rhs.maxy_; + tr.transform(&x0, &y0); + tr.transform(&x1, &y1); + tr.transform(&x2, &y2); + tr.transform(&x3, &y3); + init(static_cast(x0), static_cast(y0), + static_cast(x2), static_cast(y2)); + expand_to_include(static_cast(x1), static_cast(y1)); + expand_to_include(static_cast(x3), static_cast(y3)); +} + +template +bool box2d::operator==(box2d const& other) const +{ + return minx_==other.minx_ && + miny_==other.miny_ && + maxx_==other.maxx_ && + maxy_==other.maxy_; +} + +template +T box2d::minx() const +{ + return minx_; +} + +template +T box2d::maxx() const +{ + return maxx_; +} + +template +T box2d::miny() const +{ + return miny_; +} + +template +T box2d::maxy() const +{ + return maxy_; +} + +template +void box2d::set_minx(T v) +{ + minx_ = v; +} + +template +void box2d::set_miny(T v) +{ + miny_ = v; +} + +template +void box2d::set_maxx(T v) +{ + maxx_ = v; +} + +template +void box2d::set_maxy(T v) +{ + maxy_ = v; +} + +template +T box2d::width() const +{ + return maxx_-minx_; +} + +template +T box2d::height() const +{ + return maxy_-miny_; +} + +template +void box2d::width(T w) +{ + T cx=center().x; + minx_=static_cast(cx-w*0.5); + maxx_=static_cast(cx+w*0.5); +} + +template +void box2d::height(T h) +{ + T cy=center().y; + miny_=static_cast(cy-h*0.5); + maxy_=static_cast(cy+h*0.5); +} + +template +coord box2d::center() const +{ + return coord(static_cast(0.5*(minx_+maxx_)), + static_cast(0.5*(miny_+maxy_))); +} + +template +void box2d::expand_to_include(coord const& c) +{ + expand_to_include(c.x,c.y); +} + +template +void box2d::expand_to_include(T x,T y) +{ + if (xmaxx_) maxx_=x; + if (ymaxy_) maxy_=y; +} + +template +void box2d::expand_to_include(box2d const& other) +{ + if (other.minx_maxx_) maxx_=other.maxx_; + if (other.miny_maxy_) maxy_=other.maxy_; +} + +template +bool box2d::contains(coord const& c) const +{ + return contains(c.x,c.y); +} + +template +bool box2d::contains(T x,T y) const +{ + return x>=minx_ && x<=maxx_ && y>=miny_ && y<=maxy_; +} + +template +bool box2d::contains(box2d const& other) const +{ + return other.minx_>=minx_ && + other.maxx_<=maxx_ && + other.miny_>=miny_ && + other.maxy_<=maxy_; +} + +template +bool box2d::intersects(coord const& c) const +{ + return intersects(c.x,c.y); +} + +template +bool box2d::intersects(T x,T y) const +{ + return !(x>maxx_ || xmaxy_ || y +bool box2d::intersects(box2d const& other) const +{ + return !(other.minx_>maxx_ || other.maxx_maxy_ || other.maxy_ +box2d box2d::intersect(box2d_type const& other) const +{ + if (intersects(other)) + { + T x0=std::max(minx_,other.minx_); + T y0=std::max(miny_,other.miny_); + T x1=std::min(maxx_,other.maxx_); + T y1=std::min(maxy_,other.maxy_); + return box2d(x0,y0,x1,y1); + } + else + { + return box2d(); + } +} + +template +void box2d::re_center(T cx,T cy) +{ + T dx=cx-center().x; + T dy=cy-center().y; + minx_+=dx; + miny_+=dy; + maxx_+=dx; + maxy_+=dy; +} + +template +void box2d::re_center(coord const& c) +{ + re_center(c.x,c.y); +} + +template +void box2d::init(T x0, T y0, T x1, T y1) +{ + if (x0 < x1) + { + minx_ = x0; + maxx_ = x1; + } + else + { + minx_ = x1; + maxx_ = x0; + } + if (y0 < y1) + { + miny_ = y0; + maxy_ = y1; + } + else + { + miny_ = y1; + maxy_ = y0; + } +} + +template +void box2d::init(T x, T y) +{ + init(x, y, x, y); +} + +template +void box2d::clip(box2d_type const& other) +{ + minx_ = std::max(minx_, other.minx()); + miny_ = std::max(miny_, other.miny()); + maxx_ = std::min(maxx_, other.maxx()); + maxy_ = std::min(maxy_, other.maxy()); +} + +template +void box2d::pad(T padding) +{ + minx_ -= padding; + miny_ -= padding; + maxx_ += padding; + maxy_ += padding; +} + +template +bool box2d::from_string(std::string const& str) +{ + boost::spirit::qi::lit_type lit; + boost::spirit::qi::double_type double_; + boost::spirit::ascii::space_type space; + bool r = boost::spirit::qi::phrase_parse(str.begin(), + str.end(), + double_ >> -lit(',') >> double_ >> -lit(',') >> double_ >> -lit(',') >> double_, + space, + *this); + return r; +} + +template +bool box2d::valid() const +{ + return (minx_ <= maxx_ && miny_ <= maxy_) ; +} + +template +void box2d::move(T x, T y) +{ + minx_ += x; + maxx_ += x; + miny_ += y; + maxy_ += y; +} + +template +std::string box2d::to_string() const +{ + std::ostringstream s; + if (valid()) + { + s << "box2d(" << std::fixed << std::setprecision(16) + << minx_ << ',' << miny_ << ',' + << maxx_ << ',' << maxy_ << ')'; + } + else + { + s << "box2d(INVALID)"; + } + return s.str(); +} + + +template +box2d& box2d::operator+=(box2d const& other) +{ + expand_to_include(other); + return *this; +} + +template +box2d box2d::operator+ (T other) const +{ + return box2d(minx_ - other, miny_ - other, maxx_ + other, maxy_ + other); +} + +template +box2d& box2d::operator+= (T other) +{ + minx_ -= other; + miny_ -= other; + maxx_ += other; + maxy_ += other; + return *this; +} + + +template +box2d& box2d::operator*=(T t) +{ + coord c = center(); + T sx = static_cast(0.5 * width() * t); + T sy = static_cast(0.5 * height() * t); + minx_ = c.x - sx; + maxx_ = c.x + sx; + miny_ = c.y - sy; + maxy_ = c.y + sy; + return *this; +} + +template +box2d& box2d::operator/=(T t) +{ + coord c = center(); + T sx = static_cast(0.5 * width() / t); + T sy = static_cast(0.5 * height() / t); + minx_ = c.x - sx; + maxx_ = c.x + sx; + miny_ = c.y - sy; + maxy_ = c.y + sy; + return *this; +} + +template +T box2d::operator[] (int index) const +{ + switch(index) + { + case 0: + return minx_; + case 1: + return miny_; + case 2: + return maxx_; + case 3: + return maxy_; + case -4: + return minx_; + case -3: + return miny_; + case -2: + return maxx_; + case -1: + return maxy_; + default: + throw std::out_of_range("index out of range, max value is 3, min value is -4 "); + } +} + +template +box2d box2d::operator*(agg::trans_affine const& tr) const +{ + return box2d(*this, tr); +} + +template +box2d& box2d::operator*=(agg::trans_affine const& tr) +{ + double x0 = minx_, y0 = miny_; + double x1 = maxx_, y1 = miny_; + double x2 = maxx_, y2 = maxy_; + double x3 = minx_, y3 = maxy_; + tr.transform(&x0, &y0); + tr.transform(&x1, &y1); + tr.transform(&x2, &y2); + tr.transform(&x3, &y3); + init(static_cast(x0), static_cast(y0), + static_cast(x2), static_cast(y2)); + expand_to_include(static_cast(x1), static_cast(y1)); + expand_to_include(static_cast(x3), static_cast(y3)); + return *this; +} +} diff --git a/include/mapnik/cairo/cairo_context.hpp b/include/mapnik/cairo/cairo_context.hpp index 3f065db36..c15f87cd7 100644 --- a/include/mapnik/cairo/cairo_context.hpp +++ b/include/mapnik/cairo/cairo_context.hpp @@ -38,18 +38,20 @@ #include #include +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + // stl #include - -// cairo -#include - -// stl #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -306,6 +308,7 @@ public: void stroke(); void fill(); void paint(); + void paint(double opacity); void set_pattern(cairo_pattern const& pattern); void set_gradient(cairo_gradient const& pattern, box2d const& bbox); void add_image(double x, double y, image_rgba8 const& data, double opacity = 1.0); @@ -325,6 +328,9 @@ public: composite_mode_e halo_comp_op = src_over, double scale_factor = 1.0); + void push_group(); + void pop_group(); + template void add_path(T& path, unsigned start_index = 0) { diff --git a/include/mapnik/cairo/cairo_renderer.hpp b/include/mapnik/cairo/cairo_renderer.hpp index a39b4ed9e..0563149a6 100644 --- a/include/mapnik/cairo/cairo_renderer.hpp +++ b/include/mapnik/cairo/cairo_renderer.hpp @@ -177,6 +177,7 @@ protected: cairo_context context_; renderer_common common_; cairo_face_manager face_manager_; + bool style_level_compositing_; void setup(Map const& m); }; diff --git a/include/mapnik/color.hpp b/include/mapnik/color.hpp index b22a9989d..434a9cf21 100644 --- a/include/mapnik/color.hpp +++ b/include/mapnik/color.hpp @@ -27,8 +27,10 @@ #include #include -//boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include @@ -55,19 +57,19 @@ public: premultiplied_(false) {} - color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha = 0xff, bool premultiplied = false) - : red_(red), - green_(green), - blue_(blue), - alpha_(alpha), + color(std::uint8_t _red, std::uint8_t _green, std::uint8_t _blue, std::uint8_t _alpha = 0xff, bool premultiplied = false) + : red_(_red), + green_(_green), + blue_(_blue), + alpha_(_alpha), premultiplied_(premultiplied) {} - color(std::uint32_t rgba, bool premultiplied = false) - : red_(rgba & 0xff), - green_((rgba >> 8) & 0xff), - blue_((rgba >> 16) & 0xff), - alpha_((rgba >> 24) & 0xff), + color(std::uint32_t _rgba, bool premultiplied = false) + : red_(_rgba & 0xff), + green_((_rgba >> 8) & 0xff), + blue_((_rgba >> 16) & 0xff), + alpha_((_rgba >> 24) & 0xff), premultiplied_(premultiplied) {} // copy ctor @@ -128,23 +130,23 @@ public: return alpha_; } - inline void set_red(std::uint8_t red) + inline void set_red(std::uint8_t _red) { - red_ = red; + red_ = _red; } - inline void set_green(std::uint8_t green) + inline void set_green(std::uint8_t _green) { - green_ = green; + green_ = _green; } - inline void set_blue(std::uint8_t blue) + inline void set_blue(std::uint8_t _blue) { - blue_ = blue; + blue_ = _blue; } - inline void set_alpha(std::uint8_t alpha) + inline void set_alpha(std::uint8_t _alpha) { - alpha_ = alpha; + alpha_ = _alpha; } inline bool get_premultiplied() const { @@ -173,8 +175,7 @@ template std::basic_ostream & operator << ( std::basic_ostream & s, mapnik::color const& c ) { - std::string hex_string( c.to_string() ); - s << hex_string; + s << c.to_string(); return s; } diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp index 6461a6c08..a05caf9d4 100644 --- a/include/mapnik/config.hpp +++ b/include/mapnik/config.hpp @@ -53,6 +53,17 @@ #define PROJ_ENVELOPE_POINTS 20 #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#define BOOST_MPL_LIMIT_VECTOR_SIZE 30 + +#ifndef BOOST_MPL_LIMIT_VECTOR_SIZE + #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 +#else + #warning "WARNING: BOOST_MPL_LIMIT_VECTOR_SIZE is already defined. Ensure config.hpp is included before any Boost headers" +#endif + +#ifndef BOOST_MPL_LIMIT_LIST_SIZE + #define BOOST_MPL_LIMIT_LIST_SIZE 30 +#else + #warning "WARNING: BOOST_MPL_LIMIT_LIST_SIZE is already defined. Ensure config.hpp is included before any Boost headers" +#endif #endif // MAPNIK_CONFIG_HPP diff --git a/include/mapnik/coord.hpp b/include/mapnik/coord.hpp index fcdfa9090..f8ea3f161 100644 --- a/include/mapnik/coord.hpp +++ b/include/mapnik/coord.hpp @@ -23,8 +23,10 @@ #ifndef MAPNIK_COORD_HPP #define MAPNIK_COORD_HPP -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { template diff --git a/include/mapnik/css_color_grammar.hpp b/include/mapnik/css_color_grammar.hpp index 21e639179..8fbdeaa6f 100644 --- a/include/mapnik/css_color_grammar.hpp +++ b/include/mapnik/css_color_grammar.hpp @@ -32,261 +32,25 @@ #pragma GCC diagnostic push #include #include -#include -#include -#include -#include -#include -#include -#include #pragma GCC diagnostic pop // stl #include -BOOST_FUSION_ADAPT_ADT( - mapnik::color, - (unsigned, unsigned, obj.red(), obj.set_red(mapnik::safe_cast(val))) - (unsigned, unsigned, obj.green(), obj.set_green(mapnik::safe_cast(val))) - (unsigned, unsigned, obj.blue(), obj.set_blue(mapnik::safe_cast(val))) - (unsigned, unsigned, obj.alpha(), obj.set_alpha(mapnik::safe_cast(val))) - ) - namespace mapnik { namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; -namespace phoenix = boost::phoenix; using ascii_space_type = boost::spirit::ascii::space_type; -struct named_colors_ : qi::symbols -{ - named_colors_() - { - add - ("aliceblue", color(240, 248, 255)) - ("antiquewhite", color(250, 235, 215)) - ("aqua", color(0, 255, 255)) - ("aquamarine", color(127, 255, 212)) - ("azure", color(240, 255, 255)) - ("beige", color(245, 245, 220)) - ("bisque", color(255, 228, 196)) - ("black", color(0, 0, 0)) - ("blanchedalmond", color(255,235,205)) - ("blue", color(0, 0, 255)) - ("blueviolet", color(138, 43, 226)) - ("brown", color(165, 42, 42)) - ("burlywood", color(222, 184, 135)) - ("cadetblue", color(95, 158, 160)) - ("chartreuse", color(127, 255, 0)) - ("chocolate", color(210, 105, 30)) - ("coral", color(255, 127, 80)) - ("cornflowerblue", color(100, 149, 237)) - ("cornsilk", color(255, 248, 220)) - ("crimson", color(220, 20, 60)) - ("cyan", color(0, 255, 255)) - ("darkblue", color(0, 0, 139)) - ("darkcyan", color(0, 139, 139)) - ("darkgoldenrod", color(184, 134, 11)) - ("darkgray", color(169, 169, 169)) - ("darkgreen", color(0, 100, 0)) - ("darkgrey", color(169, 169, 169)) - ("darkkhaki", color(189, 183, 107)) - ("darkmagenta", color(139, 0, 139)) - ("darkolivegreen", color(85, 107, 47)) - ("darkorange", color(255, 140, 0)) - ("darkorchid", color(153, 50, 204)) - ("darkred", color(139, 0, 0)) - ("darksalmon", color(233, 150, 122)) - ("darkseagreen", color(143, 188, 143)) - ("darkslateblue", color(72, 61, 139)) - ("darkslategrey", color(47, 79, 79)) - ("darkturquoise", color(0, 206, 209)) - ("darkviolet", color(148, 0, 211)) - ("deeppink", color(255, 20, 147)) - ("deepskyblue", color(0, 191, 255)) - ("dimgray", color(105, 105, 105)) - ("dimgrey", color(105, 105, 105)) - ("dodgerblue", color(30, 144, 255)) - ("firebrick", color(178, 34, 34)) - ("floralwhite", color(255, 250, 240)) - ("forestgreen", color(34, 139, 34)) - ("fuchsia", color(255, 0, 255)) - ("gainsboro", color(220, 220, 220)) - ("ghostwhite", color(248, 248, 255)) - ("gold", color(255, 215, 0)) - ("goldenrod", color(218, 165, 32)) - ("gray", color(128, 128, 128)) - ("grey", color(128, 128, 128)) - ("green", color(0, 128, 0)) - ("greenyellow", color(173, 255, 47)) - ("honeydew", color(240, 255, 240)) - ("hotpink", color(255, 105, 180)) - ("indianred", color(205, 92, 92)) - ("indigo", color(75, 0, 130)) - ("ivory", color(255, 255, 240)) - ("khaki", color(240, 230, 140)) - ("lavender", color(230, 230, 250)) - ("lavenderblush", color(255, 240, 245)) - ("lawngreen", color(124, 252, 0)) - ("lemonchiffon", color(255, 250, 205)) - ("lightblue", color(173, 216, 230)) - ("lightcoral", color(240, 128, 128)) - ("lightcyan", color(224, 255, 255)) - ("lightgoldenrodyellow", color(250, 250, 210)) - ("lightgray", color(211, 211, 211)) - ("lightgreen", color(144, 238, 144)) - ("lightgrey", color(211, 211, 211)) - ("lightpink", color(255, 182, 193)) - ("lightsalmon", color(255, 160, 122)) - ("lightseagreen", color(32, 178, 170)) - ("lightskyblue", color(135, 206, 250)) - ("lightslategray", color(119, 136, 153)) - ("lightslategrey", color(119, 136, 153)) - ("lightsteelblue", color(176, 196, 222)) - ("lightyellow", color(255, 255, 224)) - ("lime", color(0, 255, 0)) - ("limegreen", color(50, 205, 50)) - ("linen", color(250, 240, 230)) - ("magenta", color(255, 0, 255)) - ("maroon", color(128, 0, 0)) - ("mediumaquamarine", color(102, 205, 170)) - ("mediumblue", color(0, 0, 205)) - ("mediumorchid", color(186, 85, 211)) - ("mediumpurple", color(147, 112, 219)) - ("mediumseagreen", color(60, 179, 113)) - ("mediumslateblue", color(123, 104, 238)) - ("mediumspringgreen", color(0, 250, 154)) - ("mediumturquoise", color(72, 209, 204)) - ("mediumvioletred", color(199, 21, 133)) - ("midnightblue", color(25, 25, 112)) - ("mintcream", color(245, 255, 250)) - ("mistyrose", color(255, 228, 225)) - ("moccasin", color(255, 228, 181)) - ("navajowhite", color(255, 222, 173)) - ("navy", color(0, 0, 128)) - ("oldlace", color(253, 245, 230)) - ("olive", color(128, 128, 0)) - ("olivedrab", color(107, 142, 35)) - ("orange", color(255, 165, 0)) - ("orangered", color(255, 69, 0)) - ("orchid", color(218, 112, 214)) - ("palegoldenrod", color(238, 232, 170)) - ("palegreen", color(152, 251, 152)) - ("paleturquoise", color(175, 238, 238)) - ("palevioletred", color(219, 112, 147)) - ("papayawhip", color(255, 239, 213)) - ("peachpuff", color(255, 218, 185)) - ("peru", color(205, 133, 63)) - ("pink", color(255, 192, 203)) - ("plum", color(221, 160, 221)) - ("powderblue", color(176, 224, 230)) - ("purple", color(128, 0, 128)) - ("red", color(255, 0, 0)) - ("rosybrown", color(188, 143, 143)) - ("royalblue", color(65, 105, 225)) - ("saddlebrown", color(139, 69, 19)) - ("salmon", color(250, 128, 114)) - ("sandybrown", color(244, 164, 96)) - ("seagreen", color(46, 139, 87)) - ("seashell", color(255, 245, 238)) - ("sienna", color(160, 82, 45)) - ("silver", color(192, 192, 192)) - ("skyblue", color(135, 206, 235)) - ("slateblue", color(106, 90, 205)) - ("slategray", color(112, 128, 144)) - ("slategrey", color(112, 128, 144)) - ("snow", color(255, 250, 250)) - ("springgreen", color(0, 255, 127)) - ("steelblue", color(70, 130, 180)) - ("tan", color(210, 180, 140)) - ("teal", color(0, 128, 128)) - ("thistle", color(216, 191, 216)) - ("tomato", color(255, 99, 71)) - ("turquoise", color(64, 224, 208)) - ("violet", color(238, 130, 238)) - ("wheat", color(245, 222, 179)) - ("white", color(255, 255, 255)) - ("whitesmoke", color(245, 245, 245)) - ("yellow", color(255, 255, 0)) - ("yellowgreen", color(154, 205, 50)) - ("transparent", color(0, 0, 0, 0)) - ; - } -} ; - -struct percent_conv_impl -{ - template - struct result - { - using type = unsigned; - }; - - unsigned operator() (double val) const - { - return safe_cast(std::lround((255.0 * val)/100.0)); - } -}; - -struct alpha_conv_impl -{ - template - struct result - { - using type = unsigned; - }; - - unsigned operator() (double val) const - { - return safe_cast(std::lround((255.0 * val))); - } -}; - -struct hsl_conv_impl -{ - template - struct result - { - using type = void; - }; - - template - void operator() (T0 & c, T1 h, T2 s, T3 l) const - { - double m1,m2; - // normalize values - h /= 360.0; - s /= 100.0; - l /= 100.0; - - if (l <= 0.5) - { - m2 = l * (s + 1.0); - } - else - { - m2 = l + s - l*s; - } - m1 = l * 2 - m2; - - double r = hue_to_rgb(m1, m2, h + 1.0/3.0); - double g = hue_to_rgb(m1, m2, h); - double b = hue_to_rgb(m1, m2, h - 1.0/3.0); - - c.set_red(safe_cast(std::lround(255.0 * r))); - c.set_green(safe_cast(std::lround(255.0 * g))); - c.set_blue(safe_cast(std::lround(255.0 * b))); - } -}; - - template struct css_color_grammar : qi::grammar { + // ctor css_color_grammar(); + // rules qi::uint_parser< unsigned, 16, 2, 2 > hex2 ; qi::uint_parser< unsigned, 16, 1, 1 > hex1 ; qi::uint_parser< unsigned, 10, 1, 3 > dec3 ; @@ -296,10 +60,6 @@ struct css_color_grammar : qi::grammar qi::rule hex_color; qi::rule hex_color_small; qi::rule css_color; - named_colors_ named; - phoenix::function percent_converter; - phoenix::function alpha_converter; - phoenix::function hsl_converter; }; } diff --git a/include/mapnik/css_color_grammar_impl.hpp b/include/mapnik/css_color_grammar_impl.hpp index c978194a4..22fa74472 100644 --- a/include/mapnik/css_color_grammar_impl.hpp +++ b/include/mapnik/css_color_grammar_impl.hpp @@ -22,10 +22,234 @@ // NOTE: This is an implementation header file and is only meant to be included // from implementation files. It therefore doesn't have an include guard. +// mapnik #include +// boost +#pragma GCC diagnostic push +#include +#include +#include +#include +#pragma GCC diagnostic pop + + +BOOST_FUSION_ADAPT_ADT( + mapnik::color, + (unsigned, unsigned, obj.red(), obj.set_red(mapnik::safe_cast(val))) + (unsigned, unsigned, obj.green(), obj.set_green(mapnik::safe_cast(val))) + (unsigned, unsigned, obj.blue(), obj.set_blue(mapnik::safe_cast(val))) + (unsigned, unsigned, obj.alpha(), obj.set_alpha(mapnik::safe_cast(val))) + ) namespace mapnik { +namespace phoenix = boost::phoenix; + +struct percent_conv_impl +{ + using result_type = unsigned; + unsigned operator() (double val) const + { + return safe_cast(std::lround((255.0 * val)/100.0)); + } +}; + +struct alpha_conv_impl +{ + using result_type = unsigned; + unsigned operator() (double val) const + { + return safe_cast(std::lround((255.0 * val))); + } +}; + +struct hsl_conv_impl +{ + using result_type = void; + template + void operator() (T0 & c, T1 h, T2 s, T3 l) const + { + double m1,m2; + // normalize values + h /= 360.0; + s /= 100.0; + l /= 100.0; + + if (l <= 0.5) + { + m2 = l * (s + 1.0); + } + else + { + m2 = l + s - l*s; + } + m1 = l * 2 - m2; + + double r = hue_to_rgb(m1, m2, h + 1.0/3.0); + double g = hue_to_rgb(m1, m2, h); + double b = hue_to_rgb(m1, m2, h - 1.0/3.0); + + c.set_red(safe_cast(std::lround(255.0 * r))); + c.set_green(safe_cast(std::lround(255.0 * g))); + c.set_blue(safe_cast(std::lround(255.0 * b))); + } +}; + +struct named_colors : qi::symbols +{ + named_colors() + { + add + ("aliceblue", color(240, 248, 255)) + ("antiquewhite", color(250, 235, 215)) + ("aqua", color(0, 255, 255)) + ("aquamarine", color(127, 255, 212)) + ("azure", color(240, 255, 255)) + ("beige", color(245, 245, 220)) + ("bisque", color(255, 228, 196)) + ("black", color(0, 0, 0)) + ("blanchedalmond", color(255,235,205)) + ("blue", color(0, 0, 255)) + ("blueviolet", color(138, 43, 226)) + ("brown", color(165, 42, 42)) + ("burlywood", color(222, 184, 135)) + ("cadetblue", color(95, 158, 160)) + ("chartreuse", color(127, 255, 0)) + ("chocolate", color(210, 105, 30)) + ("coral", color(255, 127, 80)) + ("cornflowerblue", color(100, 149, 237)) + ("cornsilk", color(255, 248, 220)) + ("crimson", color(220, 20, 60)) + ("cyan", color(0, 255, 255)) + ("darkblue", color(0, 0, 139)) + ("darkcyan", color(0, 139, 139)) + ("darkgoldenrod", color(184, 134, 11)) + ("darkgray", color(169, 169, 169)) + ("darkgreen", color(0, 100, 0)) + ("darkgrey", color(169, 169, 169)) + ("darkkhaki", color(189, 183, 107)) + ("darkmagenta", color(139, 0, 139)) + ("darkolivegreen", color(85, 107, 47)) + ("darkorange", color(255, 140, 0)) + ("darkorchid", color(153, 50, 204)) + ("darkred", color(139, 0, 0)) + ("darksalmon", color(233, 150, 122)) + ("darkseagreen", color(143, 188, 143)) + ("darkslateblue", color(72, 61, 139)) + ("darkslategrey", color(47, 79, 79)) + ("darkturquoise", color(0, 206, 209)) + ("darkviolet", color(148, 0, 211)) + ("deeppink", color(255, 20, 147)) + ("deepskyblue", color(0, 191, 255)) + ("dimgray", color(105, 105, 105)) + ("dimgrey", color(105, 105, 105)) + ("dodgerblue", color(30, 144, 255)) + ("firebrick", color(178, 34, 34)) + ("floralwhite", color(255, 250, 240)) + ("forestgreen", color(34, 139, 34)) + ("fuchsia", color(255, 0, 255)) + ("gainsboro", color(220, 220, 220)) + ("ghostwhite", color(248, 248, 255)) + ("gold", color(255, 215, 0)) + ("goldenrod", color(218, 165, 32)) + ("gray", color(128, 128, 128)) + ("grey", color(128, 128, 128)) + ("green", color(0, 128, 0)) + ("greenyellow", color(173, 255, 47)) + ("honeydew", color(240, 255, 240)) + ("hotpink", color(255, 105, 180)) + ("indianred", color(205, 92, 92)) + ("indigo", color(75, 0, 130)) + ("ivory", color(255, 255, 240)) + ("khaki", color(240, 230, 140)) + ("lavender", color(230, 230, 250)) + ("lavenderblush", color(255, 240, 245)) + ("lawngreen", color(124, 252, 0)) + ("lemonchiffon", color(255, 250, 205)) + ("lightblue", color(173, 216, 230)) + ("lightcoral", color(240, 128, 128)) + ("lightcyan", color(224, 255, 255)) + ("lightgoldenrodyellow", color(250, 250, 210)) + ("lightgray", color(211, 211, 211)) + ("lightgreen", color(144, 238, 144)) + ("lightgrey", color(211, 211, 211)) + ("lightpink", color(255, 182, 193)) + ("lightsalmon", color(255, 160, 122)) + ("lightseagreen", color(32, 178, 170)) + ("lightskyblue", color(135, 206, 250)) + ("lightslategray", color(119, 136, 153)) + ("lightslategrey", color(119, 136, 153)) + ("lightsteelblue", color(176, 196, 222)) + ("lightyellow", color(255, 255, 224)) + ("lime", color(0, 255, 0)) + ("limegreen", color(50, 205, 50)) + ("linen", color(250, 240, 230)) + ("magenta", color(255, 0, 255)) + ("maroon", color(128, 0, 0)) + ("mediumaquamarine", color(102, 205, 170)) + ("mediumblue", color(0, 0, 205)) + ("mediumorchid", color(186, 85, 211)) + ("mediumpurple", color(147, 112, 219)) + ("mediumseagreen", color(60, 179, 113)) + ("mediumslateblue", color(123, 104, 238)) + ("mediumspringgreen", color(0, 250, 154)) + ("mediumturquoise", color(72, 209, 204)) + ("mediumvioletred", color(199, 21, 133)) + ("midnightblue", color(25, 25, 112)) + ("mintcream", color(245, 255, 250)) + ("mistyrose", color(255, 228, 225)) + ("moccasin", color(255, 228, 181)) + ("navajowhite", color(255, 222, 173)) + ("navy", color(0, 0, 128)) + ("oldlace", color(253, 245, 230)) + ("olive", color(128, 128, 0)) + ("olivedrab", color(107, 142, 35)) + ("orange", color(255, 165, 0)) + ("orangered", color(255, 69, 0)) + ("orchid", color(218, 112, 214)) + ("palegoldenrod", color(238, 232, 170)) + ("palegreen", color(152, 251, 152)) + ("paleturquoise", color(175, 238, 238)) + ("palevioletred", color(219, 112, 147)) + ("papayawhip", color(255, 239, 213)) + ("peachpuff", color(255, 218, 185)) + ("peru", color(205, 133, 63)) + ("pink", color(255, 192, 203)) + ("plum", color(221, 160, 221)) + ("powderblue", color(176, 224, 230)) + ("purple", color(128, 0, 128)) + ("red", color(255, 0, 0)) + ("rosybrown", color(188, 143, 143)) + ("royalblue", color(65, 105, 225)) + ("saddlebrown", color(139, 69, 19)) + ("salmon", color(250, 128, 114)) + ("sandybrown", color(244, 164, 96)) + ("seagreen", color(46, 139, 87)) + ("seashell", color(255, 245, 238)) + ("sienna", color(160, 82, 45)) + ("silver", color(192, 192, 192)) + ("skyblue", color(135, 206, 235)) + ("slateblue", color(106, 90, 205)) + ("slategray", color(112, 128, 144)) + ("slategrey", color(112, 128, 144)) + ("snow", color(255, 250, 250)) + ("springgreen", color(0, 255, 127)) + ("steelblue", color(70, 130, 180)) + ("tan", color(210, 180, 140)) + ("teal", color(0, 128, 128)) + ("thistle", color(216, 191, 216)) + ("tomato", color(255, 99, 71)) + ("turquoise", color(64, 224, 208)) + ("violet", color(238, 130, 238)) + ("wheat", color(245, 222, 179)) + ("white", color(255, 255, 255)) + ("whitesmoke", color(245, 245, 245)) + ("yellow", color(255, 255, 0)) + ("yellowgreen", color(154, 205, 50)) + ("transparent", color(0, 0, 0, 0)) + ; + } +}; template css_color_grammar::css_color_grammar() @@ -42,6 +266,12 @@ css_color_grammar::css_color_grammar() qi::lexeme_type lexeme; ascii::no_case_type no_case; using phoenix::at_c; + // symbols + named_colors named; + // functions + phoenix::function percent_converter; + phoenix::function alpha_converter; + phoenix::function hsl_converter; css_color %= rgba_color | rgba_percent_color diff --git a/include/mapnik/csv/csv_grammar.hpp b/include/mapnik/csv/csv_grammar.hpp index f665dae87..240f11ce1 100644 --- a/include/mapnik/csv/csv_grammar.hpp +++ b/include/mapnik/csv/csv_grammar.hpp @@ -20,80 +20,60 @@ * *****************************************************************************/ -#ifndef MAPNIK_CVS_GRAMMAR_HPP -#define MAPNIK_CVS_GRAMMAR_HPP - -//#define BOOST_SPIRIT_DEBUG +#ifndef MAPNIK_CSV_GRAMMAR_HPP +#define MAPNIK_CSV_GRAMMAR_HPP +#include #include -#include namespace mapnik { namespace qi = boost::spirit::qi; -using csv_value = std::string; -using csv_line = std::vector; -using csv_data = std::vector; -template -struct csv_white_space_skipper : qi::grammar +struct csv_white_space_skipper : qi::primitive_parser { - csv_white_space_skipper() - : csv_white_space_skipper::base_type(skip) + template + struct attribute { - using namespace qi; - qi::lit_type lit; - skip = +lit(' ') - ; + typedef qi::unused_type type; + }; + + template + bool parse(Iterator& first, Iterator const& last + , Context& /*context*/, Skipper const& skipper + , Attribute& /*attr*/) const + { + qi::skip_over(first, last, skipper); + if (first != last && *first == ' ') + { + while (++first != last && *first == ' ') + ; + return true; + } + return false; + } + + template + qi::info what(Context& /*context*/) const + { + return qi::info("csv_white_space_skipper"); } - qi::rule skip; }; -template > + +template struct csv_line_grammar : qi::grammar { - csv_line_grammar() - : csv_line_grammar::base_type(line) - { - using namespace qi; - qi::_a_type _a; - qi::_r1_type _r1; - qi::_r2_type _r2; - qi::lit_type lit; - qi::_1_type _1; - qi::char_type char_; - qi::omit_type omit; - unesc_char.add - ("\\a", '\a') - ("\\b", '\b') - ("\\f", '\f') - ("\\n", '\n') - ("\\r", '\r') - ("\\t", '\t') - ("\\v", '\v') - ("\\\\",'\\') - ("\\\'", '\'') - ("\\\"", '\"') - ("\"\"", '\"') // double quote - ; - line = -omit[char_("\n\r")] >> column(_r1, _r2) % lit(_r1) - ; - column = quoted(_r2) | *(char_ - (lit(_r1))) - ; - quoted = omit[char_(_r1)[_a = _1]] > text(_a) > -lit(_a) // support unmatched quotes or not (??) - ; - text = *(unesc_char | (char_ - lit(_r1))) - ; - BOOST_SPIRIT_DEBUG_NODES((line)(column)(quoted)); - } + csv_line_grammar(); private: qi::rule line; qi::rule column; // no-skip qi::rule text; // no-skip - qi::rule, csv_value(char)> quoted; //no-skip + qi::rule quoted; // no-skip qi::symbols unesc_char; }; } -#endif // MAPNIK_CVS_GRAMMAR_HPP +#endif // MAPNIK_CSV_GRAMMAR_HPP diff --git a/include/mapnik/csv/csv_grammar_impl.hpp b/include/mapnik/csv/csv_grammar_impl.hpp new file mode 100644 index 000000000..560835443 --- /dev/null +++ b/include/mapnik/csv/csv_grammar_impl.hpp @@ -0,0 +1,61 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include + +namespace mapnik { + +namespace qi = boost::spirit::qi; + +template +csv_line_grammar::csv_line_grammar() + : csv_line_grammar::base_type(line) +{ + qi::_r1_type _r1; + qi::_r2_type _r2; + qi::lit_type lit; + qi::char_type char_; + unesc_char.add + ("\\a", '\a') + ("\\b", '\b') + ("\\f", '\f') + ("\\n", '\n') + ("\\r", '\r') + ("\\t", '\t') + ("\\v", '\v') + ("\\\\",'\\') + ("\\\'", '\'') + ("\\\"", '\"') + ("\"\"", '\"') // double quote + ; + line = -lit("\r") > -lit("\n") > column(_r1, _r2) % lit(_r1) + ; + column = quoted(_r2) | *(char_ - lit(_r1)) + ; + quoted = lit(_r1) > text(_r1) > lit(_r1) // support unmatched quotes or not (??) + ; + text = *(unesc_char | (char_ - lit(_r1))) + ; + BOOST_SPIRIT_DEBUG_NODES((line)(column)(quoted)); +} + +} // namespace mapnik diff --git a/include/mapnik/csv/csv_types.hpp b/include/mapnik/csv/csv_types.hpp new file mode 100644 index 000000000..5359c3dd6 --- /dev/null +++ b/include/mapnik/csv/csv_types.hpp @@ -0,0 +1,37 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_CSV_TYPES_HPP +#define MAPNIK_CSV_TYPES_HPP + +#include +#include + +namespace mapnik { + +using csv_value = std::string; +using csv_line = std::vector; +using csv_data = std::vector; + +} + +#endif // MAPNIK_CSV_TYPES_HPP diff --git a/include/mapnik/debug.hpp b/include/mapnik/debug.hpp index cf5e5b9c9..84290958b 100644 --- a/include/mapnik/debug.hpp +++ b/include/mapnik/debug.hpp @@ -69,15 +69,15 @@ public: static void set_severity(severity_type severity_level) { -//#ifdef MAPNIK_THREADSAFE -// std::lock_guard lock(severity_mutex_); -//#endif severity_level_ = severity_level; } // per object security levels static severity_type get_object_severity(std::string const& object_name) { +#ifdef MAPNIK_THREADSAFE + std::lock_guard lock(severity_mutex_); +#endif severity_map::iterator it = object_severity_level_.find(object_name); if (object_name.empty() || it == object_severity_level_.end()) { diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index c0cfe1e8a..9064c2d34 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -41,8 +41,8 @@ public: illegal_enum_value(): what_() {} - illegal_enum_value( std::string const& what ) : - what_( what ) + illegal_enum_value( std::string const& _what ) : + what_( _what ) { } virtual ~illegal_enum_value() throw() {} @@ -59,9 +59,9 @@ protected: /** Slim wrapper for enumerations. It creates a new type from a native enum and * a char pointer array. It almost exactly behaves like a native enumeration - * type. It supports string conversion through stream operators. This is usefull + * type. It supports string conversion through stream operators. This is useful * for debugging, serialization/deserialization and also helps with implementing - * language bindings. The two convinient macros DEFINE_ENUM() and IMPLEMENT_ENUM() + * language bindings. The two convenient macros DEFINE_ENUM() and IMPLEMENT_ENUM() * are provided to help with instanciation. * * @par Limitations: @@ -203,57 +203,12 @@ public: str + "' for enum " + our_name_); } - /** Parses the input stream @p is for a word consisting of characters and - * digits (a-z, A-Z, 0-9) and underscores (_). - * The failbit of the stream is set if the word is not a valid identifier. - */ - std::istream & parse(std::istream & is) - { - std::string word; - char c; - - while ( is.peek() != std::char_traits< char >::eof()) - { - is >> c; - if ( isspace(c) && word.empty() ) - { - continue; - } - if ( isalnum(c) || (c == '_') || c == '-' ) - { - word += c; - } - else - { - is.unget(); - break; - } - } - - try - { - from_string( word ); - } - catch (illegal_enum_value const&) - { - is.setstate(std::ios::failbit); - } - - return is; - } - /** Returns the current value as a string identifier. */ std::string as_string() const { return our_strings_[value_]; } - /** Prints the string identifier to the output stream @p os. */ - std::ostream & print(std::ostream & os = std::cerr) const - { - return os << our_strings_[value_]; - } - /** Static helper function to iterate over valid identifiers. */ static const char * get_string(unsigned i) { @@ -284,22 +239,6 @@ public: return true; } - static std::string const& get_full_qualified_name() - { - return our_name_; - } - - static std::string get_name() - { - std::string::size_type idx = our_name_.find_last_of(":"); - if ( idx == std::string::npos ) - { - return our_name_; - } else { - return our_name_.substr( idx + 1 ); - } - } - private: ENUM value_; static const char ** our_strings_ ; @@ -314,19 +253,7 @@ template std::ostream & operator<<(std::ostream & os, const mapnik::enumeration & e) { - e.print( os ); - return os; -} - -/** istream operator for enumeration - * @relates mapnik::enumeration - */ -template -std::istream & -operator>>(std::istream & is, mapnik::enumeration & e) -{ - e.parse( is ); - return is; + return os << e.as_string(); } } // end of namespace diff --git a/include/mapnik/expression_evaluator.hpp b/include/mapnik/expression_evaluator.hpp index 6ac0451ef..58b34486e 100644 --- a/include/mapnik/expression_evaluator.hpp +++ b/include/mapnik/expression_evaluator.hpp @@ -45,27 +45,27 @@ struct evaluate : feature_(f), vars_(v) {} - value_integer operator() (value_integer val) const + value_type operator() (value_integer val) const { return val; } - value_double operator() (value_double val) const + value_type operator() (value_double val) const { return val; } - value_bool operator() (value_bool val) const + value_type operator() (value_bool val) const { return val; } - value_null operator() (value_null val) const + value_type operator() (value_null val) const { return val; } - value_unicode_string const& operator() (value_unicode_string const& str) const + value_type operator() (value_unicode_string const& str) const { return str; } @@ -90,16 +90,16 @@ struct evaluate return geom.value(feature_); } - value_type operator() (binary_node const & x) const + value_type operator() (binary_node const& x) const { return (util::apply_visitor(*this, x.left).to_bool()) && (util::apply_visitor(*this, x.right).to_bool()); } - value_type operator() (binary_node const & x) const + value_type operator() (binary_node const& x) const { - return (util::apply_visitor(*this,x.left).to_bool()) - || (util::apply_visitor(*this,x.right).to_bool()); + return (util::apply_visitor(*this, x.left).to_bool()) + || (util::apply_visitor(*this, x.right).to_bool()); } template diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index ff9423ea3..ad35589bb 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -25,125 +25,18 @@ // mapnik #include -#include -#include #include -#include - #pragma GCC diagnostic push #include #include -#include -#include -#include #pragma GCC diagnostic pop -BOOST_FUSION_ADAPT_STRUCT(mapnik::unary_function_call, - (mapnik::unary_function_impl, fun) - (mapnik::unary_function_call::argument_type, arg)) - -BOOST_FUSION_ADAPT_STRUCT(mapnik::binary_function_call, - (mapnik::binary_function_impl, fun) - (mapnik::binary_function_call::argument_type, arg1) - (mapnik::binary_function_call::argument_type, arg2)) - namespace mapnik { namespace qi = boost::spirit::qi; namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; -struct unicode_impl -{ - template - struct result - { - using type = mapnik::value_unicode_string; - }; - - explicit unicode_impl(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value_unicode_string operator()(std::string const& str) const - { - return tr_.transcode(str.c_str()); - } - - mapnik::transcoder const& tr_; -}; - -struct regex_match_impl -{ - template - struct result - { - using type = expr_node; - }; - - explicit regex_match_impl(mapnik::transcoder const& tr) - : tr_(tr) {} - - template - expr_node operator() (T0 & node, T1 const& pattern) const; - - mapnik::transcoder const& tr_; -}; - -struct regex_replace_impl -{ - - template - struct result - { - using type = expr_node; - }; - - explicit regex_replace_impl(mapnik::transcoder const& tr) - : tr_(tr) {} - - template - expr_node operator() (T0 & node, T1 const& pattern, T2 const& format) const; - - mapnik::transcoder const& tr_; -}; - -struct geometry_types : qi::symbols -{ - geometry_types() - { - add - ("point", 1) - ("linestring", 2) - ("polygon",3) - ("collection",4) - ; - } -}; - -struct boolean_constants : qi::symbols -{ - boolean_constants() - { - add - ("true", true) - ("false", false) - ; - } -}; - -struct floating_point_constants : qi::symbols -{ - floating_point_constants() - { - add - ("pi", 3.1415926535897932384626433832795) - ("deg_to_rad",0.017453292519943295769236907684886) - ("rad_to_deg",57.295779513082320876798154814105) - ; - } -}; - - template struct integer_parser { @@ -176,9 +69,7 @@ struct expression_grammar : qi::grammar qi::real_parser > strict_double; typename integer_parser::type int__; mapnik::transcoder tr_; - boost::phoenix::function unicode_; - boost::phoenix::function regex_match_; - boost::phoenix::function regex_replace_; + rule_type expr; rule_type equality_expr; rule_type cond_expr; @@ -196,13 +87,12 @@ struct expression_grammar : qi::grammar qi::rule attr; qi::rule global_attr; qi::rule > quoted_ustring; + qi::rule unquoted_ustring; qi::rule ustring; qi::symbols unesc_char; qi::rule quote_char; - geometry_types geom_type; - boolean_constants bool_const; - floating_point_constants float_const; + qi::symbols constant; unary_function_types unary_func_type; binary_function_types binary_func_type; diff --git a/include/mapnik/expression_grammar_impl.hpp b/include/mapnik/expression_grammar_impl.hpp index 9c82cb8c5..ad28f0135 100644 --- a/include/mapnik/expression_grammar_impl.hpp +++ b/include/mapnik/expression_grammar_impl.hpp @@ -32,11 +32,21 @@ #pragma GCC diagnostic push #include -#include +#include #include #include +#include #pragma GCC diagnostic pop +BOOST_FUSION_ADAPT_STRUCT(mapnik::unary_function_call, + (mapnik::unary_function_impl, fun) + (mapnik::unary_function_call::argument_type, arg)) + +BOOST_FUSION_ADAPT_STRUCT(mapnik::binary_function_call, + (mapnik::binary_function_impl, fun) + (mapnik::binary_function_call::argument_type, arg1) + (mapnik::binary_function_call::argument_type, arg2)) + // fwd declare namespace mapnik { struct attribute; @@ -46,6 +56,44 @@ namespace mapnik { namespace mapnik { +struct unicode_impl +{ + using result_type = mapnik::value_unicode_string; + explicit unicode_impl(mapnik::transcoder const& tr) + : tr_(tr) {} + + mapnik::value_unicode_string operator()(std::string const& str) const + { + return tr_.transcode(str.c_str()); + } + + mapnik::transcoder const& tr_; +}; + +struct regex_match_impl +{ + using result_type = expr_node; + explicit regex_match_impl(mapnik::transcoder const& tr) + : tr_(tr) {} + + template + expr_node operator() (T0 & node, T1 const& pattern) const; + + mapnik::transcoder const& tr_; +}; + +struct regex_replace_impl +{ + using result_type = expr_node; + explicit regex_replace_impl(mapnik::transcoder const& tr) + : tr_(tr) {} + + template + expr_node operator() (T0 & node, T1 const& pattern, T2 const& format) const; + + mapnik::transcoder const& tr_; +}; + unary_function_types::unary_function_types() { add @@ -54,6 +102,7 @@ unary_function_types::unary_function_types() ("tan", tan_impl()) ("atan", atan_impl()) ("exp", exp_impl()) + ("log", log_impl()) ("abs", abs_impl()) ("length",length_impl()) ; @@ -83,10 +132,7 @@ expr_node regex_replace_impl::operator() (T0 & node, T1 const& pattern, T2 const template expression_grammar::expression_grammar(std::string const& encoding) : expression_grammar::base_type(expr), - tr_(encoding), - unicode_(unicode_impl(tr_)), - regex_match_(regex_match_impl(tr_)), - regex_replace_(regex_replace_impl(tr_)) + tr_(encoding) { qi::_1_type _1; qi::_a_type _a; @@ -103,8 +149,28 @@ expression_grammar::expression_grammar(std::string const& encoding) standard_wide::char_type char_; standard_wide::no_case_type no_case; using boost::phoenix::construct; + using boost::phoenix::if_else; - expr = logical_expr.alias(); + boost::phoenix::function unicode = unicode_impl(tr_); + boost::phoenix::function regex_match = regex_match_impl(tr_); + boost::phoenix::function regex_replace = regex_replace_impl(tr_); + + constant.add + ("null", mapnik::value_null()) + ("false", mapnik::value_bool(false)) + ("true", mapnik::value_bool(true)) + ("point", mapnik::value_integer(1)) + ("linestring", mapnik::value_integer(2)) + ("polygon", mapnik::value_integer(3)) + ("collection", mapnik::value_integer(4)) + ("pi", mapnik::value_double(3.1415926535897932384626433832795)) + ("deg_to_rad", mapnik::value_double(0.017453292519943295769236907684886)) + ("rad_to_deg", mapnik::value_double(57.295779513082320876798154814105)) + ; + + expr = logical_expr [_val = _1] + //| ustring [_val = unicode(_1)] + ; logical_expr = not_expr [_val = _1] >> @@ -140,7 +206,7 @@ expression_grammar::expression_grammar(std::string const& encoding) >> quoted_ustring [_a = _1] >> lit(',') >> quoted_ustring [_b = _1] - >> lit(')') [_val = regex_replace_(_r1,_a,_b)] + >> lit(')') [_val = regex_replace(_r1,_a,_b)] ; relational_expr = additive_expr[_val = _1] @@ -162,15 +228,16 @@ expression_grammar::expression_grammar(std::string const& encoding) >> *( '*' >> unary_expr [_val *= _1] | '/' >> unary_expr [_val /= _1] | '%' >> unary_expr [_val %= construct(_1)] //needed by clang++ with -std=c++11 - | regex_match_expr[_val = regex_match_(_val, _1)] + | regex_match_expr[_val = regex_match(_val, _1)] | regex_replace_expr(_val) [_val = _1] ) ; - unary_function_expr = unary_func_type > lit('(') > expr > lit(')') + unary_function_expr = unary_func_type >> '(' > logical_expr > ')' ; - binary_function_expr = binary_func_type > lit('(') > expr > lit(',') > expr > lit(')') + binary_function_expr = binary_func_type >> '(' > logical_expr > ',' + > logical_expr > ')' ; unary_expr = primary_expr [_val = _1] @@ -180,19 +247,18 @@ expression_grammar::expression_grammar(std::string const& encoding) primary_expr = strict_double [_val = _1] | int__[_val = _1] - | no_case[bool_const][_val = _1] - | no_case[lit("null")] [_val = value_null() ] - | no_case[geom_type][_val = _1 ] - | no_case[float_const] [_val = _1 ] - | quoted_ustring [_val = unicode_(_1)] - | lit("[mapnik::geometry_type]")[_val = construct()] - | attr [_val = construct( _1 ) ] + | no_case[constant] [_val = _1] + | quoted_ustring [_val = unicode(_1)] + | attr [if_else(_1 == "mapnik::geometry_type", + _val = construct(), + _val = construct(_1))] | global_attr [_val = construct( _1 )] - | lit("not") >> expr [_val = !_1] | unary_function_expr [_val = _1] | binary_function_expr [_val = _1] - | '(' >> expr [_val = _1 ] >> ')' - | ustring[_val = unicode_(_1)] // if we get here then try parsing as unquoted string + | '(' > logical_expr [_val = _1 ] > ')' + // TODO: this is a backward compatibility hack to allow unquoted strings + | unquoted_ustring [_val = unicode(_1)] + // ^ https://github.com/mapnik/mapnik/pull/3389 ; unesc_char.add("\\a", '\a')("\\b", '\b')("\\f", '\f')("\\n", '\n') @@ -205,6 +271,7 @@ expression_grammar::expression_grammar(std::string const& encoding) quoted_ustring %= omit[quote_char[_a = _1]] >> *(unesc_char | "\\x" >> hex | (char_ - lit(_a))) >> lit(_a); + unquoted_ustring %= no_skip[alpha >> *alnum] - lit("not"); attr %= '[' >> no_skip[+~char_(']')] >> ']'; global_attr %= '@' >> no_skip[alpha >> * (alnum | char_('-'))]; diff --git a/include/mapnik/expression_node.hpp b/include/mapnik/expression_node.hpp index 7731414a4..6fdad8f5f 100644 --- a/include/mapnik/expression_node.hpp +++ b/include/mapnik/expression_node.hpp @@ -31,6 +31,8 @@ #include #include #include +// stl +#include namespace mapnik { diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 769ca0579..1300d3220 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -90,7 +90,7 @@ private: using context_type = context >; using context_ptr = std::shared_ptr; -static const value default_feature_value; +static const value default_feature_value{}; class MAPNIK_DECL feature_impl : private util::noncopyable { @@ -101,15 +101,15 @@ public: using cont_type = std::vector; using iterator = feature_kv_iterator; - feature_impl(context_ptr const& ctx, mapnik::value_integer id) - : id_(id), + feature_impl(context_ptr const& ctx, mapnik::value_integer _id) + : id_(_id), ctx_(ctx), data_(ctx_->mapping_.size()), geom_(geometry::geometry_empty()), raster_() {} inline mapnik::value_integer id() const { return id_;} - inline void set_id(mapnik::value_integer id) { id_ = id;} + inline void set_id(mapnik::value_integer _id) { id_ = _id;} template inline void put(context_type::key_type const& key, T const& val) { @@ -154,7 +154,7 @@ public: inline bool has_key(context_type::key_type const& key) const { - return (ctx_->mapping_.find(key) != ctx_->mapping_.end()); + return (ctx_->mapping_.count(key) == 1); } inline value_type const& get(context_type::key_type const& key) const diff --git a/include/mapnik/feature_kv_iterator.hpp b/include/mapnik/feature_kv_iterator.hpp index 37093a897..77b292fd5 100644 --- a/include/mapnik/feature_kv_iterator.hpp +++ b/include/mapnik/feature_kv_iterator.hpp @@ -27,12 +27,14 @@ #include #include #include -// boost +#pragma GCC diagnostic push +#include #include #include #include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/feature_layer_desc.hpp b/include/mapnik/feature_layer_desc.hpp index 9d1186a7c..cd69d831f 100644 --- a/include/mapnik/feature_layer_desc.hpp +++ b/include/mapnik/feature_layer_desc.hpp @@ -94,12 +94,21 @@ public: { return extra_params_; } + bool has_name(std::string const& name) const { auto result = std::find_if(std::begin(descriptors_), std::end(descriptors_), [&name](attribute_descriptor const& desc) { return name == desc.get_name();}); return result != std::end(descriptors_); } + void order_by_name() + { + std::sort(std::begin(descriptors_), std::end(descriptors_), + [](attribute_descriptor const& d0, attribute_descriptor const& d1) + { + return d0.get_name() < d1.get_name(); + }); + } private: std::string name_; std::string encoding_; diff --git a/include/mapnik/feature_type_style.hpp b/include/mapnik/feature_type_style.hpp index 68240af3a..9f9f1aec9 100644 --- a/include/mapnik/feature_type_style.hpp +++ b/include/mapnik/feature_type_style.hpp @@ -29,8 +29,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/featureset.hpp b/include/mapnik/featureset.hpp index c6829d1eb..a6ad4e85d 100644 --- a/include/mapnik/featureset.hpp +++ b/include/mapnik/featureset.hpp @@ -41,8 +41,27 @@ struct MAPNIK_DECL Featureset : private util::noncopyable virtual ~Featureset() {} }; +struct MAPNIK_DECL invalid_featureset final : Featureset +{ + feature_ptr next() + { + return feature_ptr(); + } + ~invalid_featureset() {} +}; + using featureset_ptr = std::shared_ptr; +inline featureset_ptr make_invalid_featureset() +{ + return std::make_shared(); +} + +inline bool is_valid(featureset_ptr const& ptr) +{ + return (dynamic_cast(ptr.get()) == nullptr) ? true : false; +} + } #endif // MAPNIK_FEATURESET_HPP diff --git a/include/mapnik/font_engine_freetype.hpp b/include/mapnik/font_engine_freetype.hpp index 33ac45035..73227cdbf 100644 --- a/include/mapnik/font_engine_freetype.hpp +++ b/include/mapnik/font_engine_freetype.hpp @@ -100,10 +100,8 @@ private: static font_memory_cache_type global_memory_fonts_; }; -class MAPNIK_DECL face_manager : private util::noncopyable +class MAPNIK_DECL face_manager { - using face_ptr_cache_type = std::map; - public: face_manager(font_library & library, freetype_engine::font_file_mapping_type const& font_file_mapping, @@ -112,9 +110,13 @@ public: face_set_ptr get_face_set(std::string const& name); face_set_ptr get_face_set(font_set const& fset); face_set_ptr get_face_set(std::string const& name, boost::optional fset); - inline stroker_ptr get_stroker() { return stroker_; } + stroker_ptr get_stroker() const { return stroker_; } + private: - face_ptr_cache_type face_ptr_cache_; + using face_cache = std::map; + using face_cache_ptr = std::shared_ptr; + + face_cache_ptr face_cache_; font_library & library_; freetype_engine::font_file_mapping_type const& font_file_mapping_; freetype_engine::font_memory_cache_type const& font_memory_cache_; diff --git a/include/mapnik/function_call.hpp b/include/mapnik/function_call.hpp index efbaa5f28..f50829bd6 100644 --- a/include/mapnik/function_call.hpp +++ b/include/mapnik/function_call.hpp @@ -50,6 +50,17 @@ struct exp_impl }; +// log +struct log_impl +{ + //using type = T; + value_type operator() (value_type const& val) const + { + return std::log(val.to_double()); + } + +}; + // sin struct sin_impl { diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 3766ebf23..aae2bf3e8 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -24,53 +24,44 @@ #define MAPNIK_GEOMETRY_HPP #include -#include #include #include #include - - namespace mapnik { namespace geometry { template struct point { - using value_type = T; + using coord_type = T; point() {} point(T x_, T y_) : x(x_), y(y_) {} - // temp - remove when geometry is templated on value_type - point(mapnik::coord const& c) - : x(c.x), y(c.y) {} - point(point const& other) = default; - point(point && other) noexcept = default; - point & operator=(point const& other) = default; - friend inline bool operator== (point const& a, point const& b) - { - return a.x == b.x && a.y == b.y; - } - friend inline bool operator!= (point const& a, point const& b) - { - return a.x != b.x || a.y != b.y; - } - value_type x; - value_type y; + coord_type x; + coord_type y; }; +template +bool operator==(point const& lhs, point const& rhs) +{ + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +template +bool operator!=(point const& lhs, point const& rhs) +{ + return !(lhs == rhs); +} template struct line_string : std::vector > { + using coord_type = T; line_string() = default; - line_string (std::size_t size) + explicit line_string(std::size_t size) : std::vector >(size) {} - line_string (line_string && other) = default ; - line_string& operator=(line_string &&) = default; - line_string (line_string const& ) = default; - line_string& operator=(line_string const&) = default; inline std::size_t num_points() const { return std::vector>::size(); } inline void add_coord(T x, T y) { std::vector>::template emplace_back(x,y);} }; @@ -78,18 +69,14 @@ struct line_string : std::vector > template struct linear_ring : line_string { + using coord_type = T; linear_ring() = default; - linear_ring(std::size_t size) + explicit linear_ring(std::size_t size) : line_string(size) {} - linear_ring (linear_ring && other) = default ; - linear_ring& operator=(linear_ring &&) = default; linear_ring(line_string && other) - : line_string(other) {} - linear_ring (linear_ring const& ) = default; + : line_string(std::move(other)) {} linear_ring(line_string const& other) : line_string(other) {} - linear_ring& operator=(linear_ring const&) = default; - }; template @@ -98,11 +85,11 @@ using rings_container = std::vector>; template class InteriorRings = rings_container> struct polygon { - linear_ring exterior_ring; + using coord_type = T; using rings_container = InteriorRings; + linear_ring exterior_ring; rings_container interior_rings; - polygon() = default; inline void set_exterior_ring(linear_ring && ring) { exterior_ring = std::move(ring); @@ -122,13 +109,22 @@ struct polygon }; template -struct multi_point : line_string {}; +struct multi_point : line_string +{ + using coord_type = T; +}; template -struct multi_line_string : std::vector> {}; +struct multi_line_string : std::vector> +{ + using coord_type = T; +}; template -struct multi_polygon : std::vector> {}; +struct multi_polygon : std::vector> +{ + using coord_type = T; +}; template struct geometry_collection; @@ -144,23 +140,32 @@ using geometry_base = mapnik::util::variant, multi_line_string, multi_polygon, - mapnik::util::recursive_wrapper > >; + geometry_collection >; template struct geometry : geometry_base { - using value_type = T; + using coord_type = T; - geometry() - : geometry_base() {} // empty +#if __cpp_inheriting_constructors >= 200802 + + using geometry_base::geometry_base; + +#else + + geometry() = default; template geometry(G && geom) : geometry_base(std::forward(geom)) {} +#endif }; template -struct geometry_collection : std::vector> {}; +struct geometry_collection : std::vector> +{ + using coord_type = T; +}; }} diff --git a/include/mapnik/geometry_envelope.hpp b/include/mapnik/geometry_envelope.hpp index 17b8fcb44..981b97849 100644 --- a/include/mapnik/geometry_envelope.hpp +++ b/include/mapnik/geometry_envelope.hpp @@ -26,11 +26,11 @@ #include #include -namespace mapnik { +namespace mapnik { namespace geometry { template -MAPNIK_DECL mapnik::box2d envelope(T const& geom); +MAPNIK_DECL auto envelope(T const& geom) -> box2d; } // end ns geometry } // end ns mapnik diff --git a/include/mapnik/geometry_envelope_impl.hpp b/include/mapnik/geometry_envelope_impl.hpp index dbed6aa47..2ebddb9d9 100644 --- a/include/mapnik/geometry_envelope_impl.hpp +++ b/include/mapnik/geometry_envelope_impl.hpp @@ -28,23 +28,24 @@ namespace mapnik { namespace geometry { namespace detail { +template struct geometry_envelope { - using bbox_type = box2d; + using coord_type = T; + using bbox_type = box2d; bbox_type & bbox; geometry_envelope(bbox_type & bbox_) : bbox(bbox_) {} - template - void operator() (T const& geom) const + template + void operator() (U const& geom) const { return mapnik::util::apply_visitor(*this, geom); } - + void operator() (mapnik::geometry::geometry_empty const&) const {} - template void operator() (mapnik::geometry::point const& pt) const { if (!bbox.valid()) @@ -54,61 +55,62 @@ struct geometry_envelope bbox.expand_to_include(pt.x, pt.y); } - template void operator() (mapnik::geometry::line_string const& line) const { bool first = true; for (auto const& pt : line) { - if (first && !bbox.valid()) + if (first && !bbox.valid()) { bbox.init(pt.x, pt.y, pt.x, pt.y); first = false; } - else + else { bbox.expand_to_include(pt.x, pt.y); } } } - template + void operator() (mapnik::geometry::linear_ring const& ring) const + { + (*this)(static_cast const&>(ring)); + } + void operator() (mapnik::geometry::polygon const& poly) const { bool first = true; for (auto const& pt : poly.exterior_ring) { - if (first && !bbox.valid()) + if (first && !bbox.valid()) { bbox.init(pt.x, pt.y, pt.x, pt.y); first = false; } - else + else { bbox.expand_to_include(pt.x, pt.y); } } } - template void operator() (mapnik::geometry::multi_point const& multi_point) const { bool first = true; for (auto const& pt : multi_point) { - if (first && !bbox.valid()) + if (first && !bbox.valid()) { bbox.init(pt.x, pt.y, pt.x, pt.y); first = false; } - else + else { bbox.expand_to_include(pt.x, pt.y); } } } - template void operator() (mapnik::geometry::multi_line_string const& multi_line) const { for (auto const& line : multi_line) @@ -117,7 +119,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::multi_polygon const& multi_poly) const { for (auto const& poly : multi_poly) @@ -126,7 +127,6 @@ struct geometry_envelope } } - template void operator() (mapnik::geometry::geometry_collection const& collection) const { for (auto const& geom : collection) @@ -139,14 +139,14 @@ struct geometry_envelope } // end ns detail template -mapnik::box2d envelope(T const& geom) -{ - box2d bbox; - detail::geometry_envelope op(bbox); +auto envelope(T const& geom) -> box2d +{ + using coord_type = typename T::coord_type; + box2d bbox; + detail::geometry_envelope op(bbox); op(geom); return bbox; } } // end ns geometry } // end ns mapnik - diff --git a/include/mapnik/geometry_reprojection_impl.hpp b/include/mapnik/geometry_reprojection_impl.hpp index 7e78635e4..ff01bd451 100644 --- a/include/mapnik/geometry_reprojection_impl.hpp +++ b/include/mapnik/geometry_reprojection_impl.hpp @@ -36,7 +36,7 @@ geometry_empty reproject_internal(geometry_empty const&, proj_transform const&, } template -point reproject_internal(point const & p, proj_transform const& proj_trans, unsigned int & n_err) +point reproject_internal(point const& p, proj_transform const& proj_trans, unsigned int & n_err) { point new_p(p); if (!proj_trans.forward(new_p)) @@ -47,7 +47,7 @@ point reproject_internal(point const & p, proj_transform const& proj_trans } template -line_string reproject_internal(line_string const & ls, proj_transform const& proj_trans, unsigned int & n_err) +line_string reproject_internal(line_string const& ls, proj_transform const& proj_trans, unsigned int & n_err) { line_string new_ls(ls); unsigned int err = proj_trans.forward(new_ls); @@ -59,7 +59,7 @@ line_string reproject_internal(line_string const & ls, proj_transform cons } template -polygon reproject_internal(polygon const & poly, proj_transform const& proj_trans, unsigned int & n_err) +polygon reproject_internal(polygon const& poly, proj_transform const& proj_trans, unsigned int & n_err) { polygon new_poly; linear_ring new_ext(poly.exterior_ring); @@ -171,18 +171,19 @@ geometry_collection reproject_internal(geometry_collection const & c, proj } template -struct geom_reproj_copy_visitor { +struct geom_reproj_copy_visitor +{ geom_reproj_copy_visitor(proj_transform const & proj_trans, unsigned int & n_err) : proj_trans_(proj_trans), n_err_(n_err) {} - geometry operator() (geometry_empty const&) + geometry operator() (geometry_empty const&) const { return geometry_empty(); } - geometry operator() (point const& p) + geometry operator() (point const& p) const { geometry geom; // default empty unsigned int intial_err = n_err_; @@ -192,7 +193,7 @@ struct geom_reproj_copy_visitor { return geom; } - geometry operator() (line_string const& ls) + geometry operator() (line_string const& ls) const { geometry geom; // default empty unsigned int intial_err = n_err_; @@ -202,7 +203,7 @@ struct geom_reproj_copy_visitor { return geom; } - geometry operator() (polygon const& poly) + geometry operator() (polygon const& poly) const { geometry geom; // default empty polygon new_poly = reproject_internal(poly, proj_trans_, n_err_); @@ -211,7 +212,7 @@ struct geom_reproj_copy_visitor { return geom; } - geometry operator() (multi_point const& mp) + geometry operator() (multi_point const& mp) const { geometry geom; // default empty multi_point new_mp = reproject_internal(mp, proj_trans_, n_err_); @@ -220,7 +221,7 @@ struct geom_reproj_copy_visitor { return geom; } - geometry operator() (multi_line_string const& mls) + geometry operator() (multi_line_string const& mls) const { geometry geom; // default empty multi_line_string new_mls = reproject_internal(mls, proj_trans_, n_err_); @@ -229,7 +230,7 @@ struct geom_reproj_copy_visitor { return geom; } - geometry operator() (multi_polygon const& mpoly) + geometry operator() (multi_polygon const& mpoly) const { geometry geom; // default empty multi_polygon new_mpoly = reproject_internal(mpoly, proj_trans_, n_err_); @@ -238,7 +239,7 @@ struct geom_reproj_copy_visitor { return geom; } - geometry operator() (geometry_collection const& c) + geometry operator() (geometry_collection const& c) const { geometry geom; // default empty geometry_collection new_c = reproject_internal(c, proj_trans_, n_err_); @@ -283,15 +284,15 @@ struct geom_reproj_visitor { : proj_trans_(proj_trans) {} template - bool operator() (geometry & geom) + bool operator() (geometry & geom) const { return mapnik::util::apply_visitor((*this), geom); } - bool operator() (geometry_empty &) { return true; } + bool operator() (geometry_empty &) const { return true; } template - bool operator() (point & p) + bool operator() (point & p) const { if (!proj_trans_.forward(p)) { @@ -301,7 +302,7 @@ struct geom_reproj_visitor { } template - bool operator() (line_string & ls) + bool operator() (line_string & ls) const { if (proj_trans_.forward(ls) > 0) { @@ -311,7 +312,7 @@ struct geom_reproj_visitor { } template - bool operator() (polygon & poly) + bool operator() (polygon & poly) const { if (proj_trans_.forward(poly.exterior_ring) > 0) { @@ -329,13 +330,13 @@ struct geom_reproj_visitor { } template - bool operator() (multi_point & mp) + bool operator() (multi_point & mp) const { return (*this) (static_cast &>(mp)); } template - bool operator() (multi_line_string & mls) + bool operator() (multi_line_string & mls) const { for (auto & ls : mls) { @@ -348,7 +349,7 @@ struct geom_reproj_visitor { } template - bool operator() (multi_polygon & mpoly) + bool operator() (multi_polygon & mpoly) const { for (auto & poly : mpoly) { @@ -361,7 +362,7 @@ struct geom_reproj_visitor { } template - bool operator() (geometry_collection & c) + bool operator() (geometry_collection & c) const { for (auto & g : c) { diff --git a/include/mapnik/geometry_unique.hpp b/include/mapnik/geometry_unique.hpp deleted file mode 100644 index 167822801..000000000 --- a/include/mapnik/geometry_unique.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_GEOMETRY_UNIQUE_HPP -#define MAPNIK_GEOMETRY_UNIQUE_HPP - -#include -#include -#include - -#include - -namespace mapnik { namespace geometry { - -namespace detail { - -struct geometry_unique -{ - using result_type = void; - - result_type operator() (geometry & geom) const - { - mapnik::util::apply_visitor(*this, geom); - } - - result_type operator() (geometry_collection & collection) const - { - for (auto & geom : collection) - { - (*this)(geom); - } - } - - result_type operator() (line_string & line) const - { - boost::geometry::unique(line); - } - - result_type operator() (polygon & poly) const - { - boost::geometry::unique(poly); - } - - template - result_type operator() (T & geom) const - { - // no-op - } - -}; - -} - -template -inline void unique(GeomType & geom) -{ - static_assert(!std::is_const::value,"mapnik::geometry::unique on const& is invalid"); - detail::geometry_unique()(geom); -} - -}} - -#endif // MAPNIK_GEOMETRY_UNIQUE_HPP diff --git a/include/mapnik/global.hpp b/include/mapnik/global.hpp index aa5be35f5..39a8c5ff7 100644 --- a/include/mapnik/global.hpp +++ b/include/mapnik/global.hpp @@ -99,14 +99,14 @@ inline void read_int32_xdr(const char* data, std::int32_t & val) // read double XDR (big endian) inline void read_double_xdr(const char* data, double & val) { - std::int64_t bits = ((std::int64_t)data[7] & 0xff) | - ((std::int64_t)data[6] & 0xff) << 8 | - ((std::int64_t)data[5] & 0xff) << 16 | - ((std::int64_t)data[4] & 0xff) << 24 | - ((std::int64_t)data[3] & 0xff) << 32 | - ((std::int64_t)data[2] & 0xff) << 40 | - ((std::int64_t)data[1] & 0xff) << 48 | - ((std::int64_t)data[0] & 0xff) << 56 ; + std::int64_t bits = (static_cast(data[7]) & 0xff) | + (static_cast(data[6]) & 0xff) << 8 | + (static_cast(data[5]) & 0xff) << 16 | + (static_cast(data[4]) & 0xff) << 24 | + (static_cast(data[3]) & 0xff) << 32 | + (static_cast(data[2]) & 0xff) << 40 | + (static_cast(data[1]) & 0xff) << 48 | + (static_cast(data[0]) & 0xff) << 56 ; std::memcpy(&val,&bits,8); } diff --git a/include/mapnik/gradient.hpp b/include/mapnik/gradient.hpp index f8eff6e7d..ae9acb5a3 100644 --- a/include/mapnik/gradient.hpp +++ b/include/mapnik/gradient.hpp @@ -23,12 +23,13 @@ #ifndef MAPNIK_GRADIENT_HPP #define MAPNIK_GRADIENT_HPP -// agg +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // mapnik #include -#include // stl #include @@ -39,26 +40,20 @@ namespace mapnik using stop_pair = std::pair; using stop_array = std::vector; -enum gradient_enum +enum gradient_e { NO_GRADIENT, LINEAR, - RADIAL, - gradient_enum_MAX + RADIAL }; -DEFINE_ENUM( gradient_e, gradient_enum ); - -enum gradient_unit_enum +enum gradient_unit_e { USER_SPACE_ON_USE, USER_SPACE_ON_USE_BOUNDING_BOX, // used to indicate % age values were specified. This are % of the svg image extent. - OBJECT_BOUNDING_BOX, // (i.e., the abstract coordinate system where (0,0) is at the top/left of the object bounding box and (1,1) is at the bottom/right of the object bounding box) - gradient_unit_enum_MAX + OBJECT_BOUNDING_BOX // (i.e., the abstract coordinate system where (0,0) is at the top/left of the object bounding box and (1,1) is at the bottom/right of the object bounding box) }; -DEFINE_ENUM( gradient_unit_e, gradient_unit_enum ); - class MAPNIK_DECL gradient { // transform diff --git a/include/mapnik/grid/grid_rasterizer.hpp b/include/mapnik/grid/grid_rasterizer.hpp index 98a6dd31f..612944799 100644 --- a/include/mapnik/grid/grid_rasterizer.hpp +++ b/include/mapnik/grid/grid_rasterizer.hpp @@ -24,7 +24,11 @@ #define MAPNIK_GRID_RASTERIZER_HPP #include + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/grid/grid_render_marker.hpp b/include/mapnik/grid/grid_render_marker.hpp index 8f345e301..5ad5fea13 100644 --- a/include/mapnik/grid/grid_render_marker.hpp +++ b/include/mapnik/grid/grid_render_marker.hpp @@ -26,7 +26,8 @@ // mapnik #include -// agg +#pragma GCC diagnostic push +#include #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_image_filters.h" @@ -34,7 +35,7 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_span_image_filter_gray.h" - +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/grid/grid_renderer_base.hpp b/include/mapnik/grid/grid_renderer_base.hpp index 1000083df..bcc2e18c1 100644 --- a/include/mapnik/grid/grid_renderer_base.hpp +++ b/include/mapnik/grid/grid_renderer_base.hpp @@ -24,11 +24,11 @@ #define MAPNIK_GRID_RENDERER_BASE_HPP #pragma GCC diagnostic push -#include -#include "agg_renderer_base.h" +#include #include -#pragma GCC diagnostic pop #include +#include "agg_renderer_base.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/grid/grid_rendering_buffer.hpp b/include/mapnik/grid/grid_rendering_buffer.hpp index 4282e3bb9..8ab12cfc0 100644 --- a/include/mapnik/grid/grid_rendering_buffer.hpp +++ b/include/mapnik/grid/grid_rendering_buffer.hpp @@ -24,7 +24,11 @@ #define MAPNIK_GRID_RENDERING_BUFFER_HPP #include + +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/group/group_layout_manager.hpp b/include/mapnik/group/group_layout_manager.hpp index 38ee30b5d..548e37bb6 100644 --- a/include/mapnik/group/group_layout_manager.hpp +++ b/include/mapnik/group/group_layout_manager.hpp @@ -31,43 +31,51 @@ // stl #include -using std::vector; - namespace mapnik { -using bound_box = box2d; - struct group_layout_manager { - group_layout_manager(group_layout const& layout) + using bound_box = box2d; + + group_layout_manager() + : update_layout_(false) + {} + + explicit group_layout_manager(group_layout const& layout) : layout_(layout), - input_origin_(0, 0), - member_boxes_(vector()), - member_offsets_(vector()), - update_layout_(true) + update_layout_(false) { } group_layout_manager(group_layout const& layout, pixel_position const& input_origin) : layout_(layout), input_origin_(input_origin), - member_boxes_(vector()), - member_offsets_(vector()), - update_layout_(true) + update_layout_(false) { } group_layout_manager(group_layout const& layout, pixel_position const& input_origin, - vector const& item_boxes) + std::vector const& item_boxes) : layout_(layout), input_origin_(input_origin), member_boxes_(item_boxes), - member_offsets_(vector()), update_layout_(true) { } + void set_input_origin(double x, double y) + { + input_origin_.set(x, y); + update_layout_ = true; + } + + void set_input_origin(pixel_position const& input_origin) + { + input_origin_ = input_origin; + update_layout_ = true; + } + inline void set_layout(group_layout const& layout) { layout_ = layout; @@ -94,8 +102,8 @@ private: group_layout layout_; pixel_position input_origin_; - vector member_boxes_; - vector member_offsets_; + std::vector member_boxes_; + std::vector member_offsets_; bool update_layout_; }; diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index 466462404..5d8adc1da 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -365,20 +365,20 @@ private: if (r->count>0) { printf("%d: (+%d/%d/%.5f) (%d %d %d %d)\n", - id, (int)r->count, (int)r->pixel_count, r->reduce_cost, - (int)round(gamma(r->reds / r->count, gamma_)), - (int)round(gamma(r->greens / r->count, gamma_)), - (int)round(gamma(r->blues / r->count, gamma_)), - (int)(r->alphas / r->count)); + id, static_cast(r->count), static_cast(r->pixel_count), r->reduce_cost, + static_cast(round(gamma(r->reds / r->count, gamma_))), + static_cast(round(gamma(r->greens / r->count, gamma_))), + static_cast(round(gamma(r->blues / r->count, gamma_))), + static_cast((r->alphas / r->count))); } else { printf("%d: (%d/%d/%.5f) (%d %d %d %d)\n", id, - (int)r->count, (int)r->pixel_count, r->reduce_cost, - (int)round(gamma(r->reds / r->pixel_count, gamma_)), - (int)round(gamma(r->greens / r->pixel_count, gamma_)), - (int)round(gamma(r->blues / r->pixel_count, gamma_)), - (int)(r->alphas / r->pixel_count)); + static_cast(r->count), static_cast(r->pixel_count), r->reduce_cost, + static_cast(round(gamma(r->reds / r->pixel_count, gamma_))), + static_cast(round(gamma(r->greens / r->pixel_count, gamma_))), + static_cast(round(gamma(r->blues / r->pixel_count, gamma_))), + static_cast((r->alphas / r->pixel_count))); } for (unsigned idx=0; idx < 16; ++idx) { @@ -399,9 +399,9 @@ private: std::uint8_t a = std::uint8_t(itr->alphas/float(count)); if (a > InsertPolicy::MAX_ALPHA) a = 255; if (a < InsertPolicy::MIN_ALPHA) a = 0; - palette.push_back(rgba((std::uint8_t)round(gamma(itr->reds / count, gamma_)), - (std::uint8_t)round(gamma(itr->greens / count, gamma_)), - (std::uint8_t)round(gamma(itr->blues / count, gamma_)), a)); + palette.push_back(rgba(static_cast(round(gamma(itr->reds / count, gamma_))), + static_cast(round(gamma(itr->greens / count, gamma_))), + static_cast(round(gamma(itr->blues / count, gamma_))), a)); } for (unsigned idx=0; idx < 16; ++idx) { diff --git a/include/mapnik/image.hpp b/include/mapnik/image.hpp index 9ebdfc3b2..13b21c856 100644 --- a/include/mapnik/image.hpp +++ b/include/mapnik/image.hpp @@ -54,9 +54,6 @@ template struct image_dimensions { image_dimensions(int width, int height); - image_dimensions(image_dimensions const& other) = default; - image_dimensions(image_dimensions && other) = default; - image_dimensions& operator= (image_dimensions rhs); std::size_t width() const; std::size_t height() const; private: diff --git a/include/mapnik/image_any.hpp b/include/mapnik/image_any.hpp index 735ad8223..8aedf302a 100644 --- a/include/mapnik/image_any.hpp +++ b/include/mapnik/image_any.hpp @@ -55,8 +55,9 @@ struct MAPNIK_DECL image_any : image_base bool painted = false); template - image_any(T && _data) noexcept - : image_base(std::move(_data)) {} + image_any(T && _data) + noexcept(std::is_nothrow_constructible::value) + : image_base(std::forward(_data)) {} unsigned char const* bytes() const; unsigned char* bytes(); diff --git a/include/mapnik/image_compositing.hpp b/include/mapnik/image_compositing.hpp index 2967be780..82b89a398 100644 --- a/include/mapnik/image_compositing.hpp +++ b/include/mapnik/image_compositing.hpp @@ -26,8 +26,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 62a3f3b5b..a96d4cd9d 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -34,7 +34,8 @@ #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_color_rgba.h" @@ -42,6 +43,8 @@ #include "agg_scanline_u.h" #include "agg_blur.h" #include "agg_gradient_lut.h" +#pragma GCC diagnostic pop + // stl #include @@ -683,7 +686,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op) using namespace boost::gil; rgba8_view_t src_view = rgba8_view(src); bool premultiplied = src.get_premultiplied(); - + for (std::ptrdiff_t y = 0; y < src_view.height(); ++y) { rgba8_view_t::x_iterator src_it = src_view.row_begin(static_cast(y)); @@ -738,7 +741,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op) X = deviate_x * Y / deviate_y; Z = (1.0 - (deviate_x + deviate_y)) * Y / deviate_y; // Neutral grey calculated from luminance (in D65) - double neutral_X = 0.312713 * Y / 0.329016; + double neutral_X = 0.312713 * Y / 0.329016; double neutral_Z = 0.358271 * Y / 0.329016; // Difference between simulated color and neutral grey double diff_X = neutral_X - X; @@ -761,12 +764,12 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op) // Convert to RGB color space dr = X * 3.24071 + Y * -1.53726 + Z * -0.498571; // XYZ->RGB (sRGB:D65) dg = X * -0.969258 + Y * 1.87599 + Z * 0.0415557; - db = X * 0.0556352 + Y * -0.203996 + Z * 1.05707; + db = X * 0.0556352 + Y * -0.203996 + Z * 1.05707; // Compensate simulated color towards a neutral fit in RGB space double fit_r = ((dr < 0.0 ? 0.0 : 1.0) - dr) / diff_r; double fit_g = ((dg < 0.0 ? 0.0 : 1.0) - dg) / diff_g; double fit_b = ((db < 0.0 ? 0.0 : 1.0) - db) / diff_b; - double adjust = std::max( (fit_r > 1.0 || fit_r < 0.0) ? 0.0 : fit_r, + double adjust = std::max( (fit_r > 1.0 || fit_r < 0.0) ? 0.0 : fit_r, (fit_g > 1.0 || fit_g < 0.0) ? 0.0 : fit_g ); adjust = std::max((fit_b > 1.0 || fit_b < 0.0) ? 0.0 : fit_b, adjust); @@ -777,7 +780,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op) // Apply gamma correction dr = std::pow(dr, 1.0 / 2.2); dg = std::pow(dg, 1.0 / 2.2); - db = std::pow(db, 1.0 / 2.2); + db = std::pow(db, 1.0 / 2.2); // premultiply dr *= da; dg *= da; @@ -917,7 +920,7 @@ struct filter_visitor : src_(src) {} template - void operator () (T const& filter) + void operator () (T const& filter) const { apply_filter(src_, filter); } @@ -931,9 +934,9 @@ struct filter_radius_visitor filter_radius_visitor(int & radius) : radius_(radius) {} template - void operator () (T const& /*filter*/) {} + void operator () (T const& /*filter*/) const {} - void operator () (agg_stack_blur const& op) + void operator () (agg_stack_blur const& op) const { if (static_cast(op.rx) > radius_) radius_ = static_cast(op.rx); if (static_cast(op.ry) > radius_) radius_ = static_cast(op.ry); diff --git a/include/mapnik/image_filter_grammar.hpp b/include/mapnik/image_filter_grammar.hpp index 04ced605b..ca96116eb 100644 --- a/include/mapnik/image_filter_grammar.hpp +++ b/include/mapnik/image_filter_grammar.hpp @@ -20,19 +20,19 @@ * *****************************************************************************/ -#ifndef MAPNIK_IMAGE_FILITER_GRAMMAR_HPP -#define MAPNIK_IMAGE_FILITER_GRAMMAR_HPP +#ifndef MAPNIK_IMAGE_FILTER_GRAMMAR_HPP +#define MAPNIK_IMAGE_FILTER_GRAMMAR_HPP + +// mapnik +#include +#include +#include #pragma GCC diagnostic push #include #include -#include #pragma GCC diagnostic pop -// mapnik -#include -#include - // stl #include @@ -43,26 +43,11 @@ struct color_stop; struct colorize_alpha; } -} - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::filter::color_stop, - (mapnik::color, color ) - (double, offset) -) - -namespace mapnik { - namespace qi = boost::spirit::qi; struct percent_offset_impl { - template - struct result - { - using type = double; - }; - + using result_type = double; double operator() (double val) const { double result = std::abs(val/100.0); @@ -76,21 +61,27 @@ template struct image_filter_grammar : qi::grammar { + using alternative_type = qi::rule; + image_filter_grammar(); + qi::rule start; - qi::rule filter; - qi::rule, void(ContType&), qi::ascii::space_type> agg_blur_filter; - qi::rule, - void(ContType&), qi::ascii::space_type> scale_hsla_filter; - qi::rule, void(ContType&), qi::ascii::space_type> colorize_alpha_filter; + qi::rule> filter; qi::rule no_args; + qi::symbols alternatives; qi::uint_parser< unsigned, 10, 1, 3 > radius_; css_color_grammar css_color_; - qi::rule color_stop_offset; - phoenix::function percent_offset; - qi::rule, void(ContType&), qi::ascii::space_type> color_to_alpha_filter; + qi::rule color_stop_; + qi::rule color_stop_offset; + +private: + alternative_type & add(std::string const& symbol); + static constexpr unsigned max_alternatives = 16; + unsigned num_alternatives = 0; + alternative_type alternative_storage[max_alternatives]; }; -} +} // namespace mapnik -#endif // MAPNIK_IMAGE_FILITER_PARSER_HPP +#endif // MAPNIK_IMAGE_FILTER_GRAMMAR_HPP diff --git a/include/mapnik/image_filter_grammar_impl.hpp b/include/mapnik/image_filter_grammar_impl.hpp index 4dfa54038..bf1770083 100644 --- a/include/mapnik/image_filter_grammar_impl.hpp +++ b/include/mapnik/image_filter_grammar_impl.hpp @@ -29,6 +29,14 @@ #include #pragma GCC diagnostic pop +namespace { // internal + + BOOST_PHOENIX_ADAPT_FUNCTION( + typename std::remove_reference::type, ovo, // = optional_value_or + boost::get_optional_value_or, 2) + +} // namespace internal + namespace mapnik { namespace qi = boost::spirit::qi; @@ -41,97 +49,93 @@ image_filter_grammar::image_filter_grammar() qi::lit_type lit; qi::_val_type _val; qi::_1_type _1; + qi::_2_type _2; + qi::_3_type _3; + qi::_4_type _4; + qi::_5_type _5; + qi::_6_type _6; + qi::_7_type _7; + qi::_8_type _8; qi::_a_type _a; - qi::_b_type _b; - qi::_c_type _c; - qi::_d_type _d; - qi::_e_type _e; - qi::_f_type _f; - qi::_g_type _g; - qi::_h_type _h; - qi::_r1_type _r1; - qi::eps_type eps; - qi::char_type char_; + qi::attr_type attr; qi::double_type double_; - qi::no_skip_type no_skip; + qi::hold_type hold; + qi::omit_type omit; using phoenix::push_back; using phoenix::construct; - using phoenix::at_c; - start = -(filter % no_skip[*char_(", ")]) + + // functions + phoenix::function percent_offset; + + start = -(filter % *lit(',')) ; - filter = - lit("emboss") >> no_args [push_back(_val,construct())] - | - lit("blur") >> no_args [push_back(_val,construct())] - | - lit("gray") >> no_args [push_back(_val,construct())] - | - lit("edge-detect") >> no_args [push_back(_val,construct())] - | - lit("sobel") >> no_args [push_back(_val,construct())] - | - lit("sharpen") >> no_args [push_back(_val,construct())] - | - lit("x-gradient") >> no_args [push_back(_val,construct())] - | - lit("y-gradient") >> no_args [push_back(_val,construct())] - | - lit("invert") >> no_args [push_back(_val,construct())] - | - lit("color-blind-protanope") >> no_args [push_back(_val,construct())] - | - lit("color-blind-deuteranope") >> no_args [push_back(_val,construct())] - | - lit("color-blind-tritanope") >> no_args [push_back(_val,construct())] - | - agg_blur_filter(_val) - | - scale_hsla_filter(_val) - | - colorize_alpha_filter(_val) - | - color_to_alpha_filter(_val) + filter = omit[alternatives[_a = _1]] >> qi::lazy(*_a) ; - agg_blur_filter = lit("agg-stack-blur")[_a = 1, _b = 1] - >> -( lit('(') >> -( radius_[_a = _1][_b = _1] - >> -(lit(',') >> radius_[_b = _1])) - >> lit(')')) - [push_back(_r1,construct(_a,_b))] - ; + add("emboss") = no_args >> attr(construct()); + add("blur") = no_args >> attr(construct()); + add("gray") = no_args >> attr(construct()); + add("edge-detect") = no_args >> attr(construct()); + add("sobel") = no_args >> attr(construct()); + add("sharpen") = no_args >> attr(construct()); + add("x-gradient") = no_args >> attr(construct()); + add("y-gradient") = no_args >> attr(construct()); + add("invert") = no_args >> attr(construct()); + add("color-blind-protanope") = no_args >> attr(construct()); + add("color-blind-deuteranope") = no_args >> attr(construct()); + add("color-blind-tritanope") = no_args >> attr(construct()); - scale_hsla_filter = lit("scale-hsla") - >> lit('(') - >> double_[_a = _1] >> lit(',') >> double_[_b = _1] >> lit(',') - >> double_[_c = _1] >> lit(',') >> double_[_d = _1] >> lit(',') - >> double_[_e = _1] >> lit(',') >> double_[_f = _1] >> lit(',') - >> double_[_g = _1] >> lit(',') >> double_[_h = _1] >> lit(')') - [push_back(_r1, construct(_a,_b,_c,_d,_e,_f,_g,_h))] - ; - - colorize_alpha_filter = lit("colorize-alpha")[_a = construct()] - >> lit('(') - >> (css_color_[at_c<0>(_b) = _1, at_c<1>(_b) = 0] - >> -color_stop_offset(_b)) [push_back(_a,_b)] - >> -(+(lit(',') >> css_color_[at_c<0>(_b) =_1,at_c<1>(_b) = 0] - >> -color_stop_offset(_b))[push_back(_a,_b)]) - >> lit(')') [push_back(_r1,_a)] - ; - - color_stop_offset = (double_ >> lit('%'))[at_c<1>(_r1) = percent_offset(_1)] + add("agg-stack-blur") = + (lit('(') >> radius_ >> -( lit(',') >> radius_ ) >> lit(')')) + [push_back(_val, construct(_1, ovo(_2, _1)))] | - double_[at_c<1>(_r1) = _1] + no_args + [push_back(_val, construct(1, 1))] ; - color_to_alpha_filter = lit("color-to-alpha") - >> lit('(') - >> css_color_[_a = _1] - >> lit(')') - [push_back(_r1,construct(_a))] + add("scale-hsla") = + (lit('(') + >> double_ >> lit(',') >> double_ >> lit(',') + >> double_ >> lit(',') >> double_ >> lit(',') + >> double_ >> lit(',') >> double_ >> lit(',') + >> double_ >> lit(',') >> double_ >> lit(')')) + [push_back(_val, construct(_1,_2,_3,_4,_5,_6,_7,_8))] + ; + + add("colorize-alpha") = qi::as() + [lit('(') >> color_stop_ % lit(',') >> lit(')')] + [push_back(_val, _1)] + ; + + color_stop_ = (css_color_ >> -color_stop_offset) + [_val = construct(_1, ovo(_2, 0.0))] + ; + + color_stop_offset = double_[_val = _1] + >> -lit('%')[_val = percent_offset(_val)] + ; + + add("color-to-alpha") = + hold[lit('(') >> css_color_ >> lit(')')] + [push_back(_val, construct(_1))] ; no_args = -(lit('(') >> lit(')')); } +template +auto image_filter_grammar::add(std::string const& symbol) + -> alternative_type & +{ + if (num_alternatives >= max_alternatives) + { + throw std::length_error("too many alternatives in image_filter_grammar"); + } + + alternative_storage[num_alternatives].name(symbol); + alternatives.add(symbol, &alternative_storage[num_alternatives]); + return alternative_storage[num_alternatives++]; } + +} // namespace mapnik diff --git a/include/mapnik/image_impl.hpp b/include/mapnik/image_impl.hpp index 732e7ebe6..c756547b0 100644 --- a/include/mapnik/image_impl.hpp +++ b/include/mapnik/image_impl.hpp @@ -43,14 +43,6 @@ image_dimensions::image_dimensions(int width, int height) if (height < 0 || static_cast(height) > max_size) throw std::runtime_error("Invalid height for image dimensions requested"); } -template -image_dimensions& image_dimensions::operator= (image_dimensions rhs) -{ - std::swap(width_, rhs.width_); - std::swap(height_, rhs.height_); - return *this; -} - template std::size_t image_dimensions::width() const { diff --git a/include/mapnik/image_null.hpp b/include/mapnik/image_null.hpp index 67dbbd358..5a698bbc9 100644 --- a/include/mapnik/image_null.hpp +++ b/include/mapnik/image_null.hpp @@ -25,6 +25,7 @@ // mapnik #include +#include #include //stl @@ -47,9 +48,6 @@ public: bool /*initialize*/ = true, bool /*premultiplied*/ = false, bool /*painted*/ = false) {} - image(image const&) {} - image(image &&) noexcept {} - image& operator=(image) { return *this; } bool operator==(image const&) const { return true; } bool operator<(image const&) const { return false; } diff --git a/include/mapnik/image_options.hpp b/include/mapnik/image_options.hpp index fc8f9f1a5..d44b2bf35 100644 --- a/include/mapnik/image_options.hpp +++ b/include/mapnik/image_options.hpp @@ -25,7 +25,12 @@ #include #include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace mapnik { diff --git a/include/mapnik/image_reader.hpp b/include/mapnik/image_reader.hpp index a15d7c9dd..6c1c2329c 100644 --- a/include/mapnik/image_reader.hpp +++ b/include/mapnik/image_reader.hpp @@ -29,8 +29,12 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + // stl #include #include diff --git a/include/mapnik/image_scaling.hpp b/include/mapnik/image_scaling.hpp index ddae3689f..461e99f27 100644 --- a/include/mapnik/image_scaling.hpp +++ b/include/mapnik/image_scaling.hpp @@ -30,8 +30,11 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace mapnik { diff --git a/include/mapnik/image_scaling_traits.hpp b/include/mapnik/image_scaling_traits.hpp index 69eec5a05..b8daff152 100644 --- a/include/mapnik/image_scaling_traits.hpp +++ b/include/mapnik/image_scaling_traits.hpp @@ -24,9 +24,12 @@ #define MAPNIK_IMAGE_SCALING_TRAITS_HPP // mapnik -#include +#include +#include +#include -// agg +#pragma GCC diagnostic push +#include #include "agg_image_accessors.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" @@ -34,6 +37,7 @@ #include "agg_span_image_filter_gray.h" #include "agg_span_image_filter_rgba.h" #include "agg_span_interpolator_linear.h" +#pragma GCC diagnostic pop namespace mapnik { namespace detail { diff --git a/include/mapnik/image_util_jpeg.hpp b/include/mapnik/image_util_jpeg.hpp index b8b213a0c..feb810533 100644 --- a/include/mapnik/image_util_jpeg.hpp +++ b/include/mapnik/image_util_jpeg.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_IMAGE_UTIL_JPEG_HPP #define MAPNIK_IMAGE_UTIL_JPEG_HPP +#include + // stl #include #include diff --git a/include/mapnik/image_util_png.hpp b/include/mapnik/image_util_png.hpp index e02cb4427..8592c4fd4 100644 --- a/include/mapnik/image_util_png.hpp +++ b/include/mapnik/image_util_png.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_IMAGE_UTIL_PNG_HPP #define MAPNIK_IMAGE_UTIL_PNG_HPP +#include + // stl #include #include diff --git a/include/mapnik/image_view.hpp b/include/mapnik/image_view.hpp index c2f023a30..846da6691 100644 --- a/include/mapnik/image_view.hpp +++ b/include/mapnik/image_view.hpp @@ -37,11 +37,7 @@ public: static constexpr std::size_t pixel_size = sizeof(pixel_type); image_view(std::size_t x, std::size_t y, std::size_t width, std::size_t height, T const& data); - ~image_view(); - image_view(image_view const& rhs); - image_view(image_view && other) noexcept; - image_view& operator=(image_view rhs) = delete; bool operator==(image_view const& rhs) const; bool operator<(image_view const& rhs) const; diff --git a/include/mapnik/image_view_any.hpp b/include/mapnik/image_view_any.hpp index f61e33db5..23c9779d8 100644 --- a/include/mapnik/image_view_any.hpp +++ b/include/mapnik/image_view_any.hpp @@ -47,8 +47,9 @@ struct MAPNIK_DECL image_view_any : image_view_base image_view_any() = default; template - image_view_any(T && data) noexcept - : image_view_base(std::move(data)) {} + image_view_any(T && data) + noexcept(std::is_nothrow_constructible::value) + : image_view_base(std::forward(data)) {} std::size_t width() const; std::size_t height() const; diff --git a/include/mapnik/image_view_impl.hpp b/include/mapnik/image_view_impl.hpp index 89ae15182..14032042a 100644 --- a/include/mapnik/image_view_impl.hpp +++ b/include/mapnik/image_view_impl.hpp @@ -42,25 +42,6 @@ image_view::image_view(std::size_t x, std::size_t y, std::size_t width, std:: if (y_ + height_ > data_.height()) height_ = data_.height() - y_; } -template -image_view::~image_view() {} - -template -image_view::image_view(image_view const& rhs) - : x_(rhs.x_), - y_(rhs.y_), - width_(rhs.width_), - height_(rhs.height_), - data_(rhs.data_) {} - -template -image_view::image_view(image_view && other) noexcept - : x_(std::move(other.x_)), - y_(std::move(other.y_)), - width_(std::move(other.width_)), - height_(std::move(other.height_)), - data_(std::move(other.data_)) {} - template bool image_view::operator==(image_view const& rhs) const { diff --git a/include/mapnik/image_view_null.hpp b/include/mapnik/image_view_null.hpp index 5672c05dd..76ebc5f49 100644 --- a/include/mapnik/image_view_null.hpp +++ b/include/mapnik/image_view_null.hpp @@ -23,7 +23,7 @@ #ifndef MAPNIK_IMAGE_VIEW_NULL_HPP #define MAPNIK_IMAGE_VIEW_NULL_HPP -#include +#include //stl #include diff --git a/include/mapnik/json/attribute_value_visitor.hpp b/include/mapnik/json/attribute_value_visitor.hpp new file mode 100644 index 000000000..206530cae --- /dev/null +++ b/include/mapnik/json/attribute_value_visitor.hpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP +#define MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP + +// mapnik +#include +#include +#include +#include + +namespace mapnik { namespace json { + +struct attribute_value_visitor +{ +public: + attribute_value_visitor(mapnik::transcoder const& tr) + : tr_(tr) {} + + mapnik::value operator()(std::string const& val) const + { + return mapnik::value(tr_.transcode(val.c_str())); + } + + mapnik::value operator()(std::vector const& array) const + { + std::string str = stringifier()(array); + return mapnik::value(tr_.transcode(str.c_str())); + } + + mapnik::value operator()(std::vector > const& object) const + { + std::string str = stringifier()(object); + return mapnik::value(tr_.transcode(str.c_str())); + } + + template + mapnik::value operator()(T const& val) const + { + return mapnik::value(val); + } + + mapnik::transcoder const& tr_; +}; + +}} + +#endif //MAPNIK_JSON_ATTRIBUTE_VALUE_VISITOR_HPP diff --git a/include/mapnik/json/error_handler.hpp b/include/mapnik/json/error_handler.hpp index 46a92c82e..1e66427ad 100644 --- a/include/mapnik/json/error_handler.hpp +++ b/include/mapnik/json/error_handler.hpp @@ -24,13 +24,18 @@ #define MAPNIK_JSON_ERROR_HANDLER_HPP #include + #pragma GCC diagnostic push #include -#include -#include +#include +namespace boost { namespace spirit { struct info; } } #pragma GCC diagnostic pop + // mapnik +#ifdef MAPNIK_LOG #include +#endif + // stl #include #include diff --git a/include/mapnik/json/extract_bounding_box_grammar.hpp b/include/mapnik/json/extract_bounding_box_grammar.hpp index 7d0b7a1ac..906e7126d 100644 --- a/include/mapnik/json/extract_bounding_box_grammar.hpp +++ b/include/mapnik/json/extract_bounding_box_grammar.hpp @@ -32,73 +32,31 @@ #pragma GCC diagnostic push #include #include -#include -#include #pragma GCC diagnostic pop -// stl -#include - namespace mapnik { namespace json { -using position_type = mapnik::geometry::point; -using boxes_type = std::vector, std::pair>>; - namespace qi = boost::spirit::qi; -struct calculate_bounding_box_impl -{ - using result_type = void; - template - result_type operator() (T0 & bbox, T1 const& pos) const - { - if (pos) - { - double x = pos->x; - double y = pos->y; - if (!bbox.valid()) - { - bbox.init(x, y, x, y); //TODO: add init(x,y) convinience method - } - else - { - bbox.expand_to_include(x, y); - } - } - } -}; - -struct push_box_impl -{ - using result_type = void; - template - void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const - { - if (box.valid()) boxes.emplace_back(box, std::make_pair(std::distance(begin, range.begin()), std::distance(range.begin(), range.end()))); - } -}; - -template > +template > struct extract_bounding_box_grammar : - qi::grammar + qi::grammar { + using position_type = mapnik::geometry::point; + using boxes_type = Boxes; + using box_type = typename Boxes::value_type::first_type; extract_bounding_box_grammar(); // rules qi::rule start; qi::rule, void(boxes_type&), space_type> features; - qi::rule>, void(boxes_type&, Iterator const&), space_type> feature; - qi::rule>, box2d(), space_type> coords; + qi::rule, void(boxes_type&, Iterator const&), space_type> feature; + qi::rule, box_type(), space_type> coords; qi::rule(), space_type> pos; - qi::rule&), space_type> ring; - qi::rule&), space_type> rings; - qi::rule&), space_type> rings_array; + qi::rule ring; + qi::rule rings; + qi::rule rings_array; // generic JSON support json::generic_json json; - // phoenix functions - boost::phoenix::function push_box; - boost::phoenix::function calculate_bounding_box; - // error handler - boost::phoenix::function const error_handler; }; }} diff --git a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp index a6d3218cc..25ddbcd92 100644 --- a/include/mapnik/json/extract_bounding_box_grammar_impl.hpp +++ b/include/mapnik/json/extract_bounding_box_grammar_impl.hpp @@ -22,24 +22,60 @@ // mapnik #include - +#include // boost #include #include #include #include #include +#include // stl #include #include namespace mapnik { namespace json { +struct calculate_bounding_box_impl +{ + using result_type = void; + template + result_type operator() (T0 & bbox, T1 const& pos) const + { + if (pos) + { + typename T0::value_type x = pos->x; + typename T0::value_type y = pos->y; + if (!bbox.valid()) + { + bbox.init(x, y); + } + else + { + bbox.expand_to_include(x, y); + } + } + } +}; + +struct push_box_impl +{ + using result_type = void; + template + void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const + { + if (box.valid()) boxes.emplace_back(box, + std::make_pair(std::distance(begin, + range.begin()), + std::distance(range.begin(), range.end()))); + } +}; + namespace repo = boost::spirit::repository; -template -extract_bounding_box_grammar::extract_bounding_box_grammar() - : extract_bounding_box_grammar::base_type(start,"bounding boxes") +template +extract_bounding_box_grammar::extract_bounding_box_grammar() + : extract_bounding_box_grammar::base_type(start, "GeoJSON bounding boxes") { qi::lit_type lit; qi::double_type double_; @@ -61,6 +97,12 @@ extract_bounding_box_grammar::extract_bounding_box_gramm using qi::fail; using qi::on_error; + // phoenix functions + boost::phoenix::function push_box; + boost::phoenix::function calculate_bounding_box; + // error handler + boost::phoenix::function const error_handler; + start = features(_r1) ; @@ -68,7 +110,7 @@ extract_bounding_box_grammar::extract_bounding_box_gramm >> *((json.key_value - lit("\"features\"")) >> lit(',')) >> lit("\"features\"") >> lit(':')) - >> lit('[') >> (feature(_r1,_a) % lit(',')) >> lit(']') + >> lit('[') >> -(feature(_r1,_a) % lit(',')) >> lit(']') ; feature = raw[lit('{')[_a = 1] @@ -106,13 +148,10 @@ extract_bounding_box_grammar::extract_bounding_box_gramm json.value = json.object | json.array | json.string_ | json.number ; - json.pairs = json.key_value % lit(',') + json.key_value = json.string_ >> lit(':') >> json.value ; - json.key_value = (json.string_ >> lit(':') >> json.value) - ; - - json.object = lit('{') >> *json.pairs >> lit('}') + json.object = lit('{') >> json.key_value % lit(',') >> lit('}') ; json.array = lit('[') diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index a4bdfa15e..c329eb7f5 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -24,14 +24,10 @@ #define MAPNIK_FEATURE_GRAMMAR_HPP // mapnik -#include #include #include -#include -#include -#include -#include - +#include +#include #pragma GCC diagnostic push #include #include @@ -45,27 +41,6 @@ namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; namespace fusion = boost::fusion; -class attribute_value_visitor - -{ -public: - attribute_value_visitor(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value operator()(std::string const& val) const - { - return mapnik::value(tr_.transcode(val.c_str())); - } - - template - mapnik::value operator()(T const& val) const - { - return mapnik::value(val); - } - - mapnik::transcoder const& tr_; -}; - struct put_property { using result_type = void; @@ -89,13 +64,10 @@ struct set_geometry_impl } }; -template > -struct feature_grammar : - qi::grammar +template > +struct feature_grammar : qi::grammar { - feature_grammar(mapnik::transcoder const& tr); - + explicit feature_grammar(mapnik::transcoder const& tr); // generic JSON generic_json json_; // geoJSON @@ -104,9 +76,6 @@ struct feature_grammar : qi::rule feature_type; qi::rule properties; qi::rule, void(FeatureType &),space_type> attributes; - qi::rule attribute_value; - qi::rule, std::string(), space_type> stringify_object; - qi::rule, std::string(), space_type> stringify_array; // functions phoenix::function put_property_; phoenix::function set_geometry; diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index 61a23f985..0fc4205ad 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -50,23 +50,22 @@ feature_grammar::feature_grammar(mapnik::tran using phoenix::construct; // generic json types - json_.value = json_.object | json_.array | json_.string_ | json_.number + json_.value = json_.object | json_.array | json_.string_ | json_.number ; - json_.pairs = json_.key_value % lit(',') - ; - - json_.key_value = (json_.string_ > lit(':') > json_.value) + json_.key_value = json_.string_ > lit(':') > json_.value ; json_.object = lit('{') - > *json_.pairs + > -(json_.key_value % lit(',')) > lit('}') ; + json_.array = lit('[') - > json_.value > *(lit(',') > json_.value) + > -(json_.value % lit(',')) > lit(']') ; + json_.number = json_.strict_double[_val = json_.double_converter(_1)] | json_.int__[_val = json_.integer_converter(_1)] | lit("true") [_val = true] @@ -95,24 +94,13 @@ feature_grammar::feature_grammar(mapnik::tran > lit(':') > ((lit('{') > -attributes(_r1) > lit('}')) | lit("null")) ; - attributes = (json_.string_ [_a = _1] > lit(':') > attribute_value [put_property_(_r1,_a,_1)]) % lit(',') - ; - - attribute_value %= json_.number | json_.string_ | stringify_object | stringify_array - ; - - stringify_object %= char_('{')[_a = 1 ] > *(eps(_a > 0) > (char_('{')[_a +=1] | char_('}')[_a -=1] | char_)) - ; - - stringify_array %= char_('[')[_a = 1 ] > *(eps(_a > 0) > (char_('[')[_a +=1] | char_(']')[_a -=1] | char_)) + attributes = (json_.string_ [_a = _1] > lit(':') > json_.value [put_property_(_r1,_a,_1)]) % lit(',') ; feature.name("Feature"); feature_type.name("type"); properties.name("properties"); attributes.name("Attributes"); - attribute_value.name("Attribute Value"); - on_error(feature, error_handler(_1, _2, _3, _4)); } diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index 331341066..7ea1bc05f 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -31,15 +31,47 @@ #include #include #include +#include #pragma GCC diagnostic pop +#include + namespace mapnik { namespace json { namespace qi = boost::spirit::qi; namespace standard = boost::spirit::standard; namespace phoenix = boost::phoenix; using space_type = standard::space_type; -using json_value = mapnik::util::variant; + +struct json_value; + +using json_array = std::vector; +using json_object_element = std::pair; +using json_object = std::vector; +using json_value_base = mapnik::util::variant, + mapnik::util::recursive_wrapper >; +struct json_value : json_value_base +{ +#if __cpp_inheriting_constructors >= 200802 + + using json_value_base::json_value_base; + +#else + + json_value() = default; + + template + json_value(T && val) + : json_value_base(std::forward(val)) {} + +#endif +}; + using uchar = std::uint32_t; // a unicode code point // unicode string grammar via boost/libs/spirit/example/qi/json/json/parser/grammar.hpp @@ -121,10 +153,14 @@ unicode_string::unicode_string() escape = ('x' > hex) [push_utf8(_r1, _1)] - | ('u' > hex4) [push_utf8(_r1, _1)] - | ('U' > hex8) [push_utf8(_r1, _1)] - | char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)] - | eol // continue to next line + | + ('u' > hex4) [push_utf8(_r1, _1)] + | + ('U' > hex8) [push_utf8(_r1, _1)] + | + char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)] + | + eol // continue to next line ; char_esc = @@ -132,7 +168,7 @@ unicode_string::unicode_string() ; double_quoted = - '"' + '"' > *(char_esc(_val) | (~char_('"')) [_val += _1]) > '"' ; @@ -141,18 +177,17 @@ unicode_string::unicode_string() template struct generic_json { - qi::rule value; - qi::int_parser int__; + qi::rule value; + qi::int_parser int__; unicode_string string_; - qi::rule key_value; - qi::rule number; - qi::rule object; - qi::rule array; - qi::rule pairs; - qi::real_parser > strict_double; + qi::rule key_value; + qi::rule number; + qi::rule object; + qi::rule array; + qi::real_parser> strict_double; // conversions - boost::phoenix::function > integer_converter; - boost::phoenix::function > double_converter; + boost::phoenix::function> integer_converter; + boost::phoenix::function> double_converter; }; }} diff --git a/include/mapnik/json/geometry_generator_grammar.hpp b/include/mapnik/json/geometry_generator_grammar.hpp index eb484b698..0e314650b 100644 --- a/include/mapnik/json/geometry_generator_grammar.hpp +++ b/include/mapnik/json/geometry_generator_grammar.hpp @@ -27,12 +27,12 @@ #include #include #include -#include // boost #pragma GCC diagnostic push #include #include #include +#include #include // for vc++ and android whose c++11 libs lack std::trunc #include #pragma GCC diagnostic pop diff --git a/include/mapnik/json/geometry_generator_grammar_impl.hpp b/include/mapnik/json/geometry_generator_grammar_impl.hpp index 62d6a85ff..87a60db70 100644 --- a/include/mapnik/json/geometry_generator_grammar_impl.hpp +++ b/include/mapnik/json/geometry_generator_grammar_impl.hpp @@ -24,6 +24,7 @@ #include #include #include +#include // boost #pragma GCC diagnostic push diff --git a/include/mapnik/json/geometry_grammar.hpp b/include/mapnik/json/geometry_grammar.hpp index 7d768a785..4b0d1194c 100644 --- a/include/mapnik/json/geometry_grammar.hpp +++ b/include/mapnik/json/geometry_grammar.hpp @@ -30,9 +30,11 @@ #include #include -// spirit::qi +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop namespace mapnik { namespace json { @@ -49,6 +51,8 @@ struct geometry_grammar : qi::symbols geometry_type_dispatch; positions_grammar coordinates; boost::phoenix::function create_geometry; + // generic JSON + generic_json json_; // error handler ErrorHandler error_handler; }; diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index 30fad882c..285be2744 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -24,14 +24,10 @@ #include #include #include -#include - +#include // boost -#include #include -#include -#include // for clog, endl, etc -#include // for string +#include namespace mapnik { namespace json { @@ -57,12 +53,38 @@ geometry_grammar::geometry_grammar() start = geometry.alias() | lit("null"); + // generic json types + json_.value = json_.object | json_.array | json_.string_ | json_.number + ; + + json_.key_value = json_.string_ > lit(':') > json_.value + ; + + json_.object = lit('{') + > -(json_.key_value % lit(',')) + > lit('}') + ; + + json_.array = lit('[') + > -(json_.value % lit(',')) + > lit(']') + ; + + json_.number = json_.strict_double + | json_.int__ + | lit("true") + | lit ("false") + | lit("null") + ; + geometry = lit('{')[_a = 0] - > (-lit(',') >> (lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) - ^ - (-lit(',') >> (lit("\"coordinates\"") > lit(':') > coordinates[_b = _1])) - ^ - (-lit(',') >> (lit("\"geometries\"") > lit(':') > lit('[') > geometry_collection[_val = _1] > lit(']'))))[create_geometry(_val,_a,_b)] + > (((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) + | + (lit("\"coordinates\"") > lit(':') > coordinates[_b = _1]) + | + (lit("\"geometries\"") > lit(':') > lit('[') > geometry_collection[_val = _1] > lit(']')) + | + json_.key_value) % lit(',')) [create_geometry(_val,_a,_b)] > lit('}') ; diff --git a/include/mapnik/json/geometry_parser.hpp b/include/mapnik/json/geometry_parser.hpp index c83901d32..761c193f8 100644 --- a/include/mapnik/json/geometry_parser.hpp +++ b/include/mapnik/json/geometry_parser.hpp @@ -24,25 +24,13 @@ #define MAPNIK_JSON_GEOMETRY_PARSER_HPP // mapnik +#include - -#include - -// boost -#include -#include +#include namespace mapnik { namespace json { -inline bool from_geojson(std::string const& json, mapnik::geometry::geometry & geom) -{ - using namespace boost::spirit; - static const geometry_grammar g; - standard::space_type space; - char const* start = json.c_str(); - char const* end = start + json.length(); - return qi::phrase_parse(start, end, g, space, geom); -} +bool from_geojson(std::string const& json, mapnik::geometry::geometry & geom); }} diff --git a/include/mapnik/json/geometry_util.hpp b/include/mapnik/json/geometry_util.hpp index 6e8fb6794..cf538ae73 100644 --- a/include/mapnik/json/geometry_util.hpp +++ b/include/mapnik/json/geometry_util.hpp @@ -25,6 +25,7 @@ #include #include +#include namespace mapnik { namespace json { diff --git a/include/mapnik/json/positions.hpp b/include/mapnik/json/positions.hpp new file mode 100644 index 000000000..9ad10f99a --- /dev/null +++ b/include/mapnik/json/positions.hpp @@ -0,0 +1,40 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_JSON_POSITIONS_HPP +#define MAPNIK_JSON_POSITIONS_HPP + +// mapnik +#include +#include + +namespace mapnik { namespace json { + +struct empty {}; + +using position = mapnik::geometry::point; +using positions = std::vector; +using coordinates = util::variant, std::vector > > ; + +}} + +#endif // MAPNIK_JSON_POSITIONS_HPP diff --git a/include/mapnik/json/positions_grammar.hpp b/include/mapnik/json/positions_grammar.hpp index a652e8f59..75a6b21b6 100644 --- a/include/mapnik/json/positions_grammar.hpp +++ b/include/mapnik/json/positions_grammar.hpp @@ -25,51 +25,20 @@ // mapnik #include +#include #include #include #include -#include - #pragma GCC diagnostic push #include #include -#include -#include #pragma GCC diagnostic pop -// stl -#include namespace mapnik { namespace json { -struct empty {}; - -using position = mapnik::geometry::point; -using positions = std::vector; -using coordinates = util::variant, std::vector > > ; - namespace qi = boost::spirit::qi; -struct set_position_impl -{ - using result_type = void; - template - result_type operator() (T0 & coords, T1 const& pos) const - { - if (pos) coords = *pos; - } -}; - -struct push_position_impl -{ - using result_type = void; - template - result_type operator() (T0 & coords, T1 const& pos) const - { - if (pos) coords.push_back(*pos); - } -}; - template > struct positions_grammar : qi::grammar @@ -80,8 +49,6 @@ struct positions_grammar : qi::rule ring; qi::rule(), space_type> rings; qi::rule >(), space_type> rings_array; - boost::phoenix::function set_position; - boost::phoenix::function push_position; }; }} diff --git a/include/mapnik/json/positions_grammar_impl.hpp b/include/mapnik/json/positions_grammar_impl.hpp index 13476755d..65f2a93c0 100644 --- a/include/mapnik/json/positions_grammar_impl.hpp +++ b/include/mapnik/json/positions_grammar_impl.hpp @@ -22,18 +22,39 @@ // mapnik #include - +#include // boost #include #include #include #include +#include // stl #include #include namespace mapnik { namespace json { +struct set_position_impl +{ + using result_type = void; + template + result_type operator() (T0 & coords, T1 const& pos) const + { + if (pos) coords = *pos; + } +}; + +struct push_position_impl +{ + using result_type = void; + template + result_type operator() (T0 & coords, T1 const& pos) const + { + if (pos) coords.emplace_back(*pos); + } +}; + template positions_grammar::positions_grammar(ErrorHandler & error_handler) : positions_grammar::base_type(coords,"coordinates") @@ -49,6 +70,9 @@ positions_grammar::positions_grammar(ErrorHandler & erro using qi::fail; using qi::on_error; + boost::phoenix::function set_position; + boost::phoenix::function push_position; + coords = rings_array[_val = _1] | rings [_val = _1] | ring[_val = _1] | pos[set_position(_val,_1)] ; pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']') diff --git a/include/mapnik/json/properties_generator_grammar.hpp b/include/mapnik/json/properties_generator_grammar.hpp index e0f7be632..69145b8ab 100644 --- a/include/mapnik/json/properties_generator_grammar.hpp +++ b/include/mapnik/json/properties_generator_grammar.hpp @@ -25,23 +25,20 @@ #include #include -#include #pragma GCC diagnostic push #include #include -#include #include -#include -#include -#include -#include -#include -#include #pragma GCC diagnostic pop +#include +#include + namespace mapnik { namespace json { +namespace karma = boost::spirit::karma; + template struct escaped_string : karma::grammar diff --git a/include/mapnik/json/stringifier.hpp b/include/mapnik/json/stringifier.hpp new file mode 100644 index 000000000..44b9425d8 --- /dev/null +++ b/include/mapnik/json/stringifier.hpp @@ -0,0 +1,101 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_JSON_STRINGIFIER_HPP +#define MAPNIK_JSON_STRINGIFIER_HPP + +// mapnik +#include +#include +#include +// stl +#include + + +namespace mapnik { namespace json { + +struct stringifier +{ + std::string operator()(std::string const& val) const + { + return "\"" + val + "\""; + } + + std::string operator()(value_null) const + { + return "null"; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_integer val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(std::vector const& array) const + { + std::string str = "["; + bool first = true; + for (auto const& val : array) + { + if (first) first = false; + else str += ","; + str += mapnik::util::apply_visitor(*this, val); + } + str += "]"; + return str; + } + + std::string operator()(std::vector> const& object) const + { + std::string str = "{"; + bool first = true; + for (auto const& kv : object) + { + if (first) first = false; + else str += ","; + str += "\"" + kv.first + "\""; + str += ":"; + str += mapnik::util::apply_visitor(*this, kv.second); + } + str += "}"; + return str; + } +}; + +}} + + +#endif // MAPNIK_JSON_STRINGIFIER_HPP diff --git a/include/mapnik/json/symbolizer_grammar.hpp b/include/mapnik/json/symbolizer_grammar.hpp deleted file mode 100644 index 494b81f96..000000000 --- a/include/mapnik/json/symbolizer_grammar.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_SYMBOLIZER_GRAMMAR_HPP -#define MAPNIK_SYMBOLIZER_GRAMMAR_HPP - -#include - -// boost -#include -#include - -// mapnik -#include -#include -#include -#include -#include - -namespace mapnik { namespace json { - -namespace qi = boost::spirit::qi; -namespace phoenix = boost::phoenix; -namespace fusion = boost::fusion; -namespace standard_wide = boost::spirit::standard_wide; -using standard_wide::space_type; - -template -struct json_value_visitor -{ - json_value_visitor(Symbolizer & sym, mapnik::keys key) - : sym_(sym), key_(key) {} - - void operator() (value_bool val) const - { - put(sym_, key_, val); - } - - void operator() (value_integer val) const - { - put(sym_, key_, val); - } - - void operator() (value_double val) const - { - put(sym_, key_, val); - } - - void operator() (std::string const& val) const - { - set_property(sym_, key_, val); - } - - template - void operator() (T const& val) const - { - std::cerr << std::get<0>(get_meta(key_)) << ":" << val << std::endl; - //put(sym_, key_, val); - } - - Symbolizer & sym_; - keys key_; -}; - -template -struct put_property_visitor -{ - using value_type = T; - - put_property_visitor(mapnik::keys key, value_type const& val) - : key_(key), val_(val) {} - - template - void operator() (Symbolizer & sym) const - { - mapnik::util::apply_visitor(json_value_visitor(sym, key_), val_); - } - - keys key_; - value_type const& val_; -}; - -struct put_property -{ - using result_type = void; - template - result_type operator() (T0 & sym, T1 const& name, T2 const& val) const - { - try - { - mapnik::util::apply_visitor(put_property_visitor(get_key(name),val), sym); - } - catch (std::runtime_error const& err) - { - std::cerr << err.what() << std::endl; - } - } -}; - -template > -struct symbolizer_grammar : qi::grammar -{ - using json_value_type = util::variant; - symbolizer_grammar() - : symbolizer_grammar::base_type(sym, "symbolizer"), - json_() - { - qi::lit_type lit; - qi::double_type double_; - qi::int_type int_; - qi::no_skip_type no_skip; - qi::_val_type _val; - qi::_a_type _a; - qi::_r1_type _r1; - qi::_1_type _1; - standard_wide::char_type char_; - using phoenix::construct; - - // generic json types - json_.value = json_.object | json_.array | json_.string_ - | json_.number - ; - - json_.pairs = json_.key_value % lit(',') - ; - - json_.key_value = (json_.string_ >> lit(':') >> json_.value) - ; - - json_.object = lit('{') - >> *json_.pairs - >> lit('}') - ; - - json_.array = lit('[') - >> json_.value >> *(lit(',') >> json_.value) - >> lit(']') - ; - - json_.number %= json_.strict_double - | json_.int__ - | lit("true") [_val = true] - | lit ("false") [_val = false] - | lit("null")[_val = construct()] - ; - json_.unesc_char.add - ("\\\"", '\"') // quotation mark - ("\\\\", '\\') // reverse solidus - ("\\/", '/') // solidus - ("\\b", '\b') // backspace - ("\\f", '\f') // formfeed - ("\\n", '\n') // newline - ("\\r", '\r') // carrige return - ("\\t", '\t') // tab - ; - - json_.string_ %= lit('"') >> no_skip[*(json_.unesc_char | "\\u" >> json_.hex4 | (char_ - lit('"')))] >> lit('"') - ; - - sym = lit('{') - >> lit("\"type\"") >> lit(':') - >> (lit("\"PointSymbolizer\"")[_val = construct()] - | - lit("\"LineSymbolizer\"")[_val = construct()] - | - lit("\"PolygonSymbolizer\"")[_val = construct()] - ) - >> lit(',') - >> lit("\"properties\"") >> lit(':') - >> ((lit('{') >> *property(_val) >> lit('}')) | lit("null")) - >> lit('}') - ; - - property = (json_.string_ [_a = _1] >> lit(':') >> property_value [put_property_(_r1,_a,_1)]) % lit(',') - ; - - property_value %= json_.number | json_.string_ ; - - - } - - // generic JSON - generic_json json_; - // symbolizer - qi::rule sym; - qi::rule, void(mapnik::symbolizer&),space_type> property; - qi::rule property_value; - - phoenix::function put_property_; - // error - //qi::on_error(sym, error_handler(_1, _2, _3, _4)); -}; - - -}} - -#endif // MAPNIK_SYMBOLIZER_GRAMMAR_HPP diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index be64b9168..c21be95fe 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -25,14 +25,12 @@ // mapnik #include -#include #include #include #pragma GCC diagnostic push #include #include -#include #pragma GCC diagnostic pop // stl @@ -44,6 +42,138 @@ namespace qi = boost::spirit::qi; namespace fusion = boost::fusion; using space_type = mapnik::json::space_type; +struct create_point +{ + using result_type = mapnik::topojson::point; + template + result_type operator()(T0 & coord, T1 & props) const + { + mapnik::topojson::point pt; + if (coord.template is()) + { + auto const& coord_ = coord.template get(); + pt.coord = coord_; + pt.props = props; + } + return pt; + } +}; + +struct create_multi_point +{ + using result_type = mapnik::topojson::multi_point; + template + result_type operator()(T0 & coords, T1 & props) const + { + mapnik::topojson::multi_point mpt; + if (coords.template is>()) + { + auto const& points = coords.template get>(); + mpt. points = points; + mpt.props = props; + } + return mpt; + } +}; + +struct create_line_string +{ + using result_type = mapnik::topojson::linestring; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::linestring line; + if (arcs.template is>()) + { + auto const& arcs_ = arcs.template get>(); + line.rings = arcs_; + line.props = props; + } + return line; + } +}; + +struct create_multi_line_string +{ + using result_type = mapnik::topojson::multi_linestring; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::multi_linestring mline; + if (arcs.template is>>()) + { + auto const& arcs_ = arcs.template get>>(); + mline.lines = arcs_; + mline.props = props; + } + return mline; + } +}; + +struct create_polygon +{ + using result_type = mapnik::topojson::polygon; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::polygon poly; + if (arcs.template is>>()) + { + auto const& arcs_ = arcs.template get>>(); + poly.rings = arcs_; + poly.props = props; + } + return poly; + } +}; + +struct create_multi_polygon +{ + using result_type = mapnik::topojson::multi_polygon; + template + result_type operator()(T0 & arcs, T1 & props) const + { + mapnik::topojson::multi_polygon mpoly; + if (arcs.template is>>>()) + { + auto const& arcs_ = arcs.template get>>>(); + mpoly.polygons = arcs_; + mpoly.props = props; + } + return mpoly; + } +}; + + +struct create_geometry_impl +{ + using result_type = mapnik::topojson::geometry; + template + result_type operator()(T0 geom_type, T1 & coord, T2 & arcs, T3 & props) const + { + switch (geom_type) + { + case 1: //Point + return create_point()(coord, props); + case 2: //LineString + return create_line_string()(arcs, props); + case 3: //Polygon + return create_polygon()(arcs, props); + case 4: //MultiPoint + return create_multi_point()(coord, props); + case 5: //MultiLineString + return create_multi_line_string()(arcs, props); + case 6: //MultiPolygon + return create_multi_polygon()(arcs, props); + default: + break; + } + return mapnik::topojson::geometry(); //empty + } +}; + +using coordinates_type = util::variant>; +using arcs_type = util::variant, std::vector>, std::vector>>>; template > struct topojson_grammar : qi::grammar @@ -51,34 +181,24 @@ struct topojson_grammar : qi::grammar topojson_grammar(); private: // generic JSON support - json::generic_json json_; + json::generic_json json; // topoJSON qi::rule topology; qi::rule()> objects; qi::rule()> arcs; qi::rule arc; - qi::rule coordinate; + qi::rule coordinate_; + qi::rule coordinates; qi::rule transform; qi::rule bbox; - qi::rule geometry; - qi::rule point; - qi::rule multi_point; - qi::rule linestring; - qi::rule multi_linestring; - qi::rule polygon; - qi::rule multi_polygon; + qi::rule, mapnik::topojson::geometry(), space_type> geometry; qi::rule&)> geometry_collection; - qi::rule()> ring; - + qi::rule>()> rings; + qi::rule rings_array; // properties - qi::rule properties; - qi::rule attributes; - qi::rule attribute_value; - // id - qi::rule id; - // error handler - boost::phoenix::function const error_handler; + qi::rule properties_; + qi::symbols geometry_type_dispatch; }; }} diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 90e3f1a0f..f868cefc4 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -21,6 +21,51 @@ *****************************************************************************/ #include +#include + +#pragma GCC diagnostic push +#include +#include +#include +#include +#pragma GCC diagnostic pop + +BOOST_FUSION_ADAPT_STRUCT( + mapnik::topojson::coordinate, + (double, x) + (double, y) + ) + +BOOST_FUSION_ADAPT_STRUCT( + mapnik::topojson::arc, + (std::list, coordinates) + ) + +BOOST_FUSION_ADAPT_STRUCT( + mapnik::topojson::transform, + (double, scale_x) + (double, scale_y) + (double, translate_x) + (double, translate_y) + ) + +BOOST_FUSION_ADAPT_STRUCT( + mapnik::topojson::bounding_box, + (double, minx) + (double, miny) + (double, maxx) + (double, maxy) + ) + +BOOST_FUSION_ADAPT_STRUCT( + mapnik::topojson::topology, + (std::vector, geometries) + (std::vector, arcs) + (boost::optional, tr) + (boost::optional, bbox) + ) + + namespace mapnik { namespace topojson { @@ -42,30 +87,47 @@ topojson_grammar::topojson_grammar() qi::_3_type _3; qi::_4_type _4; qi::_r1_type _r1; + qi::_a_type _a; + qi::_b_type _b; + qi::_c_type _c; + qi::_d_type _d; using qi::fail; using qi::on_error; using phoenix::push_back; using phoenix::construct; - // generic json types - json_.value = json_.object | json_.array | json_.string_ | json_.number + + geometry_type_dispatch.add + ("\"Point\"",1) + ("\"LineString\"",2) + ("\"Polygon\"",3) + ("\"MultiPoint\"",4) + ("\"MultiLineString\"",5) + ("\"MultiPolygon\"",6) + ("\"GeometryCollection\"",7) ; - json_.pairs = json_.key_value % lit(',') + // error handler + boost::phoenix::function const error_handler; + boost::phoenix::function const create_geometry; + // generic JSON types + json.value = json.object | json.array | json.string_ | json.number ; - json_.key_value = (json_.string_ >> lit(':') >> json_.value) + json.key_value = json.string_ > lit(':') > json.value ; - json_.object = lit('{') >> *json_.pairs >> lit('}') + json.object = lit('{') + > -(json.key_value % lit(',')) + > lit('}') ; - json_.array = lit('[') - >> json_.value >> *(lit(',') >> json_.value) - >> lit(']') + json.array = lit('[') + > -(json.value % lit(',')) + > lit(']') ; - json_.number = json_.strict_double[_val = json_.double_converter(_1)] - | json_.int__[_val = json_.integer_converter(_1)] + json.number = json.strict_double[_val = json.double_converter(_1)] + | json.int__[_val = json.integer_converter(_1)] | lit("true")[_val = true] | lit("false")[_val = false] | lit("null")[_val = construct()] @@ -96,117 +158,70 @@ topojson_grammar::topojson_grammar() objects = lit("\"objects\"") >> lit(':') >> lit('{') - >> -((omit[json_.string_] + >> -((omit[json.string_] >> lit(':') - >> (geometry_collection(_val) | geometry)) % lit(',')) + >> (geometry_collection(_val) | geometry[push_back(_val, _1)]) % lit(','))) >> lit('}') ; - geometry = - point | - linestring | - polygon | - multi_point | - multi_linestring | - multi_polygon | - omit[json_.object] + geometry = lit('{')[_a = 0] + > ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) + | + (lit("\"coordinates\"") > lit(':') > coordinates[_b = _1]) + | + (lit("\"arcs\"") > lit(':') > rings_array[_c = _1]) + | + properties_[_d = _1] + | + json.key_value) % lit(',') + > lit('}')[_val = create_geometry(_a, _b, _c, _d)] ; + geometry_collection = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") - >> -(lit(',') >> omit[bbox]) - >> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(',')) - >> lit(']') - >> lit('}') - ; - point = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"Point\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') >> coordinate) - ^ (lit(',') >> properties) /*^ (lit(',') >> omit[id])*/) + >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") + >> lit(',') >> lit("\"geometries\"") >> lit(':') + >> lit('[') + >> -(geometry[push_back(_r1, _1)] % lit(',')) + >> lit(']') >> lit('}') ; - multi_point = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiPoint\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"coordinates\"") >> lit(':') - >> lit('[') >> -(coordinate % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - linestring = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"LineString\"") - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') >> int_ >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - multi_linestring = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiLineString\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') >> lit('[') - >> -((lit('[') >> int_ >> lit(']')) % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - polygon = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"Polygon\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') >> -(ring % lit(',')) >> lit(']')) - ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - multi_polygon = lit('{') - >> lit("\"type\"") >> lit(':') >> lit("\"MultiPolygon\"") - >> -(lit(',') >> omit[bbox]) - >> ((lit(',') >> lit("\"arcs\"") >> lit(':') - >> lit('[') - >> -((lit('[') >> -(ring % lit(',')) >> lit(']')) % lit(',')) - >> lit(']')) ^ (lit(',') >> properties) ^ (lit(',') >> omit[id])) - >> lit('}') - ; - - id = lit("\"id\"") >> lit(':') >> omit[json_.value] - ; - ring = lit('[') >> -(int_ % lit(',')) >> lit(']') ; + rings = lit('[') >> -(ring % lit(',')) >> lit(']') + ; + rings_array = lit('[') >> -(rings % lit(',')) >> lit(']') + | + rings + | + ring + ; - properties = lit("\"properties\"") + properties_ = lit("\"properties\"") >> lit(':') - >> (( lit('{') >> attributes >> lit('}')) | json_.object) + >> lit('{') >> (json.string_ >> lit(':') >> json.value) % lit(',') >> lit('}') ; - attributes = (json_.string_ >> lit(':') >> attribute_value) % lit(',') - ; - - attribute_value %= json_.number | json_.string_ ; - arcs = lit("\"arcs\"") >> lit(':') >> lit('[') >> -( arc % lit(',')) >> lit(']') ; - arc = lit('[') >> -(coordinate % lit(',')) >> lit(']') ; + arc = lit('[') >> -(coordinate_ % lit(',')) >> lit(']') ; - coordinate = lit('[') >> double_ >> lit(',') >> double_ >> lit(']'); + coordinate_ = lit('[') > double_ > lit(',') > double_ > lit(']'); + + coordinates = (lit('[') >> coordinate_ % lit(',') > lit(']')) + | coordinate_; topology.name("topology"); transform.name("transform"); objects.name("objects"); arc.name("arc"); arcs.name("arcs"); - json_.value.name("value"); - coordinate.name("coordinate"); - - point.name("point"); - multi_point.name("multi_point"); - linestring.name("linestring"); - polygon.name("polygon"); - multi_polygon.name("multi_polygon"); + json.value.name("value"); + coordinate_.name("coordinate"); + geometry.name("geometry"); + properties_.name("properties"); geometry_collection.name("geometry_collection"); // error handler on_error(topology, error_handler(_1, _2, _3, _4)); diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index be6a83a2c..40a2c91ff 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * Copyright (C) 2016 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,12 @@ // mapnik #include +#include #include +#include +#include +#include +#include namespace mapnik { namespace topojson { @@ -35,6 +40,11 @@ struct bounding_box_visitor : topo_(topo), num_arcs_(topo_.arcs.size()) {} + box2d operator() (mapnik::topojson::empty const&) const + { + return box2d(); + } + box2d operator() (mapnik::topojson::point const& pt) const { double x = pt.coord.x; @@ -50,27 +60,25 @@ struct bounding_box_visitor box2d operator() (mapnik::topojson::multi_point const& multi_pt) const { box2d bbox; - if (num_arcs_ > 0) + bool first = true; + double px = 0, py = 0; + for (auto const& pt : multi_pt.points) { - bool first = true; - for (auto const& pt : multi_pt.points) + double x = pt.x; + double y = pt.y; + if (topo_.tr) { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; // TODO : delta encoded ? - } - if (first) - { - first = false; - bbox.init(x,y,x,y); - } - else - { - bbox.expand_to_include(x,y); - } + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + if (first) + { + first = false; + bbox.init(x,y,x,y); + } + else + { + bbox.expand_to_include(x,y); } } return bbox; @@ -79,50 +87,15 @@ struct bounding_box_visitor box2d operator() (mapnik::topojson::linestring const& line) const { box2d bbox; + bool first = true; if (num_arcs_ > 0) { - index_type index = line.ring; - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - bool first = true; - double px = 0, py = 0; - auto const& arcs = topo_.arcs[arc_index]; - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - if (first) - { - first = false; - bbox.init(x, y, x, y); - } - else - { - bbox.expand_to_include(x, y); - } - } - } - } - return bbox; - } - - box2d operator() (mapnik::topojson::multi_linestring const& multi_line) const - { - box2d bbox; - if (num_arcs_ > 0) - { - bool first = true; - for (auto index : multi_line.rings) + for (auto index : line.rings) { index_type arc_index = index < 0 ? std::abs(index) - 1 : index; if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) { + double px = 0, py = 0; auto const& arcs = topo_.arcs[arc_index]; for (auto pt : arcs.coordinates) @@ -150,6 +123,47 @@ struct bounding_box_visitor return bbox; } + box2d operator() (mapnik::topojson::multi_linestring const& multi_line) const + { + box2d bbox; + if (num_arcs_ > 0) + { + bool first = true; + for (auto const& line : multi_line.lines) + { + for (auto index : line) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + double px = 0, py = 0; + auto const& arcs = topo_.arcs[arc_index]; + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + if (first) + { + first = false; + bbox.init(x, y, x, y); + } + else + { + bbox.expand_to_include(x, y); + } + } + } + } + } + } + return bbox; + } + box2d operator() (mapnik::topojson::polygon const& poly) const { box2d bbox; @@ -243,6 +257,321 @@ private: std::size_t num_arcs_; }; +namespace { + +template +void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::transcoder const& tr) +{ + if ( geom.props) + { + for (auto const& p : *geom.props) + { + feature.put_new(std::get<0>(p), mapnik::util::apply_visitor(mapnik::json::attribute_value_visitor(tr),std::get<1>(p))); + } + } +} + +} + +template +struct feature_generator +{ + feature_generator(Context & ctx, mapnik::transcoder const& tr, topology const& topo, std::size_t feature_id) + : ctx_(ctx), + tr_(tr), + topo_(topo), + num_arcs_(topo.arcs.size()), + feature_id_(feature_id) {} + + feature_ptr operator() (point const& pt) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + double x = pt.coord.x; + double y = pt.coord.y; + if (topo_.tr) + { + x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + mapnik::geometry::point point(x, y); + feature->set_geometry(std::move(point)); + assign_properties(*feature, pt, tr_); + return feature; + } + + feature_ptr operator() (multi_point const& multi_pt) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + mapnik::geometry::multi_point multi_point; + multi_point.reserve(multi_pt.points.size()); + for (auto const& pt : multi_pt.points) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + multi_point.add_coord(x, y); + } + feature->set_geometry(std::move(multi_point)); + assign_properties(*feature, multi_pt, tr_); + return feature; + } + + feature_ptr operator() (linestring const& line) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + mapnik::geometry::line_string line_string; + + for (auto index : line.rings) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + auto const& arcs = topo_.arcs[arc_index]; + double px = 0, py = 0; + line_string.reserve(line_string.size() + arcs.coordinates.size()); + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + line_string.add_coord(x,y); + } + } + } + feature->set_geometry(std::move(line_string)); + assign_properties(*feature, line, tr_); + } + return feature; + } + + feature_ptr operator() (multi_linestring const& multi_line) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + mapnik::geometry::multi_line_string multi_line_string; + bool hit = false; + for (auto const& line : multi_line.lines) + { + multi_line_string.reserve(multi_line_string.size() + line.size()); + mapnik::geometry::line_string line_string; + for (auto index : line) + { + index_type arc_index = index < 0 ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + hit = true; + double px = 0, py = 0; + auto const& arcs = topo_.arcs[arc_index]; + line_string.reserve(line_string.size() + arcs.coordinates.size()); + for (auto pt : arcs.coordinates) + { + double x = pt.x; + double y = pt.y; + if (topo_.tr) + { + x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; + y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; + } + line_string.add_coord(x, y); + } + + } + } + multi_line_string.push_back(std::move(line_string)); + } + if (hit) + { + feature->set_geometry(std::move(multi_line_string)); + assign_properties(*feature, multi_line, tr_); + } + } + return feature; + } + + feature_ptr operator() (polygon const& poly) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + std::vector processed_coords; + mapnik::geometry::polygon polygon; + if (poly.rings.size() > 1) polygon.interior_rings.reserve(poly.rings.size() - 1); + bool first = true; + bool hit = false; + for (auto const& ring : poly.rings) + { + mapnik::geometry::linear_ring linear_ring; + for (auto const& index : ring) + { + double px = 0, py = 0; + bool reverse = index < 0; + index_type arc_index = reverse ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + hit = true; + auto const& arcs = topo_.arcs[arc_index]; + auto const& coords = arcs.coordinates; + processed_coords.clear(); + processed_coords.reserve(coords.size()); + for (auto const& pt : coords ) + { + double x = pt.x; + double y = pt.y; + + if (topo_.tr) + { + transform const& tr = *topo_.tr; + x = (px += x) * tr.scale_x + tr.translate_x; + y = (py += y) * tr.scale_y + tr.translate_y; + } + processed_coords.emplace_back(coordinate{x,y}); + } + linear_ring.reserve(linear_ring.size() + processed_coords.size()); + if (reverse) + { + for (auto const& c : processed_coords | boost::adaptors::reversed) + { + linear_ring.emplace_back(c.x, c.y); + } + } + else + { + for (auto const& c : processed_coords) + { + linear_ring.emplace_back(c.x, c.y); + } + } + } + } + if (first) + { + first = false; + polygon.set_exterior_ring(std::move(linear_ring)); + } + else + { + polygon.add_hole(std::move(linear_ring)); + } + } + if (hit) + { + mapnik::geometry::correct(polygon); + feature->set_geometry(std::move(polygon)); + assign_properties(*feature, poly, tr_); + } + } + return feature; + } + + feature_ptr operator() (multi_polygon const& multi_poly) const + { + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); + if (num_arcs_ > 0) + { + std::vector processed_coords; + mapnik::geometry::multi_polygon multi_polygon; + multi_polygon.reserve(multi_poly.polygons.size()); + bool hit = false; + for (auto const& poly : multi_poly.polygons) + { + bool first = true; + mapnik::geometry::polygon polygon; + if (poly.size() > 1) polygon.interior_rings.reserve(poly.size() - 1); + + for (auto const& ring : poly) + { + mapnik::geometry::linear_ring linear_ring; + for (auto const& index : ring) + { + double px = 0, py = 0; + bool reverse = index < 0; + index_type arc_index = reverse ? std::abs(index) - 1 : index; + if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) + { + hit = true; + auto const& arcs = topo_.arcs[arc_index]; + auto const& coords = arcs.coordinates; + processed_coords.clear(); + processed_coords.reserve(coords.size()); + for (auto const& pt : coords ) + { + double x = pt.x; + double y = pt.y; + + if (topo_.tr) + { + transform const& tr = *topo_.tr; + x = (px += x) * tr.scale_x + tr.translate_x; + y = (py += y) * tr.scale_y + tr.translate_y; + } + processed_coords.emplace_back(coordinate{x,y}); + } + + using namespace boost::adaptors; + linear_ring.reserve(linear_ring.size() + processed_coords.size()); + if (reverse) + { + for (auto const& c : (processed_coords | reversed)) + { + linear_ring.add_coord(c.x, c.y); + } + } + else + { + for (auto const& c : processed_coords) + { + linear_ring.add_coord(c.x, c.y); + } + } + } + } + if (first) + { + first = false; + polygon.set_exterior_ring(std::move(linear_ring)); + } + else + { + polygon.add_hole(std::move(linear_ring)); + } + } + multi_polygon.push_back(std::move(polygon)); + } + if (hit) + { + mapnik::geometry::correct(multi_polygon); + feature->set_geometry(std::move(multi_polygon)); + assign_properties(*feature, multi_poly, tr_); + } + } + return feature; + } + + template + feature_ptr operator() (T const& ) const + { + return feature_ptr(); + } + + Context & ctx_; + mapnik::transcoder const& tr_; + topology const& topo_; + std::size_t num_arcs_; + std::size_t feature_id_; +}; + + }} #endif //MAPNIK_TOPOJSON_UTILS_HPP diff --git a/include/mapnik/json/topology.hpp b/include/mapnik/json/topology.hpp index b859cfc55..048c85528 100644 --- a/include/mapnik/json/topology.hpp +++ b/include/mapnik/json/topology.hpp @@ -28,8 +28,6 @@ #pragma GCC diagnostic push #include -#include -#include #include #pragma GCC diagnostic pop @@ -64,13 +62,13 @@ struct multi_point struct linestring { - index_type ring ; + std::vector rings ; boost::optional props; }; struct multi_linestring { - std::vector rings; + std::vector > lines; boost::optional props; }; @@ -86,7 +84,10 @@ struct multi_polygon boost::optional props; }; -using geometry = util::variant, coordinates) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::transform, - (double, scale_x) - (double, scale_y) - (double, translate_x) - (double, translate_y) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::bounding_box, - (double, minx) - (double, miny) - (double, maxx) - (double, maxy) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::point, - (mapnik::topojson::coordinate, coord) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_point, - (std::vector, points) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::linestring, - (mapnik::topojson::index_type, ring) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_linestring, - (std::vector, rings) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::polygon, - (std::vector >, rings) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::multi_polygon, - (std::vector > >, polygons) - (boost::optional, props) - ) - -BOOST_FUSION_ADAPT_STRUCT( - mapnik::topojson::topology, - (std::vector, geometries) - (std::vector, arcs) - (boost::optional, tr) - (boost::optional, bbox) - ) - #endif // MAPNIK_TOPOLOGY_HPP diff --git a/include/mapnik/label_collision_detector.hpp b/include/mapnik/label_collision_detector.hpp index 74a76be7f..f751f31c3 100644 --- a/include/mapnik/label_collision_detector.hpp +++ b/include/mapnik/label_collision_detector.hpp @@ -28,8 +28,10 @@ #include #include -// icu +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include @@ -145,17 +147,17 @@ private: public: using query_iterator = tree_t::query_iterator; - explicit label_collision_detector4(box2d const& extent) - : tree_(extent) {} + explicit label_collision_detector4(box2d const& _extent) + : tree_(_extent) {} bool has_placement(box2d const& box) { - tree_t::query_iterator itr = tree_.query_in_box(box); - tree_t::query_iterator end = tree_.query_end(); + tree_t::query_iterator tree_itr = tree_.query_in_box(box); + tree_t::query_iterator tree_end = tree_.query_end(); - for ( ;itr != end; ++itr) + for ( ;tree_itr != tree_end; ++tree_itr) { - if (itr->get().box.intersects(box)) return false; + if (tree_itr->get().box.intersects(box)) return false; } return true; @@ -168,12 +170,12 @@ public: box.maxx() + margin, box.maxy() + margin) : box); - tree_t::query_iterator itr = tree_.query_in_box(margin_box); - tree_t::query_iterator end = tree_.query_end(); + tree_t::query_iterator tree_itr = tree_.query_in_box(margin_box); + tree_t::query_iterator tree_end = tree_.query_end(); - for (;itr != end; ++itr) + for (;tree_itr != tree_end; ++tree_itr) { - if (itr->get().box.intersects(margin_box)) + if (tree_itr->get().box.intersects(margin_box)) { return false; } @@ -196,12 +198,12 @@ public: box.maxx() + margin, box.maxy() + margin) : box); - tree_t::query_iterator itr = tree_.query_in_box(repeat_box); - tree_t::query_iterator end = tree_.query_end(); + tree_t::query_iterator tree_itr = tree_.query_in_box(repeat_box); + tree_t::query_iterator tree_end = tree_.query_end(); - for ( ;itr != end; ++itr) + for ( ;tree_itr != tree_end; ++tree_itr) { - if (itr->get().box.intersects(margin_box) || (text == itr->get().text && itr->get().box.intersects(repeat_box))) + if (tree_itr->get().box.intersects(margin_box) || (text == tree_itr->get().text && tree_itr->get().box.intersects(repeat_box))) { return false; } diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 23ea96a7c..9f582791b 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -34,8 +34,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/mapped_memory_cache.hpp b/include/mapnik/mapped_memory_cache.hpp index f41c2e803..1ac8d877e 100644 --- a/include/mapnik/mapped_memory_cache.hpp +++ b/include/mapnik/mapped_memory_cache.hpp @@ -28,10 +28,15 @@ #include #include -// boost #include +#include #include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace boost { namespace interprocess { class mapped_region; } } @@ -52,6 +57,8 @@ public: void clear(); }; +extern template class MAPNIK_DECL singleton; + } #endif // MAPNIK_MAPPED_MEMORY_CACHE_HPP diff --git a/include/mapnik/marker.hpp b/include/mapnik/marker.hpp index 6f7cbf02d..1feb0fecf 100644 --- a/include/mapnik/marker.hpp +++ b/include/mapnik/marker.hpp @@ -29,8 +29,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_array.h" +#pragma GCC diagnostic pop // stl #include @@ -41,8 +43,10 @@ namespace mapnik struct image_any; namespace svg { struct path_attributes; } -using attr_storage = agg::pod_bvector; -using svg_storage_type = mapnik::svg::svg_storage; +using svg::svg_path_adapter; + +using svg_attribute_type = agg::pod_bvector; +using svg_storage_type = svg::svg_storage; using svg_path_ptr = std::shared_ptr; using image_ptr = std::shared_ptr; @@ -56,23 +60,17 @@ public: bitmap_data_.set(0xff000000); } - marker_rgba8(image_rgba8 const & data) + explicit marker_rgba8(image_rgba8 const& data) : bitmap_data_(data) {} - marker_rgba8(image_rgba8 && data) + explicit marker_rgba8(image_rgba8 && data) noexcept : bitmap_data_(std::move(data)) {} - marker_rgba8(marker_rgba8 const& rhs) - : bitmap_data_(rhs.bitmap_data_) {} - - marker_rgba8(marker_rgba8 && rhs) noexcept - : bitmap_data_(std::move(rhs.bitmap_data_)) {} - box2d bounding_box() const { - std::size_t width = bitmap_data_.width(); - std::size_t height = bitmap_data_.height(); - return box2d(static_cast(0), static_cast(0), static_cast(width), static_cast(height)); + std::size_t _width = bitmap_data_.width(); + std::size_t _height = bitmap_data_.height(); + return box2d(static_cast(0), static_cast(0), static_cast(_width), static_cast(_height)); } inline double width() const @@ -97,18 +95,12 @@ private: struct marker_svg { public: - marker_svg() { } + marker_svg() = default; - marker_svg(mapnik::svg_path_ptr data) + explicit marker_svg(mapnik::svg_path_ptr data) noexcept : vector_data_(data) {} - marker_svg(marker_svg const& rhs) - : vector_data_(rhs.vector_data_) {} - - marker_svg(marker_svg && rhs) noexcept - : vector_data_(rhs.vector_data_) {} - - box2d bounding_box() const + inline box2d bounding_box() const { return vector_data_->bounding_box(); } @@ -122,11 +114,15 @@ public: return vector_data_->bounding_box().height(); } - mapnik::svg_path_ptr get_data() const + inline mapnik::svg_path_ptr get_data() const { return vector_data_; } + inline std::tuple dimensions() const + { + return std::make_tuple(vector_data_->width(), vector_data_->height()); + } private: mapnik::svg_path_ptr vector_data_; @@ -134,9 +130,8 @@ private: struct marker_null { - marker_null() = default; public: - box2d bounding_box() const + inline box2d bounding_box() const { return box2d(); } @@ -189,8 +184,9 @@ struct marker : marker_base marker() = default; template - marker(T && data) noexcept - : marker_base(std::move(data)) {} + marker(T && _data) + noexcept(std::is_nothrow_constructible::value) + : marker_base(std::forward(_data)) {} double width() const { diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 9183d6a87..8ba3c6f4b 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -35,9 +35,13 @@ #include #include #include +#include +#include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop // stl #include @@ -52,60 +56,53 @@ template struct vector_markers_dispatch : util::noncopyable { vector_markers_dispatch(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, agg::trans_affine const& marker_trans, symbolizer_base const& sym, Detector & detector, double scale_factor, feature_impl const& feature, - attributes const& vars) - : src_(src), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - feature_(feature), - vars_(vars), - scale_factor_(scale_factor) + attributes const& vars, + bool snap_to_pixels, + markers_renderer_context & renderer_context) + : params_(src->bounding_box(), recenter(src) * marker_trans, + sym, feature, vars, scale_factor, snap_to_pixels) + , renderer_context_(renderer_context) + , src_(src) + , path_(path) + , attrs_(attrs) + , detector_(detector) {} - virtual ~vector_markers_dispatch() {} - template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, feature_, vars_); - value_bool ignore_placement = get(sym_, feature_, vars_); - value_bool allow_overlap = get(sym_, feature_, vars_); - value_bool avoid_edges = get(sym_, feature_, vars_); - value_double opacity = get(sym_, feature_, vars_); - value_double spacing = get(sym_, feature_, vars_); - value_double max_error = get(sym_, feature_, vars_); - coord2d center = src_->bounding_box().center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine tr = recenter * marker_trans_; - direction_enum direction = get(sym_, feature_, vars_); - markers_placement_params params { src_->bounding_box(), tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges, direction }; markers_placement_finder placement_finder( - placement_method, path, detector_, params); + params_.placement_method, path, detector_, params_.placement_params); double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) + while (placement_finder.get_point(x, y, angle, params_.ignore_placement)) { - agg::trans_affine matrix = tr; + agg::trans_affine matrix = params_.placement_params.tr; matrix.rotate(angle); matrix.translate(x, y); - render_marker(matrix, opacity); + renderer_context_.render_marker(src_, path_, attrs_, params_, matrix); } } - virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0; - protected: + static agg::trans_affine recenter(svg_path_ptr const& src) + { + coord2d center = src->bounding_box().center(); + return agg::trans_affine_translation(-center.x, -center.y); + } + + markers_dispatch_params params_; + markers_renderer_context & renderer_context_; svg_path_ptr const& src_; - agg::trans_affine const& marker_trans_; - symbolizer_base const& sym_; + svg_path_adapter & path_; + svg_attribute_type const& attrs_; Detector & detector_; - feature_impl const& feature_; - attributes const& vars_; - double scale_factor_; }; template @@ -117,53 +114,35 @@ struct raster_markers_dispatch : util::noncopyable Detector & detector, double scale_factor, feature_impl const& feature, - attributes const& vars) - : src_(src), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - feature_(feature), - vars_(vars), - scale_factor_(scale_factor) + attributes const& vars, + markers_renderer_context & renderer_context) + : params_(box2d(0, 0, src.width(), src.height()), + marker_trans, sym, feature, vars, scale_factor) + , renderer_context_(renderer_context) + , src_(src) + , detector_(detector) {} - virtual ~raster_markers_dispatch() {} - template void add_path(T & path) { - marker_placement_enum placement_method = get(sym_, feature_, vars_); - value_bool allow_overlap = get(sym_, feature_, vars_); - value_bool avoid_edges = get(sym_, feature_, vars_); - value_double opacity = get(sym_, feature_, vars_); - value_bool ignore_placement = get(sym_, feature_, vars_); - value_double spacing = get(sym_, feature_, vars_); - value_double max_error = get(sym_, feature_, vars_); - box2d bbox(0,0, src_.width(),src_.height()); - direction_enum direction = get(sym_, feature_, vars_); - markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges, direction }; markers_placement_finder placement_finder( - placement_method, path, detector_, params); + params_.placement_method, path, detector_, params_.placement_params); double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) + while (placement_finder.get_point(x, y, angle, params_.ignore_placement)) { - agg::trans_affine matrix = marker_trans_; + agg::trans_affine matrix = params_.placement_params.tr; matrix.rotate(angle); matrix.translate(x, y); - render_marker(matrix, opacity); + renderer_context_.render_marker(src_, params_, matrix); } } - virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0; - protected: + markers_dispatch_params params_; + markers_renderer_context & renderer_context_; image_rgba8 const& src_; - agg::trans_affine const& marker_trans_; - symbolizer_base const& sym_; Detector & detector_; - feature_impl const& feature_; - attributes const& vars_; - double scale_factor_; }; void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, attributes const& vars, @@ -182,85 +161,29 @@ void setup_transform_scaling(agg::trans_affine & tr, attributes const& vars, symbolizer_base const& sym); +using vertex_converter_type = vertex_converter; + // Apply markers to a feature with multiple geometries -template -void apply_markers_multi(feature_impl const& feature, attributes const& vars, Converter & converter, Processor & proc, symbolizer_base const& sym) -{ - using vertex_converter_type = Converter; - using apply_vertex_converter_type = detail::apply_vertex_converter; - using vertex_processor_type = geometry::vertex_processor; +template +void apply_markers_multi(feature_impl const& feature, attributes const& vars, + vertex_converter_type & converter, Processor & proc, symbolizer_base const& sym); - auto const& geom = feature.get_geometry(); - geometry::geometry_types type = geometry::geometry_type(geom); - if (type == geometry::geometry_types::Point - || type == geometry::geometry_types::LineString - || type == geometry::geometry_types::Polygon) - { - apply_vertex_converter_type apply(converter, proc); - mapnik::util::apply_visitor(vertex_processor_type(apply), geom); - } - else - { +using vector_dispatch_type = vector_markers_dispatch; +using raster_dispatch_type = raster_markers_dispatch; - marker_multi_policy_enum multi_policy = get(sym, feature, vars); - marker_placement_enum placement = get(sym, feature, vars); +extern template void apply_markers_multi(feature_impl const& feature, attributes const& vars, + vertex_converter_type & converter, vector_dispatch_type & proc, symbolizer_base const& sym); + +extern template void apply_markers_multi(feature_impl const& feature, attributes const& vars, + vertex_converter_type & converter, raster_dispatch_type & proc, symbolizer_base const& sym); - if (placement == MARKER_POINT_PLACEMENT && - multi_policy == MARKER_WHOLE_MULTI) - { - geometry::point pt; - // test if centroid is contained by bounding box - if (geometry::centroid(geom, pt) && converter.disp_.args_.bbox.contains(pt.x, pt.y)) - { - // unset any clipping since we're now dealing with a point - converter.template unset(); - geometry::point_vertex_adapter va(pt); - converter.apply(va, proc); - } - } - else if ((placement == MARKER_POINT_PLACEMENT || placement == MARKER_INTERIOR_PLACEMENT) && - multi_policy == MARKER_LARGEST_MULTI) - { - // Only apply to path with largest envelope area - // TODO: consider using true area for polygon types - if (type == geometry::geometry_types::MultiPolygon) - { - geometry::multi_polygon const& multi_poly = mapnik::util::get >(geom); - double maxarea = 0; - geometry::polygon const* largest = 0; - for (geometry::polygon const& poly : multi_poly) - { - box2d bbox = geometry::envelope(poly); - double area = bbox.width() * bbox.height(); - if (area > maxarea) - { - maxarea = area; - largest = &poly; - } - } - if (largest) - { - geometry::polygon_vertex_adapter va(*largest); - converter.apply(va, proc); - } - } - else - { - MAPNIK_LOG_WARN(marker_symbolizer) << "TODO: if you get here -> open an issue"; - } - } - else - { - if (multi_policy != MARKER_EACH_MULTI && placement != MARKER_POINT_PLACEMENT) - { - MAPNIK_LOG_WARN(marker_symbolizer) << "marker_multi_policy != 'each' has no effect with marker_placement != 'point'"; - } - apply_vertex_converter_type apply(converter, proc); - mapnik::util::apply_visitor(vertex_processor_type(apply), geom); - } - } -} } diff --git a/include/mapnik/markers_placement.hpp b/include/mapnik/markers_placement.hpp index 3e7e3e495..0d4319115 100644 --- a/include/mapnik/markers_placement.hpp +++ b/include/mapnik/markers_placement.hpp @@ -29,7 +29,6 @@ #include #include #include -#include namespace mapnik { @@ -38,70 +37,99 @@ template class markers_placement_finder : util::noncopyable { public: - using markers_placement = util::variant, - markers_line_placement, - markers_interior_placement, - markers_vertex_first_placement, - markers_vertex_last_placement>; - - class get_point_visitor - { - public: - get_point_visitor(double &x, double &y, double &angle, bool ignore_placement) - : x_(x), y_(y), angle_(angle), ignore_placement_(ignore_placement) - { - } - - template - bool operator()(T &placement) const - { - return placement.get_point(x_, y_, angle_, ignore_placement_); - } - - private: - double &x_, &y_, &angle_; - bool ignore_placement_; - }; - markers_placement_finder(marker_placement_e placement_type, Locator &locator, Detector &detector, markers_placement_params const& params) - : placement_(create(placement_type, locator, detector, params)) + : placement_type_(placement_type) { + switch (placement_type) + { + default: + case MARKER_POINT_PLACEMENT: + construct(&point_, locator, detector, params); + break; + case MARKER_INTERIOR_PLACEMENT: + construct(&interior_, locator, detector, params); + break; + case MARKER_LINE_PLACEMENT: + construct(&line_, locator, detector, params); + break; + case MARKER_VERTEX_FIRST_PLACEMENT: + construct(&vertex_first_, locator, detector, params); + break; + case MARKER_VERTEX_LAST_PLACEMENT: + construct(&vertex_last_, locator, detector, params); + break; + } + } + + ~markers_placement_finder() + { + switch (placement_type_) + { + default: + case MARKER_POINT_PLACEMENT: + destroy(&point_); + break; + case MARKER_INTERIOR_PLACEMENT: + destroy(&interior_); + break; + case MARKER_LINE_PLACEMENT: + destroy(&line_); + break; + case MARKER_VERTEX_FIRST_PLACEMENT: + destroy(&vertex_first_); + break; + case MARKER_VERTEX_LAST_PLACEMENT: + destroy(&vertex_last_); + break; + } } // Get next point where the marker should be placed. Returns true if a place is found, false if none is found. bool get_point(double &x, double &y, double &angle, bool ignore_placement) { - return util::apply_visitor(get_point_visitor(x, y, angle, ignore_placement), placement_); - } - -private: - // Factory function for particular placement implementations. - static markers_placement create(marker_placement_e placement_type, - Locator &locator, - Detector &detector, - markers_placement_params const& params) - { - switch (placement_type) + switch (placement_type_) { + default: case MARKER_POINT_PLACEMENT: - return markers_point_placement(locator,detector,params); + return point_.get_point(x, y, angle, ignore_placement); case MARKER_INTERIOR_PLACEMENT: - return markers_interior_placement(locator,detector,params); + return interior_.get_point(x, y, angle, ignore_placement); case MARKER_LINE_PLACEMENT: - return markers_line_placement(locator,detector,params); + return line_.get_point(x, y, angle, ignore_placement); case MARKER_VERTEX_FIRST_PLACEMENT: - return markers_vertex_first_placement(locator,detector,params); + return vertex_first_.get_point(x, y, angle, ignore_placement); case MARKER_VERTEX_LAST_PLACEMENT: - return markers_vertex_last_placement(locator,detector,params); - default: // point - return markers_point_placement(locator,detector,params); + return vertex_last_.get_point(x, y, angle, ignore_placement); } } - markers_placement placement_; +private: + marker_placement_e const placement_type_; + + union + { + markers_point_placement point_; + markers_line_placement line_; + markers_interior_placement interior_; + markers_vertex_first_placement vertex_first_; + markers_vertex_last_placement vertex_last_; + }; + + template + static T* construct(T* what, Locator & locator, Detector & detector, + markers_placement_params const& params) + { + return new(what) T(locator, detector, params); + } + + template + static void destroy(T* what) + { + what->~T(); + } }; } diff --git a/include/mapnik/markers_placements/basic.hpp b/include/mapnik/markers_placements/basic.hpp new file mode 100644 index 000000000..abcef5ea6 --- /dev/null +++ b/include/mapnik/markers_placements/basic.hpp @@ -0,0 +1,104 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_MARKERS_PLACEMENTS_BASIC_HPP +#define MAPNIK_MARKERS_PLACEMENTS_BASIC_HPP + +// mapnik +#include +#include +#include +#include + +#pragma GCC diagnostic push +#include +#include "agg_basics.h" +#include "agg_trans_affine.h" +#pragma GCC diagnostic pop + +namespace mapnik { + +struct markers_placement_params +{ + box2d size; + agg::trans_affine tr; + double spacing; + double max_error; + bool allow_overlap; + bool avoid_edges; + direction_enum direction; +}; + +class markers_basic_placement : util::noncopyable +{ +public: + markers_basic_placement(markers_placement_params const& params) + : params_(params) + { + } + +protected: + markers_placement_params const& params_; + + // Rotates the size_ box and translates the position. + box2d perform_transform(double angle, double dx, double dy) const + { + auto tr = params_.tr * agg::trans_affine_rotation(angle).translate(dx, dy); + return box2d(params_.size, tr); + } + + bool set_direction(double & angle) const + { + switch (params_.direction) + { + case DIRECTION_UP: + angle = 0; + return true; + case DIRECTION_DOWN: + angle = M_PI; + return true; + case DIRECTION_AUTO: + if (std::fabs(util::normalize_angle(angle)) > 0.5 * M_PI) + angle += M_PI; + return true; + case DIRECTION_AUTO_DOWN: + if (std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI) + angle += M_PI; + return true; + case DIRECTION_LEFT: + angle += M_PI; + return true; + case DIRECTION_LEFT_ONLY: + angle += M_PI; + return std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI; + case DIRECTION_RIGHT_ONLY: + return std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI; + case DIRECTION_RIGHT: + default: + return true; + } + } +}; + +} // namespace mapnik + +#endif // MAPNIK_MARKERS_PLACEMENTS_BASIC_HPP diff --git a/include/mapnik/markers_placements/interior.hpp b/include/mapnik/markers_placements/interior.hpp index 93b5e3418..6a2705e15 100644 --- a/include/mapnik/markers_placements/interior.hpp +++ b/include/mapnik/markers_placements/interior.hpp @@ -33,14 +33,8 @@ template class markers_interior_placement : public markers_point_placement { public: - markers_interior_placement(Locator &locator, Detector &detector, markers_placement_params const& params) - : markers_point_placement(locator, detector, params) - { - } - - markers_interior_placement(markers_interior_placement && rhs) - : markers_point_placement(std::move(rhs)) - {} + using point_placement = markers_point_placement; + using point_placement::point_placement; bool get_point(double &x, double &y, double &angle, bool ignore_placement) { @@ -51,7 +45,7 @@ public: if (this->locator_.type() == geometry::geometry_types::Point) { - return markers_point_placement::get_point(x, y, angle, ignore_placement); + return point_placement::get_point(x, y, angle, ignore_placement); } if (this->locator_.type() == geometry::geometry_types::LineString) @@ -73,20 +67,10 @@ public: angle = 0; - box2d box = this->perform_transform(angle, x, y); - if (this->params_.avoid_edges && !this->detector_.extent().contains(box)) + if (!this->push_to_detector(x, y, angle, ignore_placement)) { return false; } - if (!this->params_.allow_overlap && !this->detector_.has_placement(box)) - { - return false; - } - - if (!ignore_placement) - { - this->detector_.insert(box); - } this->done_ = true; return true; diff --git a/include/mapnik/markers_placements/line.hpp b/include/mapnik/markers_placements/line.hpp index fe2c2bd9f..bc99cc937 100644 --- a/include/mapnik/markers_placements/line.hpp +++ b/include/mapnik/markers_placements/line.hpp @@ -35,29 +35,23 @@ template class markers_line_placement : public markers_point_placement { public: - markers_line_placement(Locator &locator, Detector &detector, markers_placement_params const& params) - : markers_point_placement(locator, detector, params), + using point_placement = markers_point_placement; + using point_placement::point_placement; + + markers_line_placement(Locator & locator, Detector & detector, + markers_placement_params const& params) + : point_placement(locator, detector, params), first_point_(true), spacing_(0.0), marker_width_((params.size * params.tr).width()), path_(locator) { spacing_ = params.spacing < 1 ? 100 : params.spacing; - rewind(); } - markers_line_placement(markers_line_placement && rhs) - : markers_point_placement(std::move(rhs)), - first_point_(std::move(rhs.first_point_)), - spacing_(std::move(rhs.spacing_)), - marker_width_(std::move(rhs.marker_width_)), - path_(std::move(rhs.path_)) - {} - void rewind() { - this->locator_.rewind(0); - this->done_ = false; + point_placement::rewind(); first_point_ = true; } @@ -70,7 +64,7 @@ public: if (this->locator_.type() == geometry::geometry_types::Point) { - return markers_point_placement::get_point(x, y, angle, ignore_placement); + return point_placement::get_point(x, y, angle, ignore_placement); } double move = spacing_; @@ -102,16 +96,10 @@ public: { continue; } - box2d box = this->perform_transform(angle, x, y); - if ((this->params_.avoid_edges && !this->detector_.extent().contains(box)) - || (!this->params_.allow_overlap && !this->detector_.has_placement(box))) + if (!this->push_to_detector(x, y, angle, ignore_placement)) { continue; } - if (!ignore_placement) - { - this->detector_.insert(box); - } return true; } } diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index 65b95ce79..6e2f1dafb 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -23,53 +23,26 @@ #ifndef MAPNIK_MARKERS_PLACEMENTS_POINT_HPP #define MAPNIK_MARKERS_PLACEMENTS_POINT_HPP -#include #include #include -#include -#include -#include -#include - -#include "agg_basics.h" -#include "agg_trans_affine.h" - -#include +#include namespace mapnik { -struct markers_placement_params -{ - box2d const& size; - agg::trans_affine const& tr; - double spacing; - double max_error; - bool allow_overlap; - bool avoid_edges; - direction_enum direction; -}; - template -class markers_point_placement : util::noncopyable +class markers_point_placement : public markers_basic_placement { public: - markers_point_placement(Locator &locator, Detector &detector, markers_placement_params const& params) - : locator_(locator), + markers_point_placement(Locator & locator, Detector & detector, + markers_placement_params const& params) + : markers_basic_placement(params), + locator_(locator), detector_(detector), - params_(params), done_(false) { - rewind(); + locator_.rewind(0); } - markers_point_placement(markers_point_placement && rhs) - : locator_(rhs.locator_), - detector_(rhs.detector_), - params_(rhs.params_), - done_(rhs.done_) - {} - - // Start again at first marker. Returns the same list of markers only works when they were NOT added to the detector. void rewind() { @@ -80,31 +53,53 @@ public: // Get next point where the marker should be placed. Returns true if a place is found, false if none is found. bool get_point(double &x, double &y, double &angle, bool ignore_placement) { - if (done_) + if (this->done_) { return false; } - if (locator_.type() == geometry::geometry_types::LineString) + if (this->locator_.type() == geometry::geometry_types::LineString) { - if (!label::middle_point(locator_, x, y)) + if (!label::middle_point(this->locator_, x, y)) { - done_ = true; + this->done_ = true; return false; } } else { - if (!label::centroid(locator_, x, y)) + if (!label::centroid(this->locator_, x, y)) { - done_ = true; + this->done_ = true; return false; } } angle = 0; - box2d box = perform_transform(angle, x, y); + if (!this->push_to_detector(x, y, angle, ignore_placement)) + { + return false; + } + + this->done_ = true; + return true; + } + +protected: + Locator & locator_; + Detector & detector_; + bool done_; + + // Checks transformed box placement with collision detector. + // returns false if the box: + // - a) isn't wholly inside extent and avoid_edges == true + // - b) collides with something and allow_overlap == false + // otherwise returns true, and if ignore_placement == false, + // also adds the box to collision detector + bool push_to_detector(double x, double y, double angle, bool ignore_placement) + { + auto box = perform_transform(angle, x, y); if (params_.avoid_edges && !detector_.extent().contains(box)) { return false; @@ -113,73 +108,12 @@ public: { return false; } - if (!ignore_placement) { detector_.insert(box); } - - done_ = true; return true; } - -protected: - Locator &locator_; - Detector &detector_; - markers_placement_params const& params_; - bool done_; - - // Rotates the size_ box and translates the position. - box2d perform_transform(double angle, double dx, double dy) - { - double x1 = params_.size.minx(); - double x2 = params_.size.maxx(); - double y1 = params_.size.miny(); - double y2 = params_.size.maxy(); - agg::trans_affine tr = params_.tr * agg::trans_affine_rotation(angle).translate(dx, dy); - double xA = x1, yA = y1, - xB = x2, yB = y1, - xC = x2, yC = y2, - xD = x1, yD = y2; - tr.transform(&xA, &yA); - tr.transform(&xB, &yB); - tr.transform(&xC, &yC); - tr.transform(&xD, &yD); - box2d result(xA, yA, xC, yC); - result.expand_to_include(xB, yB); - result.expand_to_include(xD, yD); - return result; - } - - bool set_direction(double & angle) - { - switch (params_.direction) - { - case DIRECTION_UP: - angle = .0; - return true; - case DIRECTION_DOWN: - angle = M_PI; - return true; - case DIRECTION_AUTO: - angle = (std::fabs(util::normalize_angle(angle)) > 0.5 * M_PI) ? (angle + M_PI) : angle; - return true; - case DIRECTION_AUTO_DOWN: - angle = (std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI) ? (angle + M_PI) : angle; - return true; - case DIRECTION_LEFT: - angle += M_PI; - return true; - case DIRECTION_LEFT_ONLY: - angle += M_PI; - return std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI; - case DIRECTION_RIGHT_ONLY: - return std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI; - case DIRECTION_RIGHT: - default: - return true; - } - } }; } diff --git a/include/mapnik/markers_placements/vertext_first.hpp b/include/mapnik/markers_placements/vertext_first.hpp index bcdac2b4b..ce1b415b3 100644 --- a/include/mapnik/markers_placements/vertext_first.hpp +++ b/include/mapnik/markers_placements/vertext_first.hpp @@ -31,14 +31,8 @@ template class markers_vertex_first_placement : public markers_point_placement { public: - markers_vertex_first_placement(Locator &locator, Detector &detector, markers_placement_params const& params) - : markers_point_placement(locator, detector, params) - { - } - - markers_vertex_first_placement(markers_vertex_first_placement && rhs) - : markers_point_placement(std::move(rhs)) - {} + using point_placement = markers_point_placement; + using point_placement::point_placement; bool get_point(double &x, double &y, double &angle, bool ignore_placement) { @@ -49,7 +43,7 @@ public: if (this->locator_.type() == mapnik::geometry::geometry_types::Point) { - return markers_point_placement::get_point(x, y, angle, ignore_placement); + return point_placement::get_point(x, y, angle, ignore_placement); } double x0, y0; @@ -75,20 +69,10 @@ public: } } - box2d box = this->perform_transform(angle, x, y); - if (this->params_.avoid_edges && !this->detector_.extent().contains(box)) + if (!this->push_to_detector(x, y, angle, ignore_placement)) { return false; } - if (!this->params_.allow_overlap && !this->detector_.has_placement(box)) - { - return false; - } - - if (!ignore_placement) - { - this->detector_.insert(box); - } this->done_ = true; return true; diff --git a/include/mapnik/markers_placements/vertext_last.hpp b/include/mapnik/markers_placements/vertext_last.hpp index 4d57130a2..62c94a66a 100644 --- a/include/mapnik/markers_placements/vertext_last.hpp +++ b/include/mapnik/markers_placements/vertext_last.hpp @@ -31,13 +31,8 @@ template class markers_vertex_last_placement : public markers_point_placement { public: - markers_vertex_last_placement(Locator &locator, Detector &detector, markers_placement_params const& params) - : markers_point_placement(locator, detector, params) - {} - - markers_vertex_last_placement(markers_vertex_last_placement && rhs) - : markers_point_placement(std::move(rhs)) - {} + using point_placement = markers_point_placement; + using point_placement::point_placement; bool get_point(double &x, double &y, double &angle, bool ignore_placement) { @@ -80,20 +75,10 @@ public: } } - box2d box = this->perform_transform(angle, x, y); - if (this->params_.avoid_edges && !this->detector_.extent().contains(box)) + if (!this->push_to_detector(x, y, angle, ignore_placement)) { return false; } - if (!this->params_.allow_overlap && !this->detector_.has_placement(box)) - { - return false; - } - - if (!ignore_placement) - { - this->detector_.insert(box); - } this->done_ = true; return true; diff --git a/include/mapnik/memory_datasource.hpp b/include/mapnik/memory_datasource.hpp index cd2b61130..9b589741f 100644 --- a/include/mapnik/memory_datasource.hpp +++ b/include/mapnik/memory_datasource.hpp @@ -55,6 +55,7 @@ private: mapnik::layer_descriptor desc_; datasource::datasource_t type_; bool bbox_check_; + bool type_set_; mutable box2d extent_; mutable bool dirty_extent_ = true; }; diff --git a/include/mapnik/miniz_png.hpp b/include/mapnik/miniz_png.hpp deleted file mode 100644 index 6c46e448f..000000000 --- a/include/mapnik/miniz_png.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_MINIZ_PNG_HPP -#define MAPNIK_MINIZ_PNG_HPP - -// mapnik -#include -#include - -// stl -#include -#include -#include - -#include -#include - -/* miniz.c porting issues: - - duplicate symbols in python bindings require moving miniz.c include to just cpp file - - due to http://code.google.com/p/miniz/issues/detail?id=7 - - avoiding including miniz.c here requires fwd declaring the two structs below - - being able to fwd declare requires removing typedef from struct declarations in miniz.c - - being able to fwd declare also requires using pointers to structs - - if updated, need to apply c++11 fix: https://github.com/mapnik/mapnik/issues/1967 -*/ - -// TODO: try using #define MINIZ_HEADER_FILE_ONLY -struct tdefl_output_buffer; -struct tdefl_compressor; - -namespace mapnik { namespace MiniZ { - -using mapnik::rgb; - -class MAPNIK_DECL PNGWriter { - -public: - PNGWriter(int level, int strategy); - ~PNGWriter(); -private: - inline void writeUInt32BE(unsigned char *target, unsigned int value); - size_t startChunk(const unsigned char header[], size_t length); - void finishChunk(size_t start); -public: - void writeIHDR(unsigned int width, unsigned int height, unsigned char pixel_depth); - void writePLTE(std::vector const& palette); - void writetRNS(std::vector const& alpha); - template - void writeIDAT(T const& image); - template - void writeIDATStripAlpha(T const& image); - void writeIEND(); - void toStream(std::ostream& stream); - -private: - tdefl_compressor *compressor; - tdefl_output_buffer *buffer; - static const unsigned char preamble[]; - static const unsigned char IHDR_tpl[]; - static const unsigned char PLTE_tpl[]; - static const unsigned char tRNS_tpl[]; - static const unsigned char IDAT_tpl[]; - static const unsigned char IEND_tpl[]; -}; - -extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_gray8 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_view_gray8 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_rgba8 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_view_rgba8 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha(image_rgba8 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha(image_view_rgba8 const& image); - -}} - -#endif // MAPNIK_MINIZ_PNG_HPP diff --git a/include/mapnik/offset_converter.hpp b/include/mapnik/offset_converter.hpp index a5ac57c3e..310ed808a 100644 --- a/include/mapnik/offset_converter.hpp +++ b/include/mapnik/offset_converter.hpp @@ -482,7 +482,6 @@ private: } start_v2.x = v2.x; start_v2.y = v2.y; - bool continue_loop = true; vertex2d tmp_prev(vertex2d::no_init); while (i < points.size()) @@ -515,7 +514,6 @@ private: else if (v2.cmd == SEG_END) { if (!is_polygon) break; - continue_loop = false; v2.x = start_v2.x; v2.y = start_v2.y; } diff --git a/include/mapnik/palette.hpp b/include/mapnik/palette.hpp index 5f9627239..1276d1302 100644 --- a/include/mapnik/palette.hpp +++ b/include/mapnik/palette.hpp @@ -43,6 +43,7 @@ using rgba_hash_table = std::unordered_map; // stl #include +#include #define U2RED(x) ((x)&0xff) #define U2GREEN(x) (((x)>>8)&0xff) @@ -53,7 +54,8 @@ namespace mapnik { struct rgba; -struct MAPNIK_DECL rgb { +struct MAPNIK_DECL rgb +{ std::uint8_t r; std::uint8_t g; std::uint8_t b; @@ -92,7 +94,7 @@ struct MAPNIK_DECL rgba b(U2BLUE(c)), a(U2ALPHA(c)) {} - inline bool operator==(const rgba& y) const + inline bool operator==(rgba const& y) const { return r == y.r && g == y.g && b == y.b && a == y.a; } @@ -103,18 +105,27 @@ struct MAPNIK_DECL rgba bool operator() (const rgba& x, const rgba& y) const; }; + inline bool operator<(rgba const& y) const + { + return std::tie(r, g, b, a) < std::tie(y.r, y.g, y.b, y.a); + } + }; -class MAPNIK_DECL rgba_palette : private util::noncopyable { +class MAPNIK_DECL rgba_palette : private util::noncopyable +{ public: enum palette_type { PALETTE_RGBA = 0, PALETTE_RGB = 1, PALETTE_ACT = 2 }; explicit rgba_palette(std::string const& pal, palette_type type = PALETTE_RGBA); rgba_palette(); - const std::vector& palette() const; - const std::vector& alphaTable() const; + inline std::vector const& palette() const { return rgb_pal_;} + inline std::vector const& alpha_table() const { return alpha_pal_;} + + inline std::vector& palette() { return rgb_pal_;} + inline std::vector& alpha_table() { return alpha_pal_;} unsigned char quantize(unsigned c) const; diff --git a/include/mapnik/params.hpp b/include/mapnik/params.hpp index fc5928900..535cacb38 100644 --- a/include/mapnik/params.hpp +++ b/include/mapnik/params.hpp @@ -27,8 +27,11 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include @@ -48,9 +51,14 @@ struct value_holder : value_holder_base value_holder() : value_holder_base() {} + // C-string -> std::string + value_holder(char const* str) + : value_holder(std::string(str)) {} + // perfect forwarding template - value_holder(T && obj) noexcept + value_holder(T && obj) + noexcept(std::is_nothrow_constructible::value) : value_holder_base(std::forward(obj)) {} }; diff --git a/include/mapnik/path_expression_grammar_impl.hpp b/include/mapnik/path_expression_grammar_impl.hpp index bc2fcfb52..22002bf33 100644 --- a/include/mapnik/path_expression_grammar_impl.hpp +++ b/include/mapnik/path_expression_grammar_impl.hpp @@ -24,10 +24,13 @@ #include #include -// boost + +#pragma GCC diagnostic push +#include #include #include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/plugin.hpp b/include/mapnik/plugin.hpp index a3428de81..68e7de620 100644 --- a/include/mapnik/plugin.hpp +++ b/include/mapnik/plugin.hpp @@ -38,7 +38,8 @@ using mapnik_lib_t = struct _mapnik_lib_t; class PluginInfo : util::noncopyable { public: - using name_func = const char* (*) (); + using callable_returning_string = const char* (*) (); + using callable_returning_void = void (*) (); PluginInfo (std::string const& filename, std::string const& library_name); ~PluginInfo(); diff --git a/include/mapnik/png_io.hpp b/include/mapnik/png_io.hpp index 1b075b175..9f8b38d8f 100644 --- a/include/mapnik/png_io.hpp +++ b/include/mapnik/png_io.hpp @@ -27,19 +27,20 @@ #include #include #include -#include #include +#pragma GCC diagnostic push +#include + // zlib #include // for Z_DEFAULT_COMPRESSION -// boost - - extern "C" { #include } +#include +#pragma GCC diagnostic pop #define MAX_OCTREE_LEVELS 4 @@ -53,7 +54,6 @@ struct png_options { double gamma; bool paletted; bool use_hextree; - bool use_miniz; png_options() : colors(256), compression(Z_DEFAULT_COMPRESSION), @@ -61,8 +61,7 @@ struct png_options { trans_mode(-1), gamma(-1), paletted(true), - use_hextree(true), - use_miniz(false) {} + use_hextree(true) {} }; template @@ -85,23 +84,6 @@ void save_as_png(T1 & file, png_options const& opts) { - if (opts.use_miniz) - { - MiniZ::PNGWriter writer(opts.compression,opts.strategy); - if (opts.trans_mode == 0) - { - writer.writeIHDR(image.width(), image.height(), 24); - writer.writeIDATStripAlpha(image); - } - else - { - writer.writeIHDR(image.width(), image.height(), 32); - writer.writeIDAT(image); - } - writer.writeIEND(); - writer.toStream(file); - return; - } png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); @@ -119,10 +101,10 @@ void save_as_png(T1 & file, png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)0); + png_destroy_write_struct(&png_ptr,static_cast(0)); return; } - jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); + jmp_buf* jmp_context = static_cast(png_get_error_ptr(png_ptr)); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); @@ -140,7 +122,7 @@ void save_as_png(T1 & file, const std::unique_ptr row_pointers(new png_bytep[image.height()]); for (unsigned int i = 0; i < image.height(); i++) { - row_pointers[i] = (png_bytep)image.get_row(i); + row_pointers[i] = const_cast(reinterpret_cast(image.get_row(i))); } png_set_rows(png_ptr, info_ptr, row_pointers.get()); png_write_png(png_ptr, info_ptr, (opts.trans_mode == 0) ? PNG_TRANSFORM_STRIP_FILLER_AFTER : PNG_TRANSFORM_IDENTITY, nullptr); @@ -181,7 +163,7 @@ void reduce_8(T const& in, break; } } - if (idx>=0 && idx<(int)alpha.size()) + if (idx>=0 && idx < static_cast(alpha.size())) { alpha[idx]+=U2ALPHA(val); alphaCount[idx]++; @@ -232,7 +214,7 @@ void reduce_4(T const& in, break; } } - if (idx>=0 && idx<(int)alpha.size()) + if (idx>=0 && idx < static_cast(alpha.size())) { alpha[idx]+=U2ALPHA(val); alphaCount[idx]++; @@ -273,19 +255,6 @@ void save_as_png(T & file, std::vector const& palette, std::vector const&alpha, png_options const& opts) { - if (opts.use_miniz) - { - MiniZ::PNGWriter writer(opts.compression,opts.strategy); - // image.width()/height() does not reflect the actual image dimensions; it - // refers to the quantized scanlines. - writer.writeIHDR(width, height, color_depth); - writer.writePLTE(palette); - writer.writetRNS(alpha); - writer.writeIDAT(image); - writer.writeIEND(); - writer.toStream(file); - return; - } png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); @@ -306,10 +275,10 @@ void save_as_png(T & file, std::vector const& palette, png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)0); + png_destroy_write_struct(&png_ptr,static_cast(0)); return; } - jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); + jmp_buf* jmp_context = static_cast(png_get_error_ptr(png_ptr)); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); @@ -343,14 +312,14 @@ void save_as_png(T & file, std::vector const& palette, } if (alphaSize>0) { - png_set_tRNS(png_ptr, info_ptr, (png_bytep)&trans[0], alphaSize, 0); + png_set_tRNS(png_ptr, info_ptr, static_cast(&trans[0]), alphaSize, 0); } } png_write_info(png_ptr, info_ptr); for (unsigned i=0;i(image.get_row(i))); } png_write_end(png_ptr, info_ptr); @@ -385,7 +354,7 @@ void save_as_png8_oct(T1 & file, { for (unsigned x = 0; x < width; ++x) { - unsigned val = U2ALPHA((unsigned)image.get_row(y)[x]); + unsigned val = U2ALPHA(static_cast(image.get_row(y)[x])); alphaHist[val]++; meanAlpha += val; if (val>0 && val<255) @@ -546,19 +515,19 @@ void save_as_png8_oct(T1 & file, } //transparency values per palette index - std::vector alphaTable; - //alphaTable.resize(palette.size());//allow semitransparency also in almost opaque range + std::vector alpha_table; + //alpha_table.resize(palette.size());//allow semitransparency also in almost opaque range if (opts.trans_mode != 0) { - alphaTable.resize(palette.size() - cols[TRANSPARENCY_LEVELS-1]); + alpha_table.resize(palette.size() - cols[TRANSPARENCY_LEVELS-1]); } if (palette.size() > 16 ) { // >16 && <=256 colors -> write 8-bit color depth image_gray8 reduced_image(width,height); - reduce_8(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable); - save_as_png(file,palette,reduced_image,width,height,8,alphaTable,opts); + reduce_8(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alpha_table); + save_as_png(file,palette,reduced_image,width,height,8,alpha_table,opts); } else if (palette.size() == 1) { @@ -566,13 +535,13 @@ void save_as_png8_oct(T1 & file, unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary unsigned image_height = height; image_gray8 reduced_image(image_width,image_height); - reduce_1(image,reduced_image,trees, limits, alphaTable); + reduce_1(image,reduced_image,trees, limits, alpha_table); if (meanAlpha<255 && cols[0]==0) { - alphaTable.resize(1); - alphaTable[0] = meanAlpha; + alpha_table.resize(1); + alpha_table[0] = meanAlpha; } - save_as_png(file,palette,reduced_image,width,height,1,alphaTable,opts); + save_as_png(file,palette,reduced_image,width,height,1,alpha_table,opts); } else { @@ -580,8 +549,8 @@ void save_as_png8_oct(T1 & file, unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary unsigned image_height = height; image_gray8 reduced_image(image_width,image_height); - reduce_4(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable); - save_as_png(file,palette,reduced_image,width,height,4,alphaTable,opts); + reduce_4(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alpha_table); + save_as_png(file,palette,reduced_image,width,height,4,alpha_table,opts); } } @@ -591,7 +560,7 @@ void save_as_png8(T1 & file, T2 const& image, T3 const & tree, std::vector const& palette, - std::vector const& alphaTable, + std::vector const& alpha_table, png_options const& opts) { unsigned width = image.width(); @@ -610,7 +579,7 @@ void save_as_png8(T1 & file, row_out[x] = tree.quantize(row[x]); } } - save_as_png(file, palette, reduced_image, width, height, 8, alphaTable, opts); + save_as_png(file, palette, reduced_image, width, height, 8, alpha_table, opts); } else if (palette.size() == 1) { @@ -619,7 +588,7 @@ void save_as_png8(T1 & file, unsigned image_height = height; image_gray8 reduced_image(image_width, image_height); reduced_image.set(0); - save_as_png(file, palette, reduced_image, width, height, 1, alphaTable, opts); + save_as_png(file, palette, reduced_image, width, height, 1, alpha_table, opts); } else { @@ -643,7 +612,7 @@ void save_as_png8(T1 & file, row_out[x>>1] |= index; } } - save_as_png(file, palette, reduced_image, width, height, 4, alphaTable, opts); + save_as_png(file, palette, reduced_image, width, height, 4, alpha_table, opts); } } @@ -654,6 +623,7 @@ void save_as_png8_hex(T1 & file, { unsigned width = image.width(); unsigned height = image.height(); + if (width + height > 3) // at least 3 pixels (hextree implementation requirement) { // structure for color quantization @@ -678,20 +648,44 @@ void save_as_png8_hex(T1 & file, } //transparency values per palette index - std::vector pal; - tree.create_palette(pal); + std::vector rgba_palette; + tree.create_palette(rgba_palette); + auto size = rgba_palette.size(); std::vector palette; - std::vector alphaTable; - for (unsigned i=0; i alpha_table; + palette.reserve(size); + alpha_table.reserve(size); + for (auto const& c : rgba_palette) { - palette.push_back(rgb(pal[i].r, pal[i].g, pal[i].b)); - alphaTable.push_back(pal[i].a); + palette.emplace_back(c.r, c.g, c.b); + alpha_table.push_back(c.a); } - save_as_png8 >(file, image, tree, palette, alphaTable, opts); + save_as_png8 >(file, image, tree, palette, alpha_table, opts); } else { - throw std::runtime_error("Can't quantize images with less than 3 pixels"); + + std::set colors; + for (unsigned y = 0; y < height; ++y) + { + typename T2::pixel_type const * row = image.get_row(y); + + for (unsigned x = 0; x < width; ++x) + { + unsigned val = row[x]; + colors.emplace(U2RED(val), U2GREEN(val), U2BLUE(val), U2ALPHA(val)); + } + } + std::string str; + for (auto c : colors) + { + str.push_back(c.r); + str.push_back(c.g); + str.push_back(c.b); + str.push_back(c.a); + } + rgba_palette pal(str, rgba_palette::PALETTE_RGBA); + save_as_png8(file, image, pal, pal.palette(), pal.alpha_table(), opts); } } @@ -701,7 +695,7 @@ void save_as_png8_pal(T1 & file, rgba_palette const& pal, png_options const& opts) { - save_as_png8(file, image, pal, pal.palette(), pal.alphaTable(), opts); + save_as_png8(file, image, pal, pal.palette(), pal.alpha_table(), opts); } } diff --git a/include/mapnik/pool.hpp b/include/mapnik/pool.hpp index ecd16eb34..c37aab4e3 100644 --- a/include/mapnik/pool.hpp +++ b/include/mapnik/pool.hpp @@ -24,7 +24,6 @@ #define MAPNIK_POOL_HPP // mapnik -#include #include // boost diff --git a/include/mapnik/projection.hpp b/include/mapnik/projection.hpp index cb4284fb0..0869bb2d6 100644 --- a/include/mapnik/projection.hpp +++ b/include/mapnik/projection.hpp @@ -27,8 +27,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/ptree_helpers.hpp b/include/mapnik/ptree_helpers.hpp index 3062d7115..6a9c91e56 100644 --- a/include/mapnik/ptree_helpers.hpp +++ b/include/mapnik/ptree_helpers.hpp @@ -26,8 +26,10 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/quad_tree.hpp b/include/mapnik/quad_tree.hpp index 092bf4d60..c15f09f26 100644 --- a/include/mapnik/quad_tree.hpp +++ b/include/mapnik/quad_tree.hpp @@ -36,26 +36,27 @@ namespace mapnik { -template +template > class quad_tree : util::noncopyable { - using value_type = T; + using value_type = T0; + using bbox_type = T1; struct node { - using cont_type = std::vector; + using cont_type = std::vector; using iterator = typename cont_type::iterator; using const_iterator = typename cont_type::const_iterator; - box2d extent_; + bbox_type extent_; cont_type cont_; node * children_[4]; - explicit node(box2d const& ext) + explicit node(bbox_type const& ext) : extent_(ext) { std::fill(children_, children_ + 4, nullptr); } - box2d const& extent() const + bbox_type const& extent() const { return extent_; } @@ -99,10 +100,10 @@ class quad_tree : util::noncopyable public: using iterator = typename nodes_type::iterator; using const_iterator = typename nodes_type::const_iterator; - using result_type = typename std::vector >; + using result_type = typename std::vector >; using query_iterator = typename result_type::iterator; - explicit quad_tree(box2d const& ext, + explicit quad_tree(bbox_type const& ext, unsigned int max_depth = 8, double ratio = 0.55) : max_depth_(max_depth), @@ -114,13 +115,13 @@ public: root_ = nodes_[0].get(); } - void insert(T data, box2d const& box) + void insert(value_type data, bbox_type const& box) { - unsigned int depth=0; - do_insert_data(data,box,root_,depth); + unsigned int depth = 0; + do_insert_data(data, box, root_, depth); } - query_iterator query_in_box(box2d const& box) + query_iterator query_in_box(bbox_type const& box) { query_result_.clear(); query_node(box, query_result_, root_); @@ -145,13 +146,13 @@ public: void clear () { - box2d ext = root_->extent_; + bbox_type ext = root_->extent_; nodes_.clear(); nodes_.push_back(std::make_unique(ext)); root_ = nodes_[0].get(); } - box2d const& extent() const + bbox_type const& extent() const { return root_->extent_; } @@ -179,22 +180,17 @@ public: "Values stored in quad-tree must be standard layout types to allow serialisation"); char header[16]; std::memset(header,0,16); - header[0]='m'; - header[1]='a'; - header[2]='p'; - header[3]='n'; - header[4]='i'; - header[5]='k'; + std::strcpy(header,"mapnik-index"); out.write(header,16); write_node(out,root_); } private: - void query_node(box2d const& box, result_type & result, node * node_) const + void query_node(bbox_type const& box, result_type & result, node * node_) const { if (node_) { - box2d const& node_extent = node_->extent(); + bbox_type const& node_extent = node_->extent(); if (box.intersects(node_extent)) { for (auto & n : *node_) @@ -209,7 +205,7 @@ private: } } - void do_insert_data(T data, box2d const& box, node * n, unsigned int& depth) + void do_insert_data(value_type data, bbox_type const& box, node * n, unsigned int& depth) { if (++depth >= max_depth_) { @@ -217,8 +213,8 @@ private: } else { - box2d const& node_extent = n->extent(); - box2d ext[4]; + bbox_type const& node_extent = n->extent(); + bbox_type ext[4]; split_box(node_extent,ext); for (int i = 0; i < 4; ++i) { @@ -237,20 +233,19 @@ private: } } - void split_box(box2d const& node_extent,box2d * ext) + void split_box(bbox_type const& node_extent,bbox_type * ext) { - double width=node_extent.width(); - double height=node_extent.height(); + typename bbox_type::value_type width = node_extent.width(); + typename bbox_type::value_type height = node_extent.height(); + typename bbox_type::value_type lox = node_extent.minx(); + typename bbox_type::value_type loy = node_extent.miny(); + typename bbox_type::value_type hix = node_extent.maxx(); + typename bbox_type::value_type hiy = node_extent.maxy(); - double lox=node_extent.minx(); - double loy=node_extent.miny(); - double hix=node_extent.maxx(); - double hiy=node_extent.maxy(); - - ext[0]=box2d(lox,loy,lox + width * ratio_,loy + height * ratio_); - ext[1]=box2d(hix - width * ratio_,loy,hix,loy + height * ratio_); - ext[2]=box2d(lox,hiy - height*ratio_,lox + width * ratio_,hiy); - ext[3]=box2d(hix - width * ratio_,hiy - height*ratio_,hix,hiy); + ext[0] = bbox_type(lox, loy, lox + width * ratio_, loy + height * ratio_); + ext[1] = bbox_type(hix - width * ratio_, loy, hix, loy + height * ratio_); + ext[2] = bbox_type(lox, hiy - height * ratio_, lox + width * ratio_, hiy); + ext[3] = bbox_type(hix - width * ratio_, hiy - height * ratio_, hix, hiy); } void trim_tree(node *& n) @@ -309,7 +304,7 @@ private: { if (n->children_[i]) { - offset +=sizeof(box2d) + (n->children_[i]->cont_.size() * sizeof(value_type)) + 3 * sizeof(int); + offset +=sizeof(bbox_type) + (n->children_[i]->cont_.size() * sizeof(value_type)) + 3 * sizeof(int); offset +=subnode_offset(n->children_[i]); } } @@ -321,17 +316,17 @@ private: { if (n) { - int offset=subnode_offset(n); - int shape_count=n->cont_.size(); - int recsize=sizeof(box2d) + 3 * sizeof(int) + shape_count * sizeof(value_type); + int offset = subnode_offset(n); + int shape_count = n->cont_.size(); + int recsize = sizeof(bbox_type) + 3 * sizeof(int) + shape_count * sizeof(value_type); std::unique_ptr node_record(new char[recsize]); std::memset(node_record.get(), 0, recsize); std::memcpy(node_record.get(), &offset, 4); - std::memcpy(node_record.get() + 4, &n->extent_, sizeof(box2d)); - std::memcpy(node_record.get() + 36, &shape_count, 4); + std::memcpy(node_record.get() + 4, &n->extent_, sizeof(bbox_type)); + std::memcpy(node_record.get() + 4 + sizeof(bbox_type), &shape_count, 4); for (int i=0; i < shape_count; ++i) { - memcpy(node_record.get() + 40 + i * sizeof(value_type), &(n->cont_[i]),sizeof(value_type)); + memcpy(node_record.get() + 8 + sizeof(bbox_type) + i * sizeof(value_type), &(n->cont_[i]), sizeof(value_type)); } int num_subnodes=0; for (int i = 0; i < 4; ++i) @@ -341,7 +336,7 @@ private: ++num_subnodes; } } - std::memcpy(node_record.get() + 40 + shape_count * sizeof(value_type),&num_subnodes,4); + std::memcpy(node_record.get() + 8 + sizeof(bbox_type) + shape_count * sizeof(value_type), &num_subnodes, 4); out.write(node_record.get(),recsize); for (int i = 0; i < 4; ++i) { diff --git a/include/mapnik/raster.hpp b/include/mapnik/raster.hpp index 311c06cf0..02022d359 100644 --- a/include/mapnik/raster.hpp +++ b/include/mapnik/raster.hpp @@ -28,8 +28,11 @@ #include #include #include - // boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/raster_colorizer.hpp b/include/mapnik/raster_colorizer.hpp index c1e83aba1..86a85def2 100644 --- a/include/mapnik/raster_colorizer.hpp +++ b/include/mapnik/raster_colorizer.hpp @@ -41,12 +41,13 @@ #include #include #include - // boost -#include -// boost -#include -// stl +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +#include #include namespace mapnik @@ -164,7 +165,7 @@ public: void set_default_mode(colorizer_mode mode) { - default_mode_ = (mode == COLORIZER_INHERIT) ? COLORIZER_LINEAR:(colorizer_mode_enum)mode; + default_mode_ = (mode == COLORIZER_INHERIT) ? COLORIZER_LINEAR : static_cast(mode); } void set_default_mode_enum(colorizer_mode_enum mode) { set_default_mode(mode); } diff --git a/include/mapnik/renderer_common.hpp b/include/mapnik/renderer_common.hpp index 213443899..c9d181b42 100644 --- a/include/mapnik/renderer_common.hpp +++ b/include/mapnik/renderer_common.hpp @@ -42,13 +42,16 @@ namespace mapnik { struct renderer_common : private util::noncopyable { + using detector_ptr = std::shared_ptr; + renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor); renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor, - std::shared_ptr detector); + detector_ptr detector); renderer_common(Map const &m, request const &req, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor); + ~renderer_common(); unsigned width_; unsigned height_; @@ -60,11 +63,18 @@ struct renderer_common : private util::noncopyable face_manager_freetype font_manager_; box2d query_extent_; view_transform t_; - std::shared_ptr detector_; + detector_ptr detector_; + +protected: + // it's desirable to keep this class implicitly noncopyable to prevent + // inadvertent copying from other places; + // this copy constructor is therefore protected and should only be used + // by virtual_renderer_common + renderer_common(renderer_common const& other); private: renderer_common(Map const &m, unsigned width, unsigned height, double scale_factor, - attributes const& vars, view_transform &&t, std::shared_ptr detector); + attributes const& vars, view_transform && t, detector_ptr detector); }; } diff --git a/include/mapnik/renderer_common/apply_vertex_converter.hpp b/include/mapnik/renderer_common/apply_vertex_converter.hpp index de239c95b..503dc4176 100644 --- a/include/mapnik/renderer_common/apply_vertex_converter.hpp +++ b/include/mapnik/renderer_common/apply_vertex_converter.hpp @@ -31,7 +31,7 @@ struct apply_vertex_converter apply_vertex_converter(VertexConverter & converter, Processor & proc) : converter_(converter), proc_(proc) {} template - void operator() (Adapter const& adapter) const + void operator() (Adapter const& adapter) { converter_.apply(adapter, proc_); } diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp deleted file mode 100644 index edec30830..000000000 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ /dev/null @@ -1,403 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP -#define MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP - -// mapnik -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// agg -#include - -namespace mapnik { - -class text_symbolizer_helper; - -using svg::svg_path_adapter; -using svg_attribute_type = agg::pod_bvector; - -struct virtual_renderer_common : private util::noncopyable -{ - virtual_renderer_common(renderer_common & common) : - width_(common.width_), - height_(common.height_), - scale_factor_(common.scale_factor_), - vars_(common.vars_), - shared_font_library_(common.shared_font_library_), - font_library_(*shared_font_library_), - font_manager_(common.font_manager_), - query_extent_(common.query_extent_), - t_(common.t_), - detector_(std::make_shared(common.detector_->extent())) {} - - unsigned & width_; - unsigned & height_; - double & scale_factor_; - attributes & vars_; - // TODO: dirty hack for cairo renderer, figure out how to remove this - std::shared_ptr & shared_font_library_; - font_library & font_library_; - face_manager_freetype & font_manager_; - box2d & query_extent_; - view_transform & t_; - std::shared_ptr detector_; -}; - - -// General: - -// The approach here is to run the normal symbolizers, but in -// a 'virtual' blank environment where the changes that they -// make are recorded (the detector, the render_* calls). -// -// The recorded boxes are then used to lay out the items and -// the offsets from old to new positions can be used to perform -// the actual rendering calls. - -// This should allow us to re-use as much as possible of the -// existing symbolizer layout and rendering code while still -// being able to interpose our own decisions about whether -// a collision has occurred or not. - -// Thunk for rendering a particular instance of a point - this -// stores all the arguments necessary to re-render this point -// symbolizer at a later time. - -struct vector_marker_render_thunk : util::noncopyable -{ - svg_path_ptr src_; - svg_attribute_type attrs_; - agg::trans_affine tr_; - double opacity_; - composite_mode_e comp_op_; - bool snap_to_pixels_; - - vector_marker_render_thunk(svg_path_ptr const& src, - svg_attribute_type const& attrs, - agg::trans_affine const& marker_trans, - double opacity, - composite_mode_e comp_op, - bool snap_to_pixels); - - vector_marker_render_thunk(vector_marker_render_thunk && rhs); -}; - -struct raster_marker_render_thunk : util::noncopyable -{ - image_rgba8 const& src_; - agg::trans_affine tr_; - double opacity_; - composite_mode_e comp_op_; - bool snap_to_pixels_; - - raster_marker_render_thunk(image_rgba8 const& src, - agg::trans_affine const& marker_trans, - double opacity, - composite_mode_e comp_op, - bool snap_to_pixels); - - raster_marker_render_thunk(raster_marker_render_thunk && rhs); -}; - -using helper_ptr = std::unique_ptr; - -struct text_render_thunk : util::noncopyable -{ - // helper is stored here in order - // to keep in scope the text rendering structures - helper_ptr helper_; - placements_list const& placements_; - double opacity_; - composite_mode_e comp_op_; - halo_rasterizer_enum halo_rasterizer_; - - text_render_thunk(helper_ptr && helper, - double opacity, composite_mode_e comp_op, - halo_rasterizer_enum halo_rasterizer); - - text_render_thunk(text_render_thunk && rhs); - -}; - -// Variant type for render thunks to allow us to re-render them -// via a static visitor later. - -using render_thunk = util::variant; -using render_thunk_ptr = std::unique_ptr; -using render_thunk_list = std::list; - -// Base class for extracting the bounding boxes associated with placing -// a symbolizer at a fake, virtual point - not real geometry. -// -// The bounding boxes can be used for layout, and the thunks are -// used to re-render at locations according to the group layout. - -struct render_thunk_extractor -{ - render_thunk_extractor(box2d & box, - render_thunk_list & thunks, - feature_impl & feature, - attributes const& vars, - proj_transform const& prj_trans, - virtual_renderer_common & common, - box2d const& clipping_extent); - - void operator()(markers_symbolizer const& sym) const; - - void operator()(text_symbolizer const& sym) const; - - void operator()(shield_symbolizer const& sym) const; - - template - void operator()(T const& ) const - { - // TODO: warning if unimplemented? - } - -private: - void extract_text_thunk(helper_ptr && helper, text_symbolizer const& sym) const; - - box2d & box_; - render_thunk_list & thunks_; - feature_impl & feature_; - attributes const& vars_; - proj_transform const& prj_trans_; - virtual_renderer_common & common_; - box2d clipping_extent_; - - void update_box() const; -}; - -template -void render_offset_placements(placements_list const& placements, - pixel_position const& offset, - F render_text) { - - for (auto const& glyphs : placements) - { - // move the glyphs to the correct offset - pixel_position base_point = glyphs->get_base_point(); - glyphs->set_base_point(base_point + offset); - - // update the position of any marker - marker_info_ptr marker_info = glyphs->get_marker(); - pixel_position marker_pos = glyphs->marker_pos(); - if (marker_info) - { - glyphs->set_marker(marker_info, marker_pos + offset); - } - - render_text(glyphs); - - // Need to put the base_point back how it was in case something else calls this again - // (don't want to add offset twice) or calls with a different offset. - glyphs->set_base_point(base_point); - if (marker_info) - { - glyphs->set_marker(marker_info, marker_pos); - } - } -} - -template -void render_group_symbolizer(group_symbolizer const& sym, - feature_impl & feature, - attributes const& vars, - proj_transform const& prj_trans, - box2d const& clipping_extent, - renderer_common & common, - F render_thunks) -{ - // find all column names referenced in the group rules and symbolizers - std::set columns; - group_attribute_collector column_collector(columns, false); - column_collector(sym); - - group_symbolizer_properties_ptr props = get(sym, keys::group_properties); - - // create a new context for the sub features of this group - context_ptr sub_feature_ctx = std::make_shared(); - - // populate new context with column names referenced in the group rules and symbolizers - for (auto const& col_name : columns) - { - sub_feature_ctx->push(col_name); - } - - // keep track of the sub features that we'll want to symbolize - // along with the group rules that they matched - std::vector< std::pair > matches; - - // create a copied 'virtual' common renderer for processing sub feature symbolizers - // create an empty detector for it, so we are sure we won't hit anything - virtual_renderer_common virtual_renderer(common); - - // keep track of which lists of render thunks correspond to - // entries in the group_layout_manager. - std::vector layout_thunks; - size_t num_layout_thunks = 0; - - // layout manager to store and arrange bboxes of matched features - group_layout_manager layout_manager(props->get_layout(), pixel_position(common.width_ / 2.0, common.height_ / 2.0)); - - // run feature or sub feature through the group rules & symbolizers - // for each index value in the range - value_integer start = get(sym, keys::start_column); - value_integer end = start + get(sym, keys::num_columns); - for (value_integer col_idx = start; col_idx < end; ++col_idx) - { - // create sub feature with indexed column values - feature_ptr sub_feature = feature_factory::create(sub_feature_ctx, col_idx); - - // copy the necessary columns to sub feature - for(auto const& col_name : columns) - { - if (col_name.find('%') != std::string::npos) - { - if (col_name.size() == 1) - { - // column name is '%' by itself, so give the index as the value - sub_feature->put(col_name, col_idx); - } - else - { - // indexed column - std::string col_idx_str; - if (mapnik::util::to_string(col_idx_str,col_idx)) - { - std::string col_idx_name = col_name; - boost::replace_all(col_idx_name, "%", col_idx_str); - sub_feature->put(col_name, feature.get(col_idx_name)); - } - } - } - else - { - // non-indexed column - sub_feature->put(col_name, feature.get(col_name)); - } - } - - // add a single point geometry at pixel origin - double x = common.width_ / 2.0, y = common.height_ / 2.0, z = 0.0; - common.t_.backward(&x, &y); - prj_trans.forward(x, y, z); - // note that we choose a point in the middle of the screen to - // try to ensure that we don't get edge artefacts due to any - // symbolizers with avoid-edges set: only the avoid-edges of - // the group symbolizer itself should matter. - geometry::point origin_pt(x,y); - sub_feature->set_geometry(origin_pt); - // get the layout for this set of properties - for (auto const& rule : props->get_rules()) - { - if (util::apply_visitor(evaluate(*sub_feature,common.vars_), - *(rule->get_filter())).to_bool()) - { - // add matched rule and feature to the list of things to draw - matches.emplace_back(rule, sub_feature); - - // construct a bounding box around all symbolizers for the matched rule - bound_box bounds; - render_thunk_list thunks; - render_thunk_extractor extractor(bounds, thunks, *sub_feature, common.vars_, prj_trans, - virtual_renderer, clipping_extent); - - for (auto const& _sym : *rule) - { - // TODO: construct layout and obtain bounding box - util::apply_visitor(extractor, _sym); - } - - // add the bounding box to the layout manager - layout_manager.add_member_bound_box(bounds); - layout_thunks.emplace_back(std::move(thunks)); - ++num_layout_thunks; - break; - } - } - } - - // create a symbolizer helper - group_symbolizer_helper helper(sym, feature, vars, prj_trans, - common.width_, common.height_, - common.scale_factor_, common.t_, - *common.detector_, clipping_extent); - - for (size_t i = 0; i < matches.size(); ++i) - { - group_rule_ptr match_rule = matches[i].first; - feature_ptr match_feature = matches[i].second; - value_unicode_string rpt_key_value = ""; - - // get repeat key from matched group rule - expression_ptr rpt_key_expr = match_rule->get_repeat_key(); - - // if no repeat key was defined, use default from group symbolizer - if (!rpt_key_expr) - { - rpt_key_expr = get(sym, keys::repeat_key); - } - - // evaluate the repeat key with the matched sub feature if we have one - if (rpt_key_expr) - { - rpt_key_value = util::apply_visitor(evaluate(*match_feature,common.vars_), - *rpt_key_expr).to_unicode(); - } - helper.add_box_element(layout_manager.offset_box_at(i), rpt_key_value); - } - - pixel_position_list positions = helper.get(); - for (pixel_position const& pos : positions) - { - for (size_t layout_i = 0; layout_i < num_layout_thunks; ++layout_i) - { - pixel_position const& offset = layout_manager.offset_at(layout_i); - pixel_position render_offset = pos + offset; - render_thunks(layout_thunks[layout_i], render_offset); - } - } -} - -} // namespace mapnik - -#endif // MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp deleted file mode 100644 index f67715b06..000000000 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ /dev/null @@ -1,275 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP -#define MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP - -#include -#include -#include -#include -#include -#include - -namespace mapnik { - -template -struct render_marker_symbolizer_visitor -{ - using vector_dispatch_type = VD; - using raster_dispatch_type = RD; - using buffer_type = typename std::tuple_element<0,ContextType>::type; - - using vertex_converter_type = vertex_converter; - - render_marker_symbolizer_visitor(std::string const& filename, - markers_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans, - RendererType const& common, - box2d const& clip_box, - ContextType const& renderer_context) - : filename_(filename), - sym_(sym), - feature_(feature), - prj_trans_(prj_trans), - common_(common), - clip_box_(clip_box), - renderer_context_(renderer_context) {} - - void operator() (marker_null const&) {} - - void operator() (marker_svg const& mark) - { - using namespace mapnik::svg; - bool clip = get(sym_, feature_, common_.vars_); - double offset = get(sym_, feature_, common_.vars_); - double simplify_tolerance = get(sym_, feature_, common_.vars_); - double smooth = get(sym_, feature_, common_.vars_); - - // https://github.com/mapnik/mapnik/issues/1316 - bool snap_to_pixels = !mapnik::marker_cache::instance().is_uri(filename_); - - agg::trans_affine geom_tr; - auto transform = get_optional(sym_, keys::geometry_transform); - if (transform) evaluate_transform(geom_tr, feature_, common_.vars_, *transform, common_.scale_factor_); - agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); - - boost::optional const& stock_vector_marker = mark.get_data(); - - // special case for simple ellipse markers - // to allow for full control over rx/ry dimensions - if (filename_ == "shape://ellipse" - && (has_key(sym_,keys::width) || has_key(sym_,keys::height))) - { - svg_path_ptr marker_ellipse = std::make_shared(); - vertex_stl_adapter stl_storage(marker_ellipse->source()); - svg_path_adapter svg_path(stl_storage); - build_ellipse(sym_, feature_, common_.vars_, *marker_ellipse, svg_path); - svg_attribute_type attributes; - bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym_, feature_, common_.vars_); - auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); - vector_dispatch_type rasterizer_dispatch(marker_ellipse, - svg_path, - result ? attributes : (*stock_vector_marker)->attributes(), - image_tr, - sym_, - *common_.detector_, - common_.scale_factor_, - feature_, - common_.vars_, - snap_to_pixels, - renderer_context_); - - vertex_converter_type converter(clip_box_, - sym_, - common_.t_, - prj_trans_, - geom_tr, - feature_, - common_.vars_, - common_.scale_factor_); - if (clip) - { - geometry::geometry_types type = geometry::geometry_type(feature_.get_geometry()); - if (type == geometry::geometry_types::Polygon || type == geometry::geometry_types::MultiPolygon) - converter.template set(); - else if (type == geometry::geometry_types::LineString || type == geometry::geometry_types::MultiLineString) - converter.template set(); - } - - converter.template set(); //always transform - if (std::fabs(offset) > 0.0) converter.template set(); // parallel offset - converter.template set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.template set(); // optional simplify converter - if (smooth > 0.0) converter.template set(); // optional smooth converter - apply_markers_multi(feature_, common_.vars_, converter, rasterizer_dispatch, sym_); - } - else - { - box2d const& bbox = mark.bounding_box(); - setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature_, common_.vars_, sym_); - auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); - vertex_stl_adapter stl_storage((*stock_vector_marker)->source()); - svg_path_adapter svg_path(stl_storage); - svg_attribute_type attributes; - bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym_, feature_, common_.vars_); - vector_dispatch_type rasterizer_dispatch(*stock_vector_marker, - svg_path, - result ? attributes : (*stock_vector_marker)->attributes(), - image_tr, - sym_, - *common_.detector_, - common_.scale_factor_, - feature_, - common_.vars_, - snap_to_pixels, - renderer_context_); - - vertex_converter_type converter(clip_box_, - sym_, - common_.t_, - prj_trans_, - geom_tr, - feature_, - common_.vars_, - common_.scale_factor_); - if (clip) - { - geometry::geometry_types type = geometry::geometry_type(feature_.get_geometry()); - if (type == geometry::geometry_types::Polygon || type == geometry::geometry_types::MultiPolygon) - converter.template set(); - else if (type == geometry::geometry_types::LineString || type == geometry::geometry_types::MultiLineString) - converter.template set(); - } - - converter.template set(); //always transform - if (std::fabs(offset) > 0.0) converter.template set(); // parallel offset - converter.template set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.template set(); // optional simplify converter - if (smooth > 0.0) converter.template set(); // optional smooth converter - apply_markers_multi(feature_, common_.vars_, converter, rasterizer_dispatch, sym_); - } - } - - void operator() (marker_rgba8 const& mark) - { - using namespace mapnik::svg; - bool clip = get(sym_, feature_, common_.vars_); - double offset = get(sym_, feature_, common_.vars_); - double simplify_tolerance = get(sym_, feature_, common_.vars_); - double smooth = get(sym_, feature_, common_.vars_); - - agg::trans_affine geom_tr; - auto transform = get_optional(sym_, keys::geometry_transform); - if (transform) evaluate_transform(geom_tr, feature_, common_.vars_, *transform, common_.scale_factor_); - agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); - - setup_transform_scaling(image_tr, mark.width(), mark.height(), feature_, common_.vars_, sym_); - auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); - box2d const& bbox = mark.bounding_box(); - mapnik::image_rgba8 const& marker = mark.get_data(); - // - clamp sizes to > 4 pixels of interactivity - coord2d center = bbox.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine marker_trans = recenter * image_tr; - raster_dispatch_type rasterizer_dispatch(marker, - marker_trans, - sym_, - *common_.detector_, - common_.scale_factor_, - feature_, - common_.vars_, - renderer_context_); - - - vertex_converter_type converter(clip_box_, - sym_, - common_.t_, - prj_trans_, - geom_tr, - feature_, - common_.vars_, - common_.scale_factor_); - - if (clip) - { - geometry::geometry_types type = geometry::geometry_type(feature_.get_geometry()); - if (type == geometry::geometry_types::Polygon || type == geometry::geometry_types::MultiPolygon) - converter.template set(); - else if (type == geometry::geometry_types::LineString || type == geometry::geometry_types::MultiLineString) - converter.template set(); - } - converter.template set(); //always transform - if (std::fabs(offset) > 0.0) converter.template set(); // parallel offset - converter.template set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.template set(); // optional simplify converter - if (smooth > 0.0) converter.template set(); // optional smooth converter - apply_markers_multi(feature_, common_.vars_, converter, rasterizer_dispatch, sym_); - } - - private: - std::string const& filename_; - markers_symbolizer const& sym_; - mapnik::feature_impl & feature_; - proj_transform const& prj_trans_; - RendererType const& common_; - box2d const& clip_box_; - ContextType const& renderer_context_; -}; - -template -void render_markers_symbolizer(markers_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans, - RendererType const& common, - box2d const& clip_box, - ContextType const& renderer_context) -{ - using namespace mapnik::svg; - std::string filename = get(sym, keys::file, feature, common.vars_, "shape://ellipse"); - if (!filename.empty()) - { - std::shared_ptr mark = mapnik::marker_cache::instance().find(filename, true); - render_marker_symbolizer_visitor visitor(filename, - sym, - feature, - prj_trans, - common, - clip_box, - renderer_context); - util::apply_visitor(visitor, *mark); - } -} - -} // namespace mapnik - -#endif // MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index 12ffba508..ef0863fd6 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -61,7 +61,7 @@ void render_point_symbolizer(point_symbolizer const &sym, agg::trans_affine tr; auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform); + if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform, common.scale_factor_); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine recenter_tr = recenter * tr; diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp index f8ce32d84..7ca90a0af 100644 --- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp @@ -32,13 +32,15 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/renderer_common/render_group_symbolizer.hpp b/include/mapnik/renderer_common/render_group_symbolizer.hpp new file mode 100644 index 000000000..e7b1b2248 --- /dev/null +++ b/include/mapnik/renderer_common/render_group_symbolizer.hpp @@ -0,0 +1,66 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_RENDERER_COMMON_RENDER_GROUP_SYMBOLIZER_HPP +#define MAPNIK_RENDERER_COMMON_RENDER_GROUP_SYMBOLIZER_HPP + +// mapnik +#include +#include +#include +#include +#include + +namespace mapnik { + +struct render_thunk_list_dispatch +{ + virtual void operator()(vector_marker_render_thunk const& thunk) = 0; + virtual void operator()(raster_marker_render_thunk const& thunk) = 0; + virtual void operator()(text_render_thunk const& thunk) = 0; + + void render_list(render_thunk_list const& thunks, pixel_position const& offset) + { + offset_ = offset; + + for (render_thunk_ptr const& thunk : thunks) + { + util::apply_visitor(std::ref(*this), *thunk); + } + } + +protected: + pixel_position offset_; +}; + +MAPNIK_DECL +void render_group_symbolizer(group_symbolizer const& sym, + feature_impl & feature, + attributes const& vars, + proj_transform const& prj_trans, + box2d const& clipping_extent, + renderer_common & common, + render_thunk_list_dispatch & render_thunks); + +} // namespace mapnik + +#endif // MAPNIK_RENDERER_COMMON_RENDER_GROUP_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/render_markers_symbolizer.hpp b/include/mapnik/renderer_common/render_markers_symbolizer.hpp new file mode 100644 index 000000000..42639fbb6 --- /dev/null +++ b/include/mapnik/renderer_common/render_markers_symbolizer.hpp @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_RENDERER_COMMON_RENDER_MARKERS_SYMBOLIZER_HPP +#define MAPNIK_RENDERER_COMMON_RENDER_MARKERS_SYMBOLIZER_HPP + +#include +#include +#include +#include + +namespace mapnik { + +struct markers_dispatch_params +{ + // placement + markers_placement_params placement_params; + marker_placement_enum placement_method; + value_bool ignore_placement; + // rendering + bool snap_to_pixels; + double scale_factor; + value_double opacity; + + markers_dispatch_params(box2d const& size, + agg::trans_affine const& tr, + symbolizer_base const& sym, + feature_impl const& feature, + attributes const& vars, + double scale_factor = 1.0, + bool snap_to_pixels = false); +}; + +struct markers_renderer_context : util::noncopyable +{ + virtual void render_marker(image_rgba8 const& src, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) = 0; + + virtual void render_marker(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) = 0; +}; + +MAPNIK_DECL +void render_markers_symbolizer(markers_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans, + renderer_common const& common, + box2d const& clip_box, + markers_renderer_context & renderer_context); + +} // namespace mapnik + +#endif // MAPNIK_RENDERER_COMMON_RENDER_MARKERS_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/render_thunk.hpp b/include/mapnik/renderer_common/render_thunk.hpp new file mode 100644 index 000000000..2a957d260 --- /dev/null +++ b/include/mapnik/renderer_common/render_thunk.hpp @@ -0,0 +1,115 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_RENDERER_COMMON_RENDER_THUNK_HPP +#define MAPNIK_RENDERER_COMMON_RENDER_THUNK_HPP + +// mapnik +#include // composite_mode_e +#include // svg_attribute_type, svg_path_ptr +#include // halo_rasterizer_enum +#include +#include +#include +#include + +// agg +#include + +namespace mapnik { + +// Thunk for rendering a particular instance of a point - this +// stores all the arguments necessary to re-render this point +// symbolizer at a later time. + +struct vector_marker_render_thunk : util::movable +{ + svg_path_ptr src_; + svg_attribute_type attrs_; + agg::trans_affine tr_; + double opacity_; + composite_mode_e comp_op_; + bool snap_to_pixels_; + + vector_marker_render_thunk(svg_path_ptr const& src, + svg_attribute_type const& attrs, + agg::trans_affine const& marker_trans, + double opacity, + composite_mode_e comp_op, + bool snap_to_pixels) + : src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity), + comp_op_(comp_op), snap_to_pixels_(snap_to_pixels) + {} +}; + +struct raster_marker_render_thunk : util::movable +{ + image_rgba8 const& src_; + agg::trans_affine tr_; + double opacity_; + composite_mode_e comp_op_; + bool snap_to_pixels_; + + raster_marker_render_thunk(image_rgba8 const& src, + agg::trans_affine const& marker_trans, + double opacity, + composite_mode_e comp_op, + bool snap_to_pixels) + : src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op), + snap_to_pixels_(snap_to_pixels) + {} +}; + +struct text_render_thunk : util::movable +{ + using helper_ptr = std::unique_ptr; + // helper is stored here in order + // to keep in scope the text rendering structures + helper_ptr helper_; + placements_list const& placements_; + double opacity_; + composite_mode_e comp_op_; + halo_rasterizer_enum halo_rasterizer_; + + text_render_thunk(helper_ptr && helper, + double opacity, composite_mode_e comp_op, + halo_rasterizer_enum halo_rasterizer) + : helper_(std::move(helper)), + placements_(helper_->get()), + opacity_(opacity), + comp_op_(comp_op), + halo_rasterizer_(halo_rasterizer) + {} +}; + +// Variant type for render thunks to allow us to re-render them +// via a static visitor later. + +using render_thunk = util::variant; +using render_thunk_ptr = std::unique_ptr; +using render_thunk_list = std::list; + +} // namespace mapnik + +#endif // MAPNIK_RENDERER_COMMON_RENDER_THUNK_HPP diff --git a/include/mapnik/renderer_common/render_thunk_extractor.hpp b/include/mapnik/renderer_common/render_thunk_extractor.hpp new file mode 100644 index 000000000..3ea86f6d7 --- /dev/null +++ b/include/mapnik/renderer_common/render_thunk_extractor.hpp @@ -0,0 +1,97 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_RENDERER_COMMON_RENDER_THUNK_EXTRACTOR_HPP +#define MAPNIK_RENDERER_COMMON_RENDER_THUNK_EXTRACTOR_HPP + +// mapnik +#include +#include +#include +#include + +namespace mapnik { + +// The approach here is to run the normal symbolizers, but in +// a 'virtual' blank environment where the changes that they +// make are recorded (the detector, the render_* calls). +// +// The recorded boxes are then used to lay out the items and +// the offsets from old to new positions can be used to perform +// the actual rendering calls. + +// This should allow us to re-use as much as possible of the +// existing symbolizer layout and rendering code while still +// being able to interpose our own decisions about whether +// a collision has occurred or not. + +struct virtual_renderer_common : renderer_common +{ + explicit virtual_renderer_common(renderer_common const& other); +}; + +// Base class for extracting the bounding boxes associated with placing +// a symbolizer at a fake, virtual point - not real geometry. +// +// The bounding boxes can be used for layout, and the thunks are +// used to re-render at locations according to the group layout. + +struct render_thunk_extractor +{ + render_thunk_extractor(box2d & box, + render_thunk_list & thunks, + feature_impl & feature, + attributes const& vars, + proj_transform const& prj_trans, + virtual_renderer_common & common, + box2d const& clipping_extent); + + void operator()(markers_symbolizer const& sym) const; + + void operator()(text_symbolizer const& sym) const; + + void operator()(shield_symbolizer const& sym) const; + + template + void operator()(T const& ) const + { + // TODO: warning if unimplemented? + } + +private: + void extract_text_thunk(text_render_thunk::helper_ptr && helper, + text_symbolizer const& sym) const; + + box2d & box_; + render_thunk_list & thunks_; + feature_impl & feature_; + attributes const& vars_; + proj_transform const& prj_trans_; + virtual_renderer_common & common_; + box2d clipping_extent_; + + void update_box() const; +}; + +} // namespace mapnik + +#endif // MAPNIK_RENDERER_COMMON_RENDER_THUNK_EXTRACTOR_HPP diff --git a/include/mapnik/simplify.hpp b/include/mapnik/simplify.hpp index 71b7711bf..dd75fcf2d 100644 --- a/include/mapnik/simplify.hpp +++ b/include/mapnik/simplify.hpp @@ -7,8 +7,10 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/simplify_converter.hpp b/include/mapnik/simplify_converter.hpp index 77d367426..248842504 100644 --- a/include/mapnik/simplify_converter.hpp +++ b/include/mapnik/simplify_converter.hpp @@ -41,7 +41,7 @@ struct weighted_vertex : private util::noncopyable vertex2d const& A = prev->coord; vertex2d const& B = next->coord; vertex2d const& C = coord; - return std::abs((double)((A.x - C.x) * (B.y - A.y) - (A.x - B.x) * (C.y - A.y))) / 2.0; + return std::abs(static_cast((A.x - C.x) * (B.y - A.y) - (A.x - B.x) * (C.y - A.y))) / 2.0; } struct ascending_sort @@ -76,16 +76,16 @@ struct sleeve bool inside(vertex2d const& q) { - bool inside=false; + bool _inside=false; for (unsigned i=0;i<4;++i) { if ((((v[i+1].y <= q.y) && (q.y < v[i].y)) || ((v[i].y <= q.y) && (q.y < v[i+1].y))) && (q.x < (v[i].x - v[i+1].x) * (q.y - v[i+1].y)/ (v[i].y - v[i+1].y) + v[i+1].x)) - inside=!inside; + _inside=!_inside; } - return inside; + return _inside; } }; @@ -592,11 +592,11 @@ private: } // Slurp the points back out that haven't been marked as discarded - for (vertex2d const& vertex : vertices) + for (vertex2d const& v : vertices) { - if (vertex.cmd != SEG_END) + if (v.cmd != SEG_END) { - vertices_.emplace_back(vertex); + vertices_.emplace_back(v); } } diff --git a/include/mapnik/span_image_filter.h b/include/mapnik/span_image_filter.hpp similarity index 86% rename from include/mapnik/span_image_filter.h rename to include/mapnik/span_image_filter.hpp index cd843010b..c0a9adbb9 100644 --- a/include/mapnik/span_image_filter.h +++ b/include/mapnik/span_image_filter.hpp @@ -23,8 +23,18 @@ #ifndef MAPNIK_SPAN_IMAGE_FILTER_INCLUDED #define MAPNIK_SPAN_IMAGE_FILTER_INCLUDED +#include + +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +#pragma GCC diagnostic push +#include #include "agg_span_image_filter_gray.h" #include "agg_span_image_filter_rgba.h" +#pragma GCC diagnostic pop #include @@ -77,16 +87,19 @@ public: { base_type::interpolator().coordinates(&x, &y); - int src_x = x >> agg::image_subpixel_shift; - int src_y = y >> agg::image_subpixel_shift; - const value_type* pix = reinterpret_cast(base_type::source().span(src_x, src_y, 0)); - if (nodata_value_ && *nodata_value_ == *pix) + if (nodata_value_) { - span->v = *nodata_value_; - span->a = base_mask; - ++span; - ++base_type::interpolator(); - continue; + int src_x = x >> agg::image_subpixel_shift; + int src_y = y >> agg::image_subpixel_shift; + const value_type* pix = reinterpret_cast(base_type::source().span(src_x, src_y, 1)); + if (*nodata_value_ == *pix) + { + span->v = *nodata_value_; + span->a = base_mask; + ++span; + ++base_type::interpolator(); + continue; + } } x += base_type::filter_dx_int() - radius_x; @@ -129,19 +142,15 @@ public: fg_ptr = reinterpret_cast(base_type::source().next_y()); } - fg /= total_weight; - if (fg < std::numeric_limits::min()) + if (total_weight == 0) { - span->v = std::numeric_limits::min(); - } - else if (fg > std::numeric_limits::max()) - { - span->v = std::numeric_limits::max(); + span->v = *nodata_value_; } else { - span->v = static_cast(fg); + span->v = safe_cast(fg / total_weight); } + span->a = base_mask; ++span; diff --git a/include/mapnik/stringify_macro.hpp b/include/mapnik/stringify_macro.hpp new file mode 100644 index 000000000..41f947467 --- /dev/null +++ b/include/mapnik/stringify_macro.hpp @@ -0,0 +1,26 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_STRINGIFY +#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n) +#define MAPNIK_STRINGIFY_HELPER(n) #n +#endif \ No newline at end of file diff --git a/include/mapnik/svg/geometry_svg_generator.hpp b/include/mapnik/svg/geometry_svg_generator.hpp index 11aa5c9c1..7594c26dd 100644 --- a/include/mapnik/svg/geometry_svg_generator.hpp +++ b/include/mapnik/svg/geometry_svg_generator.hpp @@ -36,15 +36,13 @@ #pragma GCC diagnostic push #include #include -#include -#include -#include #include -#include +#include #include #include #pragma GCC diagnostic pop +#include // adapted to conform to the concepts // required by Karma to be recognized as a container of diff --git a/include/mapnik/svg/output/svg_output_grammars.hpp b/include/mapnik/svg/output/svg_output_grammars.hpp index 769671bfc..5657e2606 100644 --- a/include/mapnik/svg/output/svg_output_grammars.hpp +++ b/include/mapnik/svg/output/svg_output_grammars.hpp @@ -40,53 +40,8 @@ namespace mapnik { namespace svg { #include #include #include -#include #pragma GCC diagnostic pop -/*! - * mapnik::svg::path_output_attributes is adapted as a fusion sequence - * in order to be used directly by the svg_path_attributes_grammar (below). - * - * This adaptation is the primary reason why the attributes are stored in - * this structure before being passed to the generate_path method. - */ -BOOST_FUSION_ADAPT_STRUCT( - mapnik::svg::path_output_attributes, - (std::string, fill_color_) - (double, fill_opacity_) - (std::string, stroke_color_) - (double, stroke_opacity_) - (double, stroke_width_) - (std::string, stroke_linecap_) - (std::string, stroke_linejoin_) - (double, stroke_dashoffset_) - ); - -/*! - * mapnik::svg::rect_output_attributes is adapted as a fusion sequence - * in order to be used directly by the svg_rect_attributes_grammar (below). - */ -BOOST_FUSION_ADAPT_STRUCT( - mapnik::svg::rect_output_attributes, - (int, x_) - (int, y_) - (unsigned, width_) - (unsigned, height_) - (std::string, fill_color_) - ); - -/*! - * mapnik::svg::root_output_attributes is adapted as a fusion sequence - * in order to be used directly by the svg_root_attributes_grammar (below). - */ -BOOST_FUSION_ADAPT_STRUCT( - mapnik::svg::root_output_attributes, - (unsigned, width_) - (unsigned, height_) - (double, svg_version_) - (std::string, svg_namespace_url_) - ); - namespace mapnik { namespace svg { using namespace boost::spirit; diff --git a/include/mapnik/svg/output/svg_output_grammars_impl.hpp b/include/mapnik/svg/output/svg_output_grammars_impl.hpp index cbce9196b..ef856a05e 100644 --- a/include/mapnik/svg/output/svg_output_grammars_impl.hpp +++ b/include/mapnik/svg/output/svg_output_grammars_impl.hpp @@ -30,8 +30,53 @@ #include #include #include +#include #pragma GCC diagnostic pop +/*! + * mapnik::svg::path_output_attributes is adapted as a fusion sequence + * in order to be used directly by the svg_path_attributes_grammar (below). + * + * This adaptation is the primary reason why the attributes are stored in + * this structure before being passed to the generate_path method. + */ +BOOST_FUSION_ADAPT_STRUCT( + mapnik::svg::path_output_attributes, + (std::string, fill_color_) + (double, fill_opacity_) + (std::string, stroke_color_) + (double, stroke_opacity_) + (double, stroke_width_) + (std::string, stroke_linecap_) + (std::string, stroke_linejoin_) + (double, stroke_dashoffset_) + ); + +/*! + * mapnik::svg::rect_output_attributes is adapted as a fusion sequence + * in order to be used directly by the svg_rect_attributes_grammar (below). + */ +BOOST_FUSION_ADAPT_STRUCT( + mapnik::svg::rect_output_attributes, + (int, x_) + (int, y_) + (unsigned, width_) + (unsigned, height_) + (std::string, fill_color_) + ); + +/*! + * mapnik::svg::root_output_attributes is adapted as a fusion sequence + * in order to be used directly by the svg_root_attributes_grammar (below). + */ +BOOST_FUSION_ADAPT_STRUCT( + mapnik::svg::root_output_attributes, + (unsigned, width_) + (unsigned, height_) + (double, svg_version_) + (std::string, svg_namespace_url_) + ); + namespace mapnik { namespace svg { using namespace boost::spirit; diff --git a/include/mapnik/svg/svg_converter.hpp b/include/mapnik/svg/svg_converter.hpp index 27fee3122..9cf3c9c16 100644 --- a/include/mapnik/svg/svg_converter.hpp +++ b/include/mapnik/svg/svg_converter.hpp @@ -29,7 +29,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_path_storage.h" #include "agg_conv_transform.h" #include "agg_conv_stroke.h" @@ -37,6 +38,7 @@ #include "agg_conv_curve.h" #include "agg_color_rgba.h" #include "agg_bounding_rect.h" +#pragma GCC diagnostic pop // stl #include @@ -224,7 +226,15 @@ public: attr.stroke_color.opacity(a * s.opacity()); attr.stroke_flag = true; } - + void dash_array(dash_array && dash) + { + path_attributes& attr = cur_attr(); + attr.dash = std::move(dash); + } + void dash_offset(double offset) + { + cur_attr().dash_offset = offset; + } void even_odd(bool flag) { cur_attr().even_odd_flag = flag; diff --git a/include/mapnik/svg/svg_path_adapter.hpp b/include/mapnik/svg/svg_path_adapter.hpp index beb8222cb..8b4fb6bf2 100644 --- a/include/mapnik/svg/svg_path_adapter.hpp +++ b/include/mapnik/svg/svg_path_adapter.hpp @@ -28,10 +28,12 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_math.h" #include "agg_array.h" #include "agg_bezier_arc.h" +#pragma GCC diagnostic pop // stl #include @@ -49,7 +51,7 @@ public: using self_type = path_adapter; //-------------------------------------------------------------------- - path_adapter(VertexContainer & vertices) : vertices_(vertices), iterator_(0) {} + path_adapter(VertexContainer & _vertices) : vertices_(_vertices), iterator_(0) {} //void remove_all() { vertices_.remove_all(); iterator_ = 0; } //void free_all() { vertices_.free_all(); iterator_ = 0; } diff --git a/include/mapnik/svg/svg_path_attributes.hpp b/include/mapnik/svg/svg_path_attributes.hpp index 7e180fdce..80bf46349 100644 --- a/include/mapnik/svg/svg_path_attributes.hpp +++ b/include/mapnik/svg/svg_path_attributes.hpp @@ -23,13 +23,16 @@ #ifndef MAPNIK_SVG_PATH_ATTRIBUTES_HPP #define MAPNIK_SVG_PATH_ATTRIBUTES_HPP -// agg +// mapnik +#include +#include // dash_array + +#pragma GCC diagnostic push +#include #include "agg_math_stroke.h" #include "agg_color_rgba.h" #include "agg_trans_affine.h" - -// mapnik -#include +#pragma GCC diagnostic pop namespace mapnik { namespace svg { @@ -56,7 +59,8 @@ struct path_attributes bool even_odd_flag; bool visibility_flag; bool display_flag; - + dash_array dash; + double dash_offset; // Empty constructor path_attributes() : fill_gradient(), @@ -78,9 +82,10 @@ struct path_attributes stroke_none(false), even_odd_flag(false), visibility_flag(true), - display_flag(true) - { - } + display_flag(true), + dash(), + dash_offset(0.0) + {} // Copy constructor path_attributes(path_attributes const& attr) @@ -103,7 +108,9 @@ struct path_attributes stroke_none(attr.stroke_none), even_odd_flag(attr.even_odd_flag), visibility_flag(attr.visibility_flag), - display_flag(attr.display_flag) + display_flag(attr.display_flag), + dash(attr.dash), + dash_offset(attr.dash_offset) {} // Copy constructor with new index value path_attributes(path_attributes const& attr, unsigned idx) @@ -126,7 +133,9 @@ struct path_attributes stroke_none(attr.stroke_none), even_odd_flag(attr.even_odd_flag), visibility_flag(attr.visibility_flag), - display_flag(attr.display_flag) + display_flag(attr.display_flag), + dash(attr.dash), + dash_offset(attr.dash_offset) {} }; diff --git a/include/mapnik/svg/svg_path_commands.hpp b/include/mapnik/svg/svg_path_commands.hpp index cf69e13a5..7e7ab5fef 100644 --- a/include/mapnik/svg/svg_path_commands.hpp +++ b/include/mapnik/svg/svg_path_commands.hpp @@ -29,241 +29,130 @@ #pragma GCC diagnostic push #include -#include -#include -#include -#include +#include #pragma GCC diagnostic pop -namespace mapnik { namespace svg { +namespace mapnik { +namespace svg { -using namespace boost::fusion; inline double deg2rad(double deg) { - return (M_PI * deg)/180.0; + return (M_PI * deg) / 180.0; } -template struct move_to -{ - - template - struct result - { - using type = void; - }; - - explicit move_to(PathType & path) - : path_(path) {} - - template - void operator() (T0 v, T1 rel) const - { - path_.move_to(at_c<0>(v),at_c<1>(v),rel); // impl - } - - PathType & path_; -}; - -template -struct hline_to -{ - template - struct result - { - using type = void; - }; - - explicit hline_to(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& x, T1 rel) const - { - path_.hline_to(x,rel); - } - - PathType & path_; -}; - - -template -struct vline_to -{ - template - struct result - { - using type = void; - }; - - explicit vline_to(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& y, T1 rel) const - { - path_.vline_to(y,rel); - } - - PathType & path_; -}; - -template -struct line_to -{ - template - struct result - { - using type = void; - }; - - explicit line_to(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& v, T1 rel) const - { - path_.line_to(at_c<0>(v),at_c<1>(v),rel); // impl - } - - PathType & path_; -}; - - -template -struct curve4 -{ - template - struct result - { - using type = void; - }; - - explicit curve4(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& v0, T1 const& v1, T2 const& v2, T3 rel) const - { - path_.curve4(at_c<0>(v0),at_c<1>(v0), - at_c<0>(v1),at_c<1>(v1), - at_c<0>(v2),at_c<1>(v2), - rel); // impl - } - - PathType & path_; -}; - - -template -struct curve4_smooth -{ - template - struct result - { - using type = void; - }; - - explicit curve4_smooth(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& v0, T1 const& v1, T2 rel) const - { - path_.curve4(at_c<0>(v0),at_c<1>(v0), - at_c<0>(v1),at_c<1>(v1), - rel); // impl - } - PathType & path_; -}; - -template -struct curve3 -{ - template - struct result - { - using type = void; - }; - - explicit curve3(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& v0, T1 const& v1, T2 rel) const - { - path_.curve3(at_c<0>(v0),at_c<1>(v0), - at_c<0>(v1),at_c<1>(v1), - rel); // impl - } - - PathType & path_; -}; - -template -struct curve3_smooth -{ - template - struct result - { - using type = void; - }; - - explicit curve3_smooth(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& v0, T1 rel) const - { - path_.curve3(at_c<0>(v0),at_c<1>(v0), - rel); // impl - } - - PathType & path_; -}; - -template -struct arc_to -{ - template - struct result - { - using type = void; - }; - - explicit arc_to(PathType & path) - : path_(path) {} - - template - void operator() (T0 const& rv, T1 const& angle, T2 large_arc_flag, T3 sweep_flag, T4 const& v, T5 rel) const - { - path_.arc_to(at_c<0>(rv),at_c<1>(rv), - deg2rad(angle),large_arc_flag,sweep_flag, - at_c<0>(v),at_c<1>(v), - rel); - } - - PathType & path_; -}; - -template -struct close { using result_type = void; - explicit close(PathType & path) - : path_(path) {} - - void operator()() const + template + void operator()(PathType& path, T0 v, T1 rel) const { - path_.close_subpath(); + path.move_to(boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v), rel); // impl } - - PathType & path_; }; -}} +struct hline_to +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& x, T1 rel) const + { + path.hline_to(x, rel); + } +}; +struct vline_to +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& y, T1 rel) const + { + path.vline_to(y, rel); + } +}; + +struct line_to +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& v, T1 rel) const + { + path.line_to(boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v), rel); // impl + } +}; + +struct curve4 +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& v0, T1 const& v1, T2 const& v2, T3 rel) const + { + path.curve4(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + boost::fusion::at_c<0>(v1), boost::fusion::at_c<1>(v1), + boost::fusion::at_c<0>(v2), boost::fusion::at_c<1>(v2), + rel); // impl + } +}; + +struct curve4_smooth +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& v0, T1 const& v1, T2 rel) const + { + path.curve4(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + boost::fusion::at_c<0>(v1), boost::fusion::at_c<1>(v1), + rel); // impl + } +}; + +struct curve3 +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& v0, T1 const& v1, T2 rel) const + { + path.curve3(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + boost::fusion::at_c<0>(v1), boost::fusion::at_c<1>(v1), + rel); // impl + } +}; + +struct curve3_smooth +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& v0, T1 rel) const + { + path.curve3(boost::fusion::at_c<0>(v0), boost::fusion::at_c<1>(v0), + rel); // impl + } +}; + +struct arc_to +{ + using result_type = void; + template + void operator()(PathType& path, T0 const& rv, T1 const& angle, T2 large_arc_flag, T3 sweep_flag, T4 const& v, T5 rel) const + { + path.arc_to(boost::fusion::at_c<0>(rv), boost::fusion::at_c<1>(rv), + deg2rad(angle), large_arc_flag, sweep_flag, + boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v), + rel); + } +}; + +struct close +{ + using result_type = void; + template + void operator()(PathType& path) const + { + path.close_subpath(); + } +}; +} // namespace svg +} // namespace mapnik #endif // MAPNIK_SVG_COMMANDS_HPP diff --git a/include/mapnik/svg/svg_path_grammar.hpp b/include/mapnik/svg/svg_path_grammar.hpp index 431bf0aed..a65b27266 100644 --- a/include/mapnik/svg/svg_path_grammar.hpp +++ b/include/mapnik/svg/svg_path_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * Copyright (C) 2016 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,133 +23,39 @@ #ifndef MAPNIK_SVG_PATH_GRAMMAR_HPP #define MAPNIK_SVG_PATH_GRAMMAR_HPP -// mapnik -#include - // spirit +#pragma GCC diagnostic push +#include #include -#include -#include -#include +#pragma GCC diagnostic pop namespace mapnik { namespace svg { - using namespace boost::spirit; - using namespace boost::phoenix; +using namespace boost::spirit; - template - struct svg_path_grammar : qi::grammar - { - explicit svg_path_grammar(PathType & path) - : svg_path_grammar::base_type(start), - move_to_(move_to(path)), - hline_to_(hline_to(path)), - vline_to_(vline_to(path)), - line_to_(line_to(path)), - curve4_(curve4(path)), - curve4_smooth_(curve4_smooth(path)), - curve3_(curve3(path)), - curve3_smooth_(curve3_smooth(path)), - arc_to_(arc_to(path)), - close_(close(path)) - { - qi::_1_type _1; - qi::_2_type _2; - qi::_3_type _3; - qi::_4_type _4; - qi::_5_type _5; - qi::_a_type _a; - qi::lit_type lit; - qi::double_type double_; - qi::int_type int_; - qi::no_case_type no_case; +template +struct svg_path_grammar : qi::grammar +{ + // ctor + svg_path_grammar(); + // rules + qi::rule start; + qi::rule cmd; + qi::rule drawto_cmd; + qi::rule, void(PathType&), SkipType> M; // M,m + qi::rule, void(PathType&), SkipType> L; // L,l + qi::rule, void(PathType&), SkipType> H; // H,h + qi::rule, void(PathType&), SkipType> V; // V,v + qi::rule, void(PathType&), SkipType> C; // C,c + qi::rule, void(PathType&), SkipType> S; // S,s + qi::rule, void(PathType&), SkipType> Q; // Q,q + qi::rule, void(PathType&), SkipType> T; // T,t + qi::rule, void(PathType&), SkipType> A; // A,a + qi::rule Z; // Z,z + qi::rule(), SkipType> coord; +}; - start = +cmd; - cmd = M >> *drawto_cmd; - drawto_cmd = L | H | V | C | S | Q | T | A | Z; - - M = (lit('M')[_a = false] | lit('m')[_a = true] ) - >> coord[move_to_(_1,_a)] // move_to - >> *(-lit(',') >> coord [ line_to_(_1,_a) ] ); // *line_to - - H = (lit('H')[_a = false] | lit('h')[_a = true]) - >> +double_[ hline_to_(_1,_a) ] ; // +hline_to - - V = (lit('V')[_a = false] | lit('v')[_a = true]) - >> +double_ [ vline_to_(_1,_a) ]; // +vline_to - - L = (lit('L')[_a = false] | lit('l')[_a = true]) - >> +coord [ line_to_(_1,_a) ]; // +line_to - - C = (lit('C')[_a = false] | lit('c')[_a = true]) - >> +(coord - >> -lit(',') - >> coord - >> -lit(',') - >> coord) [ curve4_(_1,_2,_3,_a) ]; // +curve4 - - S = (lit('S')[_a = false] | lit('s')[_a = true]) - >> +(coord - >> -lit(',') - >> coord) [ curve4_smooth_(_1,_2,_a) ]; // +curve4_smooth (smooth curveto) - - Q = (lit('Q')[_a = false] | lit('q')[_a = true]) - >> +(coord - >> -lit(',') - >> coord) [ curve3_(_1,_2,_a) ]; // +curve3 (quadratic-bezier-curveto) - - T = (lit('T')[_a = false] | lit('t')[_a = true]) - >> +(coord ) [ curve3_smooth_(_1,_a) ]; // +curve3_smooth (smooth-quadratic-bezier-curveto) - - A = (lit('A')[_a = false] | lit('a')[_a = true]) - >> +(coord - >> -lit(',') - >> double_ - >> -lit(',') - >> int_ - >> -lit(',') - >> int_ - >> -lit(',') - >> coord) [arc_to_(_1,_2,_3,_4,_5,_a)]; // arc_to; - - - - Z = no_case[lit('z')] [close_()]; // close path - - coord = double_ >> -lit(',') >> double_; - } - - // rules - qi::rule start; - qi::rule cmd; - qi::rule drawto_cmd; - qi::rule,SkipType> M; // M,m - qi::rule,SkipType> L; // L,l - qi::rule,SkipType> H; // H,h - qi::rule,SkipType> V; // V,v - qi::rule,SkipType> C; // C,c - qi::rule,SkipType> S; // S,s - qi::rule,SkipType> Q; // Q,q - qi::rule,SkipType> T; // T,t - qi::rule,SkipType> A; // A,a - qi::rule Z; // Z,z - - qi::rule(),SkipType> coord; - - // commands - function > move_to_; - function > hline_to_; - function > vline_to_; - function > line_to_; - function > curve4_; - function > curve4_smooth_; - function > curve3_; - function > curve3_smooth_; - function > arc_to_; - function > close_; - }; - - }} +}} #endif // MAPNIK_SVG_PATH_GRAMMAR_HPP diff --git a/include/mapnik/svg/svg_path_grammar_impl.hpp b/include/mapnik/svg/svg_path_grammar_impl.hpp new file mode 100644 index 000000000..5d5fd1a7a --- /dev/null +++ b/include/mapnik/svg/svg_path_grammar_impl.hpp @@ -0,0 +1,112 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// NOTE: This is an implementation header file and is only meant to be included +// from implementation files. It therefore doesn't have an include guard. + +// mapnik +#include +#include + +// spirit +#pragma GCC diagnostic push +#include +#include +#include +#include +#pragma GCC diagnostic pop + +namespace mapnik { namespace svg { + +using namespace boost::spirit; +using namespace boost::phoenix; + + +template +svg_path_grammar::svg_path_grammar() + : svg_path_grammar::base_type(start) +{ + qi::_1_type _1; + qi::_2_type _2; + qi::_3_type _3; + qi::_4_type _4; + qi::_5_type _5; + qi::_a_type _a; + qi::lit_type lit; + qi::_r1_type _r1; + qi::double_type double_; + qi::int_type int_; + qi::no_case_type no_case; + + // commands + function move_to_; + function hline_to_; + function vline_to_; + function line_to_; + function curve4_; + function curve4_smooth_; + function curve3_; + function curve3_smooth_; + function arc_to_; + function close_; + // + start = +cmd(_r1); + + cmd = M(_r1) >> *drawto_cmd(_r1); + + drawto_cmd = L(_r1) | H(_r1) | V(_r1) | C(_r1) | S(_r1) | Q(_r1) | T(_r1) | A(_r1) | Z(_r1); + + M = (lit('M')[_a = false] | lit('m')[_a = true]) >> coord[move_to_(_r1, _1, _a)] // move_to + >> *(-lit(',') >> coord[line_to_(_r1, _1, _a)]); // *line_to + + H = (lit('H')[_a = false] | lit('h')[_a = true]) + >> (double_[ hline_to_(_r1, _1,_a) ] % -lit(',')) ; // +hline_to + + V = (lit('V')[_a = false] | lit('v')[_a = true]) + >> (double_ [ vline_to_(_r1, _1,_a) ] % -lit(',')); // +vline_to + + L = (lit('L')[_a = false] | lit('l')[_a = true]) + >> (coord [ line_to_(_r1, _1, _a) ] % -lit(',')); // +line_to + + C = (lit('C')[_a = false] | lit('c')[_a = true]) + >> ((coord >> -lit(',') >> coord >> -lit(',') >> coord)[curve4_(_r1, _1, _2, _3, _a)] % -lit(',')); // +curve4 + + S = (lit('S')[_a = false] | lit('s')[_a = true]) + >> ((coord >> -lit(',') >> coord) [ curve4_smooth_(_r1, _1,_2,_a) ] % -lit(',')); // +curve4_smooth (smooth curveto) + + Q = (lit('Q')[_a = false] | lit('q')[_a = true]) + >> ((coord >> -lit(',') >> coord) [ curve3_(_r1, _1,_2,_a) ] % -lit(',')); // +curve3 (quadratic-bezier-curveto) + + T = (lit('T')[_a = false] | lit('t')[_a = true]) + >> ((coord ) [ curve3_smooth_(_r1, _1,_a) ] % -lit(',')); // +curve3_smooth (smooth-quadratic-bezier-curveto) + + A = (lit('A')[_a = false] | lit('a')[_a = true]) + >> ((coord >> -lit(',') >> double_ >> -lit(',') >> int_ >> -lit(',') >> int_ >> -lit(',') >> coord) + [arc_to_(_r1, _1, _2, _3, _4, _5, _a)] % -lit(',')); // arc_to; + + Z = no_case[lit('z')] [close_(_r1)]; // close path + + coord = double_ >> -lit(',') >> double_; +} + +} // namespace svg +} // namespace mapnik diff --git a/include/mapnik/svg/svg_path_parser.hpp b/include/mapnik/svg/svg_path_parser.hpp index 35303f98d..5633b2ea9 100644 --- a/include/mapnik/svg/svg_path_parser.hpp +++ b/include/mapnik/svg/svg_path_parser.hpp @@ -23,20 +23,32 @@ #ifndef MAPNIK_SVG_PATH_PARSER_HPP #define MAPNIK_SVG_PATH_PARSER_HPP +// mapnik #include +#include +#include +// stl #include -namespace mapnik { namespace svg { +namespace mapnik { +namespace svg { - template - bool parse_path(const char * wkt, PathType & p); +template +bool parse_path(const char* wkt, PathType& p); - template - bool parse_points(const char * wkt, PathType & p); +template +bool parse_points(const char* wkt, PathType& p); + +template +bool MAPNIK_DECL parse_svg_transform(const char* wkt, TransformType& tr); + +// +extern template bool MAPNIK_DECL parse_path(const char*, svg_converter_type&); +extern template bool MAPNIK_DECL parse_points(const char*, svg_converter_type&); +extern template bool MAPNIK_DECL parse_svg_transform(const char*, svg_converter_type&); +} +} - template - bool MAPNIK_DECL parse_svg_transform(const char * wkt, TransformType & tr); -}} #endif // MAPNIK_SVG_PATH_PARSER_HPP diff --git a/include/mapnik/svg/svg_points_grammar.hpp b/include/mapnik/svg/svg_points_grammar.hpp index 94602cc3f..afbe7ee09 100644 --- a/include/mapnik/svg/svg_points_grammar.hpp +++ b/include/mapnik/svg/svg_points_grammar.hpp @@ -29,46 +29,22 @@ #pragma GCC diagnostic push #include #include -#include -#include -#include #pragma GCC diagnostic pop namespace mapnik { namespace svg { - using namespace boost::spirit; - using namespace boost::phoenix; - - template - struct svg_points_grammar : qi::grammar - { - explicit svg_points_grammar(PathType & path) - : svg_points_grammar::base_type(start), - move_to_(move_to(path)), - line_to_(line_to(path)), - close_(close(path)) - { - qi::_1_type _1; - qi::lit_type lit; - qi::double_type double_; - - start = coord[move_to_(_1,false)] // move_to - >> *(-lit(',') >> coord [ line_to_(_1,false) ] ); // *line_to - - coord = double_ >> -lit(',') >> double_; - } - - // rules - qi::rule start; - qi::rule(),SkipType> coord; - - // commands - function > move_to_; - function > line_to_; - function > close_; - }; - - }} +using namespace boost::spirit; +using namespace boost::phoenix; +template +struct svg_points_grammar : qi::grammar +{ + // ctor + svg_points_grammar(); + // rules + qi::rule start; + qi::rule(), SkipType> coord; +}; +}} #endif // SVG_POINTS_GRAMMAR_HPP diff --git a/include/mapnik/svg/svg_points_grammar_impl.hpp b/include/mapnik/svg/svg_points_grammar_impl.hpp new file mode 100644 index 000000000..5d56f7e25 --- /dev/null +++ b/include/mapnik/svg/svg_points_grammar_impl.hpp @@ -0,0 +1,61 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// NOTE: This is an implementation header file and is only meant to be included +// from implementation files. It therefore doesn't have an include guard. +// mapnik +#include +#include + +#pragma GCC diagnostic push +#include +#include +#include +#include +#include +#pragma GCC diagnostic pop + +namespace mapnik { namespace svg { + +using namespace boost::spirit; +using namespace boost::phoenix; + +template +svg_points_grammar::svg_points_grammar() + : svg_points_grammar::base_type(start) +{ + qi::_1_type _1; + qi::_r1_type _r1; + qi::lit_type lit; + qi::double_type double_; + // commands + function move_to_; + function line_to_; + function close_; + + start = coord[move_to_(_r1, _1, false)] // move_to + >> *(-lit(',') >> coord [ line_to_(_r1, _1,false) ] ); // *line_to + + coord = double_ >> -lit(',') >> double_; +} + +}} diff --git a/include/mapnik/svg/svg_renderer_agg.hpp b/include/mapnik/svg/svg_renderer_agg.hpp index ad574cc62..d99575b4d 100644 --- a/include/mapnik/svg/svg_renderer_agg.hpp +++ b/include/mapnik/svg/svg_renderer_agg.hpp @@ -37,12 +37,14 @@ #pragma GCC diagnostic pop #endif -// agg +#pragma GCC diagnostic push +#include #include "agg_path_storage.h" #include "agg_conv_transform.h" #include "agg_conv_stroke.h" #include "agg_conv_contour.h" #include "agg_conv_curve.h" +#include "agg_conv_dash.h" #include "agg_color_rgba.h" #include "agg_bounding_rect.h" #include "agg_rendering_buffer.h" @@ -56,16 +58,15 @@ #include "agg_gradient_lut.h" #include "agg_gamma_lut.h" #include "agg_span_interpolator_linear.h" +#pragma GCC diagnostic pop namespace mapnik { namespace svg { +// Arbitrary linear gradient specified by two control points. Gradient +// value is taken as the normalised distance along the line segment +// represented by the two points. -/** - * Arbitrary linear gradient specified by two control points. Gradient - * value is taken as the normalised distance along the line segment - * represented by the two points. - */ class linear_gradient_from_segment { public: @@ -105,19 +106,28 @@ template ; - using curved_stroked_type = agg::conv_stroke ; + using curved_type = agg::conv_curve; + // stroke + using curved_stroked_type = agg::conv_stroke; using curved_stroked_trans_type = agg::conv_transform; - using curved_trans_type = agg::conv_transform ; - using curved_trans_contour_type = agg::conv_contour ; - using renderer_base = agg::renderer_base ; - using vertex_source_type = VertexSource ; - using attribute_source_type = AttributeSource ; + // stroke dash-array + using curved_dashed_type = agg::conv_dash; + using curved_dashed_stroked_type = agg::conv_stroke; + using curved_dashed_stroked_trans_type = agg::conv_transform; + // fill + using curved_trans_type = agg::conv_transform; + using curved_trans_contour_type = agg::conv_contour; + // renderer + using renderer_base = agg::renderer_base; + using vertex_source_type = VertexSource; + using attribute_source_type = AttributeSource; svg_renderer_agg(VertexSource & source, AttributeSource const& attributes) : source_(source), curved_(source_), + curved_dashed_(curved_), curved_stroked_(curved_), + curved_dashed_stroked_(curved_dashed_), attributes_(attributes) {} template @@ -191,11 +201,11 @@ public: // scale everything up since agg turns things into integers a bit too soon int scaleup=255; - radius*=scaleup; - x1*=scaleup; - y1*=scaleup; - x2*=scaleup; - y2*=scaleup; + radius *= scaleup; + x1 *= scaleup; + y1 *= scaleup; + x2 *= scaleup; + y2 *= scaleup; transform.scale(scaleup,scaleup); interpolator_type span_interpolator(transform); @@ -217,10 +227,10 @@ public: color_func_type>; // scale everything up since agg turns things into integers a bit too soon int scaleup=255; - x1*=scaleup; - y1*=scaleup; - x2*=scaleup; - y2*=scaleup; + x1 *= scaleup; + y1 *= scaleup; + x2 *= scaleup; + y2 *= scaleup; transform.scale(scaleup,scaleup); @@ -247,10 +257,11 @@ public: { using namespace agg; - trans_affine transform; + curved_stroked_trans_type curved_stroked_trans(curved_stroked_,transform); - curved_trans_type curved_trans(curved_,transform); + curved_dashed_stroked_trans_type curved_dashed_stroked_trans(curved_dashed_stroked_, transform); + curved_trans_type curved_trans(curved_,transform); curved_trans_contour_type curved_trans_contour(curved_trans); curved_trans_contour.auto_detect_orientation(true); @@ -274,7 +285,6 @@ public: if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT) { ras.reset(); - // https://github.com/mapnik/mapnik/issues/1129 if(std::fabs(curved_trans_contour.width()) <= 1) { @@ -288,7 +298,8 @@ public: if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT) { - render_gradient(ras, sl, ren, attr.fill_gradient, transform, attr.fill_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index); + render_gradient(ras, sl, ren, attr.fill_gradient, transform, + attr.fill_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index); } else { @@ -304,37 +315,79 @@ public: if (attr.stroke_flag || attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) { - curved_stroked_.width(attr.stroke_width); - //m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join); - curved_stroked_.line_join(attr.line_join); - curved_stroked_.line_cap(attr.line_cap); - curved_stroked_.miter_limit(attr.miter_limit); - curved_stroked_.inner_join(inner_round); - curved_stroked_.approximation_scale(scl); - - // If the *visual* line width is considerable we - // turn on processing of curve cusps. - //--------------------- - if(attr.stroke_width * scl > 1.0) + if (attr.dash.size() > 0) { - curved_.angle_tolerance(0.2); - } - ras.reset(); - ras.add_path(curved_stroked_trans, attr.index); + curved_dashed_stroked_.width(attr.stroke_width); + curved_dashed_stroked_.line_join(attr.line_join); + curved_dashed_stroked_.line_cap(attr.line_cap); + curved_dashed_stroked_.miter_limit(attr.miter_limit); + curved_dashed_stroked_.inner_join(inner_round); + curved_dashed_stroked_.approximation_scale(scl); - if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) - { - render_gradient(ras, sl, ren, attr.stroke_gradient, transform, attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index); + // If the *visual* line width is considerable we + // turn on processing of curve cups. + //--------------------- + if (attr.stroke_width * scl > 1.0) + { + curved_.angle_tolerance(0.2); + } + ras.reset(); + curved_dashed_.remove_all_dashes(); + for (auto d : attr.dash) + { + curved_dashed_.add_dash(std::get<0>(d),std::get<1>(d)); + } + curved_dashed_.dash_start(attr.dash_offset); + ras.add_path(curved_dashed_stroked_trans, attr.index); + if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) + { + render_gradient(ras, sl, ren, attr.stroke_gradient, transform, + attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index); + } + else + { + ras.filling_rule(fill_non_zero); + color = attr.stroke_color; + color.opacity(color.opacity() * attr.stroke_opacity * attr.opacity * opacity); + ScanlineRenderer ren_s(ren); + color.premultiply(); + ren_s.color(color); + render_scanlines(ras, sl, ren_s); + } } else { - ras.filling_rule(fill_non_zero); - color = attr.stroke_color; - color.opacity(color.opacity() * attr.stroke_opacity * attr.opacity * opacity); - ScanlineRenderer ren_s(ren); - color.premultiply(); - ren_s.color(color); - render_scanlines(ras, sl, ren_s); + curved_stroked_.width(attr.stroke_width); + curved_stroked_.line_join(attr.line_join); + curved_stroked_.line_cap(attr.line_cap); + curved_stroked_.miter_limit(attr.miter_limit); + curved_stroked_.inner_join(inner_round); + curved_stroked_.approximation_scale(scl); + + // If the *visual* line width is considerable we + // turn on processing of curve cups. + //--------------------- + if (attr.stroke_width * scl > 1.0) + { + curved_.angle_tolerance(0.2); + } + ras.reset(); + ras.add_path(curved_stroked_trans, attr.index); + if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) + { + render_gradient(ras, sl, ren, attr.stroke_gradient, transform, + attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index); + } + else + { + ras.filling_rule(fill_non_zero); + color = attr.stroke_color; + color.opacity(color.opacity() * attr.stroke_opacity * attr.opacity * opacity); + ScanlineRenderer ren_s(ren); + color.premultiply(); + ren_s.color(color); + render_scanlines(ras, sl, ren_s); + } } } } @@ -409,7 +462,7 @@ public: // If the *visual* line width is considerable we // turn on processing of curve cusps. //--------------------- - if(attr.stroke_width * scl > 1.0) + if (attr.stroke_width * scl > 1.0) { curved_.angle_tolerance(0.2); } @@ -431,7 +484,9 @@ private: VertexSource & source_; curved_type curved_; + curved_dashed_type curved_dashed_; curved_stroked_type curved_stroked_; + curved_dashed_stroked_type curved_dashed_stroked_; AttributeSource const& attributes_; }; diff --git a/include/mapnik/svg/svg_transform_grammar.hpp b/include/mapnik/svg/svg_transform_grammar.hpp index 1465f3a2a..895112d4a 100644 --- a/include/mapnik/svg/svg_transform_grammar.hpp +++ b/include/mapnik/svg/svg_transform_grammar.hpp @@ -26,240 +26,31 @@ // mapnik #include -// agg -#include - #pragma GCC diagnostic push #include #include -#include -#include -#include -#include #pragma GCC diagnostic pop namespace mapnik { namespace svg { - using namespace boost::spirit; - using namespace boost::fusion; - using namespace boost::phoenix; +using namespace boost::spirit; - inline double deg2rad(double d) - { - return M_PI * d / 180.0; - } +template +struct svg_transform_grammar : qi::grammar +{ + // ctor + svg_transform_grammar(); + // rules + qi::rule start; + qi::rule transform_; + qi::rule matrix; + qi::rule translate; + qi::rule scale; + qi::rule, void(TransformType&), SkipType> rotate; + qi::rule skewX; + qi::rule skewY; +}; - template - struct process_matrix - { - template - struct result - { - using type = void; - }; - - explicit process_matrix( TransformType & tr) - :tr_(tr) {} - - void operator () (double a, double b, double c, double d, double e, double f) const - { - tr_ = agg::trans_affine(a,b,c,d,e,f) * tr_; - } - - TransformType & tr_; - }; - - template - struct process_rotate - { - template - struct result - { - using type = void; - }; - - explicit process_rotate( TransformType & tr) - :tr_(tr) {} - - template - void operator () (T0 a, T1 cx, T2 cy) const - { - if (cx == 0.0 && cy == 0.0) - { - tr_ = agg::trans_affine_rotation(deg2rad(a)) * tr_; - } - else - { - agg::trans_affine t = agg::trans_affine_translation(-cx,-cy); - t *= agg::trans_affine_rotation(deg2rad(a)); - t *= agg::trans_affine_translation(cx, cy); - tr_ = t * tr_; - } - } - - TransformType & tr_; - }; - - template - struct process_translate - { - template - struct result - { - using type = void; - }; - - explicit process_translate( TransformType & tr) - :tr_(tr) {} - - template - void operator () (T0 tx, T1 ty) const - { - if (ty) tr_ = agg::trans_affine_translation(tx,*ty) * tr_; - else tr_ = agg::trans_affine_translation(tx,0.0) * tr_; - } - - TransformType & tr_; - }; - - template - struct process_scale - { - template - struct result - { - using type = void; - }; - - explicit process_scale( TransformType & tr) - :tr_(tr) {} - - template - void operator () (T0 sx, T1 sy) const - { - if (sy) tr_ = agg::trans_affine_scaling(sx,*sy) * tr_; - else tr_ = agg::trans_affine_scaling(sx,sx) * tr_; - } - - TransformType & tr_; - }; - - - template - struct process_skew - { - template - struct result - { - using type = void; - }; - - explicit process_skew( TransformType & tr) - :tr_(tr) {} - - template - void operator () (T0 skew_x, T1 skew_y) const - { - tr_ = agg::trans_affine_skewing(deg2rad(skew_x),deg2rad(skew_y)) * tr_; - } - - TransformType & tr_; - }; - - // commented as this does not appear used and crashes clang when used with pch - /* - struct print_action - { - template - void operator()(T const& c, qi::unused_type, qi::unused_type) const - { - MAPNIK_LOG_DEBUG(svg) << typeid(c).name(); - } - }; - */ - - template - struct svg_transform_grammar : qi::grammar - { - explicit svg_transform_grammar(TransformType & tr) - : svg_transform_grammar::base_type(start), - matrix_action(process_matrix(tr)), - rotate_action(process_rotate(tr)), - translate_action(process_translate(tr)), - scale_action(process_scale(tr)), - skew_action(process_skew(tr)) - { - qi::_1_type _1; - qi::_2_type _2; - qi::_3_type _3; - qi::_4_type _4; - qi::_5_type _5; - qi::_6_type _6; - qi::_a_type _a; - qi::_b_type _b; - qi::_c_type _c; - qi::lit_type lit; - qi::double_type double_; - qi::no_case_type no_case; - - start = +transform_ ; - - transform_ = matrix | rotate | translate | scale | rotate | skewX | skewY ; - - matrix = no_case[lit("matrix")] - >> lit('(') - >> ( - double_ >> -lit(',') - >> double_ >> -lit(',') - >> double_ >> -lit(',') - >> double_ >> -lit(',') - >> double_ >> -lit(',') - >> double_) [ matrix_action(_1,_2,_3,_4,_5,_6) ] - >> lit(')') - ; - - translate = no_case[lit("translate")] - >> lit('(') - >> (double_ >> -lit(',') - >> -double_) [ translate_action(_1,_2) ] - >> lit(')'); - - scale = no_case[lit("scale")] - >> lit('(') - >> (double_ >> -lit(',') - >> -double_ )[ scale_action(_1,_2)] - >> lit(')'); - - rotate = no_case[lit("rotate")] - >> lit('(') - >> double_[_a = _1] >> -lit(',') - >> -(double_ [_b = _1] >> -lit(',') >> double_[_c = _1]) - >> lit(')') [ rotate_action(_a,_b,_c)]; - - skewX = no_case[lit("skewX")] >> lit('(') >> double_ [ skew_action(_1, 0.0)] >> lit(')'); - - skewY = no_case[lit("skewY")] >> lit('(') >> double_ [ skew_action(0.0, _1)] >> lit(')'); - - } - - // rules - qi::rule start; - qi::rule transform_; - qi::rule matrix; - qi::rule translate; - qi::rule scale; - qi::rule, SkipType> rotate; - qi::rule skewX; - qi::rule skewY; - - // actions - function > matrix_action; - function > rotate_action; - function > translate_action; - function > scale_action; - function > skew_action; - }; - - }} +}} #endif // MAPNIK_SVG_TRANSFORM_GRAMMAR_HPP diff --git a/include/mapnik/svg/svg_transform_grammar_impl.hpp b/include/mapnik/svg/svg_transform_grammar_impl.hpp new file mode 100644 index 000000000..65c05ab2c --- /dev/null +++ b/include/mapnik/svg/svg_transform_grammar_impl.hpp @@ -0,0 +1,172 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// NOTE: This is an implementation header file and is only meant to be included +// from implementation files. It therefore doesn't have an include guard. +// mapnik +#include + +#pragma GCC diagnostic push +#include +#include +#include +#include +#include +#pragma GCC diagnostic pop + +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +namespace mapnik { namespace svg { + +using namespace boost::spirit; +using namespace boost::fusion; +using namespace boost::phoenix; + +inline double deg2rad(double d) +{ + return M_PI * d / 180.0; +} + +struct process_matrix +{ + using result_type = void; + template + void operator () (TransformType & tr, double a, double b, double c, double d, double e, double f) const + { + tr = agg::trans_affine(a,b,c,d,e,f) * tr; + } +}; + +struct process_rotate +{ + using result_type = void; + + template + void operator () (TransformType & tr, T0 a, T1 cx, T2 cy) const + { + if (cx == 0.0 && cy == 0.0) + { + tr = agg::trans_affine_rotation(deg2rad(a)) * tr; + } + else + { + agg::trans_affine t = agg::trans_affine_translation(-cx,-cy); + t *= agg::trans_affine_rotation(deg2rad(a)); + t *= agg::trans_affine_translation(cx, cy); + tr = t * tr; + } + } +}; + +struct process_translate +{ + using result_type = void; + template + void operator () (TransformType & tr, T0 tx, T1 ty) const + { + if (ty) tr = agg::trans_affine_translation(tx,*ty) * tr; + else tr = agg::trans_affine_translation(tx,0.0) * tr; + } +}; + +struct process_scale +{ + using result_type = void; + template + void operator () (TransformType & tr, T0 sx, T1 sy) const + { + if (sy) tr = agg::trans_affine_scaling(sx,*sy) * tr; + else tr = agg::trans_affine_scaling(sx,sx) * tr; + } +}; + + +struct process_skew +{ + using result_type = void; + + template + void operator () (TransformType & tr, T0 skew_x, T1 skew_y) const + { + tr = agg::trans_affine_skewing(deg2rad(skew_x),deg2rad(skew_y)) * tr; + } +}; + +template +svg_transform_grammar::svg_transform_grammar() + : svg_transform_grammar::base_type(start) +{ + qi::_1_type _1; + qi::_2_type _2; + qi::_3_type _3; + qi::_4_type _4; + qi::_5_type _5; + qi::_6_type _6; + qi::_a_type _a; + qi::_b_type _b; + qi::_c_type _c; + qi::_r1_type _r1; + qi::lit_type lit; + qi::double_type double_; + qi::no_case_type no_case; + + // actions + function matrix_action; + function rotate_action; + function translate_action; + function scale_action; + function skew_action; + + start = +transform_(_r1) ; + + transform_ = matrix(_r1) | rotate(_r1) | translate(_r1) | scale(_r1) | rotate(_r1) | skewX(_r1) | skewY (_r1) ; + + matrix = no_case[lit("matrix")] >> lit('(') + >> (double_ >> -lit(',') + >> double_ >> -lit(',') + >> double_ >> -lit(',') + >> double_ >> -lit(',') + >> double_ >> -lit(',') + >> double_)[matrix_action(_r1, _1, _2, _3, _4, _5, _6)] >> lit(')'); + + translate = no_case[lit("translate")] + >> lit('(') >> (double_ >> -lit(',') >> -double_)[translate_action(_r1, _1, _2)] >> lit(')'); + + scale = no_case[lit("scale")] + >> lit('(') >> (double_ >> -lit(',') >> -double_)[scale_action(_r1, _1, _2)] >> lit(')'); + + rotate = no_case[lit("rotate")] + >> lit('(') + >> double_[_a = _1] >> -lit(',') + >> -(double_ [_b = _1] >> -lit(',') >> double_[_c = _1]) + >> lit(')') [ rotate_action(_r1, _a,_b,_c)]; + + skewX = no_case[lit("skewX")] >> lit('(') >> double_ [ skew_action(_r1, _1, 0.0)] >> lit(')'); + + skewY = no_case[lit("skewY")] >> lit('(') >> double_ [ skew_action(_r1, 0.0, _1)] >> lit(')'); + +} + +}} diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 40283b9d3..9308ecd7b 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -51,8 +51,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { @@ -317,12 +319,8 @@ struct evaluate_expression_wrapper mapnik::value_type val = util::apply_visitor(mapnik::evaluate(feature,vars), expr); if (val.is_null()) return dash_array(); dash_array dash; - std::vector buf; std::string str = val.to_string(); - if (util::parse_dasharray(str,buf)) - { - util::add_dashes(buf,dash); - } + util::parse_dasharray(str,dash); return dash; } }; diff --git a/include/mapnik/symbolizer_base.hpp b/include/mapnik/symbolizer_base.hpp index f960752c8..f07cf3d2a 100644 --- a/include/mapnik/symbolizer_base.hpp +++ b/include/mapnik/symbolizer_base.hpp @@ -58,7 +58,7 @@ MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, attributes const& vars, transform_type const& trans_expr, - double scale_factor=1.0); + double scale_factor); struct enumeration_wrapper { @@ -98,24 +98,24 @@ using value_base_type = util::variant strict_value(T const& obj) : value_base_type(typename detail::mapnik_value_type::type(obj)) {} - // move ctor - template - strict_value(T && obj) noexcept - : value_base_type(std::move(obj)) {} + template + strict_value(T && obj) + noexcept(std::is_nothrow_constructible::value) + : value_base_type(std::forward(obj)) + {} }; -} + +} // namespace detail struct MAPNIK_DECL symbolizer_base { diff --git a/include/mapnik/symbolizer_default_values.hpp b/include/mapnik/symbolizer_default_values.hpp index b70ea194b..ea5e5c02e 100644 --- a/include/mapnik/symbolizer_default_values.hpp +++ b/include/mapnik/symbolizer_default_values.hpp @@ -24,7 +24,12 @@ #define MAPNIK_SYMBOLIZER_DEFAULT_VALUES_HPP #include +#include +#include +#include +#include #include +#include #include diff --git a/include/mapnik/symbolizer_utils.hpp b/include/mapnik/symbolizer_utils.hpp index 358628bd2..cea99000c 100644 --- a/include/mapnik/symbolizer_utils.hpp +++ b/include/mapnik/symbolizer_utils.hpp @@ -404,9 +404,8 @@ struct set_symbolizer_property_impl boost::optional str = node.get_opt_attr(name); if (str) { - std::vector buf; dash_array dash; - if (util::parse_dasharray(*str,buf) && util::add_dashes(buf,dash)) + if (util::parse_dasharray(*str,dash)) { put(sym,key,dash); } diff --git a/include/mapnik/text/face.hpp b/include/mapnik/text/face.hpp index 60a37e692..3d797a1f2 100644 --- a/include/mapnik/text/face.hpp +++ b/include/mapnik/text/face.hpp @@ -23,11 +23,13 @@ #define MAPNIK_FACE_HPP //mapnik -#include #include +#include #include -// freetype2 +#pragma GCC diagnostic push +#include + extern "C" { #include @@ -35,8 +37,9 @@ extern "C" #include FT_STROKER_H } +#pragma GCC diagnostic pop + //stl -#include #include #include #include diff --git a/include/mapnik/text/font_feature_settings.hpp b/include/mapnik/text/font_feature_settings.hpp index 9d945fbe5..8bc3e33c6 100644 --- a/include/mapnik/text/font_feature_settings.hpp +++ b/include/mapnik/text/font_feature_settings.hpp @@ -31,8 +31,11 @@ #include #include #include -// harfbuzz + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // EqualityComparable inline bool operator==(hb_feature_t const& lhs, hb_feature_t const& rhs) @@ -86,7 +89,10 @@ inline bool operator==(font_feature_settings const& lhs, font_feature_settings c constexpr unsigned int font_feature_range_global_start = 0u; static const unsigned int font_feature_range_global_end = std::numeric_limits::max(); +#pragma GCC diagnostic push +#include constexpr hb_feature_t font_feature_liga_off = { HB_TAG('l', 'i', 'g', 'a'), 0, font_feature_range_global_start, font_feature_range_global_end }; +#pragma GCC diagnostic pop } // mapnik namespace diff --git a/include/mapnik/text/formatting/layout.hpp b/include/mapnik/text/formatting/layout.hpp index dd7f4b011..6892ce72b 100644 --- a/include/mapnik/text/formatting/layout.hpp +++ b/include/mapnik/text/formatting/layout.hpp @@ -26,7 +26,10 @@ #include #include +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace formatting { diff --git a/include/mapnik/text/glyph_positions.hpp b/include/mapnik/text/glyph_positions.hpp index e956edda8..aa08e3376 100644 --- a/include/mapnik/text/glyph_positions.hpp +++ b/include/mapnik/text/glyph_positions.hpp @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -#ifndef MAPNIK_PLACEMENTS_LIST_HPP -#define MAPNIK_PLACEMENTS_LIST_HPP + +#ifndef MAPNIK_TEXT_GLYPH_POSITIONS_HPP +#define MAPNIK_TEXT_GLYPH_POSITIONS_HPP + //mapnik #include #include @@ -28,8 +30,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop //stl #include @@ -79,7 +83,7 @@ public: pixel_position const& get_base_point() const; void set_base_point(pixel_position const& base_point); void set_marker(marker_info_ptr marker, pixel_position const& marker_pos); - marker_info_ptr get_marker() const; + marker_info_ptr const& get_marker() const; pixel_position const& marker_pos() const; private: std::vector data_; @@ -88,8 +92,46 @@ private: pixel_position marker_pos_; box2d bbox_; }; + using glyph_positions_ptr = std::unique_ptr; using placements_list = std::list; -} -#endif // PLACEMENTS_LIST_HPP + +struct scoped_glyph_positions_offset +{ + scoped_glyph_positions_offset(glyph_positions & glyphs, pixel_position const& offset) + : glyphs_(glyphs) + , base_point_(glyphs.get_base_point()) + , marker_pos_(glyphs.marker_pos()) + { + // move the glyphs to the correct offset + glyphs_.set_base_point(base_point_ + offset); + + // update the position of any marker + if (auto const& marker_info = glyphs_.get_marker()) + { + glyphs_.set_marker(marker_info, marker_pos_ + offset); + } + } + + ~scoped_glyph_positions_offset() + { + // set the base_point back how it was + glyphs_.set_base_point(base_point_); + + // restore marker as well, if there is any + if (auto const& marker_info = glyphs_.get_marker()) + { + glyphs_.set_marker(marker_info, marker_pos_); + } + } + +private: + glyph_positions & glyphs_; + pixel_position base_point_; + pixel_position marker_pos_; +}; + +} // namespace mapnik + +#endif // MAPNIK_TEXT_GLYPH_POSITIONS_HPP diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index 0f23bc844..8b574b095 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -36,12 +36,12 @@ #include #include -// harfbuzz +#pragma GCC diagnostic push +#include #include #include - -// icu #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/text/icu_shaper.hpp b/include/mapnik/text/icu_shaper.hpp index bcd822b27..39bc590bb 100644 --- a/include/mapnik/text/icu_shaper.hpp +++ b/include/mapnik/text/icu_shaper.hpp @@ -36,11 +36,12 @@ // stl #include -// icu +#pragma GCC diagnostic push +#include #include #include #include - +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/text/itemizer.hpp b/include/mapnik/text/itemizer.hpp index b8589448d..5087ce06f 100644 --- a/include/mapnik/text/itemizer.hpp +++ b/include/mapnik/text/itemizer.hpp @@ -34,10 +34,12 @@ #include #include -// ICU +#pragma GCC diagnostic push +#include #include #include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/text/placement_finder.hpp b/include/mapnik/text/placement_finder.hpp index f35a5d50b..3b02d8924 100644 --- a/include/mapnik/text/placement_finder.hpp +++ b/include/mapnik/text/placement_finder.hpp @@ -78,7 +78,6 @@ private: // Maps upright==auto, left-only and right-only to left,right to simplify processing. // angle = angle of at start of line (to estimate best option for upright==auto) text_upright_e simplify_upright(text_upright_e upright, double angle) const; - box2d get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot); feature_impl const& feature_; attributes const& attr_; DetectorType & detector_; diff --git a/include/mapnik/text/properties_util.hpp b/include/mapnik/text/properties_util.hpp index 0fff84e7b..5b92ed306 100644 --- a/include/mapnik/text/properties_util.hpp +++ b/include/mapnik/text/properties_util.hpp @@ -26,11 +26,14 @@ #include #include #include -#include + #include -// boost +#pragma GCC diagnostic push +#include +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace detail { diff --git a/include/mapnik/text/renderer.hpp b/include/mapnik/text/renderer.hpp index 1b6bac112..692ada3cd 100644 --- a/include/mapnik/text/renderer.hpp +++ b/include/mapnik/text/renderer.hpp @@ -28,7 +28,10 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include + #include // freetype2 @@ -39,6 +42,8 @@ extern "C" #include FT_STROKER_H } +#pragma GCC diagnostic pop + namespace mapnik { @@ -58,8 +63,35 @@ public: composite_mode_e halo_comp_op = src_over, double scale_factor = 1.0, stroker_ptr stroker = stroker_ptr()); + + void set_comp_op(composite_mode_e comp_op) + { + comp_op_ = comp_op; + } + + void set_halo_comp_op(composite_mode_e halo_comp_op) + { + halo_comp_op_ = halo_comp_op; + } + + void set_halo_rasterizer(halo_rasterizer_e rasterizer) + { + rasterizer_ = rasterizer; + } + + void set_scale_factor(double scale_factor) + { + scale_factor_ = scale_factor; + } + + void set_stroker(stroker_ptr stroker) + { + stroker_ = stroker; + } + void set_transform(agg::trans_affine const& transform); void set_halo_transform(agg::trans_affine const& halo_transform); + protected: using glyph_vector = std::vector; void prepare_glyphs(glyph_positions const& positions); diff --git a/include/mapnik/text/scrptrun.hpp b/include/mapnik/text/scrptrun.hpp index 67942b0a8..2161c510d 100644 --- a/include/mapnik/text/scrptrun.hpp +++ b/include/mapnik/text/scrptrun.hpp @@ -17,9 +17,12 @@ #ifndef __SCRPTRUN_H #define __SCRPTRUN_H +#pragma GCC diagnostic push +#include #include #include #include +#pragma GCC diagnostic pop struct ScriptRecord { @@ -102,7 +105,7 @@ private: inline ScriptRun::ScriptRun() { - reset(NULL, 0, 0); + reset(nullptr, 0, 0); } inline ScriptRun::ScriptRun(const UChar chars[], int32_t length) diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index 8a44bddfc..8fd3c155a 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -59,7 +59,7 @@ struct placement_finder_adapter }; -using vertex_converter_type = vertex_converter; +using vertex_converter_type = vertex_converter; class base_symbolizer_helper { @@ -158,6 +158,10 @@ protected: void init_marker() const; }; -} //namespace +namespace geometry { +MAPNIK_DECL mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom); +} + +} //namespace mapnik #endif // SYMBOLIZER_HELPERS_HPP diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index 654921eb2..511ba3a28 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -36,9 +36,11 @@ // stl #include -// boost +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/include/mapnik/tiff_io.hpp b/include/mapnik/tiff_io.hpp index df2b25a7a..b80142906 100644 --- a/include/mapnik/tiff_io.hpp +++ b/include/mapnik/tiff_io.hpp @@ -28,6 +28,9 @@ #include #include +#pragma GCC diagnostic push +#include + extern "C" { #include @@ -35,6 +38,9 @@ extern "C" #define RealTIFFClose TIFFClose } +#pragma GCC diagnostic pop + + //std #include diff --git a/include/mapnik/transform_expression.hpp b/include/mapnik/transform_expression.hpp index 9714b1eeb..b43f69170 100644 --- a/include/mapnik/transform_expression.hpp +++ b/include/mapnik/transform_expression.hpp @@ -30,11 +30,13 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include -// fusion #include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/transform_expression_grammar_impl.hpp b/include/mapnik/transform_expression_grammar_impl.hpp index f72126eb7..4b8c2b92a 100644 --- a/include/mapnik/transform_expression_grammar_impl.hpp +++ b/include/mapnik/transform_expression_grammar_impl.hpp @@ -45,7 +45,6 @@ transform_expression_grammar::transform_expression_grammar() qi::_3_type _3; qi::_6_type _6; qi::_val_type _val; - qi::char_type char_; qi::double_type double_; qi::lit_type lit; qi::no_case_type no_case; @@ -57,8 +56,7 @@ transform_expression_grammar::transform_expression_grammar() // the order provided. The individual transform definitions are // separated by whitespace and/or a comma. - qi::no_skip_type no_skip; - start = transform_ % no_skip[char_(", ")] ; + start = transform_ % *lit(',') ; transform_ = matrix | translate | scale | rotate | skewX | skewY ; diff --git a/include/mapnik/transform_path_adapter.hpp b/include/mapnik/transform_path_adapter.hpp index cb68e9139..08212703f 100644 --- a/include/mapnik/transform_path_adapter.hpp +++ b/include/mapnik/transform_path_adapter.hpp @@ -56,16 +56,16 @@ struct transform_path_adapter using size_type = std::size_t; using value_type = typename select_value_type::type; - transform_path_adapter(Transform const& t, - Geometry & geom, + transform_path_adapter(Transform const& _t, + Geometry & _geom, proj_transform const& prj_trans) - : t_(&t), - geom_(geom), + : t_(&_t), + geom_(_geom), prj_trans_(&prj_trans) {} - explicit transform_path_adapter(Geometry & geom) + explicit transform_path_adapter(Geometry & _geom) : t_(0), - geom_(geom), + geom_(_geom), prj_trans_(0) {} void set_proj_trans(proj_transform const& prj_trans) diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index bec6bff3b..b1d8eab73 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -29,8 +29,11 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include @@ -111,11 +114,11 @@ struct transform_processor vars_(v), scale_factor_(scale_factor) {} - void operator() (identity_node const&) + void operator() (identity_node const&) const { } - void operator() (matrix_node const& node) + void operator() (matrix_node const& node) const { double a = eval(node.a_); // scale x; double b = eval(node.b_); @@ -126,21 +129,21 @@ struct transform_processor transform_.multiply(agg::trans_affine(a, b, c, d, e, f)); } - void operator() (translate_node const& node) + void operator() (translate_node const& node) const { double tx = eval(node.tx_) * scale_factor_; double ty = eval(node.ty_, 0.0) * scale_factor_; transform_.translate(tx, ty); } - void operator() (scale_node const& node) + void operator() (scale_node const& node) const { double sx = eval(node.sx_); double sy = eval(node.sy_, sx); transform_.scale(sx, sy); } - void operator() (rotate_node const& node) + void operator() (rotate_node const& node) const { double angle = deg2rad(eval(node.angle_)); double cx = eval(node.cx_, 0.0); @@ -150,7 +153,7 @@ struct transform_processor transform_.translate(cx, cy); } - void operator() (skewX_node const& node) + void operator() (skewX_node const& node) const { auto degrees = std::fmod(eval(node.angle_),90.0); if (degrees < -89.0) degrees = -89.0; @@ -159,7 +162,7 @@ struct transform_processor transform_.multiply(agg::trans_affine_skewing(angle, 0.0)); } - void operator() (skewY_node const& node) + void operator() (skewY_node const& node) const { auto degrees = std::fmod(eval(node.angle_),90.0); if (degrees < -89.0) degrees = -89.0; diff --git a/include/mapnik/unicode.hpp b/include/mapnik/unicode.hpp index 59401abfa..f3b270cb9 100644 --- a/include/mapnik/unicode.hpp +++ b/include/mapnik/unicode.hpp @@ -45,6 +45,10 @@ public: private: UConverter * conv_; }; + +// convinience method +void MAPNIK_DECL to_utf8(mapnik::value_unicode_string const& input, std::string & target); + } #endif // MAPNIK_UNICODE_HPP diff --git a/include/mapnik/util/char_array_buffer.hpp b/include/mapnik/util/char_array_buffer.hpp new file mode 100644 index 000000000..e5b834baa --- /dev/null +++ b/include/mapnik/util/char_array_buffer.hpp @@ -0,0 +1,87 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_UTIL_CHAR_ARRAY_BUFFER_HPP +#define MAPNIK_UTIL_CHAR_ARRAY_BUFFER_HPP + +#include + +namespace mapnik { namespace util { + +// ref https://artofcode.wordpress.com/2010/12/12/deriving-from-stdstreambuf/ + +class char_array_buffer : public std::streambuf +{ +public: + char_array_buffer(char const* data, std::size_t size) + : begin_(data), end_(data + size), current_(data) {} + +private: + int_type underflow() + { + if (current_ == end_) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*current_); + } + + int_type uflow() + { + if (current_ == end_) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*current_++); + } + + int_type pbackfail(int_type ch) + { + if (current_ == begin_ || (ch != traits_type::eof() && ch != current_[-1])) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*--current_); + } + + std::streamsize showmanyc() + { + return end_ - current_; + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode which = std::ios_base::in | std::ios_base::out ) + { + if (dir == std::ios_base::beg) current_ = std::min(begin_ + off, end_); + else if (dir == std::ios_base::cur) current_ = std::min(current_ + off, end_); + else current_ = std::max(end_ - off, begin_); // dir == std::ios_base::end + return pos_type(off_type(current_ - begin_)); + } + char const * const begin_; + char const * const end_; + char const * current_; +}; + +}} + + +#endif // MAPNIK_UTIL_CHAR_ARRAY_BUFFER_HPP diff --git a/include/mapnik/util/const_rendering_buffer.hpp b/include/mapnik/util/const_rendering_buffer.hpp index 360eea564..97b98ca65 100644 --- a/include/mapnik/util/const_rendering_buffer.hpp +++ b/include/mapnik/util/const_rendering_buffer.hpp @@ -25,7 +25,10 @@ #include +#pragma GCC diagnostic push +#include #include "agg_basics.h" +#pragma GCC diagnostic pop #include diff --git a/include/mapnik/util/dasharray_parser.hpp b/include/mapnik/util/dasharray_parser.hpp index 0ef1ae887..7c5d26711 100644 --- a/include/mapnik/util/dasharray_parser.hpp +++ b/include/mapnik/util/dasharray_parser.hpp @@ -23,32 +23,13 @@ #ifndef MAPNIK_UTIL_DASHARRAY_PARSER_HPP #define MAPNIK_UTIL_DASHARRAY_PARSER_HPP +#include #include #include namespace mapnik { namespace util { -bool parse_dasharray(std::string const& value, std::vector& dasharray); - -inline bool add_dashes(std::vector & buf, std::vector > & dash) -{ - if (buf.empty()) return false; - size_t size = buf.size(); - if (size % 2 == 1) - { - buf.insert(buf.end(),buf.begin(),buf.end()); - } - std::vector::const_iterator pos = buf.begin(); - while (pos != buf.end()) - { - if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0 - { - dash.emplace_back(*pos,*(pos + 1)); - } - pos +=2; - } - return !buf.empty(); -} +bool parse_dasharray(std::string const& value, dash_array & dash); }} diff --git a/include/mapnik/util/file_io.hpp b/include/mapnik/util/file_io.hpp index d3ffe9034..b8bc22f01 100644 --- a/include/mapnik/util/file_io.hpp +++ b/include/mapnik/util/file_io.hpp @@ -58,11 +58,16 @@ public: } } - inline bool open() const + inline bool is_open() const { return file_ ? true : false; } + explicit operator bool() const + { + return this->is_open(); + } + inline std::FILE * get() const { return file_.get(); diff --git a/include/mapnik/util/geometry_to_ds_type.hpp b/include/mapnik/util/geometry_to_ds_type.hpp index 58fc89df2..e09808f3e 100644 --- a/include/mapnik/util/geometry_to_ds_type.hpp +++ b/include/mapnik/util/geometry_to_ds_type.hpp @@ -28,8 +28,13 @@ #include #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#include +#include +#pragma GCC diagnostic pop namespace mapnik { namespace util { diff --git a/include/mapnik/util/geometry_to_geojson.hpp b/include/mapnik/util/geometry_to_geojson.hpp index 5cccb0950..71c867eb7 100644 --- a/include/mapnik/util/geometry_to_geojson.hpp +++ b/include/mapnik/util/geometry_to_geojson.hpp @@ -24,18 +24,13 @@ #define MAPNIK_GEOMETRY_TO_GEOJSON_HPP // mapnik +#include -#include +#include namespace mapnik { namespace util { -inline bool to_geojson(std::string & json, mapnik::geometry::geometry const& geom) -{ - using sink_type = std::back_insert_iterator; - static const mapnik::json::geometry_generator_grammar > grammar; - sink_type sink(json); - return boost::spirit::karma::generate(sink, grammar, geom); -} +bool to_geojson(std::string & json, mapnik::geometry::geometry const& geom); }} diff --git a/include/mapnik/util/is_clockwise.hpp b/include/mapnik/util/is_clockwise.hpp index 248372722..93951df38 100644 --- a/include/mapnik/util/is_clockwise.hpp +++ b/include/mapnik/util/is_clockwise.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_UTIL_IS_CLOCKWISE_HPP #define MAPNIK_UTIL_IS_CLOCKWISE_HPP +#include + namespace mapnik { namespace util { template @@ -30,11 +32,18 @@ bool is_clockwise(T const& ring) { double area = 0.0; std::size_t num_points = ring.size(); + assert(num_points > 2); + double orig_x = ring[0].x; + double orig_y = ring[0].y; for (std::size_t i = 0; i < num_points; ++i) { auto const& p0 = ring[i]; auto const& p1 = ring[(i + 1) % num_points]; - area += p0.x * p1.y - p0.y * p1.x; + double x0 = p0.x - orig_x; + double y0 = p0.y - orig_y; + double x1 = p1.x - orig_x; + double y1 = p1.y - orig_y; + area += x0 * y1 - x1 * y0; } return (area < 0.0) ? true : false; } diff --git a/include/mapnik/util/noncopyable.hpp b/include/mapnik/util/noncopyable.hpp index 1cd4a4a31..7a6a9f8f7 100644 --- a/include/mapnik/util/noncopyable.hpp +++ b/include/mapnik/util/noncopyable.hpp @@ -28,6 +28,15 @@ namespace mapnik { namespace util { namespace non_copyable_ { +class movable +{ +protected: + constexpr movable() = default; + ~movable() = default; + movable( movable && ) = default; + movable& operator=(movable && ) = default; +}; + class noncopyable { protected: @@ -36,8 +45,10 @@ protected: noncopyable( noncopyable const& ) = delete; noncopyable& operator=(noncopyable const& ) = delete; }; + } +using movable = non_copyable_::movable; using noncopyable = non_copyable_::noncopyable; }} diff --git a/include/mapnik/util/path_iterator.hpp b/include/mapnik/util/path_iterator.hpp index 319c3461a..19b69ce26 100644 --- a/include/mapnik/util/path_iterator.hpp +++ b/include/mapnik/util/path_iterator.hpp @@ -26,8 +26,11 @@ // mapnik #include #include -// boost + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/util/recursive_wrapper.hpp b/include/mapnik/util/recursive_wrapper.hpp deleted file mode 100644 index 16a670f1e..000000000 --- a/include/mapnik/util/recursive_wrapper.hpp +++ /dev/null @@ -1,150 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - - -#ifndef MAPNIK_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP -#define MAPNIK_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP - -#include - -namespace mapnik { namespace util { - -template -class recursive_wrapper -{ -public: - using type = T; -private: - - T* p_; - -public: - - ~recursive_wrapper(); - recursive_wrapper(); - - recursive_wrapper(recursive_wrapper const& operand); - recursive_wrapper(T const& operand); - recursive_wrapper(recursive_wrapper&& operand); - recursive_wrapper(T&& operand); - -private: - - void assign(const T& rhs); - -public: - - inline recursive_wrapper& operator=(recursive_wrapper const& rhs) - { - assign( rhs.get() ); - return *this; - } - - inline recursive_wrapper& operator=(T const& rhs) - { - assign( rhs ); - return *this; - } - - inline void swap(recursive_wrapper& operand) noexcept - { - T* temp = operand.p_; - operand.p_ = p_; - p_ = temp; - } - - - recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept - { - swap(rhs); - return *this; - } - - recursive_wrapper& operator=(T&& rhs) - { - get() = std::move(rhs); - return *this; - } - - -public: - - T& get() { return *get_pointer(); } - const T& get() const { return *get_pointer(); } - T* get_pointer() { return p_; } - const T* get_pointer() const { return p_; } - operator T const&() const { return this->get(); } - operator T&() { return this->get(); } -}; - -template -recursive_wrapper::~recursive_wrapper() -{ - delete p_; -} - -template -recursive_wrapper::recursive_wrapper() - : p_(new T) -{ -} - -template -recursive_wrapper::recursive_wrapper(recursive_wrapper const& operand) - : p_(new T( operand.get() )) -{ -} - -template -recursive_wrapper::recursive_wrapper(T const& operand) - : p_(new T(operand)) -{ -} - -template -recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) - : p_(operand.p_) -{ - operand.p_ = nullptr; -} - -template -recursive_wrapper::recursive_wrapper(T&& operand) - : p_(new T( std::move(operand) )) -{ -} - -template -void recursive_wrapper::assign(const T& rhs) -{ - this->get() = rhs; -} - -template -inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept -{ - lhs.swap(rhs); -} - -}} - -#endif // MAPNIK_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP diff --git a/include/mapnik/util/spatial_index.hpp b/include/mapnik/util/spatial_index.hpp index 021bed59c..720667768 100644 --- a/include/mapnik/util/spatial_index.hpp +++ b/include/mapnik/util/spatial_index.hpp @@ -30,55 +30,68 @@ #include // stl #include +#include using mapnik::box2d; using mapnik::query; namespace mapnik { namespace util { -template + +template +bool check_spatial_index(InputStream& in) +{ + char header[17]; // mapnik-index + std::memset(header, 0, 17); + in.read(header,16); + return (std::strncmp(header, "mapnik-index",12) == 0); +} + +template > class spatial_index { + using bbox_type = BBox; public: static void query(Filter const& filter, InputStream& in,std::vector& pos); - static box2d bounding_box( InputStream& in ); + static bbox_type bounding_box( InputStream& in ); static void query_first_n(Filter const& filter, InputStream & in, std::vector& pos, std::size_t count); private: - spatial_index(); ~spatial_index(); spatial_index(spatial_index const&); spatial_index& operator=(spatial_index const&); static int read_ndr_integer(InputStream& in); - static void read_envelope(InputStream& in, box2d& envelope); + static void read_envelope(InputStream& in, bbox_type& envelope); static void query_node(Filter const& filter, InputStream& in, std::vector & results); static void query_first_n_impl(Filter const& filter, InputStream& in, std::vector & results, std::size_t count); }; -template -box2d spatial_index::bounding_box(InputStream& in) +template +BBox spatial_index::bounding_box(InputStream& in) { static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); + if (!check_spatial_index(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)"); in.seekg(16 + 4, std::ios::beg); - box2d box; + typename spatial_index::bbox_type box; read_envelope(in, box); in.seekg(0, std::ios::beg); return box; } -template -void spatial_index::query(Filter const& filter, InputStream& in, std::vector& results) +template +void spatial_index::query(Filter const& filter, InputStream& in, std::vector& results) { - static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout types"); + static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); + if (!check_spatial_index(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)"); in.seekg(16, std::ios::beg); query_node(filter, in, results); } -template -void spatial_index::query_node(Filter const& filter, InputStream& in, std::vector& results) +template +void spatial_index::query_node(Filter const& filter, InputStream& in, std::vector& results) { int offset = read_ndr_integer(in); - box2d node_ext; + typename spatial_index::bbox_type node_ext; read_envelope(in, node_ext); int num_shapes = read_ndr_integer(in); if (!filter.pass(node_ext)) @@ -101,20 +114,21 @@ void spatial_index::query_node(Filter const& filter, } } -template -void spatial_index::query_first_n(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) +template +void spatial_index::query_first_n(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) { - static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout types"); + static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); + if (!check_spatial_index(in)) throw std::runtime_error("Invalid index file (regenerate with shapeindex)"); in.seekg(16, std::ios::beg); query_first_n_impl(filter, in, results, count); } -template -void spatial_index::query_first_n_impl(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) +template +void spatial_index::query_first_n_impl(Filter const& filter, InputStream& in, std::vector& results, std::size_t count) { if (results.size() == count) return; int offset = read_ndr_integer(in); - box2d node_ext; + typename spatial_index::bbox_type node_ext; read_envelope(in, node_ext); int num_shapes = read_ndr_integer(in); if (!filter.pass(node_ext)) @@ -136,16 +150,16 @@ void spatial_index::query_first_n_impl(Filter const& } } -template -int spatial_index::read_ndr_integer(InputStream& in) +template +int spatial_index::read_ndr_integer(InputStream& in) { char b[4]; in.read(b, 4); return (b[0] & 0xff) | (b[1] & 0xff) << 8 | (b[2] & 0xff) << 16 | (b[3] & 0xff) << 24; } -template -void spatial_index::read_envelope(InputStream& in, box2d& envelope) +template +void spatial_index::read_envelope(InputStream& in, BBox& envelope) { in.read(reinterpret_cast(&envelope), sizeof(envelope)); } diff --git a/include/mapnik/util/variant.hpp b/include/mapnik/util/variant.hpp index 65eb34f35..87cfb70ff 100644 --- a/include/mapnik/util/variant.hpp +++ b/include/mapnik/util/variant.hpp @@ -24,889 +24,67 @@ #define MAPNIK_UTIL_VARIANT_HPP #include +#include -#include // swap -#include -#include -#include // runtime_error -#include // operator new -#include // size_t -#include -#include - -#include "recursive_wrapper.hpp" - +#pragma GCC diagnostic push +#include #include // spirit support - -#ifdef _MSC_VER - // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx - #ifdef NDEBUG - #define VARIANT_INLINE __forceinline - #else - #define VARIANT_INLINE __declspec(noinline) - #endif -#else - #ifdef NDEBUG - #define VARIANT_INLINE inline __attribute__((always_inline)) - #else - #define VARIANT_INLINE __attribute__((noinline)) - #endif -#endif - -#define VARIANT_MAJOR_VERSION 0 -#define VARIANT_MINOR_VERSION 1 -#define VARIANT_PATCH_VERSION 0 - -// translates to 100 -#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) +#pragma GCC diagnostic pop namespace mapnik { namespace util { -// static visitor -template -struct static_visitor -{ - using result_type = R; -protected: - static_visitor() {} - ~static_visitor() {} -}; - -namespace detail { - -static constexpr std::size_t invalid_value = std::size_t(-1); - -template -struct direct_type; - -template -struct direct_type -{ - static constexpr std::size_t index = std::is_same::value - ? sizeof...(Types) : direct_type::index; -}; - template -struct direct_type -{ - static constexpr std::size_t index = invalid_value; -}; +using recursive_wrapper = typename mapbox::util::recursive_wrapper; -template -struct convertible_type; - -template -struct convertible_type -{ - static constexpr std::size_t index = std::is_convertible::value - ? sizeof...(Types) : convertible_type::index; -}; - -template -struct convertible_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct value_traits -{ - static constexpr std::size_t direct_index = direct_type::index; - static constexpr std::size_t index = - (direct_index == invalid_value) ? convertible_type::index : direct_index; -}; - -// check if T is in Types... -template -struct has_type; - -template -struct has_type -{ - static constexpr bool value = std::is_same::value - || has_type::value; -}; - -template -struct has_type : std::false_type {}; -// - -template -struct is_valid_type; - -template -struct is_valid_type -{ - static constexpr bool value = std::is_convertible::value - || is_valid_type::value; -}; - -template -struct is_valid_type : std::false_type {}; - -template -struct select_type -{ - static_assert(N < sizeof...(Types), "index out of bounds"); -}; - -template -struct select_type -{ - using type = typename select_type::type; -}; - -template -struct select_type<0, T, Types...> -{ - using type = T; -}; - - -template -struct enable_if_type { using type = R; }; - -template -struct result_of_unary_visit -{ - using type = typename std::result_of::type; -}; - -template -struct result_of_unary_visit::type > -{ - using type = typename F::result_type; -}; - -template -struct result_of_binary_visit -{ - using type = typename std::result_of::type; -}; - - -template -struct result_of_binary_visit::type > -{ - using type = typename F::result_type; -}; - - -} // namespace detail - - -template -struct static_max; - -template -struct static_max -{ - static const std::size_t value = arg; -}; - -template -struct static_max -{ - static const std::size_t value = arg1 >= arg2 ? static_max::value : - static_max::value; -}; template -struct variant_helper; - -template -struct variant_helper -{ - VARIANT_INLINE static void destroy(const std::size_t id, void * data) - { - if (id == sizeof...(Types)) - { - reinterpret_cast(data)->~T(); - } - else - { - variant_helper::destroy(id, data); - } - } - - VARIANT_INLINE static void move(const std::size_t old_id, void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(std::move(*reinterpret_cast(old_value))); - //std::memcpy(new_value, old_value, sizeof(T)); - // ^^ DANGER: this should only be considered for relocatable types e.g built-in types - // Also, I don't see any measurable performance benefit just yet - } - else - { - variant_helper::move(old_id, old_value, new_value); - } - } - - VARIANT_INLINE static void copy(const std::size_t old_id, const void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(*reinterpret_cast(old_value)); - } - else - { - variant_helper::copy(old_id, old_value, new_value); - } - } - VARIANT_INLINE static void direct_swap(const std::size_t id, void * lhs, void * rhs) - { - using std::swap; //enable ADL - if (id == sizeof...(Types)) - { - // both lhs and rhs hold T - swap(*reinterpret_cast(lhs), *reinterpret_cast(rhs)); - } - else - { - variant_helper::direct_swap(id, lhs, rhs); - } - } -}; - -template<> struct variant_helper<> -{ - VARIANT_INLINE static void destroy(const std::size_t, void *) {} - VARIANT_INLINE static void move(const std::size_t, void *, void *) {} - VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} - VARIANT_INLINE static void direct_swap(const std::size_t, void *, void *) {} -}; - -namespace detail { - -template -struct unwrapper -{ - T const& operator() (T const& obj) const - { - return obj; - } - - T& operator() (T & obj) const - { - return obj; - } -}; - - -template -struct unwrapper> -{ - auto operator() (recursive_wrapper const& obj) const - -> typename recursive_wrapper::type const& - { - return obj.get(); - } - - auto operator() (recursive_wrapper & obj) const - -> typename recursive_wrapper::type & - { - return obj.get(); - } -}; - -template -struct unwrapper> -{ - auto operator() (std::reference_wrapper const& obj) const - -> typename recursive_wrapper::type const& - { - return obj.get(); - } -}; - -template -struct dispatcher; - -template -struct dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply_const(v, f); - } - } - - VARIANT_INLINE static result_type apply(V & v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply(v, f); - } - } -}; - -template -struct dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } - - VARIANT_INLINE static result_type apply(V &, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } -}; - - -template -struct binary_dispatcher_rhs; - -template -struct binary_dispatcher_rhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_rhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - - -template -struct binary_dispatcher_lhs; - -template -struct binary_dispatcher_lhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_lhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -template -struct binary_dispatcher; - -template -struct binary_dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply_const(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply_const(v0, v1, f); - } - return binary_dispatcher::apply_const(v0, v1, f); - } - - VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply(v0, v1, f); - } - return binary_dispatcher::apply(v0, v1, f); - } -}; - -template -struct binary_dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -// comparator functors -struct equal_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs == rhs; - } -}; - -struct less_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs < rhs; - } -}; - -template -class comparer +class variant : public mapbox::util::variant { public: - explicit comparer(Variant const& lhs) noexcept - : lhs_(lhs) {} - comparer& operator=(comparer const&) = delete; - // visitor - template - bool operator()(T const& rhs_content) const - { - T const& lhs_content = lhs_.template get(); - return Comp()(lhs_content, rhs_content); - } -private: - Variant const& lhs_; -}; - - -} // namespace detail - -struct no_init {}; - -template -class variant -{ -private: - - static const std::size_t data_size = static_max::value; - static const std::size_t data_align = static_max::value; - - using data_type = typename std::aligned_storage::type; - using helper_type = variant_helper; - - std::size_t type_index; - data_type data; - -public: - // tell spirit that this is an adapted variant struct adapted_variant_tag; using types = boost::mpl::vector; - - VARIANT_INLINE variant() - : type_index(sizeof...(Types) - 1) - { - new (&data) typename detail::select_type<0, Types...>::type(); - } - - VARIANT_INLINE variant(no_init) - : type_index(detail::invalid_value) {} - - // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers - template ::type, Types...>::value>::type> - VARIANT_INLINE variant(T && val) noexcept - : type_index(detail::value_traits::type, Types...>::index) - { - constexpr std::size_t index = sizeof...(Types) - detail::value_traits::type, Types...>::index - 1; - using target_type = typename detail::select_type::type; - new (&data) target_type(std::forward(val)); // nothrow - } - - VARIANT_INLINE variant(variant const& old) - : type_index(old.type_index) - { - helper_type::copy(old.type_index, &old.data, &data); - } - - VARIANT_INLINE variant(variant&& old) noexcept - : type_index(old.type_index) - { - helper_type::move(old.type_index, &old.data, &data); - } - -private: - VARIANT_INLINE void copy_assign(variant const& rhs) - { - helper_type::destroy(type_index, &data); - type_index = detail::invalid_value; - helper_type::copy(rhs.type_index, &rhs.data, &data); - type_index = rhs.type_index; - } - - VARIANT_INLINE void move_assign(variant && rhs) - { - helper_type::destroy(type_index, &data); - type_index = detail::invalid_value; - helper_type::move(rhs.type_index, &rhs.data, &data); - type_index = rhs.type_index; - } - -public: - VARIANT_INLINE variant& operator=(variant && other) - { - move_assign(std::move(other)); - return *this; - } - - VARIANT_INLINE variant& operator=(variant const& other) - { - copy_assign(other); - return *this; - } - - // conversions - // move-assign - template - VARIANT_INLINE variant& operator=(T && rhs) noexcept - { - variant temp(std::forward(rhs)); - move_assign(std::move(temp)); - return *this; - } - - // copy-assign - template - VARIANT_INLINE variant& operator=(T const& rhs) - { - variant temp(rhs); - copy_assign(temp); - return *this; - } - - template - VARIANT_INLINE bool is() const - { - static_assert(detail::has_type::value, "invalid type in T in `is()` for this variant"); - return (type_index == detail::direct_type::index); - } - - VARIANT_INLINE bool valid() const - { - return (type_index != detail::invalid_value); - } - - template - VARIANT_INLINE void set(Args&&... args) - { - helper_type::destroy(type_index, &data); - new (&data) T(std::forward(args)...); - type_index = detail::direct_type::index; - } - - // get() - template::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template ::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - // get() - T stored as recursive_wrapper - template , Types...>::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast*>(&data)).get(); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template , Types...>::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast const*>(&data)).get(); - } - else - { - throw std::runtime_error("in get()"); - } - } - - // get() - T stored as std::reference_wrapper - template , Types...>::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast*>(&data)).get(); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template , Types...>::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast const*>(&data)).get(); - } - else - { - throw std::runtime_error("in get()"); - } - } - - VARIANT_INLINE std::size_t get_type_index() const - { - return type_index; - } - - VARIANT_INLINE int which() const noexcept - { - return static_cast(sizeof...(Types) - type_index - 1); - } - // visitor - // unary - template - auto VARIANT_INLINE - static visit(V const& v, F f) - -> decltype(detail::dispatcher::type>::type, Types...>::apply_const(v, f)) - { - using R = typename detail::result_of_unary_visit::type>::type; - return detail::dispatcher::apply_const(v, f); - } - // non-const - template - auto VARIANT_INLINE - static visit(V & v, F f) - -> decltype(detail::dispatcher::type>::type, Types...>::apply(v, f)) - { - using R = typename detail::result_of_unary_visit::type>::type; - return detail::dispatcher::apply(v, f); - } - - // binary - // const - template - auto VARIANT_INLINE - static binary_visit(V const& v0, V const& v1, F f) - -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply_const(v0, v1, f)) - { - using R = typename detail::result_of_binary_visit::type>::type; - return detail::binary_dispatcher::apply_const(v0, v1, f); - } - // non-const - template - auto VARIANT_INLINE - static binary_visit(V& v0, V& v1, F f) - -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply(v0, v1, f)) - { - using R = typename detail::result_of_binary_visit::type>::type; - return detail::binary_dispatcher::apply(v0, v1, f); - } - - ~variant() noexcept - { - helper_type::destroy(type_index, &data); - } - - // comparison operators - // equality - VARIANT_INLINE bool operator==(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - return false; - detail::comparer visitor(*this); - return visit(rhs, visitor); - } - // less than - VARIANT_INLINE bool operator<(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - { - return this->get_type_index() < rhs.get_type_index(); - // ^^ borrowed from boost::variant - } - detail::comparer visitor(*this); - return visit(rhs, visitor); - } + // inherit ctor's + using mapbox::util::variant::variant; }; // unary visitor interface - // const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f)) +template +auto VARIANT_INLINE static apply_visitor(F && f, V const& v) -> decltype(V::visit(v, std::forward(f))) { - return V::visit(v, f); + return V::visit(v, std::forward(f)); } // non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f)) +template +auto VARIANT_INLINE static apply_visitor(F && f, V & v) -> decltype(V::visit(v, std::forward(f))) { - return V::visit(v, f); + return V::visit(v, std::forward(f)); } // binary visitor interface // const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f)) +template +auto VARIANT_INLINE static apply_visitor(F && f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward(f))) { - return V::binary_visit(v0, v1, f); + return V::binary_visit(v0, v1, std::forward(f)); } + // non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f)) +template +auto VARIANT_INLINE static apply_visitor(F && f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, std::forward(f))) { - return V::binary_visit(v0, v1, f); + return V::binary_visit(v0, v1, std::forward(f)); } // getter interface -template +template ResultType & get(T & var) { return var.template get(); } -template +template ResultType const& get(T const& var) { return var.template get(); diff --git a/include/mapnik/util/variant_io.hpp b/include/mapnik/util/variant_io.hpp index 8839a7e22..02f0be5ca 100644 --- a/include/mapnik/util/variant_io.hpp +++ b/include/mapnik/util/variant_io.hpp @@ -65,7 +65,7 @@ VARIANT_INLINE std::basic_ostream& operator<< (std::basic_ostream& out, variant const& rhs) { detail::printer> visitor(out); - apply_visitor(visitor, rhs); + mapnik::util::apply_visitor(visitor, rhs); return out; } diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 995916b2a..3bd59b4b7 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -24,991 +24,84 @@ #define MAPNIK_VALUE_HPP // mapnik +#include #include #include -#include #include -// stl -#include -#include -#include -#include -#include -#include - -// icu -#include -#include - -namespace mapnik { - -inline void to_utf8(mapnik::value_unicode_string const& input, std::string & target) -{ - if (input.isEmpty()) return; - - const int BUF_SIZE = 256; - char buf [BUF_SIZE]; - int len; - - UErrorCode err = U_ZERO_ERROR; - u_strToUTF8(buf, BUF_SIZE, &len, input.getBuffer(), input.length(), &err); - if (err == U_BUFFER_OVERFLOW_ERROR || err == U_STRING_NOT_TERMINATED_WARNING ) - { - const std::unique_ptr buf_ptr(new char [len+1]); - err = U_ZERO_ERROR; - u_strToUTF8(buf_ptr.get() , len + 1, &len, input.getBuffer(), input.length(), &err); - target.assign(buf_ptr.get() , static_cast(len)); - } - else - { - target.assign(buf, static_cast(len)); - } -} +namespace mapnik { using value_base = util::variant; -namespace impl { - -struct equals -{ - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) == rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) == rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs == static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) == rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs == static_cast(rhs); - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs == static_cast(rhs); - } - - bool operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const - { - return (lhs == rhs) ? true: false; - } - - template - bool operator() (T lhs, T rhs) const - { - return lhs == rhs; - } - - template - bool operator() (T const&, U const&) const - { - return false; - } -}; - -struct not_equals -{ - template - bool operator() (const T &, const U &) const - { - return true; - } - - template - bool operator() (T lhs, T rhs) const - { - return lhs != rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) != rhs; - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) != rhs; - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) != rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs != static_cast(rhs); - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs != static_cast(rhs); - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs != static_cast(rhs); - } - - bool operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const - { - return (lhs != rhs)? true : false; - } - - // back compatibility shim to equate empty string with null for != test - // https://github.com/mapnik/mapnik/issues/1859 - // TODO - consider removing entire specialization at Mapnik 3.x - bool operator() (value_null, value_unicode_string const& rhs) const - { - if (rhs.isEmpty()) return false; - return true; - } - -}; - -struct greater_than -{ - template - bool operator()(const T &, const U &) const - { - return false; - } - - template - bool operator()(T lhs, T rhs) const - { - return lhs > rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs > static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs > static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_unicode_string const& lhs, value_unicode_string const& rhs) const - { - return (lhs > rhs) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; - } -}; - -struct greater_or_equal -{ - template - bool operator()(const T &, const U &) const - { - return false; - } - - template - bool operator() (T lhs, T rhs) const - { - return lhs >= rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) >= rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs >= static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) >= rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs >= static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) >= rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs >= static_cast(rhs); - } - - bool operator() (value_unicode_string const& lhs, value_unicode_string const& rhs) const - { - return ( lhs >= rhs ) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; - } -}; - -struct less_than -{ - template - bool operator()(const T &, const U &) const - { - return false; - } - - template - bool operator()(T lhs, T rhs) const - { - return lhs < rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) < rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs < static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) < rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs < static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) < rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs < static_cast(rhs); - } - - bool operator()(value_unicode_string const& lhs, - value_unicode_string const& rhs ) const - { - return (lhs < rhs) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; - } -}; - -struct less_or_equal -{ - template - bool operator()(const T &, const U &) const - { - return false; - } - - template - bool operator()(T lhs, T rhs) const - { - return lhs <= rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) <= rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs <= static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) <= rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs <= static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) <= rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs <= static_cast(rhs); - } - - bool operator()(value_unicode_string const& lhs, - value_unicode_string const& rhs ) const - { - return (lhs <= rhs) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; - } -}; - -template -struct add -{ - using value_type = V; - value_type operator() (value_unicode_string const& lhs , - value_unicode_string const& rhs ) const - { - return lhs + rhs; - } - - value_type operator() (value_double lhs, value_integer rhs) const - { - return lhs + rhs; - } - - value_type operator() (value_integer lhs, value_double rhs) const - { - return lhs + rhs; - } - - value_type operator() (value_unicode_string const& lhs, value_null) const - { - return lhs; - } - - value_type operator() (value_null, value_unicode_string const& rhs) const - { - return rhs; - } - - template - value_type operator() (value_unicode_string const& lhs, R const& rhs) const - { - std::string val; - if (util::to_string(val,rhs)) - return lhs + value_unicode_string(val.c_str()); - return lhs; - } - - template - value_type operator() (L const& lhs , value_unicode_string const& rhs) const - { - std::string val; - if (util::to_string(val,lhs)) - return value_unicode_string(val.c_str()) + rhs; - return rhs; - } - - template - value_type operator() (T lhs, T rhs) const - { - return lhs + rhs ; - } - - template - value_type operator() (T1 const& lhs, T2 const&) const - { - return lhs; - } - - value_type operator() (value_bool lhs, value_bool rhs) const - { - return value_integer(lhs + rhs); - } -}; - -template -struct sub -{ - using value_type = V; - template - value_type operator() (T1 const& lhs, T2 const&) const - { - return lhs; - } - - template - value_type operator() (T lhs, T rhs) const - { - return lhs - rhs ; - } - - value_type operator() (value_unicode_string const&, - value_unicode_string const&) const - { - return value_type(); - } - - value_type operator() (value_double lhs, value_integer rhs) const - { - return lhs - rhs; - } - - value_type operator() (value_integer lhs, value_double rhs) const - { - return lhs - rhs; - } - - value_type operator() (value_bool lhs, value_bool rhs) const - { - return value_integer(lhs - rhs); - } -}; - -template -struct mult -{ - using value_type = V; - template - value_type operator() (T1 const& lhs , T2 const& ) const - { - return lhs; - } - template - value_type operator() (T lhs, T rhs) const - { - return lhs * rhs; - } - - value_type operator() (value_unicode_string const&, - value_unicode_string const&) const - { - return value_type(); - } - - value_type operator() (value_double lhs, value_integer rhs) const - { - return lhs * rhs; - } - - value_type operator() (value_integer lhs, value_double rhs) const - { - return lhs * rhs; - } - - value_type operator() (value_bool, value_bool) const - { - return value_integer(0); - } -}; - -template -struct div -{ - using value_type = V; - template - value_type operator() (T1 const& lhs, T2 const&) const - { - return lhs; - } - - template - value_type operator() (T lhs, T rhs) const - { - if (rhs == 0) return value_type(); - return lhs / rhs; - } - - value_type operator() (value_bool, value_bool) const - { - return false; - } - - value_type operator() (value_unicode_string const&, - value_unicode_string const&) const - { - return value_type(); - } - - value_type operator() (value_double lhs, value_integer rhs) const - { - if (rhs == 0) return value_type(); - return lhs / rhs; - } - - value_type operator() (value_integer lhs, value_double rhs) const - { - if (rhs == 0) return value_type(); - return lhs / rhs; - } -}; - -template -struct mod -{ - using value_type = V; - template - value_type operator() (T1 const& lhs, T2 const&) const - { - return lhs; - } - - template - value_type operator() (T lhs, T rhs) const - { - return lhs % rhs; - } - - value_type operator() (value_unicode_string const&, - value_unicode_string const&) const - { - return value_type(); - } - - value_type operator() (value_bool, - value_bool) const - { - return false; - } - - value_type operator() (value_double lhs, value_integer rhs) const - { - return std::fmod(lhs, static_cast(rhs)); - } - - value_type operator() (value_integer lhs, value_double rhs) const - { - return std::fmod(static_cast(lhs), rhs); - } - - value_type operator() (value_double lhs, value_double rhs) const - { - return std::fmod(lhs, rhs); - } -}; - -template -struct negate -{ - using value_type = V; - - template - value_type operator() (T val) const - { - return -val; - } - - value_type operator() (value_null val) const - { - return val; - } - - value_type operator() (value_bool val) const - { - return val ? value_integer(-1) : value_integer(0); - } - - value_type operator() (value_unicode_string const&) const - { - return value_type(); - } -}; - -// converters -template -struct convert {}; - -template <> -struct convert -{ - value_bool operator() (value_bool val) const - { - return val; - } - - value_bool operator() (value_unicode_string const& ustr) const - { - return !ustr.isEmpty(); - } - - value_bool operator() (value_null const&) const - { - return false; - } - - template - value_bool operator() (T val) const - { - return val > 0 ? true : false; - } -}; - -template <> -struct convert -{ - value_double operator() (value_double val) const - { - return val; - } - - value_double operator() (value_integer val) const - { - return static_cast(val); - } - - value_double operator() (value_bool val) const - { - return static_cast(val); - } - - value_double operator() (std::string const& val) const - { - value_double result; - if (util::string2double(val,result)) - return result; - return 0; - } - - value_double operator() (value_unicode_string const& val) const - { - std::string utf8; - to_utf8(val,utf8); - return operator()(utf8); - } - - value_double operator() (value_null const&) const - { - return 0.0; - } -}; - -template <> -struct convert -{ - value_integer operator() (value_integer val) const - { - return val; - } - - value_integer operator() (value_double val) const - { - return static_cast(rint(val)); - } - - value_integer operator() (value_bool val) const - { - return static_cast(val); - } - - value_integer operator() (std::string const& val) const - { - value_integer result; - if (util::string2int(val,result)) - return result; - return value_integer(0); - } - - value_integer operator() (value_unicode_string const& val) const - { - std::string utf8; - to_utf8(val,utf8); - return operator()(utf8); - } - - value_integer operator() (value_null const&) const - { - return value_integer(0); - } -}; - -template <> -struct convert -{ - template - std::string operator() (T val) const - { - std::string str; - util::to_string(str, val); - return str; - } - - // specializations - std::string operator() (value_unicode_string const& val) const - { - std::string utf8; - to_utf8(val,utf8); - return utf8; - } - - std::string operator() (value_double val) const - { - std::string str; - util::to_string(str, val); // TODO set precision(16) - return str; - } - - std::string operator() (value_bool val) const - { - return val ? "true": "false"; - } - - std::string operator() (value_null const&) const - { - return ""; - } -}; - -struct to_unicode -{ - - template - value_unicode_string operator() (T val) const - { - std::string str; - util::to_string(str,val); - return value_unicode_string(str.c_str()); - } - - // specializations - value_unicode_string const& operator() (value_unicode_string const& val) const - { - return val; - } - - value_unicode_string operator() (value_double val) const - { - std::string str; - util::to_string(str,val); - return value_unicode_string(str.c_str()); - } - - value_unicode_string operator() (value_bool val) const - { - if (val) { - std::string str("true"); - return value_unicode_string(str.c_str()); - } - std::string str("false"); - return value_unicode_string(str.c_str()); - } - - value_unicode_string operator() (value_null const&) const - { - return value_unicode_string(""); - } -}; - -struct to_expression_string -{ - explicit to_expression_string(char quote = '\'') - : quote_(quote) {} - - std::string operator() (value_unicode_string const& val) const - { - std::string utf8; - to_utf8(val,utf8); - return quote_ + utf8 + quote_; - } - - std::string operator() (value_integer val) const - { - std::string output; - util::to_string(output,val); - return output; - } - - std::string operator() (value_double val) const - { - std::string output; - util::to_string(output,val); // TODO precision(16) - return output; - } - - std::string operator() (value_bool val) const - { - return val ? "true":"false"; - } - - std::string operator() (value_null const&) const - { - return "null"; - } - - const char quote_; -}; - -} // namespace impl - namespace value_adl_barrier { -class value : public value_base +class MAPNIK_DECL value : public value_base { - friend const value operator+(value const&,value const&); - friend const value operator-(value const&,value const&); - friend const value operator*(value const&,value const&); - friend const value operator/(value const&,value const&); - friend const value operator%(value const&,value const&); + friend MAPNIK_DECL value operator+(value const&,value const&); + friend MAPNIK_DECL value operator-(value const&,value const&); + friend MAPNIK_DECL value operator*(value const&,value const&); + friend MAPNIK_DECL value operator/(value const&,value const&); + friend MAPNIK_DECL value operator%(value const&,value const&); public: - value () noexcept //-- comment out for VC++11 - : value_base(value_null()) {} + value() = default; - value (value const& other) = default; + // conversion from type T is done via a temporary of type U, which + // is determined by mapnik_value_type; + // enable_if< decay != value > is necessary to avoid ill-formed + // recursion in noexcept specifier; and it also prevents using this + // constructor where implicitly-declared copy/move should be used + // (e.g. value(value&)) + template ::value, + detail::mapnik_value_type_decay + >::type::type> + value(T && val) + noexcept(noexcept(U(std::forward(val))) && + std::is_nothrow_constructible::value) + : value_base(U(std::forward(val))) {} - value( value && other) noexcept = default; - - template - value ( T const& val) - : value_base(typename detail::mapnik_value_type::type(val)) {} - - template - value ( T && val) - : value_base(typename detail::mapnik_value_type::type(val)) {} - - value & operator=( value const& other) = default; - - bool operator==(value const& other) const + template ::value, + detail::mapnik_value_type_decay + >::type::type> + value& operator=(T && val) + noexcept(noexcept(U(std::forward(val))) && + std::is_nothrow_assignable::value) { - return util::apply_visitor(impl::equals(),*this,other); + value_base::operator=(U(std::forward(val))); + return *this; } - bool operator!=(value const& other) const - { - return util::apply_visitor(impl::not_equals(),*this,other); - } + bool operator==(value const& other) const; + bool operator!=(value const& other) const; + bool operator>(value const& other) const; + bool operator>=(value const& other) const; + bool operator<(value const& other) const; + bool operator<=(value const& other) const; - bool operator>(value const& other) const - { - return util::apply_visitor(impl::greater_than(),*this,other); - } - - bool operator>=(value const& other) const - { - return util::apply_visitor(impl::greater_or_equal(),*this,other); - } - - bool operator<(value const& other) const - { - return util::apply_visitor(impl::less_than(),*this,other); - } - - bool operator<=(value const& other) const - { - return util::apply_visitor(impl::less_or_equal(),*this,other); - } - - value operator- () const - { - return util::apply_visitor(impl::negate(), *this); - } + value operator-() const; bool is_null() const; - template - T convert() const - { - return util::apply_visitor(impl::convert(),*this); - } + template T convert() const; - value_bool to_bool() const - { - return util::apply_visitor(impl::convert(),*this); - } - - std::string to_expression_string(char quote = '\'') const - { - return util::apply_visitor(impl::to_expression_string(quote),*this); - } - - std::string to_string() const - { - return util::apply_visitor(impl::convert(),*this); - } - - value_unicode_string to_unicode() const - { - return util::apply_visitor(impl::to_unicode(),*this); - } - - value_double to_double() const - { - return util::apply_visitor(impl::convert(),*this); - } - - value_integer to_int() const - { - return util::apply_visitor(impl::convert(),*this); - } + value_bool to_bool() const; + std::string to_expression_string(char quote = '\'') const; + std::string to_string() const; + value_unicode_string to_unicode() const; + value_double to_double() const; + value_integer to_int() const; }; -inline const value operator+(value const& p1,value const& p2) -{ - return value(util::apply_visitor(impl::add(),p1, p2)); -} - -inline const value operator-(value const& p1,value const& p2) -{ - return value(util::apply_visitor(impl::sub(),p1, p2)); -} - -inline const value operator*(value const& p1,value const& p2) -{ - return value(util::apply_visitor(impl::mult(),p1, p2)); -} - -inline const value operator/(value const& p1,value const& p2) -{ - return value(util::apply_visitor(impl::div(),p1, p2)); -} - -inline const value operator%(value const& p1,value const& p2) -{ - return value(util::apply_visitor(impl::mod(),p1, p2)); -} +MAPNIK_DECL value operator+(value const& p1,value const& p2); +MAPNIK_DECL value operator-(value const& p1,value const& p2); +MAPNIK_DECL value operator*(value const& p1,value const& p2); +MAPNIK_DECL value operator/(value const& p1,value const& p2); +MAPNIK_DECL value operator%(value const& p1,value const& p2); template inline std::basic_ostream& @@ -1027,36 +120,28 @@ inline std::size_t hash_value(value const& val) } // namespace value_adl_barrier -using value_adl_barrier::value; +using value = value_adl_barrier::value; namespace detail { - struct is_null_visitor { - bool operator() (value const& val) const + bool operator()(value const& val) const { return val.is_null(); } - bool operator() (value_null const&) const + bool operator()(value_null const&) const { return true; } template - bool operator() (T const&) const + bool operator()(T const&) const { return false; } }; - } // namespace detail - -inline bool value::is_null() const -{ - return util::apply_visitor(mapnik::detail::is_null_visitor(), *this); -} - } // namespace mapnik // support for std::unordered_xxx diff --git a/include/mapnik/value_hash.hpp b/include/mapnik/value_hash.hpp index 4c12bbe97..80e10d855 100644 --- a/include/mapnik/value_hash.hpp +++ b/include/mapnik/value_hash.hpp @@ -26,20 +26,20 @@ // mapnik #include #include - // stl #include -// icu +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + namespace mapnik { namespace detail { -template -inline void hash_combine(std::size_t & seed, T const& v) +inline void hash_combine(std::size_t & seed, std::size_t val) { - std::hash hasher; - seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + seed ^= val + 0x9e3779b9 + (seed << 6) + (seed >> 2); } struct value_hasher @@ -54,6 +54,11 @@ struct value_hasher return static_cast(val.hashCode()); } + std::size_t operator()(value_integer val) const + { + return static_cast(val); + } + template std::size_t operator()(T const& val) const { @@ -67,8 +72,9 @@ struct value_hasher template std::size_t mapnik_hash_value(T const& val) { - std::size_t seed = util::apply_visitor(detail::value_hasher(), val); - detail::hash_combine(seed, val.get_type_index()); + std::size_t seed = 0; + detail::hash_combine(seed, util::apply_visitor(detail::value_hasher(), val)); + detail::hash_combine(seed, val.which()); return seed; } diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index a250b49b4..235133a34 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -27,8 +27,11 @@ #include #include -// icu + +#pragma GCC diagnostic push +#include #include // for U_NAMESPACE_QUALIFIER +#pragma GCC diagnostic pop // stl #include @@ -80,6 +83,26 @@ struct MAPNIK_DECL value_null return true; } + bool operator>(value_null) const + { + return false; + } + + bool operator>=(value_null) const + { + return true; + } + + bool operator<(value_null) const + { + return false; + } + + bool operator<=(value_null) const + { + return true; + } + template value_null operator+ (T const&) const { @@ -207,6 +230,13 @@ struct mapnik_value_type +using mapnik_value_type_decay = mapnik_value_type::type>; + +template +using is_same_decay = std::is_same::type, + typename std::decay::type>; + } // namespace detail } // namespace mapnik diff --git a/include/mapnik/version.hpp b/include/mapnik/version.hpp index a68d8b5cb..deba4287c 100644 --- a/include/mapnik/version.hpp +++ b/include/mapnik/version.hpp @@ -23,17 +23,14 @@ #ifndef MAPNIK_VERSION_HPP #define MAPNIK_VERSION_HPP +#include + #define MAPNIK_MAJOR_VERSION 3 #define MAPNIK_MINOR_VERSION 0 -#define MAPNIK_PATCH_VERSION 9 +#define MAPNIK_PATCH_VERSION 12 #define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION) -#ifndef MAPNIK_STRINGIFY -#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n) -#define MAPNIK_STRINGIFY_HELPER(n) #n -#endif - #define MAPNIK_VERSION_STRING MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \ MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \ MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION) diff --git a/include/mapnik/vertex.hpp b/include/mapnik/vertex.hpp index b05f362a5..2e1d37844 100644 --- a/include/mapnik/vertex.hpp +++ b/include/mapnik/vertex.hpp @@ -61,29 +61,12 @@ struct vertex vertex(coord_type x_,coord_type y_,unsigned cmd_) : x(x_),y(y_),cmd(cmd_) {} - vertex(vertex && rhs) noexcept - : x(std::move(rhs.x)), - y(std::move(rhs.y)), - cmd(std::move(rhs.cmd)) {} - - vertex(vertex const& rhs) - : x(rhs.x), - y(rhs.y), - cmd(rhs.cmd) {} - template vertex(vertex const& rhs) : x(coord_type(rhs.x)), y(coord_type(rhs.y)), cmd(rhs.cmd) {} - - vertex& operator=(vertex rhs) - { - swap(rhs); - return *this; - } - template vertex& operator=(vertex const& rhs) { diff --git a/include/mapnik/vertex_adapters.hpp b/include/mapnik/vertex_adapters.hpp index ae5f0d4a9..0c77d7550 100644 --- a/include/mapnik/vertex_adapters.hpp +++ b/include/mapnik/vertex_adapters.hpp @@ -32,34 +32,12 @@ namespace mapnik { namespace geometry { template struct point_vertex_adapter { - using value_type = typename point::value_type; - - point_vertex_adapter(point const& pt) - : pt_(pt), - first_(true) {} - - unsigned vertex(value_type * x, value_type * y) const - { - if (first_) - { - *x = pt_.x; - *y = pt_.y; - first_ = false; - return mapnik::SEG_MOVETO; - } - return mapnik::SEG_END; - } - - void rewind(unsigned) const - { - first_ = true; - } - - inline geometry_types type () const - { - return geometry_types::Point; - } + using coord_type = typename point::coord_type; + point_vertex_adapter(point const& pt); + unsigned vertex(coord_type * x, coord_type * y) const; + void rewind(unsigned) const; + geometry_types type () const; point const& pt_; mutable bool first_; }; @@ -67,111 +45,24 @@ struct point_vertex_adapter template struct line_string_vertex_adapter { - using value_type = typename point::value_type; - line_string_vertex_adapter(line_string const& line) - : line_(line), - current_index_(0), - end_index_(line.size()) - {} - - unsigned vertex(value_type * x, value_type * y) const - { - if (current_index_ != end_index_) - { - point const& coord = line_[current_index_++]; - *x = coord.x; - *y = coord.y; - if (current_index_ == 1) - { - return mapnik::SEG_MOVETO; - } - else - { - return mapnik::SEG_LINETO; - } - } - return mapnik::SEG_END; - } - - void rewind(unsigned) const - { - current_index_ = 0; - } - - inline geometry_types type () const - { - return geometry_types::LineString; - } - + using coord_type = typename point::coord_type; + line_string_vertex_adapter(line_string const& line); + unsigned vertex(coord_type * x, coord_type * y) const; + void rewind(unsigned) const; + geometry_types type () const; line_string const& line_; mutable std::size_t current_index_; - const std::size_t end_index_; - + const std::size_t end_index_; }; template struct polygon_vertex_adapter { - using value_type = typename point::value_type; - polygon_vertex_adapter(polygon const& poly) - : poly_(poly), - rings_itr_(0), - rings_end_(poly_.interior_rings.size() + 1), - current_index_(0), - end_index_((rings_itr_ < rings_end_) ? poly_.exterior_ring.size() : 0), - start_loop_(true) {} - - void rewind(unsigned) const - { - rings_itr_ = 0; - rings_end_ = poly_.interior_rings.size() + 1; - current_index_ = 0; - end_index_ = (rings_itr_ < rings_end_) ? poly_.exterior_ring.size() : 0; - start_loop_ = true; - } - - unsigned vertex(value_type * x, value_type * y) const - { - if (rings_itr_ == rings_end_) - { - return mapnik::SEG_END; - } - if (current_index_ < end_index_) - { - point const& coord = (rings_itr_ == 0) ? - poly_.exterior_ring[current_index_++] : poly_.interior_rings[rings_itr_- 1][current_index_++]; - *x = coord.x; - *y = coord.y; - if (start_loop_) - { - start_loop_= false; - return mapnik::SEG_MOVETO; - } - if (current_index_ == end_index_) - { - *x = 0; - *y = 0; - return mapnik::SEG_CLOSE; - } - return mapnik::SEG_LINETO; - } - else if (++rings_itr_ != rings_end_) - { - current_index_ = 0; - end_index_ = poly_.interior_rings[rings_itr_ - 1].size(); - point const& coord = poly_.interior_rings[rings_itr_ - 1][current_index_++]; - *x = coord.x; - *y = coord.y; - return mapnik::SEG_MOVETO; - } - return mapnik::SEG_END; - } - - inline geometry_types type () const - { - return geometry_types::Polygon; - } - + using coord_type = typename point::coord_type; + polygon_vertex_adapter(polygon const& poly); + void rewind(unsigned) const; + unsigned vertex(coord_type * x, coord_type * y) const; + geometry_types type () const; private: polygon const& poly_; mutable std::size_t rings_itr_; @@ -184,48 +75,11 @@ private: template struct ring_vertex_adapter { - using value_type = typename point::value_type; - ring_vertex_adapter(linear_ring const& ring) - : ring_(ring), - current_index_(0), - end_index_(ring_.size()), - start_loop_(true) {} - - void rewind(unsigned) const - { - current_index_ = 0; - end_index_ = ring_.size(); - start_loop_ = true; - } - - unsigned vertex(value_type * x, value_type * y) const - { - if (current_index_ < end_index_) - { - auto const& coord = ring_[current_index_++]; - *x = coord.x; - *y = coord.y; - if (start_loop_) - { - start_loop_= false; - return mapnik::SEG_MOVETO; - } - if (current_index_ == end_index_) - { - *x = 0; - *y = 0; - return mapnik::SEG_CLOSE; - } - return mapnik::SEG_LINETO; - } - return mapnik::SEG_END; - } - - inline geometry_types type () const - { - return geometry_types::Polygon; - } - + using coord_type = typename point::coord_type; + ring_vertex_adapter(linear_ring const& ring); + void rewind(unsigned) const; + unsigned vertex(coord_type * x, coord_type * y) const; + geometry_types type () const; private: linear_ring const& ring_; mutable std::size_t current_index_; @@ -233,6 +87,11 @@ private: mutable bool start_loop_; }; +extern template struct MAPNIK_DECL point_vertex_adapter; +extern template struct MAPNIK_DECL line_string_vertex_adapter; +extern template struct MAPNIK_DECL polygon_vertex_adapter; +extern template struct MAPNIK_DECL ring_vertex_adapter; + template struct vertex_adapter_traits {}; diff --git a/include/mapnik/vertex_cache.hpp b/include/mapnik/vertex_cache.hpp index a0a32e96b..9df786e62 100644 --- a/include/mapnik/vertex_cache.hpp +++ b/include/mapnik/vertex_cache.hpp @@ -28,8 +28,10 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" +#pragma GCC diagnostic pop // stl #include diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index f10f720dc..ba1829472 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -37,7 +37,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_math_stroke.h" #include "agg_trans_affine.h" #include "agg_conv_clip_polygon.h" @@ -46,6 +47,7 @@ #include "agg_conv_stroke.h" #include "agg_conv_dash.h" #include "agg_conv_transform.h" +#pragma GCC diagnostic pop // stl #include @@ -275,7 +277,7 @@ template struct converters_helper; template -struct converters_helper +struct converters_helper { template static void set(Dispatcher & disp, std::size_t state) diff --git a/include/mapnik/vertex_processor.hpp b/include/mapnik/vertex_processor.hpp index a3b63c133..7cd2c40a4 100644 --- a/include/mapnik/vertex_processor.hpp +++ b/include/mapnik/vertex_processor.hpp @@ -35,38 +35,38 @@ struct vertex_processor : proc_(proc) {} template - void operator() (Geometry const& geom) + void operator() (Geometry const& geom) const { util::apply_visitor(*this, geom); } - void operator() (geometry_empty const&) + void operator() (geometry_empty const&) const { // no-op } - + template - void operator() (point const& pt) + void operator() (point const& pt) const { point_vertex_adapter va(pt); proc_(va); } template - void operator() (line_string const& line) + void operator() (line_string const& line) const { line_string_vertex_adapter va(line); proc_(va); } template - void operator() (polygon const& poly) + void operator() (polygon const& poly) const { polygon_vertex_adapter va(poly); proc_(va); } template - void operator() (multi_point const& multi_pt) + void operator() (multi_point const& multi_pt) const { for (auto const& pt : multi_pt) { @@ -76,7 +76,7 @@ struct vertex_processor } template - void operator() (multi_line_string const& multi_line) + void operator() (multi_line_string const& multi_line) const { for (auto const& line : multi_line) { @@ -86,7 +86,7 @@ struct vertex_processor } template - void operator() (multi_polygon const& multi_poly) + void operator() (multi_polygon const& multi_poly) const { for ( auto const& poly : multi_poly) { @@ -96,7 +96,7 @@ struct vertex_processor } template - void operator() (geometry_collection const& collection) + void operator() (geometry_collection const& collection) const { for (auto const& geom : collection) { diff --git a/include/mapnik/view_transform.hpp b/include/mapnik/view_transform.hpp index 2f5108c5f..74fa89cf7 100644 --- a/include/mapnik/view_transform.hpp +++ b/include/mapnik/view_transform.hpp @@ -44,15 +44,15 @@ private: int offset_; public: - view_transform(int width, int height, box2d const& extent, - double offset_x = 0.0, double offset_y = 0.0) - : width_(width), - height_(height), - extent_(extent), + view_transform(int _width, int _height, box2d const& _extent, + double _offset_x = 0.0, double _offset_y = 0.0) + : width_(_width), + height_(_height), + extent_(_extent), sx_(extent_.width() > 0 ? static_cast(width_) / extent_.width() : 1.0), sy_(extent_.height() > 0 ? static_cast(height_) / extent_.height() : 1.0), - offset_x_(offset_x), - offset_y_(offset_y), + offset_x_(_offset_x), + offset_y_(_offset_y), offset_(0) {} view_transform(view_transform const&) = default; @@ -62,9 +62,9 @@ public: return offset_; } - inline void set_offset(int offset) + inline void set_offset(int _offset) { - offset_ = offset; + offset_ = _offset; } inline double offset_x() const diff --git a/include/mapnik/warning_ignore.hpp b/include/mapnik/warning_ignore.hpp index 186087bb0..95249b8bf 100644 --- a/include/mapnik/warning_ignore.hpp +++ b/include/mapnik/warning_ignore.hpp @@ -22,9 +22,9 @@ #pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc -#pragma GCC diagnostic ignored "-Wno-unknown-pragmas" // clang -#pragma GCC diagnostic ignored "-Wno-pragmas" // gcc -#pragma GCC diagnostic ignored "-Wno-unsequenced" +#pragma GCC diagnostic ignored "-Wpragmas" // gcc +#pragma GCC diagnostic ignored "-W#pragma-messages" +#pragma GCC diagnostic ignored "-Wunsequenced" #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wredeclared-class-member" @@ -33,4 +33,25 @@ #pragma GCC diagnostic ignored "-Wc++11-narrowing" #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wconversion" \ No newline at end of file +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" +#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wdocumentation" +#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wdeprecated" +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wc++98-compat" +#pragma GCC diagnostic ignored "-Wreserved-id-macro" +#pragma GCC diagnostic ignored "-Wweak-vtables" +#pragma GCC diagnostic ignored "-Wextra-semi" +#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wheader-hygiene" +#pragma GCC diagnostic ignored "-Wexit-time-destructors" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wmissing-noreturn" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#pragma GCC diagnostic ignored "-Wfloat-equal" + diff --git a/include/mapnik/warning_ignore_agg.hpp b/include/mapnik/warning_ignore_agg.hpp new file mode 100644 index 000000000..2f44c5c78 --- /dev/null +++ b/include/mapnik/warning_ignore_agg.hpp @@ -0,0 +1,32 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + + +#pragma GCC diagnostic ignored "-Wunknown-pragmas" // clang+gcc +#pragma GCC diagnostic ignored "-Wpragmas" // gcc +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wshadow" + diff --git a/include/mapnik/well_known_srs.hpp b/include/mapnik/well_known_srs.hpp index eeb478ee3..e8349e709 100644 --- a/include/mapnik/well_known_srs.hpp +++ b/include/mapnik/well_known_srs.hpp @@ -28,8 +28,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include @@ -63,7 +65,8 @@ boost::optional is_known_geographic(std::string const& srs); static inline bool lonlat2merc(double * x, double * y , int point_count) { - for(int i=0; i 180) x[i] = 180; else if (x[i] < -180) x[i] = -180; if (y[i] > MAX_LATITUDE) y[i] = MAX_LATITUDE; diff --git a/include/mapnik/wkb.hpp b/include/mapnik/wkb.hpp index ac90df7b3..98b3d30c9 100644 --- a/include/mapnik/wkb.hpp +++ b/include/mapnik/wkb.hpp @@ -24,6 +24,7 @@ #define MAPNIK_WKB_HPP // mapnik +#include #include #include @@ -59,9 +60,11 @@ class MAPNIK_DECL geometry_utils : private util::noncopyable { public: - static mapnik::geometry::geometry from_wkb(const char* wkb, - std::size_t size, - wkbFormat format = wkbGeneric); + static geometry::geometry from_wkb(char const* wkb, + std::size_t size, + wkbFormat format = wkbGeneric); + + static geometry::geometry from_twkb(char const* twkb, std::size_t size); }; } diff --git a/include/mapnik/wkt/wkt_generator_grammar.hpp b/include/mapnik/wkt/wkt_generator_grammar.hpp index 0c89601d7..f31fcc08e 100644 --- a/include/mapnik/wkt/wkt_generator_grammar.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar.hpp @@ -27,7 +27,6 @@ #include #include #include -#include #pragma GCC diagnostic push #include @@ -105,7 +104,7 @@ template struct wkt_generator_grammar : karma::grammar { - using coord_type = typename Geometry::value_type; + using coord_type = typename Geometry::coord_type; wkt_generator_grammar(); // rules karma::rule geometry; diff --git a/include/mapnik/wkt/wkt_generator_grammar_impl.hpp b/include/mapnik/wkt/wkt_generator_grammar_impl.hpp index 7205db6d8..8d950edd0 100644 --- a/include/mapnik/wkt/wkt_generator_grammar_impl.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar_impl.hpp @@ -20,11 +20,15 @@ * *****************************************************************************/ -#include +// mapnik #include #include -// boost +#include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace wkt { diff --git a/include/mapnik/wkt/wkt_grammar.hpp b/include/mapnik/wkt/wkt_grammar.hpp index a91f43692..9d23f81ca 100644 --- a/include/mapnik/wkt/wkt_grammar.hpp +++ b/include/mapnik/wkt/wkt_grammar.hpp @@ -24,9 +24,8 @@ #define MAPNIK_WKT_GRAMMAR_HPP // mapnik +#include #include -#include - #pragma GCC diagnostic push #include #include diff --git a/include/mapnik/wkt/wkt_grammar_impl.hpp b/include/mapnik/wkt/wkt_grammar_impl.hpp index 85a927451..d2444130a 100644 --- a/include/mapnik/wkt/wkt_grammar_impl.hpp +++ b/include/mapnik/wkt/wkt_grammar_impl.hpp @@ -20,14 +20,18 @@ * *****************************************************************************/ -#include #include +#include + +#pragma GCC diagnostic push +#include #include #include #include #include #include #include +#pragma GCC diagnostic pop namespace mapnik { namespace wkt { diff --git a/include/mapnik/xml_attribute_cast.hpp b/include/mapnik/xml_attribute_cast.hpp index fb3b7ebdc..cafa7e79a 100644 --- a/include/mapnik/xml_attribute_cast.hpp +++ b/include/mapnik/xml_attribute_cast.hpp @@ -55,7 +55,7 @@ struct do_xml_attribute_cast { static inline boost::optional xml_attribute_cast_impl(xml_tree const& /*tree*/, std::string const& /*source*/) { - std::string err_msg("No conversion from std::string to"); + std::string err_msg("No conversion from std::string to "); err_msg += std::string(typeid(T).name()); throw std::runtime_error(err_msg); } @@ -74,6 +74,19 @@ struct do_xml_attribute_cast } }; +// specialization for mapnik::value_bool +template <> +struct do_xml_attribute_cast +{ + static inline boost::optional xml_attribute_cast_impl(xml_tree const& /*tree*/, std::string const& source) + { + bool result; + if (mapnik::util::string2bool(source, result)) + return boost::optional(result); + return boost::optional(); + } +}; + // specialization for int template <> struct do_xml_attribute_cast diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp index 1c3602134..bf7130c20 100644 --- a/include/mapnik/xml_node.hpp +++ b/include/mapnik/xml_node.hpp @@ -26,8 +26,10 @@ //mapnik #include // for MAPNIK_DECL -//boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop //stl #include diff --git a/localize.sh b/localize.sh index d24bdcb40..3d034f508 100755 --- a/localize.sh +++ b/localize.sh @@ -1,15 +1,18 @@ #!/bin/bash + # TODO - use rpath to avoid needing this to run tests locally + export CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ $(uname -s) = 'Darwin' ]; then - export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH} -else - export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH} +if [[ $(uname -s) == 'Darwin' ]]; then + export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH:-""} +elif [[ $(uname -s) == 'Linux' ]]; then + export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH:-""} fi export PATH=$(pwd)/utils/mapnik-render/:${PATH} export PATH=$(pwd)/utils/mapnik-index/:${PATH} export PATH=$(pwd)/utils/mapnik-config/:${PATH} +export PATH=$(pwd)/utils/shapeindex/:${PATH} # mapnik-settings.env is an optional file to store # environment variables that should be used before diff --git a/mason_latest.sh b/mason_latest.sh index 62a0c94f0..d5db6963f 100755 --- a/mason_latest.sh +++ b/mason_latest.sh @@ -4,7 +4,11 @@ MASON_NAME=mapnik MASON_VERSION=latest MASON_LIB_FILE=lib/libmapnik-wkt.a -. ${MASON_DIR:-~/.mason}/mason.sh +# warning: may break when https://github.com/mapbox/mason/issues/141 lands +# hence we are pinned for now to older mason in bootstrap.sh +. ./.mason/mason.sh + +set -eu function mason_load_source { export MASON_BUILD_PATH=$(pwd) @@ -13,21 +17,38 @@ function mason_load_source { function mason_compile { HERE=$(pwd) make install - if [[ `uname` == 'Darwin' ]]; then - install_name_tool -id @loader_path/libmapnik.dylib ${MASON_PREFIX}"/lib/libmapnik.dylib"; + # this is to adapt to when mapnik is not installed in MASON_PREFIX + # originally (to make it easier to publish locally as a stopgap) + MAPNIK_PREFIX=$(mapnik-config --prefix) + if [[ ${MAPNIK_PREFIX} != ${MASON_PREFIX} ]]; then + mkdir -p ${MASON_PREFIX}/lib + mkdir -p ${MASON_PREFIX}/include + mkdir -p ${MASON_PREFIX}/bin + cp -r ${MAPNIK_PREFIX}/lib/*mapnik* ${MASON_PREFIX}/lib/ + cp -r ${MAPNIK_PREFIX}/include/mapnik ${MASON_PREFIX}/include/ + cp -r ${MAPNIK_PREFIX}/bin/mapnik* ${MASON_PREFIX}/bin/ + cp -r ${MAPNIK_PREFIX}/bin/shapeindex ${MASON_PREFIX}/bin/ + fi + if [[ $(uname -s) == 'Darwin' ]]; then + install_name_tool -id @loader_path/lib/libmapnik.dylib ${MASON_PREFIX}"/lib/libmapnik.dylib"; PLUGINDIR=${MASON_PREFIX}"/lib/mapnik/input/*.input"; for f in $PLUGINDIR; do echo $f; - echo `basename $f`; - install_name_tool -id plugins/input/`basename $f` $f; - install_name_tool -change ${MASON_PREFIX}"/lib/libmapnik.dylib" @loader_path/../../libmapnik.dylib $f; + echo $(basename $f); + install_name_tool -id plugins/input/$(basename $f) $f; + install_name_tool -change "${MAPNIK_PREFIX}/lib/libmapnik.dylib" @loader_path/../../lib/libmapnik.dylib $f; + done; + BINDIR=${MASON_PREFIX}"/bin/*"; + for f in $BINDIR; do + echo $f; + echo $(basename $f); + if [[ $(file $f) =~ 'Mach-O' ]]; then + install_name_tool -id bin/$(basename $f) $f; + install_name_tool -change "${MAPNIK_PREFIX}/lib/libmapnik.dylib" @loader_path/../lib/libmapnik.dylib $f; + fi done; fi; python -c "data=open('$MASON_PREFIX/bin/mapnik-config','r').read();open('$MASON_PREFIX/bin/mapnik-config','w').write(data.replace('$HERE','.'))" - mkdir -p ${MASON_PREFIX}/share/icu - cp -r $GDAL_DATA ${MASON_PREFIX}/share/ - cp -r $PROJ_LIB ${MASON_PREFIX}/share/ - cp -r $ICU_DATA/*dat ${MASON_PREFIX}/share/icu/ find ${MASON_PREFIX} -name "*.pyc" -exec rm {} \; } diff --git a/plugins/input/csv/build.py b/plugins/input/csv/build.py index edc3ae0ea..91675a1ae 100644 --- a/plugins/input/csv/build.py +++ b/plugins/input/csv/build.py @@ -39,6 +39,7 @@ else: plugin_sources = Split( """ + %(PLUGIN_NAME)s_utils.cpp %(PLUGIN_NAME)s_datasource.cpp %(PLUGIN_NAME)s_featureset.cpp %(PLUGIN_NAME)s_inline_featureset.cpp diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index d0dbf06d9..322940528 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include "csv_utils.hpp" +#include "csv_getline.hpp" #include "csv_datasource.hpp" #include "csv_featureset.hpp" #include "csv_inline_featureset.hpp" @@ -36,9 +37,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #if defined(MAPNIK_MEMORY_MAPPED_FILE) @@ -65,21 +69,13 @@ DATASOURCE_PLUGIN(csv_datasource) csv_datasource::csv_datasource(parameters const& params) : datasource(params), desc_(csv_datasource::name(), *params.get("encoding", "utf-8")), - extent_(), - filename_(), - row_limit_(*params.get("row_limit", 0)), - inline_string_(), - separator_(0), - quote_(0), - headers_(), - manual_headers_(mapnik::util::trim_copy(*params.get("headers", ""))), - strict_(*params.get("strict", false)), ctx_(std::make_shared()), - extent_initialized_(false), - tree_(nullptr), - locator_(), - has_disk_index_(false) + tree_(nullptr) { + row_limit_ = *params.get("row_limit", 0); + manual_headers_ = mapnik::util::trim_copy(*params.get("headers", "")); + strict_ = *params.get("strict", false); + auto quote_param = params.get("quote"); if (quote_param) { @@ -170,288 +166,89 @@ csv_datasource::csv_datasource(parameters const& params) csv_datasource::~csv_datasource() {} -template -void csv_datasource::parse_csv(T & stream) +void csv_datasource::parse_csv(std::istream & csv_file) { - auto file_length = detail::file_length(stream); - // set back to start - stream.seekg(0, std::ios::beg); - char newline; - bool has_newline; - char detected_quote; - std::tie(newline, has_newline, detected_quote) = detail::autodect_newline_and_quote(stream, file_length); - if (quote_ == 0) quote_ = detected_quote; - // set back to start - stream.seekg(0, std::ios::beg); - std::string csv_line; - csv_utils::getline_csv(stream, csv_line, newline, quote_); - if (separator_ == 0) - { - separator_ = detail::detect_separator(csv_line); - } - - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: separator: '" << separator_ - << "' quote: '" << quote_ << "'"; - stream.seekg(0, std::ios::beg); - - int line_number = 0; - if (!manual_headers_.empty()) - { - std::size_t index = 0; - auto headers = csv_utils::parse_line(manual_headers_, separator_, quote_); - for (auto const& header : headers) - { - detail::locate_geometry_column(header, index++, locator_); - headers_.push_back(header); - } - } - else // parse first line as headers - { - while (csv_utils::getline_csv(stream, csv_line, newline, quote_)) - { - try - { - auto headers = csv_utils::parse_line(csv_line, separator_, quote_); - // skip blank lines - std::string val; - if (headers.size() > 0 && headers[0].empty()) ++line_number; - else - { - std::size_t index = 0; - for (auto const& header : headers) - { - val = mapnik::util::trim_copy(header); - if (val.empty()) - { - if (strict_) - { - std::ostringstream s; - s << "CSV Plugin: expected a column header at line "; - s << line_number << ", column " << index; - s << " - ensure this row contains valid header fields: '"; - s << csv_line; - throw mapnik::datasource_exception(s.str()); - } - else - { - // create a placeholder for the empty header - std::ostringstream s; - s << "_" << index; - headers_.push_back(s.str()); - } - } - else - { - detail::locate_geometry_column(val, index, locator_); - headers_.push_back(val); - } - ++index; - } - ++line_number; - break; - } - } - catch (std::exception const& ex) - { - std::string s("CSV Plugin: error parsing headers: "); - s += ex.what(); - throw mapnik::datasource_exception(s); - } - } - } - - std::size_t num_headers = headers_.size(); - if (!detail::valid(locator_, num_headers)) - { - std::string str("CSV Plugin: could not detect column(s) with the name(s) of wkt, geojson, x/y, or "); - str += "latitude/longitude in:\n"; - str += csv_line; - str += "\n - this is required for reading geometry data"; - throw mapnik::datasource_exception(str); - } - - mapnik::value_integer feature_count = 0; - bool extent_started = false; + std::vector boxes; + csv_utils::csv_file_parser::parse_csv_and_boxes(csv_file, boxes); std::for_each(headers_.begin(), headers_.end(), [ & ](std::string const& header){ ctx_->push(header); }); - mapnik::transcoder tr(desc_.get_encoding()); - - auto pos = stream.tellg(); - // handle rare case of a single line of data and user-provided headers - // where a lack of a newline will mean that csv_utils::getline_csv returns false - bool is_first_row = false; - - if (!has_newline) + if (!has_disk_index_) { - stream.setstate(std::ios::failbit); - pos = 0; - if (!csv_line.empty()) - { - is_first_row = true; - } + // bulk insert initialise r-tree + tree_ = std::make_unique(boxes); } +} - std::vector boxes; - while (is_first_row || csv_utils::getline_csv(stream, csv_line, newline, quote_)) +void csv_datasource::add_feature(mapnik::value_integer index, + mapnik::csv_line const & values) +{ + if (index != 1) return; + + for (std::size_t i = 0; i < values.size(); ++i) { - ++line_number; - if ((row_limit_ > 0) && (line_number > row_limit_)) + std::string const& header = headers_.at(i); + std::string value = mapnik::util::trim_copy(values[i]); + int value_length = value.length(); + if (locator_.index == i && (locator_.type == csv_utils::geometry_column_locator::WKT + || locator_.type == csv_utils::geometry_column_locator::GEOJSON)) continue; + + // First we detect likely strings, + // then try parsing likely numbers, + // then try converting to bool, + // finally falling back to string type. + + // An empty string or a string of "null" will be parsed + // as a string rather than a true null value. + // Likely strings are either empty values, very long values + // or values with leading zeros like 001 (which are not safe + // to assume are numbers) + + bool matched = false; + bool has_dot = value.find(".") != std::string::npos; + if (value.empty() || (value_length > 20) || (value_length > 1 && !has_dot && value[0] == '0')) { - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: row limit hit, exiting at feature: " << feature_count; - break; + matched = true; + desc_.add_descriptor(mapnik::attribute_descriptor(header, mapnik::String)); } - auto record_offset = pos; - auto record_size = csv_line.length(); - pos = stream.tellg(); - is_first_row = false; - - // skip blank lines - if (record_size <= 10) + else if (csv_utils::is_likely_number(value)) { - std::string trimmed = csv_line; - boost::trim_if(trimmed,boost::algorithm::is_any_of("\",'\r\n ")); - if (trimmed.empty()) + bool has_e = value.find("e") != std::string::npos; + if (has_dot || has_e) { - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: empty row encountered at line: " << line_number; - continue; - } - } - - try - { - auto values = csv_utils::parse_line(csv_line, separator_, quote_); - unsigned num_fields = values.size(); - if (num_fields > num_headers || num_fields < num_headers) - { - std::ostringstream s; - s << "CSV Plugin: # of columns(" - << num_fields << ") > # of headers(" - << num_headers << ") parsed for row " << line_number; - throw mapnik::datasource_exception(s.str()); - } - - auto geom = detail::extract_geometry(values, locator_); - if (!geom.is()) - { - auto box = mapnik::geometry::envelope(geom); - boxes.emplace_back(std::move(box), make_pair(record_offset, record_size)); - if (!extent_initialized_) + double float_val = 0.0; + if (mapnik::util::string2double(value,float_val)) { - if (!extent_started) - { - extent_started = true; - extent_ = mapnik::geometry::envelope(geom); - } - else - { - extent_.expand_to_include(mapnik::geometry::envelope(geom)); - } - } - if (++feature_count != 1) continue; - auto beg = values.begin(); - for (std::size_t i = 0; i < num_headers; ++i) - { - std::string const& header = headers_.at(i); - std::string value = mapnik::util::trim_copy(*beg++); - int value_length = value.length(); - if (locator_.index == i && (locator_.type == detail::geometry_column_locator::WKT - || locator_.type == detail::geometry_column_locator::GEOJSON)) continue; - - // First we detect likely strings, - // then try parsing likely numbers, - // then try converting to bool, - // finally falling back to string type. - - // An empty string or a string of "null" will be parsed - // as a string rather than a true null value. - // Likely strings are either empty values, very long values - // or values with leading zeros like 001 (which are not safe - // to assume are numbers) - - bool matched = false; - bool has_dot = value.find(".") != std::string::npos; - if (value.empty() || (value_length > 20) || (value_length > 1 && !has_dot && value[0] == '0')) - { - matched = true; - desc_.add_descriptor(mapnik::attribute_descriptor(header, mapnik::String)); - } - else if (csv_utils::is_likely_number(value)) - { - bool has_e = value.find("e") != std::string::npos; - if (has_dot || has_e) - { - double float_val = 0.0; - if (mapnik::util::string2double(value,float_val)) - { - matched = true; - desc_.add_descriptor(mapnik::attribute_descriptor(header,mapnik::Double)); - } - } - else - { - mapnik::value_integer int_val = 0; - if (mapnik::util::string2int(value,int_val)) - { - matched = true; - desc_.add_descriptor(mapnik::attribute_descriptor(header,mapnik::Integer)); - } - } - } - if (!matched) - { - // NOTE: we don't use mapnik::util::string2bool - // here because we don't want to treat 'on' and 'off' - // as booleans, only 'true' and 'false' - if (csv_utils::ignore_case_equal(value, "true") || csv_utils::ignore_case_equal(value, "false")) - { - desc_.add_descriptor(mapnik::attribute_descriptor(header, mapnik::Boolean)); - } - else // fallback to normal string - { - desc_.add_descriptor(mapnik::attribute_descriptor(header, mapnik::String)); - } - } + matched = true; + desc_.add_descriptor(mapnik::attribute_descriptor(header,mapnik::Double)); } } else { - std::ostringstream s; - s << "CSV Plugin: expected geometry column: could not parse row " - << line_number << " " - << values.at(locator_.index) << "'"; - throw mapnik::datasource_exception(s.str()); + mapnik::value_integer int_val = 0; + if (mapnik::util::string2int(value,int_val)) + { + matched = true; + desc_.add_descriptor(mapnik::attribute_descriptor(header,mapnik::Integer)); + } } } - catch (mapnik::datasource_exception const& ex ) + if (!matched) { - if (strict_) throw ex; - else + // NOTE: we don't use mapnik::util::string2bool + // here because we don't want to treat 'on' and 'off' + // as booleans, only 'true' and 'false' + if (csv_utils::ignore_case_equal(value, "true") || csv_utils::ignore_case_equal(value, "false")) { - MAPNIK_LOG_ERROR(csv) << ex.what() << " at line: " << line_number; + desc_.add_descriptor(mapnik::attribute_descriptor(header, mapnik::Boolean)); + } + else // fallback to normal string + { + desc_.add_descriptor(mapnik::attribute_descriptor(header, mapnik::String)); } } - catch (std::exception const& ex) - { - std::ostringstream s; - s << "CSV Plugin: unexpected error parsing line: " << line_number - << " - found " << headers_.size() << " with values like: " << csv_line << "\n" - << " and got error like: " << ex.what(); - if (strict_) - { - throw mapnik::datasource_exception(s.str()); - } - else - { - MAPNIK_LOG_ERROR(csv) << s.str(); - } - } - // return early if *.index is present - if (has_disk_index_) return; } - // bulk insert initialise r-tree - tree_ = std::make_unique(boxes); } const char * csv_datasource::name() @@ -474,8 +271,8 @@ mapnik::layer_descriptor csv_datasource::get_descriptor() const return desc_; } -template -boost::optional csv_datasource::get_geometry_type_impl(T & stream) const +boost::optional +csv_datasource::get_geometry_type_impl(std::istream & stream) const { boost::optional result; if (tree_) @@ -496,7 +293,7 @@ boost::optional csv_datasource::get_geometry_type try { auto values = csv_utils::parse_line(str, separator_, quote_); - auto geom = detail::extract_geometry(values, locator_); + auto geom = csv_utils::extract_geometry(values, locator_); result = mapnik::util::to_ds_type(geom); if (result) { @@ -539,7 +336,7 @@ boost::optional csv_datasource::get_geometry_type try { auto values = csv_utils::parse_line(str, separator_, quote_); - auto geom = detail::extract_geometry(values, locator_); + auto geom = csv_utils::extract_geometry(values, locator_); result = mapnik::util::to_ds_type(geom); if (result) { @@ -634,7 +431,7 @@ mapnik::featureset_ptr csv_datasource::features(mapnik::query const& q) const return std::make_shared(filename_, filter, locator_, separator_, quote_, headers_, ctx_); } } - return mapnik::featureset_ptr(); + return mapnik::make_invalid_featureset(); } mapnik::featureset_ptr csv_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const diff --git a/plugins/input/csv/csv_datasource.hpp b/plugins/input/csv/csv_datasource.hpp index ac2482f9b..71cf2ea71 100644 --- a/plugins/input/csv/csv_datasource.hpp +++ b/plugins/input/csv/csv_datasource.hpp @@ -32,6 +32,7 @@ #include #include #include +#include "csv_utils.hpp" #pragma GCC diagnostic push #include @@ -41,8 +42,8 @@ #pragma GCC diagnostic pop // stl +#include #include -#include #include template @@ -67,7 +68,8 @@ struct options_type > }; }}}}} -class csv_datasource : public mapnik::datasource +class csv_datasource : public mapnik::datasource, + private csv_utils::csv_file_parser { public: using box_type = mapnik::box2d; @@ -84,26 +86,15 @@ public: mapnik::layer_descriptor get_descriptor() const; boost::optional get_geometry_type() const; private: - template - void parse_csv(T & stream); - template - boost::optional get_geometry_type_impl(T & stream) const; + void parse_csv(std::istream & ); + virtual void add_feature(mapnik::value_integer index, mapnik::csv_line const & values); + boost::optional get_geometry_type_impl(std::istream & ) const; mapnik::layer_descriptor desc_; - mapnik::box2d extent_; std::string filename_; - mapnik::value_integer row_limit_; std::string inline_string_; - char separator_; - char quote_; - std::vector headers_; - std::string manual_headers_; - bool strict_; mapnik::context_ptr ctx_; - bool extent_initialized_; std::unique_ptr tree_; - detail::geometry_column_locator locator_; - bool has_disk_index_; }; #endif // MAPNIK_CSV_DATASOURCE_HPP diff --git a/plugins/input/csv/csv_featureset.cpp b/plugins/input/csv/csv_featureset.cpp index 5017c825e..151811201 100644 --- a/plugins/input/csv/csv_featureset.cpp +++ b/plugins/input/csv/csv_featureset.cpp @@ -31,7 +31,7 @@ #include #include -csv_featureset::csv_featureset(std::string const& filename, detail::geometry_column_locator const& locator, char separator, char quote, +csv_featureset::csv_featureset(std::string const& filename, locator_type const& locator, char separator, char quote, std::vector const& headers, mapnik::context_ptr const& ctx, array_type && index_array) : #if defined(MAPNIK_MEMORY_MAPPED_FILE) @@ -72,12 +72,12 @@ csv_featureset::~csv_featureset() {} mapnik::feature_ptr csv_featureset::parse_feature(char const* beg, char const* end) { auto values = csv_utils::parse_line(beg, end, separator_, quote_, headers_.size()); - auto geom = detail::extract_geometry(values, locator_); + auto geom = csv_utils::extract_geometry(values, locator_); if (!geom.is()) { mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_, ++feature_id_)); feature->set_geometry(std::move(geom)); - detail::process_properties(*feature, headers_, values, locator_, tr_); + csv_utils::process_properties(*feature, headers_, values, locator_, tr_); return feature; } return mapnik::feature_ptr(); diff --git a/plugins/input/csv/csv_featureset.hpp b/plugins/input/csv/csv_featureset.hpp index 8fbf77bb8..8828fa4a5 100644 --- a/plugins/input/csv/csv_featureset.hpp +++ b/plugins/input/csv/csv_featureset.hpp @@ -28,7 +28,6 @@ #include "csv_utils.hpp" #include "csv_datasource.hpp" #include -#include #if defined(MAPNIK_MEMORY_MAPPED_FILE) #pragma GCC diagnostic push @@ -41,7 +40,7 @@ class csv_featureset : public mapnik::Featureset { - using locator_type = detail::geometry_column_locator; + using locator_type = csv_utils::geometry_column_locator; public: using array_type = std::deque; csv_featureset(std::string const& filename, @@ -70,7 +69,7 @@ private: array_type::const_iterator index_end_; mapnik::context_ptr ctx_; mapnik::value_integer feature_id_ = 0; - detail::geometry_column_locator const& locator_; + locator_type const& locator_; mapnik::transcoder tr_; }; diff --git a/plugins/input/csv/csv_getline.hpp b/plugins/input/csv/csv_getline.hpp new file mode 100644 index 000000000..9dfe5de49 --- /dev/null +++ b/plugins/input/csv/csv_getline.hpp @@ -0,0 +1,72 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_CSV_GETLINE_HPP +#define MAPNIK_CSV_GETLINE_HPP + +#include +#include +#include + +namespace csv_utils +{ + +template +std::basic_istream& getline_csv(std::istream& is, std::basic_string& s, CharT delim, CharT quote) +{ + typename std::basic_string::size_type nread = 0; + typename std::basic_istream::sentry sentry(is, true); + if (sentry) + { + std::basic_streambuf* buf = is.rdbuf(); + s.clear(); + bool has_quote = false; + while (nread < s.max_size()) + { + int c1 = buf->sbumpc(); + if (Traits::eq_int_type(c1, Traits::eof())) + { + is.setstate(std::ios_base::eofbit); + break; + } + else + { + ++nread; + CharT c = Traits::to_char_type(c1); + if (Traits::eq(c, quote)) + has_quote = !has_quote; + if (!Traits::eq(c, delim) || has_quote) + s.push_back(c); + else + break;// Character is extracted but not appended. + } + } + } + if (nread == 0 || nread >= s.max_size()) + is.setstate(std::ios_base::failbit); + + return is; +} + +} + +#endif // MAPNIK_CSV_GETLINE_HPP diff --git a/plugins/input/csv/csv_index_featureset.cpp b/plugins/input/csv/csv_index_featureset.cpp index c064579fc..e94f41bc5 100644 --- a/plugins/input/csv/csv_index_featureset.cpp +++ b/plugins/input/csv/csv_index_featureset.cpp @@ -37,7 +37,7 @@ csv_index_featureset::csv_index_featureset(std::string const& filename, mapnik::filter_in_box const& filter, - detail::geometry_column_locator const& locator, + locator_type const& locator, char separator, char quote, std::vector const& headers, @@ -89,12 +89,12 @@ csv_index_featureset::~csv_index_featureset() {} mapnik::feature_ptr csv_index_featureset::parse_feature(char const* beg, char const* end) { auto values = csv_utils::parse_line(beg, end, separator_, quote_, headers_.size()); - auto geom = detail::extract_geometry(values, locator_); + auto geom = csv_utils::extract_geometry(values, locator_); if (!geom.is()) { mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_, ++feature_id_)); feature->set_geometry(std::move(geom)); - detail::process_properties(*feature, headers_, values, locator_, tr_); + csv_utils::process_properties(*feature, headers_, values, locator_, tr_); return feature; } return mapnik::feature_ptr(); diff --git a/plugins/input/csv/csv_index_featureset.hpp b/plugins/input/csv/csv_index_featureset.hpp index 1a2c6372b..e57a356c9 100644 --- a/plugins/input/csv/csv_index_featureset.hpp +++ b/plugins/input/csv/csv_index_featureset.hpp @@ -41,7 +41,7 @@ class csv_index_featureset : public mapnik::Featureset { using value_type = std::pair; - using locator_type = detail::geometry_column_locator; + using locator_type = csv_utils::geometry_column_locator; public: csv_index_featureset(std::string const& filename, @@ -60,7 +60,7 @@ private: std::vector headers_; mapnik::context_ptr ctx_; mapnik::value_integer feature_id_ = 0; - detail::geometry_column_locator const& locator_; + locator_type const& locator_; mapnik::transcoder tr_; #if defined (MAPNIK_MEMORY_MAPPED_FILE) using file_source_type = boost::interprocess::ibufferstream; diff --git a/plugins/input/csv/csv_inline_featureset.cpp b/plugins/input/csv/csv_inline_featureset.cpp index b0fe420cf..2d91efcf4 100644 --- a/plugins/input/csv/csv_inline_featureset.cpp +++ b/plugins/input/csv/csv_inline_featureset.cpp @@ -33,7 +33,7 @@ #include csv_inline_featureset::csv_inline_featureset(std::string const& inline_string, - detail::geometry_column_locator const& locator, + locator_type const& locator, char separator, char quote, std::vector const& headers, @@ -54,13 +54,15 @@ csv_inline_featureset::~csv_inline_featureset() {} mapnik::feature_ptr csv_inline_featureset::parse_feature(std::string const& str) { - auto values = csv_utils::parse_line(str, separator_, quote_); - auto geom = detail::extract_geometry(values, locator_); + auto const* start = str.data(); + auto const* end = start + str.size(); + auto values = csv_utils::parse_line(start, end, separator_, quote_, headers_.size()); + auto geom = csv_utils::extract_geometry(values, locator_); if (!geom.is()) { mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_, ++feature_id_)); feature->set_geometry(std::move(geom)); - detail::process_properties(*feature, headers_, values, locator_, tr_); + csv_utils::process_properties(*feature, headers_, values, locator_, tr_); return feature; } return mapnik::feature_ptr(); diff --git a/plugins/input/csv/csv_inline_featureset.hpp b/plugins/input/csv/csv_inline_featureset.hpp index 3da9f638a..4873cecaa 100644 --- a/plugins/input/csv/csv_inline_featureset.hpp +++ b/plugins/input/csv/csv_inline_featureset.hpp @@ -28,11 +28,10 @@ #include "csv_utils.hpp" #include "csv_datasource.hpp" #include -#include class csv_inline_featureset : public mapnik::Featureset { - using locator_type = detail::geometry_column_locator; + using locator_type = csv_utils::geometry_column_locator; public: using array_type = std::deque; csv_inline_featureset(std::string const& inline_string, @@ -55,7 +54,7 @@ private: array_type::const_iterator index_end_; mapnik::context_ptr ctx_; mapnik::value_integer feature_id_ = 0; - detail::geometry_column_locator const& locator_; + locator_type const& locator_; mapnik::transcoder tr_; }; diff --git a/plugins/input/csv/csv_utils.cpp b/plugins/input/csv/csv_utils.cpp new file mode 100644 index 000000000..217276f6a --- /dev/null +++ b/plugins/input/csv/csv_utils.cpp @@ -0,0 +1,507 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +// csv grammar +#include +// +#include "csv_getline.hpp" +#include "csv_utils.hpp" + +#include +#include +#include +#include + +namespace csv_utils { +namespace detail { + +std::size_t file_length(std::istream & stream) +{ + stream.seekg(0, std::ios::end); + return stream.tellg(); +} + +std::tuple autodetect_csv_flavour(std::istream & stream, std::size_t file_length) +{ + // autodetect newlines/quotes/separators + char newline = '\n'; // default + bool has_newline = false; + bool has_single_quote = false; + char quote = '"'; // default + char separator = ','; // default + // local counters + int num_commas = 0; + int num_tabs = 0; + int num_pipes = 0; + int num_semicolons = 0; + + static std::size_t const max_size = 4000; + std::size_t size = std::min(file_length, max_size); + std::vector buffer; + buffer.resize(size); + stream.read(buffer.data(), size); + for (auto c : buffer) + { + switch (c) + { + case '\r': + newline = '\r'; + has_newline = true; + break; + case '\n': + has_newline = true; + break; + case '\'': + if (!has_single_quote) + { + quote = c; + has_single_quote = true; + } + break; + case ',': + if (!has_newline) ++num_commas; + break; + case '\t': + if (!has_newline) ++num_tabs; + break; + case '|': + if (!has_newline) ++num_pipes; + break; + case ';': + if (!has_newline) ++num_semicolons; + break; + } + } + // detect separator + if (num_tabs > 0 && num_tabs > num_commas) + { + separator = '\t'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected tab separator"; + } + else // pipes/semicolons + { + if (num_pipes > num_commas) + { + separator = '|'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected '|' separator"; + } + else if (num_semicolons > num_commas) + { + separator = ';'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected ';' separator"; + } + } + + if (has_newline && has_single_quote) + { + std::istringstream ss(std::string(buffer.begin(), buffer.end())); + std::size_t num_columns = 0; + for (std::string line; csv_utils::getline_csv(ss, line, newline, quote); ) + { + if (size < file_length && ss.eof()) + { + // we can't be sure that last line + // is not truncated so skip it + break; + } + if (line.size() == 0 || (line.size() == 1 && line[0] == char(0xa))) continue; // empty lines are not interesting + auto num_quotes = std::count(line.begin(), line.end(), quote); + if (num_quotes % 2 != 0) + { + quote = '"'; + break; + } + auto columns = csv_utils::parse_line(line, separator, quote); + if (num_columns > 0 && num_columns != columns.size()) + { + quote = '"'; + break; + } + num_columns = columns.size(); + } + } + return std::make_tuple(newline, has_newline, separator, quote); +} + +void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator) +{ + std::string lower_val(header); + std::transform(lower_val.begin(), lower_val.end(), lower_val.begin(), ::tolower); + if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) + { + locator.type = geometry_column_locator::WKT; + locator.index = index; + } + else if (lower_val == "geojson") + { + locator.type = geometry_column_locator::GEOJSON; + locator.index = index; + } + else if (lower_val == "x" || lower_val == "lon" + || lower_val == "lng" || lower_val == "long" + || (lower_val.find("longitude") != std::string::npos)) + { + locator.index = index; + locator.type = geometry_column_locator::LON_LAT; + } + + else if (lower_val == "y" + || lower_val == "lat" + || (lower_val.find("latitude") != std::string::npos)) + { + locator.index2 = index; + locator.type = geometry_column_locator::LON_LAT; + } +} + +bool valid(geometry_column_locator const& locator, std::size_t max_size) +{ + if (locator.type == geometry_column_locator::UNKNOWN) return false; + if (locator.index >= max_size) return false; + if (locator.type == geometry_column_locator::LON_LAT && locator.index2 >= max_size) return false; + return true; +} + +} // namespace detail + +static const mapnik::csv_line_grammar line_g; +static const mapnik::csv_white_space_skipper skipper{}; + +mapnik::csv_line parse_line(char const* start, char const* end, char separator, char quote, std::size_t num_columns) +{ + mapnik::csv_line values; + if (num_columns > 0) values.reserve(num_columns); + if (!boost::spirit::qi::phrase_parse(start, end, (line_g)(separator, quote), skipper, values)) + { + throw mapnik::datasource_exception("Failed to parse CSV line:\n" + std::string(start, end)); + } + return values; +} + +mapnik::csv_line parse_line(std::string const& line_str, char separator, char quote) +{ + auto start = line_str.c_str(); + auto end = start + line_str.length(); + return parse_line(start, end, separator, quote, 0); +} + + +bool is_likely_number(std::string const& value) +{ + return (std::strspn( value.c_str(), "e-.+0123456789" ) == value.size()); +} + +struct ignore_case_equal_pred +{ + bool operator () (unsigned char a, unsigned char b) const + { + return std::tolower(a) == std::tolower(b); + } +}; + +bool ignore_case_equal(std::string const& s0, std::string const& s1) +{ + return std::equal(s0.begin(), s0.end(), + s1.begin(), ignore_case_equal_pred()); +} + +void csv_file_parser::add_feature(mapnik::value_integer, mapnik::csv_line const & ) +{ + // no-op by default +} + +template +void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, T & boxes) +{ + using boxes_type = T; + using box_type = typename boxes_type::value_type::first_type; + + auto file_length = detail::file_length(csv_file); + // set back to start + csv_file.seekg(0, std::ios::beg); + char newline; + bool has_newline; + char detected_quote; + char detected_separator; + std::tie(newline, has_newline, detected_separator, detected_quote) = detail::autodetect_csv_flavour(csv_file, file_length); + if (quote_ == 0) quote_ = detected_quote; + if (separator_ == 0) separator_ = detected_separator; + + // set back to start + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: separator: '" << separator_ + << "' quote: '" << quote_ << "'"; + + // rewind stream + csv_file.seekg(0, std::ios::beg); + // + std::string csv_line; + csv_utils::getline_csv(csv_file, csv_line, newline, quote_); + csv_file.seekg(0, std::ios::beg); + int line_number = 0; + if (!manual_headers_.empty()) + { + std::size_t index = 0; + auto headers = csv_utils::parse_line(manual_headers_, separator_, quote_); + headers_.reserve(headers.size()); + for (auto const& header : headers) + { + detail::locate_geometry_column(header, index++, locator_); + headers_.push_back(header); + } + } + else // parse first line as headers + { + while (csv_utils::getline_csv(csv_file, csv_line, newline, quote_)) + { + try + { + auto headers = csv_utils::parse_line(csv_line, separator_, quote_); + // skip blank lines + if (headers.size() > 0 && headers[0].empty()) ++line_number; + else + { + std::size_t index = 0; + headers_.reserve(headers.size()); + for (auto & header : headers) + { + mapnik::util::trim(header); + if (header.empty()) + { + if (strict_) + { + std::ostringstream s; + s << "CSV Plugin: expected a column header at line "; + s << line_number << ", column " << index; + s << " - ensure this row contains valid header fields: '"; + s << csv_line; + throw mapnik::datasource_exception(s.str()); + } + else + { + // create a placeholder for the empty header + std::ostringstream s; + s << "_" << index; + headers_.push_back(s.str()); + } + } + else + { + detail::locate_geometry_column(header, index, locator_); + headers_.push_back(header); + } + ++index; + } + ++line_number; + break; + } + } + catch (std::exception const& ex) + { + std::string s("CSV Plugin: error parsing headers: "); + s += ex.what(); + throw mapnik::datasource_exception(s); + } + } + } + + std::size_t num_headers = headers_.size(); + if (!detail::valid(locator_, num_headers)) + { + std::string str("CSV Plugin: could not detect column(s) with the name(s) of wkt, geojson, x/y, or "); + str += "latitude/longitude in:\n"; + str += csv_line; + str += "\n - this is required for reading geometry data"; + throw mapnik::datasource_exception(str); + } + + mapnik::value_integer feature_count = 0; + auto pos = csv_file.tellg(); + // handle rare case of a single line of data and user-provided headers + // where a lack of a newline will mean that csv_utils::getline_csv returns false + bool is_first_row = false; + + if (!has_newline) + { + csv_file.setstate(std::ios::failbit); + pos = 0; + if (!csv_line.empty()) + { + is_first_row = true; + } + } + + while (is_first_row || csv_utils::getline_csv(csv_file, csv_line, newline, quote_)) + { + ++line_number; + if ((row_limit_ > 0) && (line_number > row_limit_)) + { + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: row limit hit, exiting at feature: " << feature_count; + break; + } + auto record_offset = pos; + auto record_size = csv_line.length(); + pos = csv_file.tellg(); + is_first_row = false; + + // skip blank lines + if (record_size <= 10) + { + std::string trimmed = csv_line; + boost::trim_if(trimmed, boost::algorithm::is_any_of("\",'\r\n ")); + if (trimmed.empty()) + { + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: empty row encountered at line: " << line_number; + continue; + } + } + + try + { + auto const* line_start = csv_line.data(); + auto const* line_end = line_start + csv_line.size(); + auto values = csv_utils::parse_line(line_start, line_end, separator_, quote_, num_headers); + unsigned num_fields = values.size(); + if (num_fields != num_headers) + { + std::ostringstream s; + s << "CSV Plugin: # of columns(" << num_fields << ")"; + if (num_fields > num_headers) + { + s << " > "; + } + else + { + s << " < "; + } + s << "# of headers(" << num_headers << ") parsed"; + throw mapnik::datasource_exception(s.str()); + } + + auto geom = extract_geometry(values, locator_); + if (!geom.is()) + { + auto box = mapnik::geometry::envelope(geom); + if (!extent_initialized_) + { + if (extent_.valid()) + extent_.expand_to_include(box); + else + extent_ = box; + } + boxes.emplace_back(box_type(box), make_pair(record_offset, record_size)); + add_feature(++feature_count, values); + } + else + { + std::ostringstream s; + s << "CSV Plugin: expected geometry column: could not parse row " + << line_number << " " + << values.at(locator_.index) << "'"; + throw mapnik::datasource_exception(s.str()); + } + } + catch (mapnik::datasource_exception const& ex ) + { + if (strict_) throw ex; + else + { + MAPNIK_LOG_ERROR(csv) << ex.what() << " at line: " << line_number; + } + } + catch (std::exception const& ex) + { + std::ostringstream s; + s << "CSV Plugin: unexpected error parsing line: " << line_number + << " - found " << headers_.size() << " with values like: " << csv_line << "\n" + << " and got error like: " << ex.what(); + if (strict_) + { + throw mapnik::datasource_exception(s.str()); + } + else + { + MAPNIK_LOG_ERROR(csv) << s.str(); + } + } + // return early if *.index is present + if (has_disk_index_) return; + } +} + + +mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator) +{ + mapnik::geometry::geometry geom; + if (locator.type == geometry_column_locator::WKT) + { + auto wkt_value = row.at(locator.index); + if (mapnik::from_wkt(wkt_value, geom)) + { + // correct orientations .. + mapnik::geometry::correct(geom); + } + else + { + throw mapnik::datasource_exception("Failed to parse WKT: '" + wkt_value + "'"); + } + } + else if (locator.type == geometry_column_locator::GEOJSON) + { + + auto json_value = row.at(locator.index); + if (!mapnik::json::from_geojson(json_value, geom)) + { + throw mapnik::datasource_exception("Failed to parse GeoJSON: '" + json_value + "'"); + } + } + else if (locator.type == geometry_column_locator::LON_LAT) + { + double x, y; + auto long_value = row.at(locator.index); + auto lat_value = row.at(locator.index2); + if (!mapnik::util::string2double(long_value,x)) + { + throw mapnik::datasource_exception("Failed to parse Longitude: '" + long_value + "'"); + } + if (!mapnik::util::string2double(lat_value,y)) + { + throw mapnik::datasource_exception("Failed to parse Latitude: '" + lat_value + "'"); + } + geom = mapnik::geometry::point(x,y); + } + return geom; +} + +template void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, std::vector, std::pair>> & boxes); + +template void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, std::vector, std::pair>> & boxes); + +} // namespace csv_utils diff --git a/plugins/input/csv/csv_utils.hpp b/plugins/input/csv/csv_utils.hpp index b82077381..df976e3a7 100644 --- a/plugins/input/csv/csv_utils.hpp +++ b/plugins/input/csv/csv_utils.hpp @@ -24,188 +24,26 @@ #define MAPNIK_CSV_UTILS_DATASOURCE_HPP // mapnik -#include +#include #include -#include -#include -#include +#include #include -#include #include -#include - -#pragma GCC diagnostic push -#include -#include -#pragma GCC diagnostic pop +#include +// std +#include #include -#include -#include +#include -namespace csv_utils -{ +namespace csv_utils { -static const mapnik::csv_line_grammar line_g; -static const mapnik::csv_white_space_skipper skipper; +mapnik::csv_line parse_line(char const* start, char const* end, char separator, char quote, std::size_t num_columns); +mapnik::csv_line parse_line(std::string const& line_str, char separator, char quote); -template -static mapnik::csv_line parse_line(Iterator start, Iterator end, char separator, char quote, std::size_t num_columns) -{ - mapnik::csv_line values; - if (num_columns > 0) values.reserve(num_columns); - if (!boost::spirit::qi::phrase_parse(start, end, (line_g)(separator, quote), skipper, values)) - { - throw mapnik::datasource_exception("Failed to parse CSV line:\n" + std::string(start, end)); - } - return values; -} - -static inline mapnik::csv_line parse_line(std::string const& line_str, char separator, char quote) -{ - auto start = line_str.c_str(); - auto end = start + line_str.length(); - return parse_line(start, end, separator, quote, 0); -} - -static inline bool is_likely_number(std::string const& value) -{ - return (std::strspn( value.c_str(), "e-.+0123456789" ) == value.size()); -} - -struct ignore_case_equal_pred -{ - bool operator () (unsigned char a, unsigned char b) const - { - return std::tolower(a) == std::tolower(b); - } -}; - -inline bool ignore_case_equal(std::string const& s0, std::string const& s1) -{ - return std::equal(s0.begin(), s0.end(), - s1.begin(), ignore_case_equal_pred()); -} - -template -std::basic_istream& getline_csv(std::istream& is, std::basic_string& s, CharT delim, CharT quote) -{ - typename std::basic_string::size_type nread = 0; - typename std::basic_istream::sentry sentry(is, true); - if (sentry) - { - std::basic_streambuf* buf = is.rdbuf(); - s.clear(); - bool has_quote = false; - while (nread < s.max_size()) - { - int c1 = buf->sbumpc(); - if (Traits::eq_int_type(c1, Traits::eof())) - { - is.setstate(std::ios_base::eofbit); - break; - } - else - { - ++nread; - CharT c = Traits::to_char_type(c1); - if (Traits::eq(c, quote)) - has_quote = !has_quote; - if (!Traits::eq(c, delim) || has_quote) - s.push_back(c); - else - break;// Character is extracted but not appended. - } - } - } - if (nread == 0 || nread >= s.max_size()) - is.setstate(std::ios_base::failbit); - - return is; -} - -} - - -namespace detail { - -template -std::size_t file_length(T & stream) -{ - stream.seekg(0, std::ios::end); - return stream.tellg(); -} - -static inline char detect_separator(std::string const& str) -{ - char separator = ','; // default - int num_commas = std::count(str.begin(), str.end(), ','); - // detect tabs - int num_tabs = std::count(str.begin(), str.end(), '\t'); - if (num_tabs > 0) - { - if (num_tabs > num_commas) - { - separator = '\t'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected tab separator"; - } - } - else // pipes - { - int num_pipes = std::count(str.begin(), str.end(), '|'); - if (num_pipes > num_commas) - { - separator = '|'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected '|' separator"; - } - else // semicolons - { - int num_semicolons = std::count(str.begin(), str.end(), ';'); - if (num_semicolons > num_commas) - { - separator = ';'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected ';' separator"; - } - } - } - return separator; -} - -template -std::tuple autodect_newline_and_quote(T & stream, std::size_t file_length) -{ - // autodetect newlines - char newline = '\n'; - bool has_newline = false; - bool has_quote = false; - char quote = '"'; - static std::size_t const max_size = 4000; - std::size_t size = std::min(file_length, max_size); - for (std::size_t lidx = 0; lidx < size; ++lidx) - { - char c = static_cast(stream.get()); - switch (c) - { - case '\r': - newline = '\r'; - has_newline = true; - break; - case '\n': - has_newline = true; - break; - case '\'': - case '"': - if (!has_quote) - { - quote = c; - has_quote = true; - } - break; - } - } - return std::make_tuple(newline, has_newline, quote); -} +bool is_likely_number(std::string const& value); +bool ignore_case_equal(std::string const& s0, std::string const& s1); struct geometry_column_locator { @@ -217,87 +55,8 @@ struct geometry_column_locator std::size_t index2; }; -static inline void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator) -{ - std::string lower_val(header); - std::transform(lower_val.begin(), lower_val.end(), lower_val.begin(), ::tolower); - if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) - { - locator.type = geometry_column_locator::WKT; - locator.index = index; - } - else if (lower_val == "geojson") - { - locator.type = geometry_column_locator::GEOJSON; - locator.index = index; - } - else if (lower_val == "x" || lower_val == "lon" - || lower_val == "lng" || lower_val == "long" - || (lower_val.find("longitude") != std::string::npos)) - { - locator.index = index; - locator.type = geometry_column_locator::LON_LAT; - } - else if (lower_val == "y" - || lower_val == "lat" - || (lower_val.find("latitude") != std::string::npos)) - { - locator.index2 = index; - locator.type = geometry_column_locator::LON_LAT; - } -} - -static inline bool valid(geometry_column_locator const& locator, std::size_t max_size) -{ - if (locator.type == geometry_column_locator::UNKNOWN) return false; - if (locator.index >= max_size) return false; - if (locator.type == geometry_column_locator::LON_LAT && locator.index2 >= max_size) return false; - return true; -} - -static inline mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator) -{ - mapnik::geometry::geometry geom; - if (locator.type == geometry_column_locator::WKT) - { - auto wkt_value = row.at(locator.index); - if (mapnik::from_wkt(wkt_value, geom)) - { - // correct orientations .. - mapnik::geometry::correct(geom); - } - else - { - throw mapnik::datasource_exception("Failed to parse WKT: '" + wkt_value + "'"); - } - } - else if (locator.type == geometry_column_locator::GEOJSON) - { - - auto json_value = row.at(locator.index); - if (!mapnik::json::from_geojson(json_value, geom)) - { - throw mapnik::datasource_exception("Failed to parse GeoJSON: '" + json_value + "'"); - } - } - else if (locator.type == geometry_column_locator::LON_LAT) - { - double x, y; - auto long_value = row.at(locator.index); - auto lat_value = row.at(locator.index2); - if (!mapnik::util::string2double(long_value,x)) - { - throw mapnik::datasource_exception("Failed to parse Longitude: '" + long_value + "'"); - } - if (!mapnik::util::string2double(lat_value,y)) - { - throw mapnik::datasource_exception("Failed to parse Latitude: '" + lat_value + "'"); - } - geom = mapnik::geometry::point(x,y); - } - return geom; -} +mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator); template void process_properties(Feature & feature, Headers const& headers, Values const& values, Locator const& locator, Transcoder const& tr) @@ -316,8 +75,8 @@ void process_properties(Feature & feature, Headers const& headers, Values const& std::string value = mapnik::util::trim_copy(*val_beg++); int value_length = value.length(); - if (locator.index == i && (locator.type == detail::geometry_column_locator::WKT - || locator.type == detail::geometry_column_locator::GEOJSON) ) continue; + if (locator.index == i && (locator.type == geometry_column_locator::WKT + || locator.type == geometry_column_locator::GEOJSON) ) continue; bool matched = false; @@ -369,7 +128,25 @@ void process_properties(Feature & feature, Headers const& headers, Values const& } } +struct csv_file_parser +{ + template + void parse_csv_and_boxes(std::istream & csv_file, T & boxes); -}// ns detail + virtual void add_feature(mapnik::value_integer index, mapnik::csv_line const & values); + + std::vector headers_; + std::string manual_headers_; + geometry_column_locator locator_; + mapnik::box2d extent_; + mapnik::value_integer row_limit_ = 0; + char separator_ = '\0'; + char quote_ = '\0'; + bool strict_ = false; + bool extent_initialized_ = false; + bool has_disk_index_ = false; +}; + +} // namespace csv_utils #endif // MAPNIK_CSV_UTILS_DATASOURCE_HPP diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index 8a06a92c4..2454ed65b 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -44,10 +44,19 @@ using mapnik::featureset_ptr; using mapnik::layer_descriptor; using mapnik::datasource_exception; +static std::once_flag once_flag; + +extern "C" MAPNIK_EXP void on_plugin_load() +{ + // initialize gdal formats + std::call_once(once_flag,[](){ + GDALAllRegister(); + }); +} gdal_datasource::gdal_datasource(parameters const& params) : datasource(params), - dataset_(nullptr), + dataset_(nullptr, &GDALClose), desc_(gdal_datasource::name(), "utf-8"), nodata_value_(params.get("nodata")), nodata_tolerance_(*params.get("nodata_tolerance",1e-12)) @@ -58,8 +67,6 @@ gdal_datasource::gdal_datasource(parameters const& params) mapnik::progress_timer __stats__(std::clog, "gdal_datasource::init"); #endif - GDALAllRegister(); - boost::optional file = params.get("file"); if (! file) throw datasource_exception("missing parameter"); @@ -79,12 +86,14 @@ gdal_datasource::gdal_datasource(parameters const& params) #if GDAL_VERSION_NUM >= 1600 if (shared_dataset_) { - dataset_ = reinterpret_cast(GDALOpenShared((dataset_name_).c_str(), GA_ReadOnly)); + auto ds = GDALOpenShared(dataset_name_.c_str(), GA_ReadOnly); + dataset_.reset(static_cast(ds)); } else #endif { - dataset_ = reinterpret_cast(GDALOpen((dataset_name_).c_str(), GA_ReadOnly)); + auto ds = GDALOpen(dataset_name_.c_str(), GA_ReadOnly); + dataset_.reset(static_cast(ds)); } if (! dataset_) @@ -92,7 +101,7 @@ gdal_datasource::gdal_datasource(parameters const& params) throw datasource_exception(CPLGetLastErrorMsg()); } - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: opened Dataset=" << dataset_; + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: opened Dataset=" << dataset_.get(); nbands_ = dataset_->GetRasterCount(); width_ = dataset_->GetRasterXSize(); @@ -182,8 +191,7 @@ gdal_datasource::gdal_datasource(parameters const& params) gdal_datasource::~gdal_datasource() { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Closing Dataset=" << dataset_; - GDALClose(dataset_); + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Closing Dataset=" << dataset_.get(); } datasource::datasource_t gdal_datasource::type() const @@ -217,12 +225,9 @@ featureset_ptr gdal_datasource::features(query const& q) const mapnik::progress_timer __stats__(std::clog, "gdal_datasource::features"); #endif - gdal_query gq = q; - - // TODO - move to std::make_shared, but must reduce # of args to <= 9 - return featureset_ptr(new gdal_featureset(*dataset_, + return std::make_shared(*dataset_, band_, - gq, + gdal_query(q), extent_, width_, height_, @@ -230,7 +235,7 @@ featureset_ptr gdal_datasource::features(query const& q) const dx_, dy_, nodata_value_, - nodata_tolerance_)); + nodata_tolerance_); } featureset_ptr gdal_datasource::features_at_point(coord2d const& pt, double tol) const @@ -239,12 +244,9 @@ featureset_ptr gdal_datasource::features_at_point(coord2d const& pt, double tol) mapnik::progress_timer __stats__(std::clog, "gdal_datasource::features_at_point"); #endif - gdal_query gq = pt; - - // TODO - move to std::make_shared, but must reduce # of args to <= 9 - return featureset_ptr(new gdal_featureset(*dataset_, + return std::make_shared(*dataset_, band_, - gq, + gdal_query(pt), extent_, width_, height_, @@ -252,5 +254,5 @@ featureset_ptr gdal_datasource::features_at_point(coord2d const& pt, double tol) dx_, dy_, nodata_value_, - nodata_tolerance_)); + nodata_tolerance_); } diff --git a/plugins/input/gdal/gdal_datasource.hpp b/plugins/input/gdal/gdal_datasource.hpp index 7e7b22164..3fc3036c8 100644 --- a/plugins/input/gdal/gdal_datasource.hpp +++ b/plugins/input/gdal/gdal_datasource.hpp @@ -55,8 +55,7 @@ public: boost::optional get_geometry_type() const; mapnik::layer_descriptor get_descriptor() const; private: - GDALDataset* open_dataset() const; - GDALDataset* dataset_; + std::unique_ptr dataset_; mapnik::box2d extent_; std::string dataset_name_; int band_; diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 968fc6df1..1377322e3 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -21,7 +21,7 @@ *****************************************************************************/ // mapnik -#include +#include #include #include #include @@ -29,7 +29,6 @@ #include #include #include -#include // stl #include @@ -39,14 +38,47 @@ #include "gdal_featureset.hpp" #include -using mapnik::query; -using mapnik::coord2d; using mapnik::box2d; using mapnik::feature_ptr; using mapnik::view_transform; using mapnik::datasource_exception; using mapnik::feature_factory; +#ifdef MAPNIK_LOG +namespace { + +void get_overview_meta(GDALRasterBand* band) +{ + int band_overviews = band->GetOverviewCount(); + if (band_overviews > 0) + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: " << band_overviews << " overviews found!"; + + for (int b = 0; b < band_overviews; b++) + { + GDALRasterBand * overview = band->GetOverview(b); + MAPNIK_LOG_DEBUG(gdal) << "Overview= " << b + << " Width=" << overview->GetXSize() + << " Height=" << overview->GetYSize(); + } + } + else + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No overviews found!"; + } + + int bsx,bsy; + double scale; + band->GetBlockSize(&bsx, &bsy); + scale = band->GetScale(); + + MAPNIK_LOG_DEBUG(gdal) << "Block=" << bsx << "x" << bsy + << " Scale=" << scale + << " Type=" << GDALGetDataTypeName(band->GetRasterDataType()) + << "Color=" << GDALGetColorInterpretationName(band->GetColorInterpretation()); +} +} // anonymous ns +#endif gdal_featureset::gdal_featureset(GDALDataset& dataset, int band, gdal_query q, @@ -77,8 +109,6 @@ gdal_featureset::gdal_featureset(GDALDataset& dataset, gdal_featureset::~gdal_featureset() { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Closing Dataset=" << &dataset_; - } feature_ptr gdal_featureset::next() @@ -408,15 +438,15 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) if( red->GetBand() == 1 && green->GetBand() == 2 && blue->GetBand() == 3 ) { int nBandsToRead = 3; - if( alpha != NULL && alpha->GetBand() == 4 && !raster_has_nodata ) + if( alpha != nullptr && alpha->GetBand() == 4 && !raster_has_nodata ) { nBandsToRead = 4; - alpha = NULL; // to avoid reading it again afterwards + alpha = nullptr; // to avoid reading it again afterwards } raster_io_error = dataset_.RasterIO(GF_Read, x_off, y_off, width, height, image.bytes(), image.width(), image.height(), GDT_Byte, - nBandsToRead, NULL, + nBandsToRead, nullptr, 4, 4 * image.width(), 1); if (raster_io_error == CE_Failure) { throw datasource_exception(CPLGetLastErrorMsg()); @@ -556,6 +586,32 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; } } + else if( dataset_.GetRasterCount() > 0 && dataset_.GetRasterBand(1) ) + { + // Check if we have a non-alpha mask band (for example a TIFF internal mask) + int flags = dataset_.GetRasterBand(1)->GetMaskFlags(); + GDALRasterBand* mask = 0; + if (flags == GMF_PER_DATASET) + { + mask = dataset_.GetRasterBand(1)->GetMaskBand(); + } + if (mask) + { + MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: found and processing mask band..."; + if (!raster_has_nodata) + { + raster_io_error = mask->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + } + else + { + MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of mask band"; + } + } + } mapnik::raster_ptr raster = std::make_shared(intersect, image, filter_factor); // set nodata value to be used in raster colorizer if (nodata_value_) raster->set_nodata(*nodata_value_); @@ -625,36 +681,3 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) } return feature_ptr(); } - -#ifdef MAPNIK_LOG -void gdal_featureset::get_overview_meta(GDALRasterBand* band) -{ - int band_overviews = band->GetOverviewCount(); - if (band_overviews > 0) - { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: " << band_overviews << " overviews found!"; - - for (int b = 0; b < band_overviews; b++) - { - GDALRasterBand * overview = band->GetOverview(b); - MAPNIK_LOG_DEBUG(gdal) << "Overview= " << b - << " Width=" << overview->GetXSize() - << " Height=" << overview->GetYSize(); - } - } - else - { - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No overviews found!"; - } - - int bsx,bsy; - double scale; - band->GetBlockSize(&bsx, &bsy); - scale = band->GetScale(); - - MAPNIK_LOG_DEBUG(gdal) << "Block=" << bsx << "x" << bsy - << " Scale=" << scale - << " Type=" << GDALGetDataTypeName(band->GetRasterDataType()) - << "Color=" << GDALGetColorInterpretationName(band->GetColorInterpretation()); -} -#endif diff --git a/plugins/input/gdal/gdal_featureset.hpp b/plugins/input/gdal/gdal_featureset.hpp index b90921149..f2f66f796 100644 --- a/plugins/input/gdal/gdal_featureset.hpp +++ b/plugins/input/gdal/gdal_featureset.hpp @@ -24,13 +24,12 @@ #define GDAL_FEATURESET_HPP // mapnik -#include +#include +#include #include // boost #include -#include "gdal_datasource.hpp" - class GDALDataset; class GDALRasterBand; @@ -74,11 +73,6 @@ public: private: mapnik::feature_ptr get_feature(mapnik::query const& q); mapnik::feature_ptr get_feature_at_point(mapnik::coord2d const& p); - -#ifdef MAPNIK_LOG - void get_overview_meta(GDALRasterBand * band); -#endif - GDALDataset & dataset_; mapnik::context_ptr ctx_; int band_; diff --git a/plugins/input/geojson/geojson_datasource.cpp b/plugins/input/geojson/geojson_datasource.cpp index dbb80f95b..422fcf0a5 100644 --- a/plugins/input/geojson/geojson_datasource.cpp +++ b/plugins/input/geojson/geojson_datasource.cpp @@ -151,7 +151,7 @@ geojson_datasource::geojson_datasource(parameters const& params) cache_features_ = *params.get("cache_features", true); #if !defined(MAPNIK_MEMORY_MAPPED_FILE) mapnik::util::file file(filename_); - if (!file.open()) + if (!file) { throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); } @@ -192,12 +192,28 @@ geojson_datasource::geojson_datasource(parameters const& params) } namespace { +using box_type = box2d; +using boxes_type = std::vector>>; using base_iterator_type = char const*; const mapnik::transcoder geojson_datasource_static_tr("utf8"); const mapnik::json::feature_collection_grammar geojson_datasource_static_fc_grammar(geojson_datasource_static_tr); const mapnik::json::feature_grammar_callback geojson_datasource_static_feature_callback_grammar(geojson_datasource_static_tr); const mapnik::json::feature_grammar geojson_datasource_static_feature_grammar(geojson_datasource_static_tr); -const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; +const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; +} + +void geojson_datasource::initialise_descriptor(mapnik::feature_ptr const& feature) +{ + for ( auto const& kv : *feature) + { + auto const& name = std::get<0>(kv); + if (!desc_.has_name(name)) + { + desc_.add_descriptor(mapnik::attribute_descriptor(name, + mapnik::util::apply_visitor(attr_value_converter(), + std::get<1>(kv)))); + } + } } void geojson_datasource::initialise_disk_index(std::string const& filename) @@ -213,11 +229,10 @@ void geojson_datasource::initialise_disk_index(std::string const& filename) std::vector positions; mapnik::util::spatial_index::query_first_n(filter, index, positions, 5); + std::ifstream>::query_first_n(filter, index, positions, num_features_to_query_); mapnik::util::file file(filename_); - if (!file.open()) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); - + if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); for (auto const& pos : positions) { std::fseek(file.get(), pos.first, SEEK_SET); @@ -227,7 +242,7 @@ void geojson_datasource::initialise_disk_index(std::string const& filename) auto const* start = record.data(); auto const* end = start + record.size(); mapnik::context_ptr ctx = std::make_shared(); - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1)); + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, -1)); using namespace boost::spirit; standard::space_type space; if (!boost::spirit::qi::phrase_parse(start, end, @@ -236,23 +251,15 @@ void geojson_datasource::initialise_disk_index(std::string const& filename) { throw std::runtime_error("Failed to parse geojson feature"); } - for ( auto const& kv : *feature) - { - auto const& name = std::get<0>(kv); - if (!desc_.has_name(name)) - { - desc_.add_descriptor(mapnik::attribute_descriptor(name, - mapnik::util::apply_visitor(attr_value_converter(), - std::get<1>(kv)))); - } - } + initialise_descriptor(feature); } + desc_.order_by_name(); } template void geojson_datasource::initialise_index(Iterator start, Iterator end) { - mapnik::json::boxes_type boxes; + boxes_type boxes; boost::spirit::standard::space_type space; Iterator itr = start; if (!boost::spirit::qi::phrase_parse(itr, end, (geojson_datasource_static_bbox_grammar)(boost::phoenix::ref(boxes)) , space)) @@ -285,20 +292,18 @@ void geojson_datasource::initialise_index(Iterator start, Iterator end) if (geometry_index == 0) { extent_ = box; - for ( auto const& kv : *f) - { - desc_.add_descriptor(mapnik::attribute_descriptor(std::get<0>(kv), - mapnik::util::apply_visitor(attr_value_converter(), - std::get<1>(kv)))); - } } else { extent_.expand_to_include(box); } values.emplace_back(box, std::make_pair(geometry_index,0)); + + } + if (geometry_index++ < num_features_to_query_) + { + initialise_descriptor(f); } - ++geometry_index; } // packing algorithm tree_ = std::make_unique(values); @@ -308,14 +313,16 @@ void geojson_datasource::initialise_index(Iterator start, Iterator end) // bulk insert initialise r-tree tree_ = std::make_unique(boxes); // calculate total extent + std::size_t feature_count = 0; for (auto const& item : boxes) { auto const& box = std::get<0>(item); auto const& geometry_index = std::get<1>(item); - if (!extent_.valid()) + if (!extent_.valid()) extent_ = box; + else extent_.expand_to_include(box); + if (feature_count++ < num_features_to_query_) { - extent_ = box; - // parse first feature to extract attributes schema. + // parse first N features to extract attributes schema. // NOTE: this doesn't yield correct answer for geoJSON in general, just an indication Iterator itr2 = start + geometry_index.first; Iterator end2 = itr2 + geometry_index.second; @@ -327,19 +334,12 @@ void geojson_datasource::initialise_index(Iterator start, Iterator end) { throw std::runtime_error("Failed to parse geojson feature"); } - for ( auto const& kv : *feature) - { - desc_.add_descriptor(mapnik::attribute_descriptor(std::get<0>(kv), - mapnik::util::apply_visitor(attr_value_converter(), - std::get<1>(kv)))); - } - } - else - { - extent_.expand_to_include(box); + + initialise_descriptor(feature); } } } + desc_.order_by_name(); } template @@ -399,12 +399,7 @@ void geojson_datasource::parse_geojson(Iterator start, Iterator end) if (geometry_index == 0) { extent_ = box; - for ( auto const& kv : *f) - { - desc_.add_descriptor(mapnik::attribute_descriptor(std::get<0>(kv), - mapnik::util::apply_visitor(attr_value_converter(), - std::get<1>(kv)))); - } + } else { @@ -412,6 +407,10 @@ void geojson_datasource::parse_geojson(Iterator start, Iterator end) } values.emplace_back(box, std::make_pair(geometry_index,0)); } + if (geometry_index < num_features_to_query_) + { + initialise_descriptor(f); + } ++geometry_index; } // packing algorithm @@ -419,7 +418,7 @@ void geojson_datasource::parse_geojson(Iterator start, Iterator end) } -geojson_datasource::~geojson_datasource() { } +geojson_datasource::~geojson_datasource() {} const char * geojson_datasource::name() { @@ -454,11 +453,11 @@ boost::optional geojson_datasource::get_geometry_ std::vector positions; mapnik::util::spatial_index::query_first_n(filter, index, positions, 5); + std::ifstream>::query_first_n(filter, index, positions, num_features_to_query_); mapnik::util::file file(filename_); - if (!file.open()) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); + if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); for (auto const& pos : positions) { @@ -494,7 +493,7 @@ boost::optional geojson_datasource::get_geometry_ else if (cache_features_) { unsigned num_features = features_.size(); - for (unsigned i = 0; i < num_features && i < 5; ++i) + for (unsigned i = 0; i < num_features && i < num_features_to_query_; ++i) { result = mapnik::util::to_ds_type(features_[i]->get_geometry()); if (result) @@ -512,14 +511,14 @@ boost::optional geojson_datasource::get_geometry_ else { mapnik::util::file file(filename_); - if (!file.open()) + if (!file) { throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); } auto itr = tree_->qbegin(boost::geometry::index::intersects(extent_)); auto end = tree_->qend(); mapnik::context_ptr ctx = std::make_shared(); - for (std::size_t count = 0; itr !=end && count < 5; ++itr,++count) + for (std::size_t count = 0; itr !=end && count < num_features_to_query_; ++itr,++count) { geojson_datasource::item_type const& item = *itr; std::size_t file_offset = item.second.first; @@ -589,8 +588,8 @@ mapnik::featureset_ptr geojson_datasource::features(mapnik::query const& q) cons } } - // otherwise return an empty featureset pointer - return mapnik::featureset_ptr(); + // otherwise return an empty featureset + return mapnik::make_invalid_featureset(); } mapnik::featureset_ptr geojson_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const diff --git a/plugins/input/geojson/geojson_datasource.hpp b/plugins/input/geojson/geojson_datasource.hpp index 66f338337..a50bd9567 100644 --- a/plugins/input/geojson/geojson_datasource.hpp +++ b/plugins/input/geojson/geojson_datasource.hpp @@ -94,6 +94,7 @@ public: void initialise_index(Iterator start, Iterator end); void initialise_disk_index(std::string const& filename); private: + void initialise_descriptor(mapnik::feature_ptr const&); mapnik::datasource::datasource_t type_; mapnik::layer_descriptor desc_; std::string filename_; @@ -103,6 +104,7 @@ private: std::unique_ptr tree_; bool cache_features_ = true; bool has_disk_index_ = false; + const std::size_t num_features_to_query_ = 5; }; diff --git a/plugins/input/geojson/geojson_index_featureset.cpp b/plugins/input/geojson/geojson_index_featureset.cpp index bdf7f8a9c..4cd139899 100644 --- a/plugins/input/geojson/geojson_index_featureset.cpp +++ b/plugins/input/geojson/geojson_index_featureset.cpp @@ -24,7 +24,6 @@ #include "geojson_index_featureset.hpp" #include #include -#include #include #include #include diff --git a/plugins/input/geojson/geojson_memory_index_featureset.cpp b/plugins/input/geojson/geojson_memory_index_featureset.cpp index 61c5053b6..32b851373 100644 --- a/plugins/input/geojson/geojson_memory_index_featureset.cpp +++ b/plugins/input/geojson/geojson_memory_index_featureset.cpp @@ -23,7 +23,6 @@ // mapnik #include #include -#include #include #include #include diff --git a/plugins/input/ogr/ogr_converter.cpp b/plugins/input/ogr/ogr_converter.cpp index f2eb60294..207c0e1e4 100644 --- a/plugins/input/ogr/ogr_converter.cpp +++ b/plugins/input/ogr/ogr_converter.cpp @@ -25,9 +25,12 @@ #include // ogr +#pragma GCC diagnostic push +#include #include "ogr_converter.hpp" #include #include +#pragma GCC diagnostic pop mapnik::geometry::geometry ogr_converter::convert_geometry(OGRGeometry* ogr_geom) { diff --git a/plugins/input/ogr/ogr_datasource.cpp b/plugins/input/ogr/ogr_datasource.cpp index 41c0ebbe6..706a376e3 100644 --- a/plugins/input/ogr/ogr_datasource.cpp +++ b/plugins/input/ogr/ogr_datasource.cpp @@ -59,6 +59,16 @@ using mapnik::datasource_exception; using mapnik::filter_in_box; using mapnik::filter_at_point; +static std::once_flag once_flag; + +extern "C" MAPNIK_EXP void on_plugin_load() +{ + // initialize ogr formats + // NOTE: in GDAL >= 2.0 this is the same as GDALAllRegister() + std::call_once(once_flag,[](){ + OGRRegisterAll(); + }); +} ogr_datasource::ogr_datasource(parameters const& params) : datasource(params), @@ -87,10 +97,6 @@ void ogr_datasource::init(mapnik::parameters const& params) mapnik::progress_timer __stats__(std::clog, "ogr_datasource::init"); #endif - // initialize ogr formats - // NOTE: in GDAL >= 2.0 this is the same as GDALAllRegister() - OGRRegisterAll(); - boost::optional file = params.get("file"); boost::optional string = params.get("string"); if (!string) string = params.get("inline"); @@ -371,7 +377,7 @@ void ogr_datasource::init(mapnik::parameters const& params) } mapnik::parameters & extra_params = desc_.get_extra_parameters(); OGRSpatialReference * srs_ref = layer->GetSpatialRef(); - char * srs_output = NULL; + char * srs_output = nullptr; if (srs_ref && srs_ref->exportToProj4( &srs_output ) == OGRERR_NONE ) { extra_params["proj4"] = mapnik::util::trim_copy(srs_output); } @@ -554,7 +560,7 @@ featureset_ptr ogr_datasource::features(query const& q) const } } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } featureset_ptr ogr_datasource::features_at_point(coord2d const& pt, double tol) const @@ -597,5 +603,5 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt, double tol) } } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } diff --git a/plugins/input/pgraster/build.py b/plugins/input/pgraster/build.py index 7b859ee5b..7d120e482 100644 --- a/plugins/input/pgraster/build.py +++ b/plugins/input/pgraster/build.py @@ -60,8 +60,7 @@ if env['PLUGIN_LINKING'] == 'shared': SHLIBPREFIX='', SHLIBSUFFIX='.input', source=plugin_sources, - LIBS=libraries, - LINKFLAGS=env['CUSTOM_LDFLAGS']) + LIBS=libraries) # if the plugin links to libmapnik ensure it is built first Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) diff --git a/plugins/input/pgraster/pgraster_datasource.cpp b/plugins/input/pgraster/pgraster_datasource.cpp index 451c74e52..e6eddf758 100644 --- a/plugins/input/pgraster/pgraster_datasource.cpp +++ b/plugins/input/pgraster/pgraster_datasource.cpp @@ -257,7 +257,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params) if (srid_ == 0) { const char* srid_c = rs->getValue("srid"); - if (srid_c != NULL) + if (srid_c != nullptr) { int result = 0; const char * end = srid_c + std::strlen(srid_c); @@ -274,7 +274,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params) } else { - MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: no response from metadata query " << s.str(); + MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: no response from metadata query " << s.str(); } rs->close(); } @@ -297,7 +297,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params) if (rs->next()) { const char* srid_c = rs->getValue("srid"); - if (srid_c != NULL) + if (srid_c != nullptr) { int result = 0; const char * end = srid_c + std::strlen(srid_c); @@ -878,9 +878,10 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process std::string table_with_bbox; std::string col = geometryColumn_; - if ( use_overviews_ ) { - std::string sch = schema_; - std::string tab = mapnik::sql_utils::unquote_double(raster_table_); + if ( use_overviews_ && !overviews_.empty()) { + std::string sch = overviews_[0].schema; + std::string tab = overviews_[0].table; + col = overviews_[0].column; const double scale = std::min(px_gw, px_gh); std::vector::const_reverse_iterator i; for (i=overviews_.rbegin(); i!=overviews_.rend(); ++i) { @@ -997,7 +998,7 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } @@ -1010,7 +1011,7 @@ featureset_ptr pgraster_datasource::features_at_point(coord2d const& pt, double if (pool) { shared_ptr conn = pool->borrowObject(); - if (!conn) return featureset_ptr(); + if (!conn) return mapnik::make_invalid_featureset(); if (conn->isOK()) { @@ -1081,7 +1082,7 @@ featureset_ptr pgraster_datasource::features_at_point(coord2d const& pt, double } } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } box2d pgraster_datasource::envelope() const diff --git a/plugins/input/pgraster/pgraster_wkb_reader.cpp b/plugins/input/pgraster/pgraster_wkb_reader.cpp index 87f71c093..4a9fd1c8f 100644 --- a/plugins/input/pgraster/pgraster_wkb_reader.cpp +++ b/plugins/input/pgraster/pgraster_wkb_reader.cpp @@ -66,7 +66,7 @@ read_uint16(const uint8_t** from, uint8_t littleEndian) { /* int16_t read_int16(const uint8_t** from, uint8_t littleEndian) { - assert(NULL != from); + assert(nullptr != from); return read_uint16(from, littleEndian); } @@ -183,17 +183,16 @@ mapnik::raster_ptr read_data_band(mapnik::box2d const& bbox, { mapnik::image_gray32f image(width, height); float* data = image.data(); - double val; - val = reader(); // nodata value, need to read anyway + double nodataval = reader(); for (int y=0; y(bbox, image, 1.0); - if ( hasnodata ) raster->set_nodata(val); + if ( hasnodata ) raster->set_nodata(nodataval); return raster; } @@ -270,15 +269,13 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d const& bbox, image.set(0xffffffff); - int val; - int nodataval; uint8_t * data = image.bytes(); int ps = 4; // sizeof(image::pixel_type) int off; - nodataval = reader(); // nodata value, need to read anyway + int nodataval = reader(); for (int y=0; y 255 ) val = 255; @@ -298,7 +295,7 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d const& bbox, } } mapnik::raster_ptr raster = std::make_shared(bbox, image, 1.0); - if ( hasnodata ) raster->set_nodata(val); + if ( hasnodata ) raster->set_nodata(nodataval); return raster; } diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index d95aa3392..10ce521d0 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -88,6 +88,17 @@ postgis_datasource::postgis_datasource(parameters const& params) extent_from_subquery_(*params.get("extent_from_subquery", false)), max_async_connections_(*params_.get("max_async_connection", 1)), asynchronous_request_(false), + twkb_encoding_(false), + twkb_rounding_adjustment_(*params_.get("twkb_rounding_adjustment", 0.0)), + simplify_snap_ratio_(*params_.get("simplify_snap_ratio", 1.0/40.0)), + // 1/20 of pixel seems to be a good compromise to avoid + // drop of collapsed polygons. + // See https://github.com/mapnik/mapnik/issues/1639 + // See http://trac.osgeo.org/postgis/ticket/2093 + simplify_dp_ratio_(*params_.get("simplify_dp_ratio", 1.0/20.0)), + simplify_prefilter_(*params_.get("simplify_prefilter", 0.0)), + simplify_dp_preserve_(false), + simplify_clip_resolution_(*params_.get("simplify_clip_resolution", 0.0)), // TODO - use for known tokens too: "(@\\w+|!\\w+!)" pattern_(boost::regex("(@\\w+)",boost::regex::normal | boost::regbase::icase)), // params below are for testing purposes only and may be removed at any time @@ -130,6 +141,12 @@ postgis_datasource::postgis_datasource(parameters const& params) boost::optional simplify_opt = params.get("simplify_geometries", false); simplify_geometries_ = simplify_opt && *simplify_opt; + boost::optional twkb_opt = params.get("twkb_encoding", false); + twkb_encoding_ = twkb_opt && *twkb_opt; + + boost::optional simplify_preserve_opt = params.get("simplify_dp_preserve", false); + simplify_dp_preserve_ = simplify_preserve_opt && *simplify_preserve_opt; + ConnectionManager::instance().registerPool(creator_, *initial_size, pool_max_size_); CnxPool_ptr pool = ConnectionManager::instance().getPool(creator_.id()); if (pool) @@ -462,7 +479,7 @@ postgis_datasource::postgis_datasource(parameters const& params) // Finally, add unique metadata to layer descriptor mapnik::parameters & extra_params = desc_.get_extra_parameters(); // explicitly make copies of values due to https://github.com/mapnik/mapnik/issues/2651 - extra_params["srid"] = srid_; + extra_params["srid"] = mapnik::value_integer(srid_); if (!key_field_.empty()) { extra_params["key_field"] = key_field_; @@ -794,25 +811,91 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo const double px_gw = 1.0 / std::get<0>(q.resolution()); const double px_gh = 1.0 / std::get<1>(q.resolution()); + const double px_sz = std::min(px_gw, px_gh); - s << "SELECT ST_AsBinary("; + if (twkb_encoding_) + { + // This will only work against PostGIS 2.2, or a back-patched version + // that has (a) a ST_Simplify with a "preserve collapsed" flag and + // (b) a ST_RemoveRepeatedPoints with a tolerance parameter and + // (c) a ST_AsTWKB implementation - if (simplify_geometries_) { - s << "ST_Simplify("; + // What number of decimals of rounding does the pixel size imply? + const int twkb_rounding = -1 * std::lround(log10(px_sz) + twkb_rounding_adjustment_) + 1; + // And what's that in map units? + const double twkb_tolerance = pow(10.0, -1.0 * twkb_rounding); + + s << "SELECT ST_AsTWKB("; + s << "ST_Simplify("; + s << "ST_RemoveRepeatedPoints("; + + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "ST_ClipByBox2D("; + } + s << "\"" << geometryColumn_ << "\""; + + // ! ST_ClipByBox2D() + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "," << sql_bbox(box) << ")"; + } + + // ! ST_RemoveRepeatedPoints() + s << "," << twkb_tolerance << ")"; + // ! ST_Simplify(), with parameter to keep collapsed geometries + s << "," << twkb_tolerance << ",true)"; + // ! ST_TWKB() + s << "," << twkb_rounding << ") AS geom"; } + else + { + s << "SELECT ST_AsBinary("; + if (simplify_geometries_) + { + s << "ST_Simplify("; + } + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "ST_ClipByBox2D("; + } + if (simplify_geometries_ && simplify_snap_ratio_ > 0.0) + { + s<< "ST_SnapToGrid("; + } - s << "\"" << geometryColumn_ << "\""; + // Geometry column! + s << "\"" << geometryColumn_ << "\""; - if (simplify_geometries_) { - // 1/20 of pixel seems to be a good compromise to avoid - // drop of collapsed polygons. - // See https://github.com/mapnik/mapnik/issues/1639 - const double tolerance = std::min(px_gw, px_gh) / 20.0; - s << ", " << tolerance << ")"; + // ! ST_SnapToGrid() + if (simplify_geometries_ && simplify_snap_ratio_ > 0.0) + { + const double tolerance = px_sz * simplify_snap_ratio_; + s << "," << tolerance << ")"; + } + + // ! ST_ClipByBox2D() + if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz) + { + s << "," << sql_bbox(box) << ")"; + } + + // ! ST_Simplify() + if (simplify_geometries_) + { + const double tolerance = px_sz * simplify_dp_ratio_; + s << ", " << tolerance; + // Add parameter to ST_Simplify to keep collapsed geometries + if (simplify_dp_preserve_) + { + s << ", true"; + } + s << ")"; + } + + // ! ST_AsBinary() + s << ") AS geom"; } - - s << ") AS geom"; - mapnik::context_ptr ctx = std::make_shared(); std::set const& props = q.property_names(); std::set::const_iterator pos = props.begin(); @@ -854,11 +937,12 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo } std::shared_ptr rs = get_resultset(conn, s.str(), pool, proc_ctx); - return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), key_field_as_attribute_); + return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), + key_field_as_attribute_, twkb_encoding_); } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } @@ -871,7 +955,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t if (pool) { shared_ptr conn = pool->borrowObject(); - if (!conn) return featureset_ptr(); + if (!conn) return mapnik::make_invalid_featureset(); if (conn->isOK()) { @@ -941,11 +1025,12 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t } std::shared_ptr rs = get_resultset(conn, s.str(), pool); - return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), key_field_as_attribute_); + return std::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty(), + key_field_as_attribute_, twkb_encoding_); } } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } box2d postgis_datasource::envelope() const diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index 2f5d24f47..80ba89495 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -119,6 +119,13 @@ private: bool estimate_extent_; int max_async_connections_; bool asynchronous_request_; + bool twkb_encoding_; + mapnik::value_double twkb_rounding_adjustment_; + mapnik::value_double simplify_snap_ratio_; + mapnik::value_double simplify_dp_ratio_; + mapnik::value_double simplify_prefilter_; + bool simplify_dp_preserve_; + mapnik::value_double simplify_clip_resolution_; boost::regex pattern_; int intersect_min_scale_; int intersect_max_scale_; diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 6d417bef1..25e2b6b4b 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -49,14 +49,16 @@ postgis_featureset::postgis_featureset(std::shared_ptr const& rs, context_ptr const& ctx, std::string const& encoding, bool key_field, - bool key_field_as_attribute) + bool key_field_as_attribute, + bool twkb_encoding) : rs_(rs), ctx_(ctx), tr_(new transcoder(encoding)), totalGeomSize_(0), feature_id_(1), key_field_(key_field), - key_field_as_attribute_(key_field_as_attribute) + key_field_as_attribute_(key_field_as_attribute), + twkb_encoding_(twkb_encoding) { } @@ -123,8 +125,14 @@ feature_ptr postgis_featureset::next() int size = rs_->getFieldLength(0); const char *data = rs_->getValue(0); - mapnik::geometry::geometry geometry = geometry_utils::from_wkb(data, size); - feature->set_geometry(std::move(geometry)); + if (twkb_encoding_ ) + { + feature->set_geometry(geometry_utils::from_twkb(data, size)); + } + else + { + feature->set_geometry(geometry_utils::from_wkb(data, size)); + } totalGeomSize_ += size; unsigned num_attrs = ctx_->size() + 1; diff --git a/plugins/input/postgis/postgis_featureset.hpp b/plugins/input/postgis/postgis_featureset.hpp index 4984ec968..9ef8cb392 100644 --- a/plugins/input/postgis/postgis_featureset.hpp +++ b/plugins/input/postgis/postgis_featureset.hpp @@ -44,7 +44,8 @@ public: context_ptr const& ctx, std::string const& encoding, bool key_field, - bool key_field_as_attribute); + bool key_field_as_attribute, + bool twkb_encoding); feature_ptr next(); ~postgis_featureset(); @@ -56,6 +57,7 @@ private: mapnik::value_integer feature_id_; bool key_field_; bool key_field_as_attribute_; + bool twkb_encoding_; }; #endif // POSTGIS_FEATURESET_HPP diff --git a/plugins/input/raster/raster_datasource.cpp b/plugins/input/raster/raster_datasource.cpp index 4d8b5f99a..e059247cd 100644 --- a/plugins/input/raster/raster_datasource.cpp +++ b/plugins/input/raster/raster_datasource.cpp @@ -224,5 +224,5 @@ featureset_ptr raster_datasource::features_at_point(coord2d const&, double tol) { MAPNIK_LOG_WARN(raster) << "raster_datasource: feature_at_point not supported"; - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } diff --git a/plugins/input/shape/shape_datasource.cpp b/plugins/input/shape/shape_datasource.cpp index 644e60135..56d7a6aae 100644 --- a/plugins/input/shape/shape_datasource.cpp +++ b/plugins/input/shape/shape_datasource.cpp @@ -98,11 +98,11 @@ shape_datasource::shape_datasource(parameters const& params) mapnik::progress_timer __stats2__(std::clog, "shape_datasource::init(get_column_description)"); #endif - std::unique_ptr shape_ref = std::make_unique(shape_name_); - init(*shape_ref); - for (int i=0;idbf().num_fields();++i) + shape_io shape(shape_name_); + init(shape); + for (int i = 0; i < shape.dbf().num_fields(); ++i) { - field_descriptor const& fd = shape_ref->dbf().descriptor(i); + field_descriptor const& fd = shape.dbf().descriptor(i); std::string fld_name=fd.name_; switch (fd.type_) { diff --git a/plugins/input/shape/shape_index_featureset.cpp b/plugins/input/shape/shape_index_featureset.cpp index f91d7acf4..c4b1918d8 100644 --- a/plugins/input/shape/shape_index_featureset.cpp +++ b/plugins/input/shape/shape_index_featureset.cpp @@ -52,6 +52,9 @@ shape_index_featureset::shape_index_featureset(filterT const& filter, ctx_(std::make_shared()), shape_ptr_(std::move(shape_ptr)), tr_(new mapnik::transcoder(encoding)), + offsets_(), + itr_(), + attr_ids_(), row_limit_(row_limit), count_(0), feature_bbox_() @@ -63,12 +66,13 @@ shape_index_featureset::shape_index_featureset(filterT const& filter, if (index) { #if defined(MAPNIK_MEMORY_MAPPED_FILE) - mapnik::util::spatial_index::query(filter, index->file(), offsets_); + mapnik::util::spatial_index::query(filter, index->file(), offsets_); #else - mapnik::util::spatial_index::query(filter, index->file(), offsets_); + mapnik::util::spatial_index::query(filter, index->file(), offsets_); #endif } - std::sort(offsets_.begin(), offsets_.end()); + std::sort(offsets_.begin(), offsets_.end(), [](mapnik::detail::node const& n0, mapnik::detail::node const& n1) + {return n0.offset != n1.offset ? n0.offset < n1.offset : n0.start < n1.start;}); MAPNIK_LOG_DEBUG(shape) << "shape_index_featureset: Query size=" << offsets_.size(); itr_ = offsets_.begin(); } @@ -83,7 +87,14 @@ feature_ptr shape_index_featureset::next() while ( itr_ != offsets_.end()) { - shape_ptr_->move_to(*itr_++); + int offset = itr_->offset; + shape_ptr_->move_to(offset); + std::vector> parts; + while (itr_ != offsets_.end() && itr_->offset == offset) + { + if (itr_->start!= -1) parts.emplace_back(itr_->start, itr_->end); + ++itr_; + } mapnik::value_integer feature_id = shape_ptr_->id(); shape_file::record_type record(shape_ptr_->reclength_ * 2); shape_ptr_->shp().read_record(record); @@ -124,7 +135,8 @@ feature_ptr shape_index_featureset::next() { shape_io::read_bbox(record, feature_bbox_); if (!filter_.pass(feature_bbox_)) continue; - feature->set_geometry(shape_io::read_polyline(record)); + if (parts.size() < 2) feature->set_geometry(shape_io::read_polyline(record)); + else feature->set_geometry(shape_io::read_polyline_parts(record, parts)); break; } case shape_io::shape_polygon: @@ -133,7 +145,8 @@ feature_ptr shape_index_featureset::next() { shape_io::read_bbox(record, feature_bbox_); if (!filter_.pass(feature_bbox_)) continue; - feature->set_geometry(shape_io::read_polygon(record)); + if (parts.size() < 2) feature->set_geometry(shape_io::read_polygon(record)); + else feature->set_geometry(shape_io::read_polygon_parts(record, parts)); break; } default : diff --git a/plugins/input/shape/shape_index_featureset.hpp b/plugins/input/shape/shape_index_featureset.hpp index 80c8fa681..d104e0f20 100644 --- a/plugins/input/shape/shape_index_featureset.hpp +++ b/plugins/input/shape/shape_index_featureset.hpp @@ -45,6 +45,21 @@ using mapnik::box2d; using mapnik::feature_ptr; using mapnik::context_ptr; +namespace mapnik { namespace detail +{ +struct node +{ + node() = default; + node(int offset_, int start_, int end_) + : offset(offset_), + start(start_), + end(end_) {} + int offset; + int start; + int end; +}; +}} // ns + template class shape_index_featureset : public Featureset { @@ -63,8 +78,8 @@ private: context_ptr ctx_; std::unique_ptr shape_ptr_; const std::unique_ptr tr_; - std::vector offsets_; - std::vector::iterator itr_; + std::vector offsets_; + std::vector::iterator itr_; std::vector attr_ids_; mapnik::value_integer row_limit_; mutable int count_; diff --git a/plugins/input/shape/shape_io.cpp b/plugins/input/shape/shape_io.cpp index bb9d78334..5dd591996 100644 --- a/plugins/input/shape/shape_io.cpp +++ b/plugins/input/shape/shape_io.cpp @@ -125,6 +125,7 @@ mapnik::geometry::geometry shape_io::read_polyline(shape_file::record_ty std::for_each(parts.begin(), parts.end(), [&](int & part) { part = record.read_ndr_integer();}); int start, end; mapnik::geometry::multi_line_string multi_line; + multi_line.reserve(num_parts); for (int k = 0; k < num_parts; ++k) { start = parts[k]; @@ -152,6 +153,34 @@ mapnik::geometry::geometry shape_io::read_polyline(shape_file::record_ty return geom; } +mapnik::geometry::geometry shape_io::read_polyline_parts(shape_file::record_type & record, std::vector> const& parts) +{ + mapnik::geometry::geometry geom; // default empty + int total_num_parts = record.read_ndr_integer(); + int num_parts = parts.size(); + mapnik::geometry::multi_line_string multi_line; + multi_line.reserve(num_parts); + for (int k = 0; k < num_parts; ++k) + { + int start = parts[k].first; + int end = parts[k].second; + unsigned pos = 4 + 32 + 8 + 4 * total_num_parts + start * 16; + record.set_pos(pos); + + mapnik::geometry::line_string line; + line.reserve(end - start); + for (int j = start; j < end; ++j) + { + double x = record.read_double(); + double y = record.read_double(); + line.emplace_back(x, y); + } + multi_line.push_back(std::move(line)); + } + geom = std::move(multi_line); + return geom; +} + mapnik::geometry::geometry shape_io::read_polygon(shape_file::record_type & record) { @@ -207,3 +236,53 @@ mapnik::geometry::geometry shape_io::read_polygon(shape_file::record_typ mapnik::geometry::correct(geom); return geom; } + +mapnik::geometry::geometry shape_io::read_polygon_parts(shape_file::record_type & record, std::vector> const& parts) +{ + mapnik::geometry::geometry geom; // default empty + int total_num_parts = record.read_ndr_integer(); + mapnik::geometry::polygon poly; + mapnik::geometry::multi_polygon multi_poly; + int num_parts = parts.size(); + for (int k = 0; k < num_parts; ++k) + { + int start = parts[k].first; + int end = parts[k].second; + unsigned pos = 4 + 32 + 8 + 4 * total_num_parts + start * 16; + record.set_pos(pos); + mapnik::geometry::linear_ring ring; + ring.reserve(end - start); + for (int j = start; j < end; ++j) + { + double x = record.read_double(); + double y = record.read_double(); + ring.emplace_back(x, y); + } + if (k == 0) + { + poly.set_exterior_ring(std::move(ring)); + } + else if (mapnik::util::is_clockwise(ring)) + { + multi_poly.emplace_back(std::move(poly)); + poly.interior_rings.clear(); + poly.set_exterior_ring(std::move(ring)); + } + else + { + poly.add_hole(std::move(ring)); + } + } + + if (multi_poly.size() > 0) // multi + { + multi_poly.emplace_back(std::move(poly)); + geom = std::move(multi_poly); + } + else + { + geom = std::move(poly); + } + mapnik::geometry::correct(geom); + return geom; +} diff --git a/plugins/input/shape/shape_io.hpp b/plugins/input/shape/shape_io.hpp index ab28f9999..1828ebd54 100644 --- a/plugins/input/shape/shape_io.hpp +++ b/plugins/input/shape/shape_io.hpp @@ -23,16 +23,16 @@ #ifndef SHAPE_IO_HPP #define SHAPE_IO_HPP +// stl +#include +#include // mapnik #include #include - +#include // boost #include - -// stl -#include - +// #include "dbfile.hpp" #include "shapefile.hpp" @@ -72,7 +72,13 @@ public: inline bool has_index() const { - return (index_ && index_->is_open()); + if (index_ && index_->is_open()) + { + bool status = mapnik::util::check_spatial_index(index_->file()); + index_->seek(0);// rewind + return status; + } + return false; } inline int id() const { return id_;} @@ -80,6 +86,8 @@ public: static void read_bbox(shape_file::record_type & record, mapnik::box2d & bbox); static mapnik::geometry::geometry read_polyline(shape_file::record_type & record); static mapnik::geometry::geometry read_polygon(shape_file::record_type & record); + static mapnik::geometry::geometry read_polyline_parts(shape_file::record_type & record,std::vector> const& parts); + static mapnik::geometry::geometry read_polygon_parts(shape_file::record_type & record, std::vector> const& parts); shapeType type_; shape_file shp_; diff --git a/plugins/input/shape/shapefile.hpp b/plugins/input/shape/shapefile.hpp index 664dc8852..15e5c7757 100644 --- a/plugins/input/shape/shapefile.hpp +++ b/plugins/input/shape/shapefile.hpp @@ -105,6 +105,11 @@ struct shape_record pos += n; } + void set_pos(unsigned pos_) + { + pos = pos_; + } + int read_ndr_integer() { std::int32_t val; diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 939d9d319..28add6453 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -551,7 +551,7 @@ featureset_ptr sqlite_datasource::features(query const& q) const using_subquery_); } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt, double tol) const @@ -631,5 +631,5 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt, double to using_subquery_); } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } diff --git a/plugins/input/topojson/topojson_datasource.cpp b/plugins/input/topojson/topojson_datasource.cpp index f9ba8ecc9..2cfad1fb8 100644 --- a/plugins/input/topojson/topojson_datasource.cpp +++ b/plugins/input/topojson/topojson_datasource.cpp @@ -66,18 +66,9 @@ struct attr_value_converter { return mapnik::Boolean; } - - mapnik::eAttributeType operator() (std::string const& /*val*/) const - { - return mapnik::String; - } - - mapnik::eAttributeType operator() (mapnik::value_unicode_string const& /*val*/) const - { - return mapnik::String; - } - - mapnik::eAttributeType operator() (mapnik::value_null const& /*val*/) const + // string, object, array + template + mapnik::eAttributeType operator() (T const& /*val*/) const { return mapnik::String; } @@ -109,6 +100,11 @@ struct geometry_type_visitor { return static_cast(mapnik::datasource_geometry_t::Polygon); } + template + int operator() (T const& ) const + { + return 0; + } }; struct collect_attributes_visitor @@ -117,6 +113,9 @@ struct collect_attributes_visitor collect_attributes_visitor(mapnik::layer_descriptor & desc): desc_(desc) {} + // no-op + void operator() (mapnik::topojson::empty) {} + // template void operator() (GeomType const& g) { @@ -166,7 +165,7 @@ topojson_datasource::topojson_datasource(parameters const& params) else { mapnik::util::file file(filename_); - if (!file.open()) + if (!file) { throw mapnik::datasource_exception("TopoJSON Plugin: could not open: '" + filename_ + "'"); } @@ -285,7 +284,7 @@ mapnik::featureset_ptr topojson_datasource::features(mapnik::query const& q) con } } // otherwise return an empty featureset pointer - return mapnik::featureset_ptr(); + return mapnik::make_invalid_featureset(); } mapnik::featureset_ptr topojson_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const diff --git a/plugins/input/topojson/topojson_featureset.cpp b/plugins/input/topojson/topojson_featureset.cpp index 9e7c23ee4..36dbdf9db 100644 --- a/plugins/input/topojson/topojson_featureset.cpp +++ b/plugins/input/topojson/topojson_featureset.cpp @@ -21,13 +21,8 @@ *****************************************************************************/ // mapnik -#include -#include #include -#include -#include -#include - +#include // stl #include #include @@ -40,334 +35,6 @@ #include "topojson_featureset.hpp" -namespace mapnik { namespace topojson { - -struct attribute_value_visitor - -{ -public: - attribute_value_visitor(mapnik::transcoder const& tr) - : tr_(tr) {} - - mapnik::value operator()(std::string const& val) const - { - return mapnik::value(tr_.transcode(val.c_str())); - } - - template - mapnik::value operator()(T const& val) const - { - return mapnik::value(val); - } - - mapnik::transcoder const& tr_; -}; - -template -void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::transcoder const& tr) -{ - if ( geom.props) - { - for (auto const& p : *geom.props) - { - feature.put_new(std::get<0>(p), mapnik::util::apply_visitor(attribute_value_visitor(tr),std::get<1>(p))); - } - } -} - -template -struct feature_generator -{ - feature_generator(Context & ctx, mapnik::transcoder const& tr, topology const& topo, std::size_t feature_id) - : ctx_(ctx), - tr_(tr), - topo_(topo), - num_arcs_(topo.arcs.size()), - feature_id_(feature_id) {} - - feature_ptr operator() (point const& pt) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - double x = pt.coord.x; - double y = pt.coord.y; - if (topo_.tr) - { - x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - mapnik::geometry::point point(x, y); - feature->set_geometry(std::move(point)); - assign_properties(*feature, pt, tr_); - return feature; - } - - feature_ptr operator() (multi_point const& multi_pt) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - mapnik::geometry::multi_point multi_point; - multi_point.reserve(multi_pt.points.size()); - for (auto const& pt : multi_pt.points) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = x * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = y * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - multi_point.add_coord(x, y); - } - feature->set_geometry(std::move(multi_point)); - assign_properties(*feature, multi_pt, tr_); - return feature; - } - - feature_ptr operator() (linestring const& line) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - index_type index = line.ring; - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - auto const& arcs = topo_.arcs[arc_index]; - double px = 0, py = 0; - mapnik::geometry::line_string line_string; - line_string.reserve(arcs.coordinates.size()); - - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - line_string.add_coord(x,y); - } - feature->set_geometry(std::move(line_string)); - assign_properties(*feature, line, tr_); - } - } - return feature; - } - - feature_ptr operator() (multi_linestring const& multi_line) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - mapnik::geometry::multi_line_string multi_line_string; - bool hit = false; - multi_line_string.reserve(multi_line.rings.size()); - for (auto const& index : multi_line.rings) - { - index_type arc_index = index < 0 ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - hit = true; - double px = 0, py = 0; - mapnik::geometry::line_string line_string; - auto const& arcs = topo_.arcs[arc_index]; - line_string.reserve(arcs.coordinates.size()); - for (auto pt : arcs.coordinates) - { - double x = pt.x; - double y = pt.y; - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - line_string.add_coord(x, y); - } - multi_line_string.push_back(std::move(line_string)); - } - } - if (hit) - { - feature->set_geometry(std::move(multi_line_string)); - assign_properties(*feature, multi_line, tr_); - } - } - return feature; - } - - feature_ptr operator() (polygon const& poly) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - std::vector processed_coords; - mapnik::geometry::polygon polygon; - if (poly.rings.size() > 1) polygon.interior_rings.reserve(poly.rings.size() - 1); - bool first = true; - bool hit = false; - for (auto const& ring : poly.rings) - { - mapnik::geometry::linear_ring linear_ring; - for (auto const& index : ring) - { - double px = 0, py = 0; - bool reverse = index < 0; - index_type arc_index = reverse ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - hit = true; - auto const& arcs = topo_.arcs[arc_index]; - auto const& coords = arcs.coordinates; - processed_coords.clear(); - processed_coords.reserve(coords.size()); - for (auto const& pt : coords ) - { - double x = pt.x; - double y = pt.y; - - if (topo_.tr) - { - transform const& tr = *topo_.tr; - x = (px += x) * tr.scale_x + tr.translate_x; - y = (py += y) * tr.scale_y + tr.translate_y; - } - processed_coords.emplace_back(coordinate{x,y}); - } - - if (reverse) - { - for (auto const& c : processed_coords | boost::adaptors::reversed) - { - linear_ring.emplace_back(c.x, c.y); - } - } - else - { - for (auto const& c : processed_coords) - { - linear_ring.emplace_back(c.x, c.y); - } - } - } - } - if (first) - { - first = false; - polygon.set_exterior_ring(std::move(linear_ring)); - } - else - { - polygon.add_hole(std::move(linear_ring)); - } - } - if (hit) - { - mapnik::geometry::correct(polygon); - feature->set_geometry(std::move(polygon)); - assign_properties(*feature, poly, tr_); - } - } - return feature; - } - - feature_ptr operator() (multi_polygon const& multi_poly) const - { - mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_id_)); - if (num_arcs_ > 0) - { - std::vector processed_coords; - mapnik::geometry::multi_polygon multi_polygon; - multi_polygon.reserve(multi_poly.polygons.size()); - bool hit = false; - for (auto const& poly : multi_poly.polygons) - { - bool first = true; - mapnik::geometry::polygon polygon; - if (poly.size() > 1) polygon.interior_rings.reserve(poly.size() - 1); - - for (auto const& ring : poly) - { - mapnik::geometry::linear_ring linear_ring; - for (auto const& index : ring) - { - double px = 0, py = 0; - bool reverse = index < 0; - index_type arc_index = reverse ? std::abs(index) - 1 : index; - if (arc_index >= 0 && arc_index < static_cast(num_arcs_)) - { - hit = true; - auto const& arcs = topo_.arcs[arc_index]; - auto const& coords = arcs.coordinates; - processed_coords.clear(); - processed_coords.reserve(coords.size()); - for (auto const& pt : coords ) - { - double x = pt.x; - double y = pt.y; - - if (topo_.tr) - { - x = (px += x) * (*topo_.tr).scale_x + (*topo_.tr).translate_x; - y = (py += y) * (*topo_.tr).scale_y + (*topo_.tr).translate_y; - } - processed_coords.emplace_back(coordinate{x,y}); - } - - using namespace boost::adaptors; - - if (reverse) - { - for (auto const& c : (processed_coords | reversed)) - { - linear_ring.add_coord(c.x, c.y); - } - } - else - { - for (auto const& c : processed_coords) - { - linear_ring.add_coord(c.x, c.y); - } - } - } - } - if (first) - { - first = false; - polygon.set_exterior_ring(std::move(linear_ring)); - } - else - { - polygon.add_hole(std::move(linear_ring)); - } - } - multi_polygon.push_back(std::move(polygon)); - } - if (hit) - { - mapnik::geometry::correct(multi_polygon); - feature->set_geometry(std::move(multi_polygon)); - assign_properties(*feature, multi_poly, tr_); - } - } - return feature; - } - - template - feature_ptr operator() (T const& ) const - { - return feature_ptr(); - } - - Context & ctx_; - mapnik::transcoder const& tr_; - topology const& topo_; - std::size_t num_arcs_; - std::size_t feature_id_; -}; - -}} - topojson_featureset::topojson_featureset(mapnik::topojson::topology const& topo, mapnik::transcoder const& tr, array_type && index_array) diff --git a/scons/scons-LICENSE b/scons/scons-LICENSE index bd5632d16..060ceaf25 100644 --- a/scons/scons-LICENSE +++ b/scons/scons-LICENSE @@ -3,7 +3,7 @@ This copyright and license do not apply to any other software with which this software may have been included. -Copyright (c) 2001 - 2015 The SCons Foundation +Copyright (c) 2001 - 2016 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/scons/scons-README b/scons/scons-README index 40a1a194d..7717b9bd2 100644 --- a/scons/scons-README +++ b/scons/scons-README @@ -1,4 +1,4 @@ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation SCons - a software construction tool diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_collections.py b/scons/scons-local-2.4.1/SCons/compat/_scons_collections.py deleted file mode 100644 index 4a0d96b9e..000000000 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_collections.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2001 - 2015 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__doc__ = """ -collections compatibility module for older (pre-2.4) Python versions - -This does not not NOT (repeat, *NOT*) provide complete collections -functionality. It only wraps the portions of collections functionality -used by SCons, in an interface that looks enough like collections for -our purposes. -""" - -__revision__ = "src/engine/SCons/compat/_scons_collections.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" - -# Use exec to hide old names from fixers. -exec("""if True: - from UserDict import UserDict - from UserList import UserList - from UserString import UserString""") - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_sets.py b/scons/scons-local-2.4.1/SCons/compat/_scons_sets.py deleted file mode 100644 index 0fde9941d..000000000 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_sets.py +++ /dev/null @@ -1,563 +0,0 @@ -"""Classes to represent arbitrary sets (including sets of sets). - -This module implements sets using dictionaries whose values are -ignored. The usual operations (union, intersection, deletion, etc.) -are provided as both methods and operators. - -Important: sets are not sequences! While they support 'x in s', -'len(s)', and 'for x in s', none of those operations are unique for -sequences; for example, mappings support all three as well. The -characteristic operation for sequences is subscripting with small -integers: s[i], for i in range(len(s)). Sets don't support -subscripting at all. Also, sequences allow multiple occurrences and -their elements have a definite order; sets on the other hand don't -record multiple occurrences and don't remember the order of element -insertion (which is why they don't support s[i]). - -The following classes are provided: - -BaseSet -- All the operations common to both mutable and immutable - sets. This is an abstract class, not meant to be directly - instantiated. - -Set -- Mutable sets, subclass of BaseSet; not hashable. - -ImmutableSet -- Immutable sets, subclass of BaseSet; hashable. - An iterable argument is mandatory to create an ImmutableSet. - -_TemporarilyImmutableSet -- A wrapper around a Set, hashable, - giving the same hash value as the immutable set equivalent - would have. Do not use this class directly. - -Only hashable objects can be added to a Set. In particular, you cannot -really add a Set as an element to another Set; if you try, what is -actually added is an ImmutableSet built from it (it compares equal to -the one you tried adding). - -When you ask if `x in y' where x is a Set and y is a Set or -ImmutableSet, x is wrapped into a _TemporarilyImmutableSet z, and -what's tested is actually `z in y'. - -""" - -# Code history: -# -# - Greg V. Wilson wrote the first version, using a different approach -# to the mutable/immutable problem, and inheriting from dict. -# -# - Alex Martelli modified Greg's version to implement the current -# Set/ImmutableSet approach, and make the data an attribute. -# -# - Guido van Rossum rewrote much of the code, made some API changes, -# and cleaned up the docstrings. -# -# - Raymond Hettinger added a number of speedups and other -# improvements. - -# protect this import from the fixers... -exec('from itertools import ifilterfalse as filterfalse') - -__all__ = ['BaseSet', 'Set', 'ImmutableSet'] - -class BaseSet(object): - """Common base class for mutable and immutable sets.""" - - __slots__ = ['_data'] - - # Constructor - - def __init__(self): - """This is an abstract class.""" - # Don't call this from a concrete subclass! - if self.__class__ is BaseSet: - raise TypeError("BaseSet is an abstract class. " - "Use Set or ImmutableSet.") - - # Standard protocols: __len__, __repr__, __str__, __iter__ - - def __len__(self): - """Return the number of elements of a set.""" - return len(self._data) - - def __repr__(self): - """Return string representation of a set. - - This looks like 'Set([])'. - """ - return self._repr() - - # __str__ is the same as __repr__ - __str__ = __repr__ - - def _repr(self, sort_them=False): - elements = list(self._data.keys()) - if sort_them: - elements.sort() - return '%s(%r)' % (self.__class__.__name__, elements) - - def __iter__(self): - """Return an iterator over the elements or a set. - - This is the keys iterator for the underlying dict. - """ - # Wrapping name in () prevents fixer from "fixing" this - return (self._data.iterkeys)() - - # Three-way comparison is not supported. However, because __eq__ is - # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and - # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this - # case). - - def __cmp__(self, other): - raise TypeError("can't compare sets using cmp()") - - # Equality comparisons using the underlying dicts. Mixed-type comparisons - # are allowed here, where Set == z for non-Set z always returns False, - # and Set != z always True. This allows expressions like "x in y" to - # give the expected result when y is a sequence of mixed types, not - # raising a pointless TypeError just because y contains a Set, or x is - # a Set and y contain's a non-set ("in" invokes only __eq__). - # Subtle: it would be nicer if __eq__ and __ne__ could return - # NotImplemented instead of True or False. Then the other comparand - # would get a chance to determine the result, and if the other comparand - # also returned NotImplemented then it would fall back to object address - # comparison (which would always return False for __eq__ and always - # True for __ne__). However, that doesn't work, because this type - # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented, - # Python tries __cmp__ next, and the __cmp__ here then raises TypeError. - - def __eq__(self, other): - if isinstance(other, BaseSet): - return self._data == other._data - else: - return False - - def __ne__(self, other): - if isinstance(other, BaseSet): - return self._data != other._data - else: - return True - - # Copying operations - - def copy(self): - """Return a shallow copy of a set.""" - result = self.__class__() - result._data.update(self._data) - return result - - __copy__ = copy # For the copy module - - def __deepcopy__(self, memo): - """Return a deep copy of a set; used by copy module.""" - # This pre-creates the result and inserts it in the memo - # early, in case the deep copy recurses into another reference - # to this same set. A set can't be an element of itself, but - # it can certainly contain an object that has a reference to - # itself. - from copy import deepcopy - result = self.__class__() - memo[id(self)] = result - data = result._data - value = True - for elt in self: - data[deepcopy(elt, memo)] = value - return result - - # Standard set operations: union, intersection, both differences. - # Each has an operator version (e.g. __or__, invoked with |) and a - # method version (e.g. union). - # Subtle: Each pair requires distinct code so that the outcome is - # correct when the type of other isn't suitable. For example, if - # we did "union = __or__" instead, then Set().union(3) would return - # NotImplemented instead of raising TypeError (albeit that *why* it - # raises TypeError as-is is also a bit subtle). - - def __or__(self, other): - """Return the union of two sets as a new set. - - (I.e. all elements that are in either set.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.union(other) - - def union(self, other): - """Return the union of two sets as a new set. - - (I.e. all elements that are in either set.) - """ - result = self.__class__(self) - result._update(other) - return result - - def __and__(self, other): - """Return the intersection of two sets as a new set. - - (I.e. all elements that are in both sets.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.intersection(other) - - def intersection(self, other): - """Return the intersection of two sets as a new set. - - (I.e. all elements that are in both sets.) - """ - if not isinstance(other, BaseSet): - other = Set(other) - if len(self) <= len(other): - little, big = self, other - else: - little, big = other, self - common = iter(filter(big._data.has_key, little)) - return self.__class__(common) - - def __xor__(self, other): - """Return the symmetric difference of two sets as a new set. - - (I.e. all elements that are in exactly one of the sets.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.symmetric_difference(other) - - def symmetric_difference(self, other): - """Return the symmetric difference of two sets as a new set. - - (I.e. all elements that are in exactly one of the sets.) - """ - result = self.__class__() - data = result._data - value = True - selfdata = self._data - try: - otherdata = other._data - except AttributeError: - otherdata = Set(other)._data - for elt in filterfalse(otherdata.has_key, selfdata): - data[elt] = value - for elt in filterfalse(selfdata.has_key, otherdata): - data[elt] = value - return result - - def __sub__(self, other): - """Return the difference of two sets as a new Set. - - (I.e. all elements that are in this set and not in the other.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.difference(other) - - def difference(self, other): - """Return the difference of two sets as a new Set. - - (I.e. all elements that are in this set and not in the other.) - """ - result = self.__class__() - data = result._data - try: - otherdata = other._data - except AttributeError: - otherdata = Set(other)._data - value = True - for elt in filterfalse(otherdata.has_key, self): - data[elt] = value - return result - - # Membership test - - def __contains__(self, element): - """Report whether an element is a member of a set. - - (Called in response to the expression `element in self'.) - """ - try: - return element in self._data - except TypeError: - transform = getattr(element, "__as_temporarily_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - return transform() in self._data - - # Subset and superset test - - def issubset(self, other): - """Report whether another set contains this set.""" - self._binary_sanity_check(other) - if len(self) > len(other): # Fast check for obvious cases - return False - for elt in filterfalse(other._data.has_key, self): - return False - return True - - def issuperset(self, other): - """Report whether this set contains another set.""" - self._binary_sanity_check(other) - if len(self) < len(other): # Fast check for obvious cases - return False - for elt in filterfalse(self._data.has_key, other): - return False - return True - - # Inequality comparisons using the is-subset relation. - __le__ = issubset - __ge__ = issuperset - - def __lt__(self, other): - self._binary_sanity_check(other) - return len(self) < len(other) and self.issubset(other) - - def __gt__(self, other): - self._binary_sanity_check(other) - return len(self) > len(other) and self.issuperset(other) - - # Assorted helpers - - def _binary_sanity_check(self, other): - # Check that the other argument to a binary operation is also - # a set, raising a TypeError otherwise. - if not isinstance(other, BaseSet): - raise TypeError("Binary operation only permitted between sets") - - def _compute_hash(self): - # Calculate hash code for a set by xor'ing the hash codes of - # the elements. This ensures that the hash code does not depend - # on the order in which elements are added to the set. This is - # not called __hash__ because a BaseSet should not be hashable; - # only an ImmutableSet is hashable. - result = 0 - for elt in self: - result ^= hash(elt) - return result - - def _update(self, iterable): - # The main loop for update() and the subclass __init__() methods. - data = self._data - - # Use the fast update() method when a dictionary is available. - if isinstance(iterable, BaseSet): - data.update(iterable._data) - return - - value = True - - if type(iterable) in (list, tuple, xrange): - # Optimized: we know that __iter__() and next() can't - # raise TypeError, so we can move 'try:' out of the loop. - it = iter(iterable) - while True: - try: - for element in it: - data[element] = value - return - except TypeError: - transform = getattr(element, "__as_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - data[transform()] = value - else: - # Safe: only catch TypeError where intended - for element in iterable: - try: - data[element] = value - except TypeError: - transform = getattr(element, "__as_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - data[transform()] = value - - -class ImmutableSet(BaseSet): - """Immutable set class.""" - - __slots__ = ['_hashcode'] - - # BaseSet + hashing - - def __init__(self, iterable=None): - """Construct an immutable set from an optional iterable.""" - self._hashcode = None - self._data = {} - if iterable is not None: - self._update(iterable) - - def __hash__(self): - if self._hashcode is None: - self._hashcode = self._compute_hash() - return self._hashcode - - def __getstate__(self): - return self._data, self._hashcode - - def __setstate__(self, state): - self._data, self._hashcode = state - -class Set(BaseSet): - """ Mutable set class.""" - - __slots__ = [] - - # BaseSet + operations requiring mutability; no hashing - - def __init__(self, iterable=None): - """Construct a set from an optional iterable.""" - self._data = {} - if iterable is not None: - self._update(iterable) - - def __getstate__(self): - # getstate's results are ignored if it is not - return self._data, - - def __setstate__(self, data): - self._data, = data - - def __hash__(self): - """A Set cannot be hashed.""" - # We inherit object.__hash__, so we must deny this explicitly - raise TypeError("Can't hash a Set, only an ImmutableSet.") - - # In-place union, intersection, differences. - # Subtle: The xyz_update() functions deliberately return None, - # as do all mutating operations on built-in container types. - # The __xyz__ spellings have to return self, though. - - def __ior__(self, other): - """Update a set with the union of itself and another.""" - self._binary_sanity_check(other) - self._data.update(other._data) - return self - - def union_update(self, other): - """Update a set with the union of itself and another.""" - self._update(other) - - def __iand__(self, other): - """Update a set with the intersection of itself and another.""" - self._binary_sanity_check(other) - self._data = (self & other)._data - return self - - def intersection_update(self, other): - """Update a set with the intersection of itself and another.""" - if isinstance(other, BaseSet): - self &= other - else: - self._data = (self.intersection(other))._data - - def __ixor__(self, other): - """Update a set with the symmetric difference of itself and another.""" - self._binary_sanity_check(other) - self.symmetric_difference_update(other) - return self - - def symmetric_difference_update(self, other): - """Update a set with the symmetric difference of itself and another.""" - data = self._data - value = True - if not isinstance(other, BaseSet): - other = Set(other) - if self is other: - self.clear() - for elt in other: - if elt in data: - del data[elt] - else: - data[elt] = value - - def __isub__(self, other): - """Remove all elements of another set from this set.""" - self._binary_sanity_check(other) - self.difference_update(other) - return self - - def difference_update(self, other): - """Remove all elements of another set from this set.""" - data = self._data - if not isinstance(other, BaseSet): - other = Set(other) - if self is other: - self.clear() - for elt in filter(data.has_key, other): - del data[elt] - - # Python dict-like mass mutations: update, clear - - def update(self, iterable): - """Add all values from an iterable (such as a list or file).""" - self._update(iterable) - - def clear(self): - """Remove all elements from this set.""" - self._data.clear() - - # Single-element mutations: add, remove, discard - - def add(self, element): - """Add an element to a set. - - This has no effect if the element is already present. - """ - try: - self._data[element] = True - except TypeError: - transform = getattr(element, "__as_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - self._data[transform()] = True - - def remove(self, element): - """Remove an element from a set; it must be a member. - - If the element is not a member, raise a KeyError. - """ - try: - del self._data[element] - except TypeError: - transform = getattr(element, "__as_temporarily_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - del self._data[transform()] - - def discard(self, element): - """Remove an element from a set if it is a member. - - If the element is not a member, do nothing. - """ - try: - self.remove(element) - except KeyError: - pass - - def pop(self): - """Remove and return an arbitrary set element.""" - return self._data.popitem()[0] - - def __as_immutable__(self): - # Return a copy of self as an immutable set - return ImmutableSet(self) - - def __as_temporarily_immutable__(self): - # Return self wrapped in a temporarily immutable set - return _TemporarilyImmutableSet(self) - - -class _TemporarilyImmutableSet(BaseSet): - # Wrap a mutable set as if it was temporarily immutable. - # This only supplies hashing and equality comparisons. - - def __init__(self, set): - self._set = set - self._data = set._data # Needed by ImmutableSet.__eq__() - - def __hash__(self): - return self._set._compute_hash() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_subprocess.py b/scons/scons-local-2.4.1/SCons/compat/_scons_subprocess.py deleted file mode 100644 index eebe53d34..000000000 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_subprocess.py +++ /dev/null @@ -1,1281 +0,0 @@ -# subprocess - Subprocesses with accessible I/O streams -# -# For more information about this module, see PEP 324. -# -# This module should remain compatible with Python 2.2, see PEP 291. -# -# Copyright (c) 2003-2005 by Peter Astrand -# -# Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/2.4/license for licensing details. - -r"""subprocess - Subprocesses with accessible I/O streams - -This module allows you to spawn processes, connect to their -input/output/error pipes, and obtain their return codes. This module -intends to replace several other, older modules and functions, like: - -os.system -os.spawn* -os.popen* -popen2.* -commands.* - -Information about how the subprocess module can be used to replace these -modules and functions can be found below. - - - -Using the subprocess module -=========================== -This module defines one class called Popen: - -class Popen(args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0): - - -Arguments are: - -args should be a string, or a sequence of program arguments. The -program to execute is normally the first item in the args sequence or -string, but can be explicitly set by using the executable argument. - -On UNIX, with shell=False (default): In this case, the Popen class -uses os.execvp() to execute the child program. args should normally -be a sequence. A string will be treated as a sequence with the string -as the only item (the program to execute). - -On UNIX, with shell=True: If args is a string, it specifies the -command string to execute through the shell. If args is a sequence, -the first item specifies the command string, and any additional items -will be treated as additional shell arguments. - -On Windows: the Popen class uses CreateProcess() to execute the child -program, which operates on strings. If args is a sequence, it will be -converted to a string using the list2cmdline method. Please note that -not all MS Windows applications interpret the command line the same -way: The list2cmdline is designed for applications using the same -rules as the MS C runtime. - -bufsize, if given, has the same meaning as the corresponding argument -to the built-in open() function: 0 means unbuffered, 1 means line -buffered, any other positive value means use a buffer of -(approximately) that size. A negative bufsize means to use the system -default, which usually means fully buffered. The default value for -bufsize is 0 (unbuffered). - -stdin, stdout and stderr specify the executed programs' standard -input, standard output and standard error file handles, respectively. -Valid values are PIPE, an existing file descriptor (a positive -integer), an existing file object, and None. PIPE indicates that a -new pipe to the child should be created. With None, no redirection -will occur; the child's file handles will be inherited from the -parent. Additionally, stderr can be STDOUT, which indicates that the -stderr data from the applications should be captured into the same -file handle as for stdout. - -If preexec_fn is set to a callable object, this object will be called -in the child process just before the child is executed. - -If close_fds is true, all file descriptors except 0, 1 and 2 will be -closed before the child process is executed. - -if shell is true, the specified command will be executed through the -shell. - -If cwd is not None, the current directory will be changed to cwd -before the child is executed. - -If env is not None, it defines the environment variables for the new -process. - -If universal_newlines is true, the file objects stdout and stderr are -opened as a text files, but lines may be terminated by any of '\n', -the Unix end-of-line convention, '\r', the Macintosh convention or -'\r\n', the Windows convention. All of these external representations -are seen as '\n' by the Python program. Note: This feature is only -available if Python is built with universal newline support (the -default). Also, the newlines attribute of the file objects stdout, -stdin and stderr are not updated by the communicate() method. - -The startupinfo and creationflags, if given, will be passed to the -underlying CreateProcess() function. They can specify things such as -appearance of the main window and priority for the new process. -(Windows only) - - -This module also defines two shortcut functions: - -call(*popenargs, **kwargs): - Run command with arguments. Wait for command to complete, then - return the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - retcode = call(["ls", "-l"]) - -check_call(*popenargs, **kwargs): - Run command with arguments. Wait for command to complete. If the - exit code was zero then return, otherwise raise - CalledProcessError. The CalledProcessError object will have the - return code in the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - check_call(["ls", "-l"]) - -Exceptions ----------- -Exceptions raised in the child process, before the new program has -started to execute, will be re-raised in the parent. Additionally, -the exception object will have one extra attribute called -'child_traceback', which is a string containing traceback information -from the childs point of view. - -The most common exception raised is OSError. This occurs, for -example, when trying to execute a non-existent file. Applications -should prepare for OSErrors. - -A ValueError will be raised if Popen is called with invalid arguments. - -check_call() will raise CalledProcessError, if the called process -returns a non-zero return code. - - -Security --------- -Unlike some other popen functions, this implementation will never call -/bin/sh implicitly. This means that all characters, including shell -metacharacters, can safely be passed to child processes. - - -Popen objects -============= -Instances of the Popen class have the following methods: - -poll() - Check if child process has terminated. Returns returncode - attribute. - -wait() - Wait for child process to terminate. Returns returncode attribute. - -communicate(input=None) - Interact with process: Send data to stdin. Read data from stdout - and stderr, until end-of-file is reached. Wait for process to - terminate. The optional stdin argument should be a string to be - sent to the child process, or None, if no data should be sent to - the child. - - communicate() returns a tuple (stdout, stderr). - - Note: The data read is buffered in memory, so do not use this - method if the data size is large or unlimited. - -The following attributes are also available: - -stdin - If the stdin argument is PIPE, this attribute is a file object - that provides input to the child process. Otherwise, it is None. - -stdout - If the stdout argument is PIPE, this attribute is a file object - that provides output from the child process. Otherwise, it is - None. - -stderr - If the stderr argument is PIPE, this attribute is file object that - provides error output from the child process. Otherwise, it is - None. - -pid - The process ID of the child process. - -returncode - The child return code. A None value indicates that the process - hasn't terminated yet. A negative value -N indicates that the - child was terminated by signal N (UNIX only). - - -Replacing older functions with the subprocess module -==================================================== -In this section, "a ==> b" means that b can be used as a replacement -for a. - -Note: All functions in this section fail (more or less) silently if -the executed program cannot be found; this module raises an OSError -exception. - -In the following examples, we assume that the subprocess module is -imported with "from subprocess import *". - - -Replacing /bin/sh shell backquote ---------------------------------- -output=`mycmd myarg` -==> -output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] - - -Replacing shell pipe line -------------------------- -output=`dmesg | grep hda` -==> -p1 = Popen(["dmesg"], stdout=PIPE) -p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) -output = p2.communicate()[0] - - -Replacing os.system() ---------------------- -sts = os.system("mycmd" + " myarg") -==> -p = Popen("mycmd" + " myarg", shell=True) -pid, sts = os.waitpid(p.pid, 0) - -Note: - -* Calling the program through the shell is usually not required. - -* It's easier to look at the returncode attribute than the - exitstatus. - -A more real-world example would look like this: - -try: - retcode = call("mycmd" + " myarg", shell=True) - if retcode < 0: - print >>sys.stderr, "Child was terminated by signal", -retcode - else: - print >>sys.stderr, "Child returned", retcode -except OSError, e: - print >>sys.stderr, "Execution failed:", e - - -Replacing os.spawn* -------------------- -P_NOWAIT example: - -pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") -==> -pid = Popen(["/bin/mycmd", "myarg"]).pid - - -P_WAIT example: - -retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") -==> -retcode = call(["/bin/mycmd", "myarg"]) - - -Vector example: - -os.spawnvp(os.P_NOWAIT, path, args) -==> -Popen([path] + args[1:]) - - -Environment example: - -os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) -==> -Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) - - -Replacing os.popen* -------------------- -pipe = os.popen(cmd, mode='r', bufsize) -==> -pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout - -pipe = os.popen(cmd, mode='w', bufsize) -==> -pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin - - -(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) -==> -p = Popen(cmd, shell=True, bufsize=bufsize, - stdin=PIPE, stdout=PIPE, close_fds=True) -(child_stdin, child_stdout) = (p.stdin, p.stdout) - - -(child_stdin, - child_stdout, - child_stderr) = os.popen3(cmd, mode, bufsize) -==> -p = Popen(cmd, shell=True, bufsize=bufsize, - stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) -(child_stdin, - child_stdout, - child_stderr) = (p.stdin, p.stdout, p.stderr) - - -(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) -==> -p = Popen(cmd, shell=True, bufsize=bufsize, - stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) -(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) - - -Replacing popen2.* ------------------- -Note: If the cmd argument to popen2 functions is a string, the command -is executed through /bin/sh. If it is a list, the command is directly -executed. - -(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) -==> -p = Popen(["somestring"], shell=True, bufsize=bufsize - stdin=PIPE, stdout=PIPE, close_fds=True) -(child_stdout, child_stdin) = (p.stdout, p.stdin) - - -(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) -==> -p = Popen(["mycmd", "myarg"], bufsize=bufsize, - stdin=PIPE, stdout=PIPE, close_fds=True) -(child_stdout, child_stdin) = (p.stdout, p.stdin) - -The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen, -except that: - -* subprocess.Popen raises an exception if the execution fails -* the capturestderr argument is replaced with the stderr argument. -* stdin=PIPE and stdout=PIPE must be specified. -* popen2 closes all filedescriptors by default, but you have to specify - close_fds=True with subprocess.Popen. - - -""" - -import sys -mswindows = (sys.platform == "win32") - -import os -import types -import traceback - -# Exception classes used by this module. -class CalledProcessError(Exception): - """This exception is raised when a process run by check_call() returns - a non-zero exit status. The exit status will be stored in the - returncode attribute.""" - def __init__(self, returncode, cmd): - self.returncode = returncode - self.cmd = cmd - def __str__(self): - return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) - - -if mswindows: - try: - import threading - except ImportError: - # SCons: the threading module is only used by the communicate() - # method, which we don't actually use, so don't worry if we - # can't import it. - pass - import msvcrt - try: - # Try to get _subprocess - from _subprocess import * - class STARTUPINFO(object): - dwFlags = 0 - hStdInput = None - hStdOutput = None - hStdError = None - wShowWindow = 0 - class pywintypes(object): - error = IOError - except ImportError: - # If not there, then drop back to requiring pywin32 - # TODO: Should this be wrapped in try as well? To notify user to install - # pywin32 ? With URL to it? - import pywintypes - from win32api import GetStdHandle, STD_INPUT_HANDLE, \ - STD_OUTPUT_HANDLE, STD_ERROR_HANDLE - from win32api import GetCurrentProcess, DuplicateHandle, \ - GetModuleFileName, GetVersion - from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE - from win32pipe import CreatePipe - from win32process import CreateProcess, STARTUPINFO, \ - GetExitCodeProcess, STARTF_USESTDHANDLES, \ - STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE - from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 - - -else: - import select - import errno - import fcntl - import pickle - - try: - fcntl.F_GETFD - except AttributeError: - fcntl.F_GETFD = 1 - - try: - fcntl.F_SETFD - except AttributeError: - fcntl.F_SETFD = 2 - -__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] - -try: - MAXFD = os.sysconf("SC_OPEN_MAX") -except KeyboardInterrupt: - raise # SCons: don't swallow keyboard interrupts -except: - MAXFD = 256 - -try: - isinstance(1, int) -except TypeError: - def is_int(obj): - return isinstance(obj, type(1)) - def is_int_or_long(obj): - return type(obj) in (type(1), type(1L)) -else: - def is_int(obj): - return isinstance(obj, int) - def is_int_or_long(obj): - return isinstance(obj, (int, long)) - -try: - types.StringTypes -except AttributeError: - try: - types.StringTypes = (str, unicode) - except NameError: - types.StringTypes = (str,) -def is_string(obj): - return isinstance(obj, types.StringTypes) - -_active = [] - -def _cleanup(): - for inst in _active[:]: - if inst.poll(_deadstate=sys.maxsize) >= 0: - try: - _active.remove(inst) - except ValueError: - # This can happen if two threads create a new Popen instance. - # It's harmless that it was already removed, so ignore. - pass - -PIPE = -1 -STDOUT = -2 - - -def call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete, then - return the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - retcode = call(["ls", "-l"]) - """ - return apply(Popen, popenargs, kwargs).wait() - - -def check_call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete. If - the exit code was zero then return, otherwise raise - CalledProcessError. The CalledProcessError object will have the - return code in the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - check_call(["ls", "-l"]) - """ - retcode = call(*popenargs, **kwargs) - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - if retcode: - raise CalledProcessError(retcode, cmd) - return retcode - - -def list2cmdline(seq): - """ - Translate a sequence of arguments into a command line - string, using the same rules as the MS C runtime: - - 1) Arguments are delimited by white space, which is either a - space or a tab. - - 2) A string surrounded by double quotation marks is - interpreted as a single argument, regardless of white space - contained within. A quoted string can be embedded in an - argument. - - 3) A double quotation mark preceded by a backslash is - interpreted as a literal double quotation mark. - - 4) Backslashes are interpreted literally, unless they - immediately precede a double quotation mark. - - 5) If backslashes immediately precede a double quotation mark, - every pair of backslashes is interpreted as a literal - backslash. If the number of backslashes is odd, the last - backslash escapes the next double quotation mark as - described in rule 3. - """ - - # See - # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp - result = [] - needquote = False - for arg in seq: - bs_buf = [] - - # Add a space to separate this argument from the others - if result: - result.append(' ') - - needquote = (" " in arg) or ("\t" in arg) - if needquote: - result.append('"') - - for c in arg: - if c == '\\': - # Don't know if we need to double yet. - bs_buf.append(c) - elif c == '"': - # Double backspaces. - result.append('\\' * len(bs_buf)*2) - bs_buf = [] - result.append('\\"') - else: - # Normal char - if bs_buf: - result.extend(bs_buf) - bs_buf = [] - result.append(c) - - # Add remaining backspaces, if any. - if bs_buf: - result.extend(bs_buf) - - if needquote: - result.extend(bs_buf) - result.append('"') - - return ''.join(result) - -class Popen(object): - def __init__(self, args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0): - """Create new Popen instance.""" - _cleanup() - - self._child_created = False - if not is_int_or_long(bufsize): - raise TypeError("bufsize must be an integer") - - if mswindows: - if preexec_fn is not None: - raise ValueError("preexec_fn is not supported on Windows " - "platforms") - if close_fds: - raise ValueError("close_fds is not supported on Windows " - "platforms") - else: - # POSIX - if startupinfo is not None: - raise ValueError("startupinfo is only supported on Windows " - "platforms") - if creationflags != 0: - raise ValueError("creationflags is only supported on Windows " - "platforms") - - self.stdin = None - self.stdout = None - self.stderr = None - self.pid = None - self.returncode = None - self.universal_newlines = universal_newlines - - # Input and output objects. The general principle is like - # this: - # - # Parent Child - # ------ ----- - # p2cwrite ---stdin---> p2cread - # c2pread <--stdout--- c2pwrite - # errread <--stderr--- errwrite - # - # On POSIX, the child objects are file descriptors. On - # Windows, these are Windows file handles. The parent objects - # are file descriptors on both platforms. The parent objects - # are None when not using PIPEs. The child objects are None - # when not redirecting. - - (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) = self._get_handles(stdin, stdout, stderr) - - self._execute_child(args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, - startupinfo, creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) - - if p2cwrite: - self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) - if c2pread: - if universal_newlines: - self.stdout = os.fdopen(c2pread, 'rU', bufsize) - else: - self.stdout = os.fdopen(c2pread, 'rb', bufsize) - if errread: - if universal_newlines: - self.stderr = os.fdopen(errread, 'rU', bufsize) - else: - self.stderr = os.fdopen(errread, 'rb', bufsize) - - - def _translate_newlines(self, data): - data = data.replace("\r\n", "\n") - data = data.replace("\r", "\n") - return data - - - def __del__(self): - if not self._child_created: - # We didn't get to successfully create a child process. - return - # In case the child hasn't been waited on, check if it's done. - self.poll(_deadstate=sys.maxsize) - if self.returncode is None and _active is not None: - # Child is still running, keep us alive until we can wait on it. - _active.append(self) - - - def communicate(self, input=None): - """Interact with process: Send data to stdin. Read data from - stdout and stderr, until end-of-file is reached. Wait for - process to terminate. The optional input argument should be a - string to be sent to the child process, or None, if no data - should be sent to the child. - - communicate() returns a tuple (stdout, stderr).""" - - # Optimization: If we are only using one pipe, or no pipe at - # all, using select() or threads is unnecessary. - if [self.stdin, self.stdout, self.stderr].count(None) >= 2: - stdout = None - stderr = None - if self.stdin: - if input: - self.stdin.write(input) - self.stdin.close() - elif self.stdout: - stdout = self.stdout.read() - elif self.stderr: - stderr = self.stderr.read() - self.wait() - return (stdout, stderr) - - return self._communicate(input) - - - if mswindows: - # - # Windows methods - # - def _get_handles(self, stdin, stdout, stderr): - """Construct and return tupel with IO objects: - p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite - """ - if stdin is None and stdout is None and stderr is None: - return (None, None, None, None, None, None) - - p2cread, p2cwrite = None, None - c2pread, c2pwrite = None, None - errread, errwrite = None, None - - if stdin is None: - p2cread = GetStdHandle(STD_INPUT_HANDLE) - elif stdin == PIPE: - p2cread, p2cwrite = CreatePipe(None, 0) - # Detach and turn into fd - p2cwrite = p2cwrite.Detach() - p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) - elif is_int(stdin): - p2cread = msvcrt.get_osfhandle(stdin) - else: - # Assuming file-like object - p2cread = msvcrt.get_osfhandle(stdin.fileno()) - p2cread = self._make_inheritable(p2cread) - - if stdout is None: - c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) - elif stdout == PIPE: - c2pread, c2pwrite = CreatePipe(None, 0) - # Detach and turn into fd - c2pread = c2pread.Detach() - c2pread = msvcrt.open_osfhandle(c2pread, 0) - elif is_int(stdout): - c2pwrite = msvcrt.get_osfhandle(stdout) - else: - # Assuming file-like object - c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) - c2pwrite = self._make_inheritable(c2pwrite) - - if stderr is None: - errwrite = GetStdHandle(STD_ERROR_HANDLE) - elif stderr == PIPE: - errread, errwrite = CreatePipe(None, 0) - # Detach and turn into fd - errread = errread.Detach() - errread = msvcrt.open_osfhandle(errread, 0) - elif stderr == STDOUT: - errwrite = c2pwrite - elif is_int(stderr): - errwrite = msvcrt.get_osfhandle(stderr) - else: - # Assuming file-like object - errwrite = msvcrt.get_osfhandle(stderr.fileno()) - errwrite = self._make_inheritable(errwrite) - - return (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) - - - def _make_inheritable(self, handle): - """Return a duplicate of handle, which is inheritable""" - return DuplicateHandle(GetCurrentProcess(), handle, - GetCurrentProcess(), 0, 1, - DUPLICATE_SAME_ACCESS) - - - def _find_w9xpopen(self): - """Find and return absolut path to w9xpopen.exe""" - w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), - "w9xpopen.exe") - if not os.path.exists(w9xpopen): - # Eeek - file-not-found - possibly an embedding - # situation - see if we can locate it in sys.exec_prefix - w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), - "w9xpopen.exe") - if not os.path.exists(w9xpopen): - raise RuntimeError("Cannot locate w9xpopen.exe, which is " - "needed for Popen to work with your " - "shell or platform.") - return w9xpopen - - - def _execute_child(self, args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, - startupinfo, creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite): - """Execute program (MS Windows version)""" - - if not isinstance(args, types.StringTypes): - args = list2cmdline(args) - - # Process startup details - if startupinfo is None: - startupinfo = STARTUPINFO() - if None not in (p2cread, c2pwrite, errwrite): - startupinfo.dwFlags = startupinfo.dwFlags | STARTF_USESTDHANDLES - startupinfo.hStdInput = p2cread - startupinfo.hStdOutput = c2pwrite - startupinfo.hStdError = errwrite - - if shell: - startupinfo.dwFlags = startupinfo.dwFlags | STARTF_USESHOWWINDOW - startupinfo.wShowWindow = SW_HIDE - comspec = os.environ.get("COMSPEC", "cmd.exe") - args = comspec + " /c " + args - if (GetVersion() >= 0x80000000L or - os.path.basename(comspec).lower() == "command.com"): - # Win9x, or using command.com on NT. We need to - # use the w9xpopen intermediate program. For more - # information, see KB Q150956 - # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp) - w9xpopen = self._find_w9xpopen() - args = '"%s" %s' % (w9xpopen, args) - # Not passing CREATE_NEW_CONSOLE has been known to - # cause random failures on win9x. Specifically a - # dialog: "Your program accessed mem currently in - # use at xxx" and a hopeful warning about the - # stability of your system. Cost is Ctrl+C wont - # kill children. - creationflags = creationflags | CREATE_NEW_CONSOLE - - # Start the process - try: - hp, ht, pid, tid = CreateProcess(executable, args, - # no special security - None, None, - # must inherit handles to pass std - # handles - 1, - creationflags, - env, - cwd, - startupinfo) - except pywintypes.error, e: - # Translate pywintypes.error to WindowsError, which is - # a subclass of OSError. FIXME: We should really - # translate errno using _sys_errlist (or simliar), but - # how can this be done from Python? - raise WindowsError(*e.args) - - # Retain the process handle, but close the thread handle - self._child_created = True - self._handle = hp - self.pid = pid - ht.Close() - - # Child is launched. Close the parent's copy of those pipe - # handles that only the child should have open. You need - # to make sure that no handles to the write end of the - # output pipe are maintained in this process or else the - # pipe will not close when the child process exits and the - # ReadFile will hang. - if p2cread is not None: - p2cread.Close() - if c2pwrite is not None: - c2pwrite.Close() - if errwrite is not None: - errwrite.Close() - - - def poll(self, _deadstate=None): - """Check if child process has terminated. Returns returncode - attribute.""" - if self.returncode is None: - if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: - self.returncode = GetExitCodeProcess(self._handle) - return self.returncode - - - def wait(self): - """Wait for child process to terminate. Returns returncode - attribute.""" - if self.returncode is None: - obj = WaitForSingleObject(self._handle, INFINITE) - self.returncode = GetExitCodeProcess(self._handle) - return self.returncode - - - def _readerthread(self, fh, buffer): - buffer.append(fh.read()) - - - def _communicate(self, input): - stdout = None # Return - stderr = None # Return - - if self.stdout: - stdout = [] - stdout_thread = threading.Thread(target=self._readerthread, - args=(self.stdout, stdout)) - stdout_thread.setDaemon(True) - stdout_thread.start() - if self.stderr: - stderr = [] - stderr_thread = threading.Thread(target=self._readerthread, - args=(self.stderr, stderr)) - stderr_thread.setDaemon(True) - stderr_thread.start() - - if self.stdin: - if input is not None: - self.stdin.write(input) - self.stdin.close() - - if self.stdout: - stdout_thread.join() - if self.stderr: - stderr_thread.join() - - # All data exchanged. Translate lists into strings. - if stdout is not None: - stdout = stdout[0] - if stderr is not None: - stderr = stderr[0] - - # Translate newlines, if requested. We cannot let the file - # object do the translation: It is based on stdio, which is - # impossible to combine with select (unless forcing no - # buffering). - if self.universal_newlines and hasattr(file, 'newlines'): - if stdout: - stdout = self._translate_newlines(stdout) - if stderr: - stderr = self._translate_newlines(stderr) - - self.wait() - return (stdout, stderr) - - else: - # - # POSIX methods - # - def _get_handles(self, stdin, stdout, stderr): - """Construct and return tupel with IO objects: - p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite - """ - p2cread, p2cwrite = None, None - c2pread, c2pwrite = None, None - errread, errwrite = None, None - - if stdin is None: - pass - elif stdin == PIPE: - p2cread, p2cwrite = os.pipe() - elif is_int(stdin): - p2cread = stdin - else: - # Assuming file-like object - p2cread = stdin.fileno() - - if stdout is None: - pass - elif stdout == PIPE: - c2pread, c2pwrite = os.pipe() - elif is_int(stdout): - c2pwrite = stdout - else: - # Assuming file-like object - c2pwrite = stdout.fileno() - - if stderr is None: - pass - elif stderr == PIPE: - errread, errwrite = os.pipe() - elif stderr == STDOUT: - errwrite = c2pwrite - elif is_int(stderr): - errwrite = stderr - else: - # Assuming file-like object - errwrite = stderr.fileno() - - return (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) - - - def _set_cloexec_flag(self, fd): - try: - cloexec_flag = fcntl.FD_CLOEXEC - except AttributeError: - cloexec_flag = 1 - - old = fcntl.fcntl(fd, fcntl.F_GETFD) - fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) - - - def _close_fds(self, but): - for i in range(3, MAXFD): - if i == but: - continue - try: - os.close(i) - except KeyboardInterrupt: - raise # SCons: don't swallow keyboard interrupts - except: - pass - - - def _execute_child(self, args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, - startupinfo, creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite): - """Execute program (POSIX version)""" - - if is_string(args): - args = [args] - - if shell: - args = ["/bin/sh", "-c"] + args - - if executable is None: - executable = args[0] - - # For transferring possible exec failure from child to parent - # The first char specifies the exception type: 0 means - # OSError, 1 means some other error. - errpipe_read, errpipe_write = os.pipe() - self._set_cloexec_flag(errpipe_write) - - self.pid = os.fork() - self._child_created = True - if self.pid == 0: - # Child - try: - # Close parent's pipe ends - if p2cwrite: - os.close(p2cwrite) - if c2pread: - os.close(c2pread) - if errread: - os.close(errread) - os.close(errpipe_read) - - # Dup fds for child - if p2cread: - os.dup2(p2cread, 0) - if c2pwrite: - os.dup2(c2pwrite, 1) - if errwrite: - os.dup2(errwrite, 2) - - # Close pipe fds. Make sure we don't close the same - # fd more than once, or standard fds. - try: - set - except NameError: - # Fall-back for earlier Python versions, so epydoc - # can use this module directly to execute things. - if p2cread: - os.close(p2cread) - if c2pwrite and c2pwrite not in (p2cread,): - os.close(c2pwrite) - if errwrite and errwrite not in (p2cread, c2pwrite): - os.close(errwrite) - else: - for fd in set((p2cread, c2pwrite, errwrite))-set((0,1,2)): - if fd: os.close(fd) - - # Close all other fds, if asked for - if close_fds: - self._close_fds(but=errpipe_write) - - if cwd is not None: - os.chdir(cwd) - - if preexec_fn: - apply(preexec_fn) - - if env is None: - os.execvp(executable, args) - else: - os.execvpe(executable, args, env) - - except KeyboardInterrupt: - raise # SCons: don't swallow keyboard interrupts - - except: - exc_type, exc_value, tb = sys.exc_info() - # Save the traceback and attach it to the exception object - exc_lines = traceback.format_exception(exc_type, - exc_value, - tb) - exc_value.child_traceback = ''.join(exc_lines) - os.write(errpipe_write, pickle.dumps(exc_value)) - - # This exitcode won't be reported to applications, so it - # really doesn't matter what we return. - os._exit(255) - - # Parent - os.close(errpipe_write) - if p2cread and p2cwrite: - os.close(p2cread) - if c2pwrite and c2pread: - os.close(c2pwrite) - if errwrite and errread: - os.close(errwrite) - - # Wait for exec to fail or succeed; possibly raising exception - data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB - os.close(errpipe_read) - if data != "": - os.waitpid(self.pid, 0) - child_exception = pickle.loads(data) - raise child_exception - - - def _handle_exitstatus(self, sts): - if os.WIFSIGNALED(sts): - self.returncode = -os.WTERMSIG(sts) - elif os.WIFEXITED(sts): - self.returncode = os.WEXITSTATUS(sts) - else: - # Should never happen - raise RuntimeError("Unknown child exit status!") - - - def poll(self, _deadstate=None): - """Check if child process has terminated. Returns returncode - attribute.""" - if self.returncode is None: - try: - pid, sts = os.waitpid(self.pid, os.WNOHANG) - if pid == self.pid: - self._handle_exitstatus(sts) - except os.error: - if _deadstate is not None: - self.returncode = _deadstate - return self.returncode - - - def wait(self): - """Wait for child process to terminate. Returns returncode - attribute.""" - if self.returncode is None: - pid, sts = os.waitpid(self.pid, 0) - self._handle_exitstatus(sts) - return self.returncode - - - def _communicate(self, input): - read_set = [] - write_set = [] - stdout = None # Return - stderr = None # Return - - if self.stdin: - # Flush stdio buffer. This might block, if the user has - # been writing to .stdin in an uncontrolled fashion. - self.stdin.flush() - if input: - write_set.append(self.stdin) - else: - self.stdin.close() - if self.stdout: - read_set.append(self.stdout) - stdout = [] - if self.stderr: - read_set.append(self.stderr) - stderr = [] - - input_offset = 0 - while read_set or write_set: - rlist, wlist, xlist = select.select(read_set, write_set, []) - - if self.stdin in wlist: - # When select has indicated that the file is writable, - # we can write up to PIPE_BUF bytes without risk - # blocking. POSIX defines PIPE_BUF >= 512 - m = memoryview(input)[input_offset:input_offset+512] - bytes_written = os.write(self.stdin.fileno(), m) - input_offset = input_offset + bytes_written - if input_offset >= len(input): - self.stdin.close() - write_set.remove(self.stdin) - - if self.stdout in rlist: - data = os.read(self.stdout.fileno(), 1024) - if data == "": - self.stdout.close() - read_set.remove(self.stdout) - stdout.append(data) - - if self.stderr in rlist: - data = os.read(self.stderr.fileno(), 1024) - if data == "": - self.stderr.close() - read_set.remove(self.stderr) - stderr.append(data) - - # All data exchanged. Translate lists into strings. - if stdout is not None: - stdout = ''.join(stdout) - if stderr is not None: - stderr = ''.join(stderr) - - # Translate newlines, if requested. We cannot let the file - # object do the translation: It is based on stdio, which is - # impossible to combine with select (unless forcing no - # buffering). - if self.universal_newlines and hasattr(file, 'newlines'): - if stdout: - stdout = self._translate_newlines(stdout) - if stderr: - stderr = self._translate_newlines(stderr) - - self.wait() - return (stdout, stderr) - - -def _demo_posix(): - # - # Example 1: Simple redirection: Get process list - # - plist = Popen(["ps"], stdout=PIPE).communicate()[0] - print "Process list:" - print plist - - # - # Example 2: Change uid before executing child - # - if os.getuid() == 0: - p = Popen(["id"], preexec_fn=lambda: os.setuid(100)) - p.wait() - - # - # Example 3: Connecting several subprocesses - # - print "Looking for 'hda'..." - p1 = Popen(["dmesg"], stdout=PIPE) - p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) - print repr(p2.communicate()[0]) - - # - # Example 4: Catch execution error - # - print - print "Trying a weird file..." - try: - print Popen(["/this/path/does/not/exist"]).communicate() - except OSError, e: - if e.errno == errno.ENOENT: - print "The file didn't exist. I thought so..." - print "Child traceback:" - print e.child_traceback - else: - print "Error", e.errno - else: - sys.stderr.write( "Gosh. No error.\n" ) - - -def _demo_windows(): - # - # Example 1: Connecting several subprocesses - # - print "Looking for 'PROMPT' in set output..." - p1 = Popen("set", stdout=PIPE, shell=True) - p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) - print repr(p2.communicate()[0]) - - # - # Example 2: Simple execution of program - # - print "Executing calc..." - p = Popen("calc") - p.wait() - - -if __name__ == "__main__": - if mswindows: - _demo_windows() - else: - _demo_posix() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scons/scons-local-2.4.1/SCons/Action.py b/scons/scons-local-2.5.0/SCons/Action.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Action.py rename to scons/scons-local-2.5.0/SCons/Action.py index 7a4203c89..6c34a4331 100644 --- a/scons/scons-local-2.4.1/SCons/Action.py +++ b/scons/scons-local-2.5.0/SCons/Action.py @@ -76,7 +76,7 @@ way for wrapping up the functions. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -97,7 +97,7 @@ way for wrapping up the functions. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Action.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Action.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import dis import os @@ -235,11 +235,7 @@ def _code_contents(code): # The code contents depends on the number of local variables # but not their actual names. contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames))) - try: - contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) - except AttributeError: - # Older versions of Python do not support closures. - contents.append(",0,0") + contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) # The code contents depends on any constants accessed by the # function. Note that we have to call _object_contents on each @@ -276,11 +272,7 @@ def _function_contents(func): contents.append(',()') # The function contents depends on the closure captured cell values. - try: - closure = func.func_closure or [] - except AttributeError: - # Older versions of Python do not support closures. - closure = [] + closure = func.func_closure or [] #xxx = [_object_contents(x.cell_contents) for x in closure] try: @@ -946,7 +938,6 @@ class LazyAction(CommandGeneratorAction, CommandAction): def __init__(self, var, kw): if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.LazyAction') - #FUTURE CommandAction.__init__(self, '${'+var+'}', **kw) CommandAction.__init__(self, '${'+var+'}', **kw) self.var = SCons.Util.to_String(var) self.gen_kw = kw diff --git a/scons/scons-local-2.4.1/SCons/Builder.py b/scons/scons-local-2.5.0/SCons/Builder.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/Builder.py rename to scons/scons-local-2.5.0/SCons/Builder.py index 6bdd0082c..060b1a865 100644 --- a/scons/scons-local-2.4.1/SCons/Builder.py +++ b/scons/scons-local-2.5.0/SCons/Builder.py @@ -76,7 +76,7 @@ There are the following methods for internal use within this module: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -97,7 +97,7 @@ There are the following methods for internal use within this module: # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Builder.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Builder.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import collections @@ -299,7 +299,7 @@ def _node_errors(builder, env, tlist, slist): msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env)) SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg) else: - msg = "Two environments with different actions were specified for the same target: %s" % t + msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (t,t_contents,contents) raise UserError(msg) if builder.multi: if t.builder != builder: diff --git a/scons/scons-local-2.4.1/SCons/CacheDir.py b/scons/scons-local-2.5.0/SCons/CacheDir.py similarity index 70% rename from scons/scons-local-2.4.1/SCons/CacheDir.py rename to scons/scons-local-2.5.0/SCons/CacheDir.py index 086d44d3c..05199d931 100644 --- a/scons/scons-local-2.4.1/SCons/CacheDir.py +++ b/scons/scons-local-2.5.0/SCons/CacheDir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,17 +21,19 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/CacheDir.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/CacheDir.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """ CacheDir support """ -import os.path +import json +import os import stat import sys import SCons.Action +import SCons.Warnings cache_enabled = True cache_debug = False @@ -71,7 +73,8 @@ CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString) CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None) def CachePushFunc(target, source, env): - if cache_readonly: return + if cache_readonly: + return t = target[0] if t.nocache: @@ -124,6 +127,10 @@ def CachePushFunc(target, source, env): CachePush = SCons.Action.Action(CachePushFunc, None) +# Nasty hack to cut down to one warning for each cachedir path that needs +# upgrading. +warned = dict() + class CacheDir(object): def __init__(self, path): @@ -132,11 +139,63 @@ class CacheDir(object): except ImportError: msg = "No hashlib or MD5 module available, CacheDir() not supported" SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg) - self.path = None - else: - self.path = path + path = None + self.path = path self.current_cache_debug = None self.debugFP = None + self.config = dict() + if path is None: + return + # See if there's a config file in the cache directory. If there is, + # use it. If there isn't, and the directory exists and isn't empty, + # produce a warning. If the directory doesn't exist or is empty, + # write a config file. + config_file = os.path.join(path, 'config') + if not os.path.exists(config_file): + # A note: There is a race hazard here, if two processes start and + # attempt to create the cache directory at the same time. However, + # python doesn't really give you the option to do exclusive file + # creation (it doesn't even give you the option to error on opening + # an existing file for writing...). The ordering of events here + # as an attempt to alleviate this, on the basis that it's a pretty + # unlikely occurence (it'd require two builds with a brand new cache + # directory) + if os.path.isdir(path) and len(os.listdir(path)) != 0: + self.config['prefix_len'] = 1 + # When building the project I was testing this on, the warning + # was output over 20 times. That seems excessive + global warned + if self.path not in warned: + msg = "Please upgrade your cache by running " +\ + " scons-configure-cache.py " + self.path + SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg) + warned[self.path] = True + else: + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError: + # If someone else is trying to create the directory at + # the same time as me, bad things will happen + msg = "Failed to create cache directory " + path + raise SCons.Errors.EnvironmentError(msg) + + self.config['prefix_len'] = 2 + if not os.path.exists(config_file): + try: + with open(config_file, 'w') as config: + json.dump(self.config, config) + except: + msg = "Failed to write cache configuration for " + path + raise SCons.Errors.EnvironmentError(msg) + else: + try: + with open(config_file) as config: + self.config = json.load(config) + except ValueError: + msg = "Failed to read cache configuration for " + path + raise SCons.Errors.EnvironmentError(msg) + def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: @@ -151,7 +210,7 @@ class CacheDir(object): self.debugFP.write(fmt % (target, os.path.split(cachefile)[1])) def is_enabled(self): - return (cache_enabled and not self.path is None) + return cache_enabled and not self.path is None def is_readonly(self): return cache_readonly @@ -163,7 +222,7 @@ class CacheDir(object): return None, None sig = node.get_cachedir_bsig() - subdir = sig[0].upper() + subdir = sig[:self.config['prefix_len']].upper() dir = os.path.join(self.path, subdir) return dir, os.path.join(dir, sig) diff --git a/scons/scons-local-2.4.1/SCons/Conftest.py b/scons/scons-local-2.5.0/SCons/Conftest.py similarity index 100% rename from scons/scons-local-2.4.1/SCons/Conftest.py rename to scons/scons-local-2.5.0/SCons/Conftest.py diff --git a/scons/scons-local-2.4.1/SCons/Debug.py b/scons/scons-local-2.5.0/SCons/Debug.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Debug.py rename to scons/scons-local-2.5.0/SCons/Debug.py index 22d09ab6b..2ba97cd3a 100644 --- a/scons/scons-local-2.4.1/SCons/Debug.py +++ b/scons/scons-local-2.5.0/SCons/Debug.py @@ -1,12 +1,15 @@ """SCons.Debug Code for debugging SCons internal things. Shouldn't be -needed by most users. +needed by most users. Quick shortcuts: + +from SCons.Debug import caller_trace +caller_trace() """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +31,7 @@ needed by most users. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Debug.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Debug.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import sys @@ -137,8 +140,12 @@ def caller_stack(): caller_bases = {} caller_dicts = {} -# trace a caller's stack def caller_trace(back=0): + """ + Trace caller stack and save info into global dicts, which + are printed automatically at the end of SCons execution. + """ + global caller_bases, caller_dicts import traceback tb = traceback.extract_stack(limit=3+back) tb.reverse() diff --git a/scons/scons-local-2.4.1/SCons/Defaults.py b/scons/scons-local-2.5.0/SCons/Defaults.py similarity index 88% rename from scons/scons-local-2.4.1/SCons/Defaults.py rename to scons/scons-local-2.5.0/SCons/Defaults.py index 8c86c955b..91f8f2c74 100644 --- a/scons/scons-local-2.4.1/SCons/Defaults.py +++ b/scons/scons-local-2.5.0/SCons/Defaults.py @@ -10,7 +10,7 @@ from distutils.msvccompiler. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ from distutils.msvccompiler. # from __future__ import division -__revision__ = "src/engine/SCons/Defaults.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Defaults.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os @@ -169,15 +169,73 @@ def get_paths_str(dest): else: return '"' + str(dest) + '"' +permission_dic = { + 'u':{ + 'r':stat.S_IRUSR, + 'w':stat.S_IWUSR, + 'x':stat.S_IXUSR + }, + 'g':{ + 'r':stat.S_IRGRP, + 'w':stat.S_IWGRP, + 'x':stat.S_IXGRP + }, + 'o':{ + 'r':stat.S_IROTH, + 'w':stat.S_IWOTH, + 'x':stat.S_IXOTH + } +} + def chmod_func(dest, mode): + import SCons.Util + from string import digits SCons.Node.FS.invalidate_node_memos(dest) if not SCons.Util.is_List(dest): dest = [dest] - for element in dest: - os.chmod(str(element), mode) + if SCons.Util.is_String(mode) and not 0 in [i in digits for i in mode]: + mode = int(mode, 8) + if not SCons.Util.is_String(mode): + for element in dest: + os.chmod(str(element), mode) + else: + mode = str(mode) + for operation in mode.split(","): + if "=" in operation: + operator = "=" + elif "+" in operation: + operator = "+" + elif "-" in operation: + operator = "-" + else: + raise SyntaxError("Could not find +, - or =") + operation_list = operation.split(operator) + if len(operation_list) is not 2: + raise SyntaxError("More than one operator found") + user = operation_list[0].strip().replace("a", "ugo") + permission = operation_list[1].strip() + new_perm = 0 + for u in user: + for p in permission: + try: + new_perm = new_perm | permission_dic[u][p] + except KeyError: + raise SyntaxError("Unrecognized user or permission format") + for element in dest: + curr_perm = os.stat(str(element)).st_mode + if operator == "=": + os.chmod(str(element), new_perm) + elif operator == "+": + os.chmod(str(element), curr_perm | new_perm) + elif operator == "-": + os.chmod(str(element), curr_perm & ~new_perm) def chmod_strfunc(dest, mode): - return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) + import SCons.Util + if not SCons.Util.is_String(mode): + return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) + else: + return 'Chmod(%s, "%s")' % (get_paths_str(dest), str(mode)) Chmod = ActionFactory(chmod_func, chmod_strfunc) @@ -493,7 +551,7 @@ def __libversionflags(env, version_var, flags_var): ConstructionEnvironment = { 'BUILDERS' : {}, - 'SCANNERS' : [], + 'SCANNERS' : [ SCons.Tool.SourceFileScanner ], 'CONFIGUREDIR' : '#/.sconf_temp', 'CONFIGURELOG' : '#/config.log', 'CPPSUFFIXES' : SCons.Tool.CSuffixes, diff --git a/scons/scons-local-2.4.1/SCons/Environment.py b/scons/scons-local-2.5.0/SCons/Environment.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/Environment.py rename to scons/scons-local-2.5.0/SCons/Environment.py index b779302bd..71361add4 100644 --- a/scons/scons-local-2.4.1/SCons/Environment.py +++ b/scons/scons-local-2.5.0/SCons/Environment.py @@ -10,7 +10,7 @@ Environment """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ Environment # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Environment.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Environment.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import copy @@ -857,25 +857,6 @@ class SubstitutionEnvironment(object): self[key] = t return self -# def MergeShellPaths(self, args, prepend=1): -# """ -# Merge the dict in args into the shell environment in env['ENV']. -# Shell path elements are appended or prepended according to prepend. - -# Uses Pre/AppendENVPath, so it always appends or prepends uniquely. - -# Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'}) -# prepends /usr/local/lib to env['ENV']['LIBPATH']. -# """ - -# for pathname, pathval in args.items(): -# if not pathval: -# continue -# if prepend: -# self.PrependENVPath(pathname, pathval) -# else: -# self.AppendENVPath(pathname, pathval) - def default_decide_source(dependency, target, prev_ni): f = SCons.Defaults.DefaultEnvironment().decide_source diff --git a/scons/scons-local-2.4.1/SCons/Errors.py b/scons/scons-local-2.5.0/SCons/Errors.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Errors.py rename to scons/scons-local-2.5.0/SCons/Errors.py index d19d8e46e..81131b7ca 100644 --- a/scons/scons-local-2.4.1/SCons/Errors.py +++ b/scons/scons-local-2.5.0/SCons/Errors.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ and user errors in SCons. """ -__revision__ = "src/engine/SCons/Errors.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Errors.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util @@ -73,7 +73,7 @@ class BuildError(Exception): Information about the cause of the location of the error: --------------------------------------------------------- - node : the error occured while building this target node(s) + node : the error occurred while building this target node(s) executor : the executor that caused the build to fail (might be None if the build failures is not due to the diff --git a/scons/scons-local-2.4.1/SCons/Executor.py b/scons/scons-local-2.5.0/SCons/Executor.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Executor.py rename to scons/scons-local-2.5.0/SCons/Executor.py index f7a4ee15e..8161502cc 100644 --- a/scons/scons-local-2.4.1/SCons/Executor.py +++ b/scons/scons-local-2.5.0/SCons/Executor.py @@ -6,7 +6,7 @@ Nodes. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Nodes. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Executor.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Executor.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import collections @@ -122,7 +122,6 @@ def execute_action_list(obj, target, kw): kw = obj.get_kw(kw) status = 0 for act in obj.get_action_list(): - #args = (self.get_all_targets(), self.get_all_sources(), env) args = ([], [], env) status = act(*args, **kw) if isinstance(status, SCons.Errors.BuildError): @@ -218,7 +217,9 @@ class Executor(object): us = [] ut = [] for b in self.batches: - if b.targets[0].is_up_to_date(): + # don't add targets marked always build to unchanged lists + # add to changed list as they always need to build + if not b.targets[0].always_build and b.targets[0].is_up_to_date(): us.extend(list(map(rfile, b.sources))) ut.extend(b.targets) else: @@ -244,14 +245,12 @@ class Executor(object): return self._changed_targets_list def _get_source(self, *args, **kw): - #return SCons.Util.NodeList([rfile(self.batches[0].sources[0]).get_subst_proxy()]) return rfile(self.batches[0].sources[0]).get_subst_proxy() def _get_sources(self, *args, **kw): return SCons.Util.NodeList([rfile(n).get_subst_proxy() for n in self.get_all_sources()]) def _get_target(self, *args, **kw): - #return SCons.Util.NodeList([self.batches[0].targets[0].get_subst_proxy()]) return self.batches[0].targets[0].get_subst_proxy() def _get_targets(self, *args, **kw): @@ -486,29 +485,15 @@ class Executor(object): each individual target, which is a hell of a lot more efficient. """ env = self.get_build_env() + path = self.get_build_scanner_path + kw = self.get_kw() # TODO(batch): scan by batches) deps = [] - if scanner: - for node in node_list: - node.disambiguate() - s = scanner.select(node) - if not s: - continue - path = self.get_build_scanner_path(s) - deps.extend(node.get_implicit_deps(env, s, path)) - else: - kw = self.get_kw() - for node in node_list: - node.disambiguate() - scanner = node.get_env_scanner(env, kw) - if not scanner: - continue - scanner = scanner.select(node) - if not scanner: - continue - path = self.get_build_scanner_path(scanner) - deps.extend(node.get_implicit_deps(env, scanner, path)) + + for node in node_list: + node.disambiguate() + deps.extend(node.get_implicit_deps(env, scanner, path, kw)) deps.extend(self.get_implicit_deps()) diff --git a/scons/scons-local-2.4.1/SCons/Job.py b/scons/scons-local-2.5.0/SCons/Job.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Job.py rename to scons/scons-local-2.5.0/SCons/Job.py index 08c6c30f5..19cf3be9d 100644 --- a/scons/scons-local-2.4.1/SCons/Job.py +++ b/scons/scons-local-2.5.0/SCons/Job.py @@ -7,7 +7,7 @@ stop, and wait on jobs. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ stop, and wait on jobs. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Job.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Job.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.compat @@ -70,7 +70,7 @@ class Jobs(object): def __init__(self, num, taskmaster): """ - create 'num' jobs using the given taskmaster. + Create 'num' jobs using the given taskmaster. If 'num' is 1 or less, then a serial job will be used, otherwise a parallel job with 'num' worker threads will @@ -126,10 +126,10 @@ class Jobs(object): c) SIGHUP: Controlling shell exiting We handle all of these cases by stopping the taskmaster. It - turns out that it very difficult to stop the build process + turns out that it's very difficult to stop the build process by throwing asynchronously an exception such as KeyboardInterrupt. For example, the python Condition - variables (threading.Condition) and queue's do not seem to + variables (threading.Condition) and queues do not seem to be asynchronous-exception-safe. It would require adding a whole bunch of try/finally block and except KeyboardInterrupt all over the place. @@ -177,7 +177,7 @@ class Serial(object): The taskmaster's next_task() method should return the next task that needs to be executed, or None if there are no more tasks. The taskmaster's executed() method will be called for each task when it - is successfully executed or failed() will be called if it failed to + is successfully executed, or failed() will be called if it failed to execute (e.g. execute() raised an exception).""" self.taskmaster = taskmaster @@ -351,7 +351,7 @@ else: The taskmaster's next_task() method should return the next task that needs to be executed, or None if there are no more tasks. The taskmaster's executed() method will be called - for each task when it is successfully executed or failed() + for each task when it is successfully executed, or failed() will be called if the task failed to execute (i.e. execute() raised an exception). diff --git a/scons/scons-local-2.4.1/SCons/Memoize.py b/scons/scons-local-2.5.0/SCons/Memoize.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Memoize.py rename to scons/scons-local-2.5.0/SCons/Memoize.py index 8051c6bc3..495e13c05 100644 --- a/scons/scons-local-2.4.1/SCons/Memoize.py +++ b/scons/scons-local-2.5.0/SCons/Memoize.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Memoize.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Memoize.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Memoizer diff --git a/scons/scons-local-2.4.1/SCons/Node/Alias.py b/scons/scons-local-2.5.0/SCons/Node/Alias.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Node/Alias.py rename to scons/scons-local-2.5.0/SCons/Node/Alias.py index 3b58d4d88..d6adbf8e9 100644 --- a/scons/scons-local-2.4.1/SCons/Node/Alias.py +++ b/scons/scons-local-2.5.0/SCons/Node/Alias.py @@ -8,7 +8,7 @@ This creates a hash of global Aliases (dummy targets). """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ This creates a hash of global Aliases (dummy targets). # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/Alias.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Node/Alias.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import collections diff --git a/scons/scons-local-2.4.1/SCons/Node/FS.py b/scons/scons-local-2.5.0/SCons/Node/FS.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Node/FS.py rename to scons/scons-local-2.5.0/SCons/Node/FS.py index bd43676b2..57085ecd1 100644 --- a/scons/scons-local-2.4.1/SCons/Node/FS.py +++ b/scons/scons-local-2.5.0/SCons/Node/FS.py @@ -11,7 +11,7 @@ that can be used by scripts or modules looking for the canonical default. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ that can be used by scripts or modules looking for the canonical default. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Node/FS.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Node/FS.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import fnmatch import os @@ -186,7 +186,7 @@ needs_normpath_check = re.compile( # We need to renormalize the path if it contains a '.' # directory, but NOT if it is a single '.' '/' characters. We # do not want to match a single '.' because this case is checked - # for explicitely since this is common enough case. + # for explicitly since this is common enough case. # # Note that we check for all the following cases: # @@ -1165,15 +1165,6 @@ class LocalFS(object): return '' -#class RemoteFS: -# # Skeleton for the obvious methods we might need from the -# # abstraction layer for a remote filesystem. -# def upload(self, local_src, remote_dst): -# pass -# def download(self, remote_src, local_dst): -# pass - - class FS(LocalFS): def __init__(self, path = None): @@ -2234,7 +2225,6 @@ class Dir(Base): # the overall list will also be filtered later, # after we exit this loop. if pattern[0] != '.': - #disk_names = [ d for d in disk_names if d[0] != '.' ] disk_names = [x for x in disk_names if x[0] != '.'] disk_names = fnmatch.filter(disk_names, pattern) dirEntry = dir.Entry @@ -2627,13 +2617,6 @@ class File(Base): the directory of this file.""" return self.dir.File(name) - #def generate_build_dict(self): - # """Return an appropriate dictionary of values for building - # this File.""" - # return {'Dir' : self.Dir, - # 'File' : self.File, - # 'RDirs' : self.RDirs} - def _morph(self): """Turn a file system node into a File object.""" self.scanner_paths = {} @@ -2907,9 +2890,7 @@ class File(Base): pass if scanner: - # result = [n.disambiguate() for n in scanner(self, env, path)] - result = scanner(self, env, path) - result = [N.disambiguate() for N in result] + result = [n.disambiguate() for n in scanner(self, env, path)] else: result = [] @@ -3519,36 +3500,6 @@ class FileFinder(object): filedir, filename = os.path.split(filename) if filedir: - # More compact code that we can't use until we drop - # support for Python 1.5.2: - # - #def filedir_lookup(p, fd=filedir): - # """ - # A helper function that looks up a directory for a file - # we're trying to find. This only creates the Dir Node - # if it exists on-disk, since if the directory doesn't - # exist we know we won't find any files in it... :-) - # """ - # dir, name = os.path.split(fd) - # if dir: - # p = filedir_lookup(p, dir) - # if not p: - # return None - # norm_name = _my_normcase(name) - # try: - # node = p.entries[norm_name] - # except KeyError: - # return p.dir_on_disk(name) - # if isinstance(node, Dir): - # return node - # if isinstance(node, Entry): - # node.must_be_same(Dir) - # return node - # if isinstance(node, Dir) or isinstance(node, Entry): - # return node - # return None - #paths = [_f for _f in map(filedir_lookup, paths) if _f] - self.default_filedir = filedir paths = [_f for _f in map(self.filedir_lookup, paths) if _f] diff --git a/scons/scons-local-2.4.1/SCons/Node/Python.py b/scons/scons-local-2.5.0/SCons/Node/Python.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Node/Python.py rename to scons/scons-local-2.5.0/SCons/Node/Python.py index 171752807..f3f6c2316 100644 --- a/scons/scons-local-2.4.1/SCons/Node/Python.py +++ b/scons/scons-local-2.5.0/SCons/Node/Python.py @@ -5,7 +5,7 @@ Python nodes. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Python nodes. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/Python.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Node/Python.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Node diff --git a/scons/scons-local-2.4.1/SCons/Node/__init__.py b/scons/scons-local-2.5.0/SCons/Node/__init__.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Node/__init__.py rename to scons/scons-local-2.5.0/SCons/Node/__init__.py index 4cd62d5d5..3ce481b1f 100644 --- a/scons/scons-local-2.4.1/SCons/Node/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Node/__init__.py @@ -20,7 +20,7 @@ be able to depend on any other type of "thing." """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -41,7 +41,7 @@ be able to depend on any other type of "thing." # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Node/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Node/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import collections import copy @@ -916,35 +916,56 @@ class Node(object): """ return [] - def get_implicit_deps(self, env, scanner, path): + def get_implicit_deps(self, env, initial_scanner, path_func, kw = {}): """Return a list of implicit dependencies for this node. This method exists to handle recursive invocation of the scanner on the implicit dependencies returned by the scanner, if the scanner's recursive flag says that we should. """ - if not scanner: - return [] - - # Give the scanner a chance to select a more specific scanner - # for this Node. - #scanner = scanner.select(self) - nodes = [self] seen = {} seen[self] = 1 - deps = [] + dependencies = [] + + root_node_scanner = self._get_scanner(env, initial_scanner, None, kw) + while nodes: - n = nodes.pop(0) - d = [x for x in n.get_found_includes(env, scanner, path) if x not in seen] - if d: - deps.extend(d) - for n in d: - seen[n] = 1 - nodes.extend(scanner.recurse_nodes(d)) + node = nodes.pop(0) - return deps + scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw) + + if not scanner: + continue + path = path_func(scanner) + + included_deps = [x for x in node.get_found_includes(env, scanner, path) if x not in seen] + if included_deps: + dependencies.extend(included_deps) + for dep in included_deps: + seen[dep] = 1 + nodes.extend(scanner.recurse_nodes(included_deps)) + + return dependencies + + def _get_scanner(self, env, initial_scanner, root_node_scanner, kw): + if not initial_scanner: + # handle implicit scanner case + scanner = self.get_env_scanner(env, kw) + if scanner: + scanner = scanner.select(self) + else: + # handle explicit scanner case + scanner = initial_scanner.select(self) + + if not scanner: + # no scanner could be found for the given node's scanner key; + # thus, make an attempt at using a default. + scanner = root_node_scanner + + return scanner + def get_env_scanner(self, env, kw={}): return env.get_scanner(self.scanner_key()) @@ -1260,11 +1281,6 @@ class Node(object): def _add_child(self, collection, set, child): """Adds 'child' to 'collection', first checking 'set' to see if it's already present.""" - #if type(child) is not type([]): - # child = [child] - #for c in child: - # if not isinstance(c, Node): - # raise TypeError, c added = None for c in child: if c not in set: diff --git a/scons/scons-local-2.4.1/SCons/Options/BoolOption.py b/scons/scons-local-2.5.0/SCons/Options/BoolOption.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Options/BoolOption.py rename to scons/scons-local-2.5.0/SCons/Options/BoolOption.py index 62aa952a2..3c583868e 100644 --- a/scons/scons-local-2.4.1/SCons/Options/BoolOption.py +++ b/scons/scons-local-2.5.0/SCons/Options/BoolOption.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/BoolOption.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Options/BoolOption.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Options module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/Options/EnumOption.py b/scons/scons-local-2.5.0/SCons/Options/EnumOption.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Options/EnumOption.py rename to scons/scons-local-2.5.0/SCons/Options/EnumOption.py index 3e689afb0..913aef68f 100644 --- a/scons/scons-local-2.4.1/SCons/Options/EnumOption.py +++ b/scons/scons-local-2.5.0/SCons/Options/EnumOption.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/EnumOption.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Options/EnumOption.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Options module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/Options/ListOption.py b/scons/scons-local-2.5.0/SCons/Options/ListOption.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Options/ListOption.py rename to scons/scons-local-2.5.0/SCons/Options/ListOption.py index c9a7f8f39..820358d3a 100644 --- a/scons/scons-local-2.4.1/SCons/Options/ListOption.py +++ b/scons/scons-local-2.5.0/SCons/Options/ListOption.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/ListOption.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Options/ListOption.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Options module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/Options/PackageOption.py b/scons/scons-local-2.5.0/SCons/Options/PackageOption.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Options/PackageOption.py rename to scons/scons-local-2.5.0/SCons/Options/PackageOption.py index 5a12cbe76..4d27f9cdf 100644 --- a/scons/scons-local-2.4.1/SCons/Options/PackageOption.py +++ b/scons/scons-local-2.5.0/SCons/Options/PackageOption.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/PackageOption.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Options/PackageOption.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Options module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/Options/PathOption.py b/scons/scons-local-2.5.0/SCons/Options/PathOption.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Options/PathOption.py rename to scons/scons-local-2.5.0/SCons/Options/PathOption.py index 00070b142..db7f921f2 100644 --- a/scons/scons-local-2.4.1/SCons/Options/PathOption.py +++ b/scons/scons-local-2.5.0/SCons/Options/PathOption.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/PathOption.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Options/PathOption.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Options module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/Options/__init__.py b/scons/scons-local-2.5.0/SCons/Options/__init__.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Options/__init__.py rename to scons/scons-local-2.5.0/SCons/Options/__init__.py index 5612ad047..6ba4d20ff 100644 --- a/scons/scons-local-2.4.1/SCons/Options/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Options/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Options/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Options module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/PathList.py b/scons/scons-local-2.5.0/SCons/PathList.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/PathList.py rename to scons/scons-local-2.5.0/SCons/PathList.py index 61b64ffaf..a0d9e744e 100644 --- a/scons/scons-local-2.4.1/SCons/PathList.py +++ b/scons/scons-local-2.5.0/SCons/PathList.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/PathList.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/PathList.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """SCons.PathList A module for handling lists of directory paths (the sort of things that get set as CPPPATH, LIBPATH, etc.) with as much caching of data and -efficiency as we can while still keeping the evaluation delayed so that we +efficiency as we can, while still keeping the evaluation delayed so that we Do the Right Thing (almost) regardless of how the variable is specified. """ diff --git a/scons/scons-local-2.4.1/SCons/Platform/__init__.py b/scons/scons-local-2.5.0/SCons/Platform/__init__.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Platform/__init__.py rename to scons/scons-local-2.5.0/SCons/Platform/__init__.py index d8be160dc..e3db28a32 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Platform/__init__.py @@ -12,7 +12,7 @@ environment. Consequently, we'll examine both sys.platform and os.name (and anything else that might come in to play) in order to return some specification which is unique enough for our purposes. -Note that because this subsysem just *selects* a callable that can +Note that because this subsystem just *selects* a callable that can modify a construction environment, it's possible for people to define their own "platform specification" in an arbitrary callable function. No one needs to use or tie in to this subsystem in order to roll @@ -20,7 +20,7 @@ their own platform definition. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -42,7 +42,7 @@ their own platform definition. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.compat diff --git a/scons/scons-local-2.4.1/SCons/Platform/aix.py b/scons/scons-local-2.5.0/SCons/Platform/aix.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Platform/aix.py rename to scons/scons-local-2.5.0/SCons/Platform/aix.py index f36eab68c..65ee701e2 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/aix.py +++ b/scons/scons-local-2.5.0/SCons/Platform/aix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/aix.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/aix.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import subprocess diff --git a/scons/scons-local-2.4.1/SCons/Platform/cygwin.py b/scons/scons-local-2.5.0/SCons/Platform/cygwin.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Platform/cygwin.py rename to scons/scons-local-2.5.0/SCons/Platform/cygwin.py index a901ac363..3f8fc1789 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/cygwin.py +++ b/scons/scons-local-2.5.0/SCons/Platform/cygwin.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/cygwin.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/cygwin.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import posix from SCons.Platform import TempFileMunge diff --git a/scons/scons-local-2.4.1/SCons/Platform/darwin.py b/scons/scons-local-2.5.0/SCons/Platform/darwin.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Platform/darwin.py rename to scons/scons-local-2.5.0/SCons/Platform/darwin.py index 73f140f4e..279cfc296 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/darwin.py +++ b/scons/scons-local-2.5.0/SCons/Platform/darwin.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/darwin.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/darwin.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import posix import os diff --git a/scons/scons-local-2.4.1/SCons/Platform/hpux.py b/scons/scons-local-2.5.0/SCons/Platform/hpux.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Platform/hpux.py rename to scons/scons-local-2.5.0/SCons/Platform/hpux.py index 36e676415..d2de3035d 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/hpux.py +++ b/scons/scons-local-2.5.0/SCons/Platform/hpux.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/hpux.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/hpux.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import posix diff --git a/scons/scons-local-2.4.1/SCons/Platform/irix.py b/scons/scons-local-2.5.0/SCons/Platform/irix.py similarity index 90% rename from scons/scons-local-2.4.1/SCons/Platform/irix.py rename to scons/scons-local-2.5.0/SCons/Platform/irix.py index e947b5484..c55713108 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/irix.py +++ b/scons/scons-local-2.5.0/SCons/Platform/irix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/irix.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/irix.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import posix diff --git a/scons/scons-local-2.4.1/SCons/Platform/os2.py b/scons/scons-local-2.5.0/SCons/Platform/os2.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Platform/os2.py rename to scons/scons-local-2.5.0/SCons/Platform/os2.py index 5f32844d0..736363608 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/os2.py +++ b/scons/scons-local-2.5.0/SCons/Platform/os2.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/os2.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/os2.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import win32 def generate(env): diff --git a/scons/scons-local-2.4.1/SCons/Platform/posix.py b/scons/scons-local-2.5.0/SCons/Platform/posix.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Platform/posix.py rename to scons/scons-local-2.5.0/SCons/Platform/posix.py index 78e80f301..6edfd784a 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/posix.py +++ b/scons/scons-local-2.5.0/SCons/Platform/posix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/posix.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/posix.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import errno import os @@ -48,16 +48,18 @@ exitvalmap = { } def escape(arg): - "escape shell special characters" + "escape shell special characters" slash = '\\' - special = '"$()' + special = '"$' arg = arg.replace(slash, slash+slash) for c in special: arg = arg.replace(c, slash+c) + # print "ESCAPE RESULT: %s"%arg return '"' + arg + '"' + def exec_subprocess(l, env): proc = subprocess.Popen(l, env = env, close_fds = True) return proc.wait() diff --git a/scons/scons-local-2.4.1/SCons/Platform/sunos.py b/scons/scons-local-2.5.0/SCons/Platform/sunos.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Platform/sunos.py rename to scons/scons-local-2.5.0/SCons/Platform/sunos.py index 7646eb7e3..d053e2180 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/sunos.py +++ b/scons/scons-local-2.5.0/SCons/Platform/sunos.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/sunos.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/sunos.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import posix diff --git a/scons/scons-local-2.4.1/SCons/Platform/win32.py b/scons/scons-local-2.5.0/SCons/Platform/win32.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Platform/win32.py rename to scons/scons-local-2.5.0/SCons/Platform/win32.py index f5c787af6..556c7d480 100644 --- a/scons/scons-local-2.4.1/SCons/Platform/win32.py +++ b/scons/scons-local-2.5.0/SCons/Platform/win32.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/win32.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Platform/win32.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path @@ -60,10 +60,8 @@ except AttributeError: else: parallel_msg = None - import builtins - - _builtin_file = builtins.file - _builtin_open = builtins.open + _builtin_file = file + _builtin_open = open class _scons_file(_builtin_file): def __init__(self, *args, **kw): @@ -78,8 +76,8 @@ else: 0) return fp - builtins.file = _scons_file - builtins.open = _scons_open + file = _scons_file + open = _scons_open try: import threading diff --git a/scons/scons-local-2.4.1/SCons/SConf.py b/scons/scons-local-2.5.0/SCons/SConf.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/SConf.py rename to scons/scons-local-2.5.0/SCons/SConf.py index 5a158564f..fb1124b1f 100644 --- a/scons/scons-local-2.4.1/SCons/SConf.py +++ b/scons/scons-local-2.5.0/SCons/SConf.py @@ -12,7 +12,7 @@ libraries are installed, if some command line options are supported etc. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ libraries are installed, if some command line options are supported etc. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/SConf.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/SConf.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.compat @@ -254,14 +254,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): else: self.display('Caught exception while building "%s":\n' % self.targets[0]) - try: - excepthook = sys.excepthook - except AttributeError: - # Earlier versions of Python don't have sys.excepthook... - def excepthook(type, value, tb): - traceback.print_tb(tb) - print type, value - excepthook(*self.exc_info()) + sys.excepthook(*self.exc_info()) return SCons.Taskmaster.Task.failed(self) def collect_node_states(self): @@ -355,8 +348,6 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): raise SCons.Errors.ExplicitExit(self.targets[0],exc_value.code) except Exception, e: for t in self.targets: - #binfo = t.get_binfo() - #binfo.__class__ = SConfBuildInfo binfo = SConfBuildInfo() binfo.merge(t.get_binfo()) binfo.set_build_result(1, s.getvalue()) @@ -375,8 +366,6 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): raise e else: for t in self.targets: - #binfo = t.get_binfo() - #binfo.__class__ = SConfBuildInfo binfo = SConfBuildInfo() binfo.merge(t.get_binfo()) binfo.set_build_result(0, s.getvalue()) @@ -399,16 +388,16 @@ class SConfBase(object): tests, be sure to call the Finish() method, which returns the modified environment. Some words about caching: In most cases, it is not necessary to cache - Test results explicitely. Instead, we use the scons dependency checking + Test results explicitly. Instead, we use the scons dependency checking mechanism. For example, if one wants to compile a test program (SConf.TryLink), the compiler is only called, if the program dependencies have changed. However, if the program could not be compiled in a former - SConf run, we need to explicitely cache this error. + SConf run, we need to explicitly cache this error. """ def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR', log_file='$CONFIGURELOG', config_h = None, _depth = 0): - """Constructor. Pass additional tests in the custom_tests-dictinary, + """Constructor. Pass additional tests in the custom_tests-dictionary, e.g. custom_tests={'CheckPrivate':MyPrivateTest}, where MyPrivateTest defines a custom test. Note also the conf_dir and log_file arguments (you may want to @@ -766,10 +755,10 @@ class CheckContext(object): A typical test is just a callable with an instance of CheckContext as first argument: - def CheckCustom(context, ...) - context.Message('Checking my weird test ... ') - ret = myWeirdTestFunction(...) - context.Result(ret) + def CheckCustom(context, ...): + context.Message('Checking my weird test ... ') + ret = myWeirdTestFunction(...) + context.Result(ret) Often, myWeirdTestFunction will be one of context.TryCompile/context.TryLink/context.TryRun. The results of diff --git a/scons/scons-local-2.4.1/SCons/SConsign.py b/scons/scons-local-2.5.0/SCons/SConsign.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/SConsign.py rename to scons/scons-local-2.5.0/SCons/SConsign.py index 7ce8c5ec2..3166258a3 100644 --- a/scons/scons-local-2.4.1/SCons/SConsign.py +++ b/scons/scons-local-2.5.0/SCons/SConsign.py @@ -5,7 +5,7 @@ Writing and reading information to the .sconsign file or files. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Writing and reading information to the .sconsign file or files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/SConsign.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/SConsign.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.compat diff --git a/scons/scons-local-2.4.1/SCons/Scanner/C.py b/scons/scons-local-2.5.0/SCons/Scanner/C.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Scanner/C.py rename to scons/scons-local-2.5.0/SCons/Scanner/C.py index bdccb34d3..4c6118739 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/C.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/C.py @@ -1,11 +1,11 @@ """SCons.Scanner.C -This module implements the depenency scanner for C/C++ code. +This module implements the dependency scanner for C/C++ code. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the depenency scanner for C/C++ code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/C.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/C.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/scons/scons-local-2.4.1/SCons/Scanner/D.py b/scons/scons-local-2.5.0/SCons/Scanner/D.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Scanner/D.py rename to scons/scons-local-2.5.0/SCons/Scanner/D.py index 0b917d582..eba6e385a 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/D.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/D.py @@ -8,7 +8,7 @@ Coded by Andy Friesen """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ Coded by Andy Friesen # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/D.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/D.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import re diff --git a/scons/scons-local-2.4.1/SCons/Scanner/Dir.py b/scons/scons-local-2.5.0/SCons/Scanner/Dir.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Scanner/Dir.py rename to scons/scons-local-2.5.0/SCons/Scanner/Dir.py index 6956d64fc..d744c41fc 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/Dir.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/Dir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/Dir.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Dir.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/scons/scons-local-2.4.1/SCons/Scanner/Fortran.py b/scons/scons-local-2.5.0/SCons/Scanner/Fortran.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Scanner/Fortran.py rename to scons/scons-local-2.5.0/SCons/Scanner/Fortran.py index 97cd3b261..887232ff1 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/Fortran.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/Fortran.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for Fortran code. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ This module implements the dependency scanner for Fortran code. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/Fortran.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Fortran.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import re diff --git a/scons/scons-local-2.4.1/SCons/Scanner/IDL.py b/scons/scons-local-2.5.0/SCons/Scanner/IDL.py similarity index 88% rename from scons/scons-local-2.4.1/SCons/Scanner/IDL.py rename to scons/scons-local-2.5.0/SCons/Scanner/IDL.py index 0df939ca1..84616e938 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/IDL.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/IDL.py @@ -1,12 +1,12 @@ """SCons.Scanner.IDL -This module implements the depenency scanner for IDL (Interface +This module implements the dependency scanner for IDL (Interface Definition Language) files. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Definition Language) files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/IDL.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/IDL.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/scons/scons-local-2.4.1/SCons/Scanner/LaTeX.py b/scons/scons-local-2.5.0/SCons/Scanner/LaTeX.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/Scanner/LaTeX.py rename to scons/scons-local-2.5.0/SCons/Scanner/LaTeX.py index 487627ca0..10a61973e 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/LaTeX.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/LaTeX.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for LaTeX code. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for LaTeX code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re diff --git a/scons/scons-local-2.4.1/SCons/Scanner/Prog.py b/scons/scons-local-2.5.0/SCons/Scanner/Prog.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Scanner/Prog.py rename to scons/scons-local-2.5.0/SCons/Scanner/Prog.py index d464c89fd..de842d5e2 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/Prog.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/Prog.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Prog.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Prog.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Node import SCons.Node.FS diff --git a/scons/scons-local-2.4.1/SCons/Scanner/RC.py b/scons/scons-local-2.5.0/SCons/Scanner/RC.py similarity index 89% rename from scons/scons-local-2.4.1/SCons/Scanner/RC.py rename to scons/scons-local-2.5.0/SCons/Scanner/RC.py index ea3893b2b..527a0fbf8 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/RC.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/RC.py @@ -1,12 +1,12 @@ """SCons.Scanner.RC -This module implements the depenency scanner for RC (Interface +This module implements the dependency scanner for RC (Interface Definition Language) files. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Definition Language) files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/RC.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/RC.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_io.py b/scons/scons-local-2.5.0/SCons/Scanner/SWIG.py similarity index 65% rename from scons/scons-local-2.4.1/SCons/compat/_scons_io.py rename to scons/scons-local-2.5.0/SCons/Scanner/SWIG.py index 25cf11960..1e70ddc83 100644 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_io.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/SWIG.py @@ -1,5 +1,11 @@ +"""SCons.Scanner.SWIG + +This module implements the dependency scanner for SWIG code. + +""" + # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,22 +27,16 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__doc__ = """ -io compatibility module for older (pre-2.6) Python versions +__revision__ = "src/engine/SCons/Scanner/SWIG.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" -This does not not NOT (repeat, *NOT*) provide complete io -functionality. It only wraps the portions of io functionality used -by SCons, in an interface that looks enough like io for our purposes. -""" +import SCons.Scanner -__revision__ = "src/engine/SCons/compat/_scons_io.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +SWIGSuffixes = [ '.i' ] -# Use the "imp" module to protect the imports below from fixers. -import imp - -_cStringIO = imp.load_module('cStringIO', *imp.find_module('cStringIO')) -StringIO = _cStringIO.StringIO -del _cStringIO +def SWIGScanner(): + expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' + scanner = SCons.Scanner.ClassicCPP("SWIGScanner", ".i", "SWIGPATH", expr) + return scanner # Local Variables: # tab-width:4 diff --git a/scons/scons-local-2.4.1/SCons/Scanner/__init__.py b/scons/scons-local-2.5.0/SCons/Scanner/__init__.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Scanner/__init__.py rename to scons/scons-local-2.5.0/SCons/Scanner/__init__.py index aca07e2c3..b13120cea 100644 --- a/scons/scons-local-2.4.1/SCons/Scanner/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Scanner/__init__.py @@ -5,7 +5,7 @@ The Scanner package for the SCons software construction utility. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ The Scanner package for the SCons software construction utility. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import re diff --git a/scons/scons-local-2.4.1/SCons/Script/Interactive.py b/scons/scons-local-2.5.0/SCons/Script/Interactive.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Script/Interactive.py rename to scons/scons-local-2.5.0/SCons/Script/Interactive.py index afb35af02..bb9ab9332 100644 --- a/scons/scons-local-2.4.1/SCons/Script/Interactive.py +++ b/scons/scons-local-2.5.0/SCons/Script/Interactive.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Script/Interactive.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Script/Interactive.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """ SCons interactive mode @@ -304,14 +304,8 @@ class SConsInteractiveCmd(cmd.Cmd): return self._strip_initial_spaces(doc) def _strip_initial_spaces(self, s): - #lines = s.split('\n') lines = s.split('\n') spaces = re.match(' *', lines[0]).group(0) - #def strip_spaces(l): - # if l.startswith(spaces): - # l = l[len(spaces):] - # return l - #return '\n'.join([ strip_spaces(l) for l in lines ]) def strip_spaces(l, spaces=spaces): if l[:len(spaces)] == spaces: l = l[len(spaces):] diff --git a/scons/scons-local-2.4.1/SCons/Script/Main.py b/scons/scons-local-2.5.0/SCons/Script/Main.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Script/Main.py rename to scons/scons-local-2.5.0/SCons/Script/Main.py index d1ed77a5f..3c5b377ba 100644 --- a/scons/scons-local-2.4.1/SCons/Script/Main.py +++ b/scons/scons-local-2.5.0/SCons/Script/Main.py @@ -10,10 +10,10 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ -unsupported_python_version = (2, 3, 0) +unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ deprecated_python_version = (2, 7, 0) # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Script/Main.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Script/Main.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.compat @@ -43,15 +43,6 @@ import sys import time import traceback -# Strip the script directory from sys.path() so on case-insensitive -# (Windows) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own version directory so, if -# if they're there, we pick up the right version of the build engine -# modules. -#sys.path = [os.path.join(sys.prefix, -# 'lib', -# 'scons-%d' % SCons.__version__)] + sys.path[1:] - import SCons.CacheDir import SCons.Debug import SCons.Defaults @@ -74,7 +65,7 @@ def fetch_win32_parallel_msg(): # so we don't have to pull it in on all platforms, and so that an # in-line "import" statement in the _main() function below doesn't # cause warnings about local names shadowing use of the 'SCons' - # globl in nest scopes and UnboundLocalErrors and the like in some + # global in nest scopes and UnboundLocalErrors and the like in some # versions (2.1) of Python. import SCons.Platform.win32 return SCons.Platform.win32.parallel_msg @@ -368,7 +359,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # issue, an IOError would indicate something like # the file not existing. In either case, print a # message and keep going to try to remove as many - # targets aa possible. + # targets as possible. print "scons: Could not remove '%s':" % str(t), e.strerror else: if removed: @@ -383,7 +374,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # we don't want, like store .sconsign information. executed = SCons.Taskmaster.Task.executed_without_callbacks - # Have the taskmaster arrange to "execute" all of the targets, because + # Have the Taskmaster arrange to "execute" all of the targets, because # we'll figure out ourselves (in remove() or show() above) whether # anything really needs to be done. make_ready = SCons.Taskmaster.Task.make_ready_all @@ -487,7 +478,6 @@ def SetOption(name, value): def PrintHelp(file=None): OptionsParser.print_help(file=file) -# class Stats(object): def __init__(self): self.stats = [] @@ -574,7 +564,7 @@ def find_deepest_user_frame(tb): def _scons_user_error(e): """Handle user errors. Print out a message and a description of the - error, along with the line number and routine where it occured. + error, along with the line number and routine where it occurred. The file and line number will be the deepest stack frame that is not part of SCons itself. """ @@ -589,7 +579,7 @@ def _scons_user_error(e): def _scons_user_warning(e): """Handle user warnings. Print out a message and a description of - the warning, along with the line number and routine where it occured. + the warning, along with the line number and routine where it occurred. The file and line number will be the deepest stack frame that is not part of SCons itself. """ @@ -711,7 +701,6 @@ def _load_site_scons_dir(topdir, site_dir_name=None): site_tools_dir = os.path.join(site_dir, site_tools_dirname) if os.path.exists(site_init_file): import imp, re - # TODO(2.4): turn this into try:-except:-finally: try: try: fp, pathname, description = imp.find_module(site_init_modname, @@ -1024,7 +1013,7 @@ def _main(parser): # the SConscript file. # # We delay enabling the PythonVersionWarning class until here so that, - # if they explicity disabled it in either in the command line or in + # if they explicitly disabled it in either in the command line or in # $SCONSFLAGS, or in the SConscript file, then the search through # the list of deprecated warning classes will find that disabling # first and not issue the warning. @@ -1232,13 +1221,8 @@ def _build_targets(fs, options, targets, target_top): def order(dependencies): """Randomize the dependencies.""" import random - # This is cribbed from the implementation of - # random.shuffle() in Python 2.X. - d = dependencies - for i in range(len(d)-1, 0, -1): - j = int(random.random() * (i+1)) - d[i], d[j] = d[j], d[i] - return d + random.shuffle(dependencies) + return dependencies else: def order(dependencies): """Leave the order of dependencies alone.""" @@ -1316,18 +1300,6 @@ def _exec_main(parser, values): # compat layer imports "cProfile" for us if it's available. from profile import Profile - # Some versions of Python 2.4 shipped a profiler that had the - # wrong 'c_exception' entry in its dispatch table. Make sure - # we have the right one. (This may put an unnecessary entry - # in the table in earlier versions of Python, but its presence - # shouldn't hurt anything). - try: - dispatch = Profile.dispatch - except AttributeError: - pass - else: - dispatch['c_exception'] = Profile.trace_dispatch_return - prof = Profile() try: prof.runcall(_main, parser) @@ -1360,7 +1332,7 @@ def main(): pass parts.append(version_string("engine", SCons)) parts.append(path_string("engine", SCons)) - parts.append("Copyright (c) 2001 - 2015 The SCons Foundation") + parts.append("Copyright (c) 2001 - 2016 The SCons Foundation") version = ''.join(parts) import SConsOptions diff --git a/scons/scons-local-2.4.1/SCons/Script/SConsOptions.py b/scons/scons-local-2.5.0/SCons/Script/SConsOptions.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Script/SConsOptions.py rename to scons/scons-local-2.5.0/SCons/Script/SConsOptions.py index 6d02b0a65..9e9d5ce0c 100644 --- a/scons/scons-local-2.4.1/SCons/Script/SConsOptions.py +++ b/scons/scons-local-2.5.0/SCons/Script/SConsOptions.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/SConsOptions.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Script/SConsOptions.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import optparse import re @@ -426,7 +426,7 @@ class SConsOptionParser(optparse.OptionParser): result = group.add_option(*args, **kw) if result: - # The option was added succesfully. We now have to add the + # The option was added successfully. We now have to add the # default value to our object that holds the default values # (so that an attempt to fetch the option's attribute will # yield the default value when not overridden) and then @@ -449,11 +449,6 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): "SCons Options." Unfortunately, we have to do this here, because those titles are hard-coded in the optparse calls. """ - if heading == 'options': - # The versions of optparse.py shipped with Pythons 2.3 and - # 2.4 pass this in uncapitalized; override that so we get - # consistent output on all versions. - heading = "Options" if heading == 'Options': heading = "SCons Options" return optparse.IndentedHelpFormatter.format_heading(self, heading) @@ -488,13 +483,7 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): # read data from FILENAME result = [] - try: - opts = self.option_strings[option] - except AttributeError: - # The Python 2.3 version of optparse attaches this to - # to the option argument, not to this object. - opts = option.option_strings - + opts = self.option_strings[option] opt_width = self.help_position - self.current_indent - 2 if len(opts) > opt_width: wrapper = textwrap.TextWrapper(width=self.width, @@ -509,14 +498,7 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): result.append(opts) if option.help: - try: - expand_default = self.expand_default - except AttributeError: - # The HelpFormatter base class in the Python 2.3 version - # of optparse has no expand_default() method. - help_text = option.help - else: - help_text = expand_default(option) + help_text = self.expand_default(option) # SCons: indent every line of the help text but the first. wrapper = textwrap.TextWrapper(width=self.help_width, @@ -530,34 +512,6 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): result.append("\n") return "".join(result) - # For consistent help output across Python versions, we provide a - # subclass copy of format_option_strings() and these two variables. - # This is necessary (?) for Python2.3, which otherwise concatenates - # a short option with its metavar. - _short_opt_fmt = "%s %s" - _long_opt_fmt = "%s=%s" - - def format_option_strings(self, option): - """Return a comma-separated list of option strings & metavariables.""" - if option.takes_value(): - metavar = option.metavar or option.dest.upper() - short_opts = [] - for sopt in option._short_opts: - short_opts.append(self._short_opt_fmt % (sopt, metavar)) - long_opts = [] - for lopt in option._long_opts: - long_opts.append(self._long_opt_fmt % (lopt, metavar)) - else: - short_opts = option._short_opts - long_opts = option._long_opts - - if self.short_first: - opts = short_opts + long_opts - else: - opts = long_opts + short_opts - - return ", ".join(opts) - def Parser(version): """ Returns an options parser object initialized with the standard diff --git a/scons/scons-local-2.4.1/SCons/Script/SConscript.py b/scons/scons-local-2.5.0/SCons/Script/SConscript.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Script/SConscript.py rename to scons/scons-local-2.5.0/SCons/Script/SConscript.py index 2d66f5c5a..3f6c4e393 100644 --- a/scons/scons-local-2.4.1/SCons/Script/SConscript.py +++ b/scons/scons-local-2.5.0/SCons/Script/SConscript.py @@ -6,7 +6,7 @@ files. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import division -__revision__ = "src/engine/SCons/Script/SConscript.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Script/SConscript.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons import SCons.Action @@ -52,16 +52,6 @@ import re import sys import traceback -# The following variables used to live in this module. Some -# SConscript files out there may have referred to them directly as -# SCons.Script.SConscript.*. This is now supported by some special -# handling towards the bottom of the SConscript.__init__.py module. -#Arguments = {} -#ArgList = [] -#BuildTargets = TargetList() -#CommandLineTargets = [] -#DefaultTargets = [] - class SConscriptReturn(Exception): pass @@ -446,7 +436,7 @@ class SConsEnvironment(SCons.Environment.Base): # # Public methods of an SConsEnvironment. These get - # entry points in the global name space so they can be called + # entry points in the global namespace so they can be called # as global functions. # diff --git a/scons/scons-local-2.4.1/SCons/Script/__init__.py b/scons/scons-local-2.5.0/SCons/Script/__init__.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Script/__init__.py rename to scons/scons-local-2.5.0/SCons/Script/__init__.py index f9c4e514e..56f06cfcc 100644 --- a/scons/scons-local-2.4.1/SCons/Script/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Script/__init__.py @@ -12,7 +12,7 @@ it goes here. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ it goes here. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Script/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import time start_time = time.time() @@ -270,12 +270,6 @@ def HelpFunction(text, append=False): s.close() else: help_text = "" -# -# Was in original patch but this text is arbitrary and breaks tests -# so I removed it (Deegan) -# help_text = help_text + "\nLocal Build Variables:\n" + text -# else: -# help_text = help_text + text help_text= help_text + text diff --git a/scons/scons-local-2.4.1/SCons/Sig.py b/scons/scons-local-2.5.0/SCons/Sig.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Sig.py rename to scons/scons-local-2.5.0/SCons/Sig.py index 6069d55d4..2d090982b 100644 --- a/scons/scons-local-2.4.1/SCons/Sig.py +++ b/scons/scons-local-2.5.0/SCons/Sig.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Sig.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Sig.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Place-holder for the old SCons.Sig module hierarchy diff --git a/scons/scons-local-2.4.1/SCons/Subst.py b/scons/scons-local-2.5.0/SCons/Subst.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Subst.py rename to scons/scons-local-2.5.0/SCons/Subst.py index 8a3a35963..63c15423b 100644 --- a/scons/scons-local-2.4.1/SCons/Subst.py +++ b/scons/scons-local-2.5.0/SCons/Subst.py @@ -5,7 +5,7 @@ SCons string substitution. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ SCons string substitution. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Subst.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Subst.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import collections import re @@ -344,7 +344,6 @@ _remove = re.compile(r'\$\([^\$]*(\$[^\)][^\$]*)*\$\)') _regex_remove = [ _rm, None, _remove ] def _rm_list(list): - #return [ l for l in list if not l in ('$(', '$)') ] return [l for l in list if not l in ('$(', '$)')] def _remove_list(list): @@ -580,8 +579,6 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ return result -#Subst_List_Strings = {} - def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None): """Substitute construction variables in a string (or list or other object) and separate the arguments into a command list. @@ -590,12 +587,6 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv substitutions within strings, so see that function instead if that's what you're looking for. """ -# try: -# Subst_List_Strings[strSubst] = Subst_List_Strings[strSubst] + 1 -# except KeyError: -# Subst_List_Strings[strSubst] = 1 -# import SCons.Debug -# SCons.Debug.caller_trace(1) class ListSubber(collections.UserList): """A class to construct the results of a scons_subst_list() call. diff --git a/scons/scons-local-2.4.1/SCons/Taskmaster.py b/scons/scons-local-2.5.0/SCons/Taskmaster.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Taskmaster.py rename to scons/scons-local-2.5.0/SCons/Taskmaster.py index f77bde1fb..829e1fc30 100644 --- a/scons/scons-local-2.4.1/SCons/Taskmaster.py +++ b/scons/scons-local-2.5.0/SCons/Taskmaster.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -47,7 +47,7 @@ interface and the SCons build engine. There are two key classes here: target(s) that it decides need to be evaluated and/or built. """ -__revision__ = "src/engine/SCons/Taskmaster.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Taskmaster.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from itertools import chain import operator @@ -107,7 +107,7 @@ fmt = "%(considered)3d "\ def dump_stats(): for n in sorted(StatsNodes, key=lambda a: str(a)): - print (fmt % n.stats.__dict__) + str(n) + print (fmt % n.attributes.stats.__dict__) + str(n) @@ -122,7 +122,7 @@ class Task(object): aspects of controlling a build, so any given application *should* be able to do what it wants by sub-classing this class and overriding methods as appropriate. If an application - needs to customze something by sub-classing Taskmaster (or + needs to customize something by sub-classing Taskmaster (or some other build engine class), we should first try to migrate that functionality into this class. @@ -147,7 +147,7 @@ class Task(object): This hook gets called as part of preparing a task for execution (that is, a Node to be built). As part of figuring out what Node - should be built next, the actually target list may be altered, + should be built next, the actual target list may be altered, along with a message describing the alteration. The calling interface can subclass Task and provide a concrete implementation of this method to see those messages. @@ -664,9 +664,9 @@ class Taskmaster(object): its parent node. A pending child can occur when the Taskmaster completes a loop - through a cycle. For example, lets imagine a graph made of - three node (A, B and C) making a cycle. The evaluation starts - at node A. The taskmaster first consider whether node A's + through a cycle. For example, let's imagine a graph made of + three nodes (A, B and C) making a cycle. The evaluation starts + at node A. The Taskmaster first considers whether node A's child B is up-to-date. Then, recursively, node B needs to check whether node C is up-to-date. This leaves us with a dependency graph looking like: @@ -781,10 +781,10 @@ class Taskmaster(object): # return node if CollectStats: - if not hasattr(node, 'stats'): - node.stats = Stats() + if not hasattr(node.attributes, 'stats'): + node.attributes.stats = Stats() StatsNodes.append(node) - S = node.stats + S = node.attributes.stats S.considered = S.considered + 1 else: S = None @@ -951,7 +951,7 @@ class Taskmaster(object): task.make_ready() except: # We had a problem just trying to get this task ready (like - # a child couldn't be linked in to a VariantDir when deciding + # a child couldn't be linked to a VariantDir when deciding # whether this node is current). Arrange to raise the # exception when the Task is "executed." self.ready_exc = sys.exc_info() diff --git a/scons/scons-local-2.4.1/SCons/Tool/386asm.py b/scons/scons-local-2.5.0/SCons/Tool/386asm.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/386asm.py rename to scons/scons-local-2.5.0/SCons/Tool/386asm.py index 56b8b3858..2a87a2819 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/386asm.py +++ b/scons/scons-local-2.5.0/SCons/Tool/386asm.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/386asm.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/386asm.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.PharLapCommon import addPharLapPaths import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/BitKeeper.py b/scons/scons-local-2.5.0/SCons/Tool/BitKeeper.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/BitKeeper.py rename to scons/scons-local-2.5.0/SCons/Tool/BitKeeper.py index 88fabd1e2..21a2ab3da 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/BitKeeper.py +++ b/scons/scons-local-2.5.0/SCons/Tool/BitKeeper.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/BitKeeper.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/BitKeeper.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder @@ -49,7 +49,6 @@ def generate(env): act = SCons.Action.Action("$BITKEEPERCOM", "$BITKEEPERCOMSTR") return SCons.Builder.Builder(action = act, env = env) - #setattr(env, 'BitKeeper', BitKeeperFactory) env.BitKeeper = BitKeeperFactory env['BITKEEPER'] = 'bk' diff --git a/scons/scons-local-2.4.1/SCons/Tool/CVS.py b/scons/scons-local-2.5.0/SCons/Tool/CVS.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/CVS.py rename to scons/scons-local-2.5.0/SCons/Tool/CVS.py index e85223680..91a8d627a 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/CVS.py +++ b/scons/scons-local-2.5.0/SCons/Tool/CVS.py @@ -8,7 +8,7 @@ selection method. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/CVS.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/CVS.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder @@ -55,7 +55,6 @@ def generate(env): CVSREPOSITORY = repos, CVSMODULE = module) - #setattr(env, 'CVS', CVSFactory) env.CVS = CVSFactory env['CVS'] = 'cvs' diff --git a/scons/scons-local-2.4.1/SCons/Tool/DCommon.py b/scons/scons-local-2.5.0/SCons/Tool/DCommon.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/DCommon.py rename to scons/scons-local-2.5.0/SCons/Tool/DCommon.py index c38334932..8738ece72 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/DCommon.py +++ b/scons/scons-local-2.5.0/SCons/Tool/DCommon.py @@ -6,7 +6,7 @@ Coded by Russel Winder (russel@winder.org.uk) 2012-09-06 """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Coded by Russel Winder (russel@winder.org.uk) # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/DCommon.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/DCommon.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/FortranCommon.py b/scons/scons-local-2.5.0/SCons/Tool/FortranCommon.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/FortranCommon.py rename to scons/scons-local-2.5.0/SCons/Tool/FortranCommon.py index 45bd6485e..cf6486880 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/FortranCommon.py +++ b/scons/scons-local-2.5.0/SCons/Tool/FortranCommon.py @@ -5,7 +5,7 @@ Stuff for processing Fortran, common to all fortran dialects. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Stuff for processing Fortran, common to all fortran dialects. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/FortranCommon.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/FortranCommon.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import re import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/GettextCommon.py b/scons/scons-local-2.5.0/SCons/Tool/GettextCommon.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/GettextCommon.py rename to scons/scons-local-2.5.0/SCons/Tool/GettextCommon.py index 36f8fa23a..6dfb615b5 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/GettextCommon.py +++ b/scons/scons-local-2.5.0/SCons/Tool/GettextCommon.py @@ -3,7 +3,7 @@ Used by several tools of `gettext` toolset. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Used by several tools of `gettext` toolset. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/GettextCommon.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/GettextCommon.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Warnings import re @@ -251,7 +251,7 @@ class RPaths(object): recently re-created. For such reason, we need a function, which always returns relative paths. This is the purpose of `RPaths` callable object. - The `__call__` method returns paths relative to current woking directory, but + The `__call__` method returns paths relative to current working directory, but we assume, that *xgettext(1)* is run from the directory, where target file is going to be created. @@ -330,7 +330,7 @@ def _init_po_files(target, source, env): autoinit = False # Well, if everything outside works well, this loop should do single # iteration. Otherwise we are rebuilding all the targets even, if just - # one has changed (but is this out fault?). + # one has changed (but is this our fault?). for tgt in target: if not tgt.exists(): if autoinit: diff --git a/scons/scons-local-2.4.1/SCons/Tool/JavaCommon.py b/scons/scons-local-2.5.0/SCons/Tool/JavaCommon.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/JavaCommon.py rename to scons/scons-local-2.5.0/SCons/Tool/JavaCommon.py index 0c149957f..26be53027 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/JavaCommon.py +++ b/scons/scons-local-2.5.0/SCons/Tool/JavaCommon.py @@ -5,7 +5,7 @@ Stuff for processing Java. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Stuff for processing Java. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommon.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommon.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/__init__.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/__init__.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/__init__.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/__init__.py index 6340a3048..8e72feaea 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """ Common functions for Microsoft Visual Studio and Visual C/C++. diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/arch.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/arch.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/arch.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/arch.py index 804721521..f7d28daf4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/arch.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/arch.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Module to define supported Windows chip architectures. """ diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/common.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/common.py similarity index 89% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/common.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/common.py index a7bc4070e..59296c229 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/common.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/common.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """ Common helper functions for working with the Microsoft tool chain. @@ -93,7 +93,7 @@ def has_reg(value): try: SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, value) ret = True - except WindowsError: + except SCons.Util.WinError: ret = False return ret @@ -180,7 +180,7 @@ def get_output(vcbat, args = None, env = None): stdout = popen.stdout.read() stderr = popen.stderr.read() - # Extra debug logic, uncomment if necessar + # Extra debug logic, uncomment if necessary # debug('get_output():stdout:%s'%stdout) # debug('get_output():stderr:%s'%stderr) @@ -226,33 +226,6 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): return dkeep -# TODO(sgk): unused -def output_to_dict(output): - """Given an output string, parse it to find env variables. - - Return a dict where keys are variables names, and values their content""" - envlinem = re.compile(r'^([a-zA-z0-9]+)=([\S\s]*)$') - parsedenv = {} - for line in output.splitlines(): - m = envlinem.match(line) - if m: - parsedenv[m.group(1)] = m.group(2) - return parsedenv - -# TODO(sgk): unused -def get_new(l1, l2): - """Given two list l1 and l2, return the items in l2 which are not in l1. - Order is maintained.""" - - # We don't try to be smart: lists are small, and this is not the bottleneck - # is any case - new = [] - for i in l2: - if i not in l1: - new.append(i) - - return new - # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/netframework.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/netframework.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/netframework.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/netframework.py index 6062e1178..935a8a5e8 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/netframework.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/netframework.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,13 +20,14 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """ """ import os import re +import SCons.Util from common import read_reg, debug @@ -40,7 +41,7 @@ def find_framework_root(): try: froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT) debug("Found framework install root in registry: %s" % froot) - except WindowsError, e: + except SCons.Util.WinError, e: debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT) return None diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/sdk.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/sdk.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/sdk.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/sdk.py index 1b605b967..601f4f8f4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/sdk.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/sdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Module to detect the Platform/Windows SDK @@ -80,7 +80,7 @@ class SDKDefinition(object): try: sdk_dir = common.read_reg(hkey) - except WindowsError, e: + except SCons.Util.WinError, e: debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) return None @@ -168,7 +168,7 @@ SDK70VCSetupScripts = { 'x86' : r'bin\vcvars32.bat', # # The first SDK found in the list is the one used by default if there # are multiple SDKs installed. Barring good reasons to the contrary, -# this means we should list SDKs with from most recent to oldest. +# this means we should list SDKs from most recent to oldest. # # If you update this list, update the documentation in Tool/mssdk.xml. SupportedSDKList = [ @@ -306,29 +306,6 @@ def set_sdk_by_directory(env, sdk_dir): for variable, directory in env_tuple_list: env.PrependENVPath(variable, directory) - -# TODO(sgk): currently unused; remove? -def get_cur_sdk_dir_from_reg(): - """Try to find the platform sdk directory from the registry. - - Return None if failed or the directory does not exist""" - if not SCons.Util.can_read_reg: - debug('SCons cannot read registry') - return None - - try: - val = common.read_reg(_CURINSTALLED_SDK_HKEY_ROOT) - debug("Found current sdk dir in registry: %s" % val) - except WindowsError, e: - debug("Did not find current sdk in registry") - return None - - if not os.path.exists(val): - debug("Current sdk dir %s not on fs" % val) - return None - - return val - def get_sdk_by_version(mssdk): if mssdk not in SupportedSDKMap: msg = "SDK version %s is not supported" % repr(mssdk) @@ -343,9 +320,6 @@ def get_default_sdk(): return None return InstalledSDKList[0] - - - def mssdk_setup_env(env): debug('sdk.py:mssdk_setup_env()') if 'MSSDK_DIR' in env: diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/vc.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/vc.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/vc.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/vc.py index 7f124082c..baf859afd 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/vc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/vc.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Module for Visual C/C++ detection and configuration. """ @@ -244,13 +244,13 @@ def find_vc_pdir(msvc_version): try: # ordinally at win64, try Wow6432Node first. comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) - except WindowsError, e: + except SCons.Util.WinError, e: # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node pass if not comps: # not Win64, or Microsoft Visual Studio for Python 2.7 comps = common.read_reg(root + key, hkroot) - except WindowsError, e: + except SCons.Util.WinError, e: debug('find_vc_dir(): no VC registry key %s' % repr(key)) else: debug('find_vc_dir(): found VC in registry: %s' % comps) diff --git a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/vs.py b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/vs.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/MSCommon/vs.py rename to scons/scons-local-2.5.0/SCons/Tool/MSCommon/vs.py index 86cd3a49b..82b989d82 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/MSCommon/vs.py +++ b/scons/scons-local-2.5.0/SCons/Tool/MSCommon/vs.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """Module to detect Visual Studio and/or Visual C/C++ """ @@ -52,8 +52,6 @@ class VisualStudio(object): self.__dict__.update(kw) self._cache = {} - # - def find_batch_file(self): vs_dir = self.get_vs_dir() if not vs_dir: @@ -85,7 +83,7 @@ class VisualStudio(object): key = root + key try: comps = read_reg(key) - except WindowsError, e: + except SCons.Util.WinError, e: debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) else: debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) @@ -116,8 +114,6 @@ class VisualStudio(object): return None return executable - # - def get_batch_file(self): try: return self._cache['batch_file'] @@ -471,7 +467,7 @@ def get_default_version(env): """Returns the default version string to use for MSVS. If no version was requested by the user through the MSVS environment - variable, query all the available the visual studios through + variable, query all the available visual studios through get_installed_visual_studios, and take the highest one. Return diff --git a/scons/scons-local-2.4.1/SCons/Tool/Perforce.py b/scons/scons-local-2.5.0/SCons/Tool/Perforce.py similarity index 90% rename from scons/scons-local-2.4.1/SCons/Tool/Perforce.py rename to scons/scons-local-2.5.0/SCons/Tool/Perforce.py index 409c7bea8..47d609658 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/Perforce.py +++ b/scons/scons-local-2.5.0/SCons/Tool/Perforce.py @@ -8,7 +8,7 @@ selection method. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/Perforce.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/Perforce.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os @@ -38,9 +38,6 @@ import SCons.Builder import SCons.Node.FS import SCons.Util -# This function should maybe be moved to SCons.Util? -from SCons.Tool.PharLapCommon import addPathIfNotExists - # Variables that we want to import from the base OS environment. _import_env = [ 'P4PORT', 'P4CLIENT', 'P4USER', 'USER', 'USERNAME', 'P4PASSWD', @@ -58,7 +55,6 @@ def generate(env): W.warn(W.DeprecatedSourceCodeWarning, """The Perforce() factory is deprecated and there is no replacement.""") return SCons.Builder.Builder(action = PerforceAction, env = env) - #setattr(env, 'Perforce', PerforceFactory) env.Perforce = PerforceFactory env['P4'] = 'p4' @@ -87,7 +83,7 @@ def generate(env): k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, 'Software\\Perforce\\environment') val, tok = SCons.Util.RegQueryValueEx(k, 'P4INSTROOT') - addPathIfNotExists(environ, 'PATH', val) + SCons.Util.AddPathIfNotExists(environ, 'PATH', val) except SCons.Util.RegError: # Can't detect where Perforce is, hope the user has it set in the # PATH. diff --git a/scons/scons-local-2.4.1/SCons/Tool/PharLapCommon.py b/scons/scons-local-2.5.0/SCons/Tool/PharLapCommon.py similarity index 72% rename from scons/scons-local-2.4.1/SCons/Tool/PharLapCommon.py rename to scons/scons-local-2.5.0/SCons/Tool/PharLapCommon.py index 46acb2ceb..863d2080f 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/PharLapCommon.py +++ b/scons/scons-local-2.5.0/SCons/Tool/PharLapCommon.py @@ -7,7 +7,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/PharLapCommon.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/PharLapCommon.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path @@ -85,28 +85,6 @@ def getPharLapVersion(): # Default return for Phar Lap 9.1 return 910 -def addPathIfNotExists(env_dict, key, path, sep=os.pathsep): - """This function will take 'key' out of the dictionary - 'env_dict', then add the path 'path' to that key if it is not - already there. This treats the value of env_dict[key] as if it - has a similar format to the PATH variable...a list of paths - separated by tokens. The 'path' will get added to the list if it - is not already there.""" - try: - is_list = 1 - paths = env_dict[key] - if not SCons.Util.is_List(env_dict[key]): - paths = paths.split(sep) - is_list = 0 - if os.path.normcase(path) not in list(map(os.path.normcase, paths)): - paths = [ path ] + paths - if is_list: - env_dict[key] = paths - else: - env_dict[key] = sep.join(paths) - except KeyError: - env_dict[key] = path - def addPharLapPaths(env): """This function adds the path to the Phar Lap binaries, includes, and libraries, if they are not already there.""" @@ -117,14 +95,14 @@ def addPharLapPaths(env): except KeyError: env_dict = {} env['ENV'] = env_dict - addPathIfNotExists(env_dict, 'PATH', - os.path.join(ph_path, 'bin')) - addPathIfNotExists(env_dict, 'INCLUDE', - os.path.join(ph_path, 'include')) - addPathIfNotExists(env_dict, 'LIB', - os.path.join(ph_path, 'lib')) - addPathIfNotExists(env_dict, 'LIB', - os.path.join(ph_path, os.path.normpath('lib/vclib'))) + SCons.Util.AddPathIfNotExists(env_dict, 'PATH', + os.path.join(ph_path, 'bin')) + SCons.Util.AddPathIfNotExists(env_dict, 'INCLUDE', + os.path.join(ph_path, 'include')) + SCons.Util.AddPathIfNotExists(env_dict, 'LIB', + os.path.join(ph_path, 'lib')) + SCons.Util.AddPathIfNotExists(env_dict, 'LIB', + os.path.join(ph_path, os.path.normpath('lib/vclib'))) env['PHARLAP_PATH'] = getPharLapPath() env['PHARLAP_VERSION'] = str(getPharLapVersion()) diff --git a/scons/scons-local-2.4.1/SCons/Tool/RCS.py b/scons/scons-local-2.5.0/SCons/Tool/RCS.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/RCS.py rename to scons/scons-local-2.5.0/SCons/Tool/RCS.py index 177e8285d..29dec38d8 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/RCS.py +++ b/scons/scons-local-2.5.0/SCons/Tool/RCS.py @@ -8,7 +8,7 @@ selection method. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/RCS.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/RCS.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder @@ -46,7 +46,6 @@ def generate(env): act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR') return SCons.Builder.Builder(action = act, env = env) - #setattr(env, 'RCS', RCSFactory) env.RCS = RCSFactory env['RCS'] = 'rcs' diff --git a/scons/scons-local-2.4.1/SCons/Tool/SCCS.py b/scons/scons-local-2.5.0/SCons/Tool/SCCS.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/SCCS.py rename to scons/scons-local-2.5.0/SCons/Tool/SCCS.py index 772c8897e..faf10b550 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/SCCS.py +++ b/scons/scons-local-2.5.0/SCons/Tool/SCCS.py @@ -8,7 +8,7 @@ selection method. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/SCCS.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/SCCS.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder @@ -46,7 +46,6 @@ def generate(env): act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR') return SCons.Builder.Builder(action = act, env = env) - #setattr(env, 'SCCS', SCCSFactory) env.SCCS = SCCSFactory env['SCCS'] = 'sccs' diff --git a/scons/scons-local-2.4.1/SCons/Tool/Subversion.py b/scons/scons-local-2.5.0/SCons/Tool/Subversion.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/Subversion.py rename to scons/scons-local-2.5.0/SCons/Tool/Subversion.py index cfcf7e77f..f1f10df26 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/Subversion.py +++ b/scons/scons-local-2.5.0/SCons/Tool/Subversion.py @@ -8,7 +8,7 @@ selection method. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/Subversion.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/Subversion.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path @@ -54,7 +54,6 @@ def generate(env): SVNREPOSITORY = repos, SVNMODULE = module) - #setattr(env, 'Subversion', SubversionFactory) env.Subversion = SubversionFactory env['SVN'] = 'svn' diff --git a/scons/scons-local-2.4.1/SCons/Tool/__init__.py b/scons/scons-local-2.5.0/SCons/Tool/__init__.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/Tool/__init__.py rename to scons/scons-local-2.5.0/SCons/Tool/__init__.py index ac2413459..0207292d7 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Tool/__init__.py @@ -14,7 +14,7 @@ tool definition. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -35,7 +35,7 @@ tool definition. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import imp import sys @@ -51,6 +51,7 @@ import SCons.Scanner.C import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog +import SCons.Scanner.SWIG DefaultToolpath=[] @@ -60,6 +61,7 @@ LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner() PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner() ProgramScanner = SCons.Scanner.Prog.ProgramScanner() SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner') +SWIGScanner = SCons.Scanner.SWIG.SWIGScanner() CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", ".h", ".H", ".hxx", ".hpp", ".hh", @@ -73,12 +75,17 @@ IDLSuffixes = [".idl", ".IDL"] LaTeXSuffixes = [".tex", ".ltx", ".latex"] +SWIGSuffixes = ['.i'] + for suffix in CSuffixes: SourceFileScanner.add_scanner(suffix, CScanner) for suffix in DSuffixes: SourceFileScanner.add_scanner(suffix, DScanner) +for suffix in SWIGSuffixes: + SourceFileScanner.add_scanner(suffix, SWIGScanner) + # FIXME: what should be done here? Two scanners scan the same extensions, # but look for different files, e.g., "picture.eps" vs. "picture.pdf". # The builders for DVI and PDF explicitly reference their scanners @@ -101,7 +108,7 @@ class Tool(object): self.options = module.options def _tool_module(self): - # TODO: Interchange zipimport with normal initilization for better error reporting + # TODO: Interchange zipimport with normal initialization for better error reporting oldpythonpath = sys.path sys.path = self.toolpath + sys.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/aixc++.py b/scons/scons-local-2.5.0/SCons/Tool/aixc++.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/aixc++.py rename to scons/scons-local-2.5.0/SCons/Tool/aixc++.py index a3fa10216..699dacb8d 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/aixc++.py +++ b/scons/scons-local-2.5.0/SCons/Tool/aixc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixc++.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixc++.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/aixcc.py b/scons/scons-local-2.5.0/SCons/Tool/aixcc.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/aixcc.py rename to scons/scons-local-2.5.0/SCons/Tool/aixcc.py index 8c7d71bb0..30735c96a 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/aixcc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/aixcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixcc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixcc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/aixf77.py b/scons/scons-local-2.5.0/SCons/Tool/aixf77.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/aixf77.py rename to scons/scons-local-2.5.0/SCons/Tool/aixf77.py index 7603a4a53..f23c1cbd8 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/aixf77.py +++ b/scons/scons-local-2.5.0/SCons/Tool/aixf77.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixf77.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixf77.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path @@ -41,7 +41,7 @@ import f77 # It would be good to look for the AIX F77 package the same way we're now # looking for the C and C++ packages. This should be as easy as supplying # the correct package names in the following list and uncommenting the -# SCons.Platform.aix_get_xlc() call the in the function below. +# SCons.Platform.aix_get_xlc() call in the function below. packages = [] def get_xlf77(env): diff --git a/scons/scons-local-2.4.1/SCons/Tool/aixlink.py b/scons/scons-local-2.5.0/SCons/Tool/aixlink.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/aixlink.py rename to scons/scons-local-2.5.0/SCons/Tool/aixlink.py index 2e6e65254..483068c4f 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/aixlink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/aixlink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixlink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixlink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/applelink.py b/scons/scons-local-2.5.0/SCons/Tool/applelink.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/applelink.py rename to scons/scons-local-2.5.0/SCons/Tool/applelink.py index e48689c2e..4e7a679d2 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/applelink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/applelink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/applelink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/applelink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/ar.py b/scons/scons-local-2.5.0/SCons/Tool/ar.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/ar.py rename to scons/scons-local-2.5.0/SCons/Tool/ar.py index ca0dc2429..a64ddfaee 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ar.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ar.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ar.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/as.py b/scons/scons-local-2.5.0/SCons/Tool/as.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/as.py rename to scons/scons-local-2.5.0/SCons/Tool/as.py index 1b122d0f6..75992d59e 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/as.py +++ b/scons/scons-local-2.5.0/SCons/Tool/as.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/as.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/as.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/bcc32.py b/scons/scons-local-2.5.0/SCons/Tool/bcc32.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/bcc32.py rename to scons/scons-local-2.5.0/SCons/Tool/bcc32.py index 15e21222b..ffd29f263 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/bcc32.py +++ b/scons/scons-local-2.5.0/SCons/Tool/bcc32.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/bcc32.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/bcc32.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/c++.py b/scons/scons-local-2.5.0/SCons/Tool/c++.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/c++.py rename to scons/scons-local-2.5.0/SCons/Tool/c++.py index 00630fe6f..b0c4e62e3 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/c++.py +++ b/scons/scons-local-2.5.0/SCons/Tool/c++.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/c++.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/c++.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/cc.py b/scons/scons-local-2.5.0/SCons/Tool/cc.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/cc.py rename to scons/scons-local-2.5.0/SCons/Tool/cc.py index c34dad2bb..b0a73f843 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/cc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/cc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Tool import SCons.Defaults diff --git a/scons/scons-local-2.4.1/SCons/Tool/cvf.py b/scons/scons-local-2.5.0/SCons/Tool/cvf.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/cvf.py rename to scons/scons-local-2.5.0/SCons/Tool/cvf.py index 51c137fbe..06ea06378 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/cvf.py +++ b/scons/scons-local-2.5.0/SCons/Tool/cvf.py @@ -5,7 +5,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cvf.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cvf.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import fortran diff --git a/scons/scons-local-2.4.1/SCons/Tool/cyglink.py b/scons/scons-local-2.5.0/SCons/Tool/cyglink.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/Tool/cyglink.py rename to scons/scons-local-2.5.0/SCons/Tool/cyglink.py index 5230910ae..921f0ebf4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/cyglink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/cyglink.py @@ -143,7 +143,7 @@ def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): implib_libtype=kw['libtype']) def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): - """Generate link names that should be created for a versioned shared lirbrary. + """Generate link names that should be created for a versioned shared library. Returns a list in the form [ (link, linktarget), ... ] """ Verbose = False diff --git a/scons/scons-local-2.4.1/SCons/Tool/default.py b/scons/scons-local-2.5.0/SCons/Tool/default.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/default.py rename to scons/scons-local-2.5.0/SCons/Tool/default.py index 102121392..848e0b72c 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/default.py +++ b/scons/scons-local-2.5.0/SCons/Tool/default.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/default.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/default.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/dmd.py b/scons/scons-local-2.5.0/SCons/Tool/dmd.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/dmd.py rename to scons/scons-local-2.5.0/SCons/Tool/dmd.py index c5561518e..a08421c10 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/dmd.py +++ b/scons/scons-local-2.5.0/SCons/Tool/dmd.py @@ -36,7 +36,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -58,7 +58,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dmd.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dmd.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import subprocess diff --git a/scons/scons-local-2.4.1/SCons/Tool/docbook/__init__.py b/scons/scons-local-2.5.0/SCons/Tool/docbook/__init__.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/docbook/__init__.py rename to scons/scons-local-2.5.0/SCons/Tool/docbook/__init__.py index aead43c69..83b3ecd90 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/docbook/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Tool/docbook/__init__.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001-7,2010 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -852,30 +852,16 @@ def generate(env): ) _detect(env) - try: - env.AddMethod(DocbookEpub, "DocbookEpub") - env.AddMethod(DocbookHtml, "DocbookHtml") - env.AddMethod(DocbookHtmlChunked, "DocbookHtmlChunked") - env.AddMethod(DocbookHtmlhelp, "DocbookHtmlhelp") - env.AddMethod(DocbookPdf, "DocbookPdf") - env.AddMethod(DocbookMan, "DocbookMan") - env.AddMethod(DocbookSlidesPdf, "DocbookSlidesPdf") - env.AddMethod(DocbookSlidesHtml, "DocbookSlidesHtml") - env.AddMethod(DocbookXInclude, "DocbookXInclude") - env.AddMethod(DocbookXslt, "DocbookXslt") - except AttributeError: - # Looks like we use a pre-0.98 version of SCons... - from SCons.Script.SConscript import SConsEnvironment - SConsEnvironment.DocbookEpub = DocbookEpub - SConsEnvironment.DocbookHtml = DocbookHtml - SConsEnvironment.DocbookHtmlChunked = DocbookHtmlChunked - SConsEnvironment.DocbookHtmlhelp = DocbookHtmlhelp - SConsEnvironment.DocbookPdf = DocbookPdf - SConsEnvironment.DocbookMan = DocbookMan - SConsEnvironment.DocbookSlidesPdf = DocbookSlidesPdf - SConsEnvironment.DocbookSlidesHtml = DocbookSlidesHtml - SConsEnvironment.DocbookXInclude = DocbookXInclude - SConsEnvironment.DocbookXslt = DocbookXslt + env.AddMethod(DocbookEpub, "DocbookEpub") + env.AddMethod(DocbookHtml, "DocbookHtml") + env.AddMethod(DocbookHtmlChunked, "DocbookHtmlChunked") + env.AddMethod(DocbookHtmlhelp, "DocbookHtmlhelp") + env.AddMethod(DocbookPdf, "DocbookPdf") + env.AddMethod(DocbookMan, "DocbookMan") + env.AddMethod(DocbookSlidesPdf, "DocbookSlidesPdf") + env.AddMethod(DocbookSlidesHtml, "DocbookSlidesHtml") + env.AddMethod(DocbookXInclude, "DocbookXInclude") + env.AddMethod(DocbookXslt, "DocbookXslt") def exists(env): diff --git a/scons/scons-local-2.4.1/SCons/Tool/dvi.py b/scons/scons-local-2.5.0/SCons/Tool/dvi.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/dvi.py rename to scons/scons-local-2.5.0/SCons/Tool/dvi.py index 9ad1beedf..cc3c8ca63 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/dvi.py +++ b/scons/scons-local-2.5.0/SCons/Tool/dvi.py @@ -5,7 +5,7 @@ Common DVI Builder definition for various other Tool modules that use it. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Common DVI Builder definition for various other Tool modules that use it. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvi.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvi.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Builder import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/dvipdf.py b/scons/scons-local-2.5.0/SCons/Tool/dvipdf.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/dvipdf.py rename to scons/scons-local-2.5.0/SCons/Tool/dvipdf.py index 9af25987b..d6a5dbbe6 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/dvipdf.py +++ b/scons/scons-local-2.5.0/SCons/Tool/dvipdf.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/dvipdf.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvipdf.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Defaults diff --git a/scons/scons-local-2.4.1/SCons/Tool/dvips.py b/scons/scons-local-2.5.0/SCons/Tool/dvips.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/dvips.py rename to scons/scons-local-2.5.0/SCons/Tool/dvips.py index 59a16f458..dcffa48c1 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/dvips.py +++ b/scons/scons-local-2.5.0/SCons/Tool/dvips.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvips.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvips.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-2.4.1/SCons/Tool/f03.py b/scons/scons-local-2.5.0/SCons/Tool/f03.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/f03.py rename to scons/scons-local-2.5.0/SCons/Tool/f03.py index b84850a25..9e804d21e 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/f03.py +++ b/scons/scons-local-2.5.0/SCons/Tool/f03.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f03.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f03.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/f77.py b/scons/scons-local-2.5.0/SCons/Tool/f77.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/f77.py rename to scons/scons-local-2.5.0/SCons/Tool/f77.py index b6c138a47..14cfc952d 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/f77.py +++ b/scons/scons-local-2.5.0/SCons/Tool/f77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f77.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f77.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Scanner.Fortran diff --git a/scons/scons-local-2.4.1/SCons/Tool/f90.py b/scons/scons-local-2.5.0/SCons/Tool/f90.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/f90.py rename to scons/scons-local-2.5.0/SCons/Tool/f90.py index 059f6390f..04ea509fc 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/f90.py +++ b/scons/scons-local-2.5.0/SCons/Tool/f90.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f90.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f90.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Scanner.Fortran diff --git a/scons/scons-local-2.4.1/SCons/Tool/f95.py b/scons/scons-local-2.5.0/SCons/Tool/f95.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/f95.py rename to scons/scons-local-2.5.0/SCons/Tool/f95.py index dffbbda17..7398064a2 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/f95.py +++ b/scons/scons-local-2.5.0/SCons/Tool/f95.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f95.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f95.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/filesystem.py b/scons/scons-local-2.5.0/SCons/Tool/filesystem.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/filesystem.py rename to scons/scons-local-2.5.0/SCons/Tool/filesystem.py index c9493e97b..8d11a4f93 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/filesystem.py +++ b/scons/scons-local-2.5.0/SCons/Tool/filesystem.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/filesystem.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/filesystem.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons from SCons.Tool.install import copyFunc diff --git a/scons/scons-local-2.4.1/SCons/Tool/fortran.py b/scons/scons-local-2.5.0/SCons/Tool/fortran.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/fortran.py rename to scons/scons-local-2.5.0/SCons/Tool/fortran.py index 43635d866..e536a84d5 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/fortran.py +++ b/scons/scons-local-2.5.0/SCons/Tool/fortran.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/fortran.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/fortran.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/g++.py b/scons/scons-local-2.5.0/SCons/Tool/g++.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/g++.py rename to scons/scons-local-2.5.0/SCons/Tool/g++.py index f1a23f1bb..f66adc1c4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/g++.py +++ b/scons/scons-local-2.5.0/SCons/Tool/g++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g++.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/g++.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/g77.py b/scons/scons-local-2.5.0/SCons/Tool/g77.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/g77.py rename to scons/scons-local-2.5.0/SCons/Tool/g77.py index 3e1af3c91..f685b01e4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/g77.py +++ b/scons/scons-local-2.5.0/SCons/Tool/g77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g77.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/g77.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env diff --git a/scons/scons-local-2.4.1/SCons/Tool/gas.py b/scons/scons-local-2.5.0/SCons/Tool/gas.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/gas.py rename to scons/scons-local-2.5.0/SCons/Tool/gas.py index 373a336da..acebe5d1a 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gas.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gas.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gas.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gas.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" as_module = __import__('as', globals(), locals(), []) diff --git a/scons/scons-local-2.4.1/SCons/Tool/gcc.py b/scons/scons-local-2.5.0/SCons/Tool/gcc.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/gcc.py rename to scons/scons-local-2.5.0/SCons/Tool/gcc.py index 06aba5860..e4032eaf4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gcc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gcc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gcc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gcc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import cc import os diff --git a/scons/scons-local-2.4.1/SCons/Tool/gdc.py b/scons/scons-local-2.5.0/SCons/Tool/gdc.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/gdc.py rename to scons/scons-local-2.5.0/SCons/Tool/gdc.py index e1d2c9c66..1c41858c9 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gdc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gdc.py @@ -24,7 +24,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -46,7 +46,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gdc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gdc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Defaults diff --git a/scons/scons-local-2.4.1/SCons/Tool/gettext.py b/scons/scons-local-2.5.0/SCons/Tool/gettext.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/gettext.py rename to scons/scons-local-2.5.0/SCons/Tool/gettext.py index 43f88e948..99fbd3237 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gettext.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gettext.py @@ -2,7 +2,7 @@ """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/gettext.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gettext.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" ############################################################################# def generate(env,**kw): diff --git a/scons/scons-local-2.4.1/SCons/Tool/gfortran.py b/scons/scons-local-2.5.0/SCons/Tool/gfortran.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/gfortran.py rename to scons/scons-local-2.5.0/SCons/Tool/gfortran.py index 0538cedb3..62f434ea9 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gfortran.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gfortran.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gfortran.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gfortran.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/gnulink.py b/scons/scons-local-2.5.0/SCons/Tool/gnulink.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/gnulink.py rename to scons/scons-local-2.5.0/SCons/Tool/gnulink.py index 109330321..3df077ba3 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gnulink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gnulink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gnulink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gnulink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util import SCons.Tool @@ -60,7 +60,7 @@ def generate(env): link._setup_versioned_lib_variables(env, tool = 'gnulink', use_soname = use_soname) env['LINKCALLBACKS'] = link._versioned_lib_callbacks() - # For backward-compatiblity with older SCons versions + # For backward-compatibility with older SCons versions env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('-Wl,-Bsymbolic') def exists(env): diff --git a/scons/scons-local-2.4.1/SCons/Tool/gs.py b/scons/scons-local-2.5.0/SCons/Tool/gs.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/gs.py rename to scons/scons-local-2.5.0/SCons/Tool/gs.py index ddb22e680..b0874fda4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/gs.py +++ b/scons/scons-local-2.5.0/SCons/Tool/gs.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gs.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gs.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-2.4.1/SCons/Tool/hpc++.py b/scons/scons-local-2.5.0/SCons/Tool/hpc++.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/hpc++.py rename to scons/scons-local-2.5.0/SCons/Tool/hpc++.py index bd2b5f9ea..8e79af4e2 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/hpc++.py +++ b/scons/scons-local-2.5.0/SCons/Tool/hpc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpc++.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpc++.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/hpcc.py b/scons/scons-local-2.5.0/SCons/Tool/hpcc.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/hpcc.py rename to scons/scons-local-2.5.0/SCons/Tool/hpcc.py index 19c22d852..25835942e 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/hpcc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/hpcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpcc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpcc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/hplink.py b/scons/scons-local-2.5.0/SCons/Tool/hplink.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/hplink.py rename to scons/scons-local-2.5.0/SCons/Tool/hplink.py index 931f8cfb5..0b7777a41 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/hplink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/hplink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hplink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hplink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/icc.py b/scons/scons-local-2.5.0/SCons/Tool/icc.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/icc.py rename to scons/scons-local-2.5.0/SCons/Tool/icc.py index 3e639adf2..f6f071168 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/icc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/icc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/icc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import cc diff --git a/scons/scons-local-2.4.1/SCons/Tool/icl.py b/scons/scons-local-2.5.0/SCons/Tool/icl.py similarity index 88% rename from scons/scons-local-2.4.1/SCons/Tool/icl.py rename to scons/scons-local-2.5.0/SCons/Tool/icl.py index bee5bcbcb..b14adf6dc 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/icl.py +++ b/scons/scons-local-2.5.0/SCons/Tool/icl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,11 +31,11 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icl.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/icl.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Tool.intelc -# This has been completely superceded by intelc.py, which can +# This has been completely superseded by intelc.py, which can # handle both Windows and Linux versions. def generate(*args, **kw): diff --git a/scons/scons-local-2.4.1/SCons/Tool/ifl.py b/scons/scons-local-2.5.0/SCons/Tool/ifl.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/ifl.py rename to scons/scons-local-2.5.0/SCons/Tool/ifl.py index 8c287fc98..e8b309108 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ifl.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ifl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifl.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ifl.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan diff --git a/scons/scons-local-2.4.1/SCons/Tool/ifort.py b/scons/scons-local-2.5.0/SCons/Tool/ifort.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/ifort.py rename to scons/scons-local-2.5.0/SCons/Tool/ifort.py index 3400a8951..a00e2491d 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ifort.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ifort.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifort.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ifort.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan diff --git a/scons/scons-local-2.4.1/SCons/Tool/ilink.py b/scons/scons-local-2.5.0/SCons/Tool/ilink.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/ilink.py rename to scons/scons-local-2.5.0/SCons/Tool/ilink.py index e3828ca7c..4532d9b12 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ilink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ilink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ilink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/ilink32.py b/scons/scons-local-2.5.0/SCons/Tool/ilink32.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/ilink32.py rename to scons/scons-local-2.5.0/SCons/Tool/ilink32.py index 7a63b36d6..a4ccff011 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ilink32.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ilink32.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink32.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ilink32.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Tool import SCons.Tool.bcc32 diff --git a/scons/scons-local-2.4.1/SCons/Tool/install.py b/scons/scons-local-2.5.0/SCons/Tool/install.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/install.py rename to scons/scons-local-2.5.0/SCons/Tool/install.py index 9ae78fa0a..f3e4227eb 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/install.py +++ b/scons/scons-local-2.5.0/SCons/Tool/install.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/install.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/install.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import re @@ -39,7 +39,7 @@ import stat import SCons.Action import SCons.Tool -from SCons.Util import make_path_relative +import SCons.Util # # We keep track of *all* installed files. @@ -91,7 +91,7 @@ def scons_copytree(src, dst, symlinks=False): errors.extend(err.args[0]) try: shutil.copystat(src, dst) - except WindowsError: + except SCons.Util.WinError: # can't copy file access times on Windows pass except OSError, why: @@ -225,7 +225,7 @@ def stringFunc(target, source, env): # Emitter functions # def add_targets_to_INSTALLED_FILES(target, source, env): - """ an emitter that adds all target files to the list stored in the + """ An emitter that adds all target files to the list stored in the _INSTALLED_FILES global variable. This way all installed files of one scons call will be collected. """ @@ -236,7 +236,7 @@ def add_targets_to_INSTALLED_FILES(target, source, env): return (target, source) def add_versioned_targets_to_INSTALLED_FILES(target, source, env): - """ an emitter that adds all target files to the list stored in the + """ An emitter that adds all target files to the list stored in the _INSTALLED_FILES global variable. This way all installed files of one scons call will be collected. """ @@ -254,7 +254,7 @@ def add_versioned_targets_to_INSTALLED_FILES(target, source, env): return (target, source) class DESTDIR_factory(object): - """ a node factory, where all files will be relative to the dir supplied + """ A node factory, where all files will be relative to the dir supplied in the constructor. """ def __init__(self, env, dir): @@ -262,11 +262,11 @@ class DESTDIR_factory(object): self.dir = env.arg2nodes( dir, env.fs.Dir )[0] def Entry(self, name): - name = make_path_relative(name) + name = SCons.Util.make_path_relative(name) return self.dir.Entry(name) def Dir(self, name): - name = make_path_relative(name) + name = SCons.Util.make_path_relative(name) return self.dir.Dir(name) # @@ -304,14 +304,12 @@ def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw): # '#' on the file name portion as meaning the Node should # be relative to the top-level SConstruct directory. target = env.fs.Entry('.'+os.sep+src.name, dnode) - #tgt.extend(BaseInstallBuilder(env, target, src, **kw)) tgt.extend(BaseInstallBuilder(env, target, src, **kw)) return tgt def InstallAsBuilderWrapper(env, target=None, source=None, **kw): result = [] for src, tgt in map(lambda x, y: (x, y), source, target): - #result.extend(BaseInstallBuilder(env, tgt, src, **kw)) result.extend(BaseInstallBuilder(env, tgt, src, **kw)) return result @@ -374,6 +372,7 @@ def generate(env): source_factory = env.fs.Entry, multi = 1, emitter = [ add_targets_to_INSTALLED_FILES, ], + source_scanner = SCons.Scanner.Base( {}, name = 'Install', recursive = False ), name = 'InstallBuilder') global BaseVersionedInstallBuilder diff --git a/scons/scons-local-2.4.1/SCons/Tool/intelc.py b/scons/scons-local-2.5.0/SCons/Tool/intelc.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/intelc.py rename to scons/scons-local-2.5.0/SCons/Tool/intelc.py index ebf25345a..24b1dc527 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/intelc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/intelc.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import division -__revision__ = "src/engine/SCons/Tool/intelc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/intelc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import math, sys, os.path, glob, string, re @@ -62,15 +62,6 @@ class MissingDirError(IntelCError): # dir not found class NoRegistryModuleError(IntelCError): # can't read registry at all pass -def uniquify(s): - """Return a sequence containing only one copy of each unique element from input sequence s. - Does not preserve order. - Input sequence must be hashable (i.e. must be usable as a dictionary key).""" - u = {} - for x in s: - u[x] = 1 - return list(u.keys()) - def linux_ver_normalize(vstr): """Normalize a Linux compiler version number. Intel changed from "80" to "9.0" in 2005, so we assume if the number @@ -191,7 +182,7 @@ def get_intel_registry_value(valuename, version=None, abi=None): except SCons.Util.RegError: raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) - except WindowsError: + except SCons.Util.WinError: raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) # Get the value: @@ -215,7 +206,7 @@ def get_all_compiler_versions(): try: k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, keyname) - except WindowsError: + except SCons.Util.WinError: # For version 13 or later, check for default instance UUID if is_win64: keyname = 'Software\\WoW6432Node\\Intel\\Suites' @@ -224,7 +215,7 @@ def get_all_compiler_versions(): try: k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, keyname) - except WindowsError: + except SCons.Util.WinError: return [] i = 0 versions = [] @@ -298,11 +289,17 @@ def get_all_compiler_versions(): m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d) if m: versions.append("%s.%s"%(m.group(1), m.group(2))) + for d in glob.glob('/opt/intel/compilers_and_libraries_*'): + # JPA: For the new version of Intel compiler 2016.1. + m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d) + if m: + versions.append("%s.%s"%(m.group(1), m,group(2))) + def keyfunc(str): """Given a dot-separated version string, return a tuple of ints representing it.""" return [int(x) for x in str.split('.')] # split into ints, sort, then remove dups - return sorted(uniquify(versions), key=keyfunc, reverse=True) + return sorted(SCons.Util.unique(versions), key=keyfunc, reverse=True) def get_intel_compiler_top(version, abi): """ @@ -379,7 +376,16 @@ def get_intel_compiler_top(version, abi): top = d break return top - top = find_in_2011style_dir(version) or find_in_2010style_dir(version) or find_in_2008style_dir(version) + def find_in_2016style_dir(version): + # The 2016 (compiler v16) dirs are inconsistent from previous. + top = None + for d in glob.glob('/opt/intel/compilers_and_libraries_%s/linux'%version): + if os.path.exists(os.path.join(d, "bin", "ia32", "icc")) or os.path.exists(os.path.join(d, "bin", "intel64", "icc")): + top = d + break + return top + + top = find_in_2016style_dir(version) or find_in_2011style_dir(version) or find_in_2010style_dir(version) or find_in_2008style_dir(version) # print "INTELC: top=",top if not top: raise MissingDirError("Can't find version %s Intel compiler in %s (abi='%s')"%(version,top, abi)) diff --git a/scons/scons-local-2.4.1/SCons/Tool/ipkg.py b/scons/scons-local-2.5.0/SCons/Tool/ipkg.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/ipkg.py rename to scons/scons-local-2.5.0/SCons/Tool/ipkg.py index b7f16740a..474f762d9 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ipkg.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ipkg.py @@ -11,7 +11,7 @@ packages fake_root. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ packages fake_root. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ipkg.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ipkg.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os diff --git a/scons/scons-local-2.4.1/SCons/Tool/jar.py b/scons/scons-local-2.5.0/SCons/Tool/jar.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/jar.py rename to scons/scons-local-2.5.0/SCons/Tool/jar.py index 885720974..eed1bc627 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/jar.py +++ b/scons/scons-local-2.5.0/SCons/Tool/jar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/jar.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/jar.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Subst import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/javac.py b/scons/scons-local-2.5.0/SCons/Tool/javac.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/javac.py rename to scons/scons-local-2.5.0/SCons/Tool/javac.py index bbaa47d77..51dd199bd 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/javac.py +++ b/scons/scons-local-2.5.0/SCons/Tool/javac.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/javac.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/javac.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/javah.py b/scons/scons-local-2.5.0/SCons/Tool/javah.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/javah.py rename to scons/scons-local-2.5.0/SCons/Tool/javah.py index 4c20393b0..c16077288 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/javah.py +++ b/scons/scons-local-2.5.0/SCons/Tool/javah.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/javah.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/javah.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/latex.py b/scons/scons-local-2.5.0/SCons/Tool/latex.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/latex.py rename to scons/scons-local-2.5.0/SCons/Tool/latex.py index e329d3f2c..6ed84c6ed 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/latex.py +++ b/scons/scons-local-2.5.0/SCons/Tool/latex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/latex.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/latex.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Defaults diff --git a/scons/scons-local-2.4.1/SCons/Tool/ldc.py b/scons/scons-local-2.5.0/SCons/Tool/ldc.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/ldc.py rename to scons/scons-local-2.5.0/SCons/Tool/ldc.py index b37f2d72f..663df3836 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/ldc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/ldc.py @@ -24,7 +24,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -46,7 +46,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ldc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ldc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import subprocess diff --git a/scons/scons-local-2.4.1/SCons/Tool/lex.py b/scons/scons-local-2.5.0/SCons/Tool/lex.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/lex.py rename to scons/scons-local-2.5.0/SCons/Tool/lex.py index 9baecb574..d0ac82db0 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/lex.py +++ b/scons/scons-local-2.5.0/SCons/Tool/lex.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/lex.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/lex.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/link.py b/scons/scons-local-2.5.0/SCons/Tool/link.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/link.py rename to scons/scons-local-2.5.0/SCons/Tool/link.py index 08dce9942..7a883a574 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/link.py +++ b/scons/scons-local-2.5.0/SCons/Tool/link.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/link.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/link.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import sys import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/linkloc.py b/scons/scons-local-2.5.0/SCons/Tool/linkloc.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/linkloc.py rename to scons/scons-local-2.5.0/SCons/Tool/linkloc.py index a8415b893..9fbc59935 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/linkloc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/linkloc.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/linkloc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/linkloc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/m4.py b/scons/scons-local-2.5.0/SCons/Tool/m4.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/m4.py rename to scons/scons-local-2.5.0/SCons/Tool/m4.py index de9c3f649..7fd4a2fa7 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/m4.py +++ b/scons/scons-local-2.5.0/SCons/Tool/m4.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/m4.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/m4.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-2.4.1/SCons/Tool/masm.py b/scons/scons-local-2.5.0/SCons/Tool/masm.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/masm.py rename to scons/scons-local-2.5.0/SCons/Tool/masm.py index 3e00d3340..bc1f83e31 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/masm.py +++ b/scons/scons-local-2.5.0/SCons/Tool/masm.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/masm.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/masm.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/midl.py b/scons/scons-local-2.5.0/SCons/Tool/midl.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/midl.py rename to scons/scons-local-2.5.0/SCons/Tool/midl.py index a46c1eb95..27ab01aee 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/midl.py +++ b/scons/scons-local-2.5.0/SCons/Tool/midl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/midl.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/midl.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-2.4.1/SCons/Tool/mingw.py b/scons/scons-local-2.5.0/SCons/Tool/mingw.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/mingw.py rename to scons/scons-local-2.5.0/SCons/Tool/mingw.py index 0afd55935..182fd7447 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/mingw.py +++ b/scons/scons-local-2.5.0/SCons/Tool/mingw.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mingw.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mingw.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/msgfmt.py b/scons/scons-local-2.5.0/SCons/Tool/msgfmt.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/msgfmt.py rename to scons/scons-local-2.5.0/SCons/Tool/msgfmt.py index 9904f1168..12b750405 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/msgfmt.py +++ b/scons/scons-local-2.5.0/SCons/Tool/msgfmt.py @@ -1,6 +1,6 @@ """ msgfmt tool """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msgfmt.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msgfmt.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Builder import BuilderBase ############################################################################# diff --git a/scons/scons-local-2.4.1/SCons/Tool/msginit.py b/scons/scons-local-2.5.0/SCons/Tool/msginit.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/msginit.py rename to scons/scons-local-2.5.0/SCons/Tool/msginit.py index 7afd804a3..0f5950b15 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/msginit.py +++ b/scons/scons-local-2.5.0/SCons/Tool/msginit.py @@ -3,7 +3,7 @@ Tool specific initialization of msginit tool. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization of msginit tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msginit.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msginit.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Warnings import SCons.Builder diff --git a/scons/scons-local-2.4.1/SCons/Tool/msgmerge.py b/scons/scons-local-2.5.0/SCons/Tool/msgmerge.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/msgmerge.py rename to scons/scons-local-2.5.0/SCons/Tool/msgmerge.py index a1b4b73fe..3473597da 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/msgmerge.py +++ b/scons/scons-local-2.5.0/SCons/Tool/msgmerge.py @@ -3,7 +3,7 @@ Tool specific initialization for `msgmerge` tool. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization for `msgmerge` tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msgmerge.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msgmerge.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" ############################################################################# def _update_or_init_po_files(target, source, env): diff --git a/scons/scons-local-2.4.1/SCons/Tool/mslib.py b/scons/scons-local-2.5.0/SCons/Tool/mslib.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/mslib.py rename to scons/scons-local-2.5.0/SCons/Tool/mslib.py index c4f1b0e5b..70c164334 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/mslib.py +++ b/scons/scons-local-2.5.0/SCons/Tool/mslib.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mslib.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mslib.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/mslink.py b/scons/scons-local-2.5.0/SCons/Tool/mslink.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/mslink.py rename to scons/scons-local-2.5.0/SCons/Tool/mslink.py index ce561fa17..27745d16a 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/mslink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/mslink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mslink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mslink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path @@ -305,7 +305,7 @@ def generate(env): # if the manifest actually exists before trying to run mt with it. env['MTEXECOM'] = '-$MT $MTFLAGS -manifest ${TARGET}.manifest $_MANIFEST_SOURCES -outputresource:$TARGET;1' env['MTSHLIBCOM'] = '-$MT $MTFLAGS -manifest ${TARGET}.manifest $_MANIFEST_SOURCES -outputresource:$TARGET;2' - # Future work garyo 27-Feb-11 + # TODO Future work garyo 27-Feb-11 env['_MANIFEST_SOURCES'] = None # _windowsManifestSources # Set-up ms tools paths diff --git a/scons/scons-local-2.4.1/SCons/Tool/mssdk.py b/scons/scons-local-2.5.0/SCons/Tool/mssdk.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/mssdk.py rename to scons/scons-local-2.5.0/SCons/Tool/mssdk.py index 66bf75d66..1dddbe770 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/mssdk.py +++ b/scons/scons-local-2.5.0/SCons/Tool/mssdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mssdk.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mssdk.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" """engine.SCons.Tool.mssdk diff --git a/scons/scons-local-2.4.1/SCons/Tool/msvc.py b/scons/scons-local-2.5.0/SCons/Tool/msvc.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/msvc.py rename to scons/scons-local-2.5.0/SCons/Tool/msvc.py index bf4de4578..f60bf3404 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/msvc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/msvc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/msvc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/msvs.py b/scons/scons-local-2.5.0/SCons/Tool/msvs.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/msvs.py rename to scons/scons-local-2.5.0/SCons/Tool/msvs.py index d47a93956..df80edf34 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/msvs.py +++ b/scons/scons-local-2.5.0/SCons/Tool/msvs.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msvs.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvs.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.compat @@ -100,42 +100,6 @@ def msvs_parse_version(s): num, suite = version_re.match(s).groups() return float(num), suite -# os.path.relpath has been introduced in Python 2.6 -# We define it locally for earlier versions of Python -def relpath(path, start=os.path.curdir): - """Return a relative version of a path""" - import sys - if not path: - raise ValueError("no path specified") - start_list = os.path.abspath(start).split(os.sep) - path_list = os.path.abspath(path).split(os.sep) - if 'posix' in sys.builtin_module_names: - # Work out how much of the filepath is shared by start and path. - i = len(os.path.commonprefix([start_list, path_list])) - else: - if start_list[0].lower() != path_list[0].lower(): - unc_path, rest = os.path.splitunc(path) - unc_start, rest = os.path.splitunc(start) - if bool(unc_path) ^ bool(unc_start): - raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" - % (path, start)) - else: - raise ValueError("path is on drive %s, start on drive %s" - % (path_list[0], start_list[0])) - # Work out how much of the filepath is shared by start and path. - for i in range(min(len(start_list), len(path_list))): - if start_list[i].lower() != path_list[i].lower(): - break - else: - i += 1 - rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return os.path.curdir - return os.path.join(*rel_list) - -if not "relpath" in os.path.__all__: - os.path.relpath = relpath - # This is how we re-invoke SCons from inside MSVS Project files. # The problem is that we might have been invoked as either scons.bat # or scons.py. If we were invoked directly as scons.py, then we could @@ -204,7 +168,7 @@ class _UserGenerator(object): Base class for .dsp.user file generator ''' # Default instance values. - # Ok ... a bit defensive, but it does not seems reasonable to crash the + # Ok ... a bit defensive, but it does not seem reasonable to crash the # build for a workspace user file. :-) usrhead = None usrdebg = None @@ -212,7 +176,7 @@ class _UserGenerator(object): createfile = False def __init__(self, dspfile, source, env): # DebugSettings should be a list of debug dictionary sorted in the same order - # than the target list and variants + # as the target list and variants if 'variant' not in env: raise SCons.Errors.InternalError("You must specify a 'variant' argument (i.e. 'Debug' or " +\ "'Release') to create an MSVSProject.") @@ -543,9 +507,7 @@ class _DSPGenerator(object): self.sources[t[0]].append(self.env[t[1]]) for n in sourcenames: - #TODO 2.4: compat layer supports sorted(key=) but not sort(key=) - #TODO 2.4: self.sources[n].sort(key=lambda a: a.lower()) - self.sources[n] = sorted(self.sources[n], key=lambda a: a.lower()) + self.sources[n].sort(key=lambda a: a.lower()) def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, dspfile=dspfile): config = Config() diff --git a/scons/scons-local-2.4.1/SCons/Tool/mwcc.py b/scons/scons-local-2.5.0/SCons/Tool/mwcc.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/mwcc.py rename to scons/scons-local-2.5.0/SCons/Tool/mwcc.py index 31d815ef8..2694a46d9 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/mwcc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/mwcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mwcc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mwcc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/mwld.py b/scons/scons-local-2.5.0/SCons/Tool/mwld.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/mwld.py rename to scons/scons-local-2.5.0/SCons/Tool/mwld.py index 434f26036..e187273f4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/mwld.py +++ b/scons/scons-local-2.5.0/SCons/Tool/mwld.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mwld.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mwld.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/nasm.py b/scons/scons-local-2.5.0/SCons/Tool/nasm.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/nasm.py rename to scons/scons-local-2.5.0/SCons/Tool/nasm.py index 663e91897..5c8ff4ca2 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/nasm.py +++ b/scons/scons-local-2.5.0/SCons/Tool/nasm.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/nasm.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/nasm.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/__init__.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/__init__.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/__init__.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/__init__.py index d0a8dca05..78bc679f5 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/__init__.py @@ -4,7 +4,7 @@ SCons Packaging Tool. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ SCons Packaging Tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Environment from SCons.Variables import * @@ -77,7 +77,6 @@ def Tag(env, target, source, *more_tags, **kw_tags): # differentiate between "normal" object attributes and the # packaging attributes. As the user should not be bothered with # that, the prefix will be added here if missing. - #if not k.startswith('PACKAGING_'): if k[:10] != 'PACKAGING_': k='PACKAGING_'+k t.Tag(k, v) @@ -175,7 +174,7 @@ def Package(env, target=None, source=None, **kw): args=[x for x in args if x not in kw] if len(args)==0: - raise # must be a different error, so reraise + raise # must be a different error, so re-raise elif len(args)==1: raise SCons.Errors.UserError( "Missing Packagetag '%s' for %s packager"\ % (args[0],packager.__name__) ) @@ -232,8 +231,6 @@ def options(opts): def copy_attr(f1, f2): """ copies the special packaging file attributes from f1 to f2. """ - #pattrs = [x for x in dir(f1) if not hasattr(f2, x) and\ - # x.startswith('PACKAGING_')] copyit = lambda x: not hasattr(f2, x) and x[:10] == 'PACKAGING_' if f1._tags: pattrs = list(filter(copyit, f1._tags)) @@ -278,7 +275,7 @@ def putintopackageroot(target, source, env, pkgroot, honor_install_location=1): return (target, new_source) def stripinstallbuilder(target, source, env): - """ strips the install builder action from the source list and stores + """ Strips the install builder action from the source list and stores the final installation location as the "PACKAGING_INSTALL_LOCATION" of the source of the source file. This effectively removes the final installed files from the source list while remembering the installation location. diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/ipk.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/ipk.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/ipk.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/ipk.py index ae4d7fc83..fbf3c2b1e 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/ipk.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/ipk.py @@ -2,7 +2,7 @@ """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/ipk.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/ipk.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Builder import SCons.Node.FS @@ -35,7 +35,7 @@ from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot def package(env, target, source, PACKAGEROOT, NAME, VERSION, DESCRIPTION, SUMMARY, X_IPK_PRIORITY, X_IPK_SECTION, SOURCE_URL, X_IPK_MAINTAINER, X_IPK_DEPENDS, **kw): - """ this function prepares the packageroot directory for packaging with the + """ This function prepares the packageroot directory for packaging with the ipkg builder. """ SCons.Tool.Tool('ipkg').generate(env) @@ -45,7 +45,7 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, DESCRIPTION, target, source = stripinstallbuilder(target, source, env) target, source = putintopackageroot(target, source, env, PACKAGEROOT) - # This should be overridable from the construction environment, + # This should be overrideable from the construction environment, # which it is by using ARCHITECTURE=. # Guessing based on what os.uname() returns at least allows it # to work for both i386 and x86_64 Linux systems. @@ -61,7 +61,7 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, DESCRIPTION, if 'ARCHITECTURE' in kw: buildarchitecture = kw['ARCHITECTURE'] - # setup the kw to contain the mandatory arguments to this fucntion. + # setup the kw to contain the mandatory arguments to this function. # do this before calling any builder or setup function loc=locals() del loc['kw'] @@ -104,7 +104,7 @@ def gen_ipk_dir(proot, source, env, kw): return proot def build_specfiles(source, target, env): - """ filter the targets for the needed files and use the variables in env + """ Filter the targets for the needed files and use the variables in env to create the specfile. """ # diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/msi.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/msi.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/msi.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/msi.py index cc563b832..29095e811 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/msi.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/msi.py @@ -4,7 +4,7 @@ The msi packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ The msi packager. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/msi.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/msi.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import SCons @@ -70,7 +70,7 @@ def convert_to_id(s, id_set): try: return id_set[id][s] except KeyError: - # no we did not so initialize with the id + # no we did not, so initialize with the id if id not in id_set: id_set[id] = { s : id } # there is a collision, generate an id which is unique by appending # the collision number @@ -79,7 +79,7 @@ def convert_to_id(s, id_set): return id_set[id][s] def is_dos_short_file_name(file): - """ examine if the given file is in the 8.3 form. + """ Examine if the given file is in the 8.3 form. """ fname, ext = os.path.splitext(file) proper_ext = len(ext) == 0 or (2 <= len(ext) <= 4) # the ext contains the dot @@ -88,7 +88,7 @@ def is_dos_short_file_name(file): return proper_ext and proper_fname def gen_dos_short_file_name(file, filename_set): - """ see http://support.microsoft.com/default.aspx?scid=kb;en-us;Q142982 + """ See http://support.microsoft.com/default.aspx?scid=kb;en-us;Q142982 These are no complete 8.3 dos short names. The ~ char is missing and replaced with one character from the filename. WiX warns about such @@ -186,7 +186,7 @@ def string_wxsfile(target, source, env): return "building WiX file %s"%( target[0].path ) def build_wxsfile(target, source, env): - """ compiles a .wxs file from the keywords given in env['msi_spec'] and + """ Compiles a .wxs file from the keywords given in env['msi_spec'] and by analyzing the tree of source nodes and their tags. """ file = open(target[0].get_abspath(), 'w') @@ -268,7 +268,7 @@ def create_default_directory_layout(root, NAME, VERSION, VENDOR, filename_set): # mandatory and optional file tags # def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, id_set): - """ builds the Component sections of the wxs file with their included files. + """ Builds the Component sections of the wxs file with their included files. Files need to be specified in 8.3 format and in the long name format, long filenames will be converted automatically. @@ -280,7 +280,7 @@ def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, factory = Document() def get_directory( node, dir ): - """ returns the node under the given node representing the directory. + """ Returns the node under the given node representing the directory. Returns the component node if dir is None or empty. """ @@ -415,7 +415,7 @@ def build_wxsfile_features_section(root, files, NAME, VERSION, SUMMARY, id_set): root.getElementsByTagName('Product')[0].childNodes.append(Feature) def build_wxsfile_default_gui(root): - """ this function adds a default GUI to the wxs file + """ This function adds a default GUI to the wxs file """ factory = Document() Product = root.getElementsByTagName('Product')[0] @@ -429,7 +429,7 @@ def build_wxsfile_default_gui(root): Product.childNodes.append(UIRef) def build_license_file(directory, spec): - """ creates a License.rtf file with the content of "X_MSI_LICENSE_TEXT" + """ Creates a License.rtf file with the content of "X_MSI_LICENSE_TEXT" in the given directory """ name, text = '', '' diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/rpm.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/rpm.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/rpm.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/rpm.py index cf3ea8193..6c00e8c5d 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/rpm.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/rpm.py @@ -4,7 +4,7 @@ The rpm packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ The rpm packager. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/rpm.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/rpm.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os @@ -72,7 +72,6 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, # if no "SOURCE_URL" tag is given add a default one. if 'SOURCE_URL' not in kw: - #kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '') kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '') # mangle the source and target list for the rpmbuild @@ -86,26 +85,21 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, def collectintargz(target, source, env): """ Puts all source files into a tar.gz file. """ - # the rpm tool depends on a source package, until this is chagned + # the rpm tool depends on a source package, until this is changed # this hack needs to be here that tries to pack all sources in. sources = env.FindSourceFiles() # filter out the target we are building the source list for. - #sources = [s for s in sources if not (s in target)] sources = [s for s in sources if s not in target] # find the .spec file for rpm and add it since it is not necessarily found # by the FindSourceFiles function. - #sources.extend( [s for s in source if str(s).rfind('.spec')!=-1] ) - spec_file = lambda s: str(s).rfind('.spec') != -1 - sources.extend( list(filter(spec_file, source)) ) + sources.extend( [s for s in source if str(s).rfind('.spec')!=-1] ) # as the source contains the url of the source package this rpm package # is built from, we extract the target name - #tarball = (str(target[0])+".tar.gz").replace('.rpm', '') tarball = (str(target[0])+".tar.gz").replace('.rpm', '') try: - #tarball = env['SOURCE_URL'].split('/')[-1] tarball = env['SOURCE_URL'].split('/')[-1] except KeyError, e: raise SCons.Errors.UserError( "Missing PackageTag '%s' for RPM packager" % e.args[0] ) @@ -194,7 +188,7 @@ def build_specfile_sections(spec): return str def build_specfile_header(spec): - """ Builds all section but the %file of a rpm specfile + """ Builds all sections but the %file of a rpm specfile """ str = "" @@ -312,11 +306,10 @@ class SimpleTagCompiler(object): self.mandatory = mandatory def compile(self, values): - """ compiles the tagset and returns a str containing the result + """ Compiles the tagset and returns a str containing the result """ def is_international(tag): - #return tag.endswith('_') - return tag[-1:] == '_' + return tag.endswith('_') def get_country_code(tag): return tag[-2:] @@ -327,7 +320,6 @@ class SimpleTagCompiler(object): replacements = list(self.tagset.items()) str = "" - #domestic = [ (k,v) for k,v in replacements if not is_international(k) ] domestic = [t for t in replacements if not is_international(t[0])] for key, replacement in domestic: try: @@ -336,11 +328,9 @@ class SimpleTagCompiler(object): if self.mandatory: raise e - #international = [ (k,v) for k,v in replacements if is_international(k) ] international = [t for t in replacements if is_international(t[0])] for key, replacement in international: try: - #int_values_for_key = [ (get_country_code(k),v) for k,v in values.items() if strip_country_code(k) == key ] x = [t for t in values.items() if strip_country_code(t[0]) == key] int_values_for_key = [(get_country_code(t[0]),t[1]) for t in x] for v in int_values_for_key: diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/src_tarbz2.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/src_tarbz2.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/src_tarbz2.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/src_tarbz2.py index 6314e6438..b72f42e5d 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/src_tarbz2.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/src_tarbz2.py @@ -4,7 +4,7 @@ The tarbz2 SRC packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The tarbz2 SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_tarbz2.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_tarbz2.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.packaging import putintopackageroot diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/src_targz.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/src_targz.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/src_targz.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/src_targz.py index 7431fb79c..c8e91ec89 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/src_targz.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/src_targz.py @@ -4,7 +4,7 @@ The targz SRC packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The targz SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_targz.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_targz.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.packaging import putintopackageroot diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/src_zip.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/src_zip.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/src_zip.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/src_zip.py index 99f8c06ae..41d5e45b1 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/src_zip.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/src_zip.py @@ -4,7 +4,7 @@ The zip SRC packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The zip SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_zip.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_zip.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.packaging import putintopackageroot diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/tarbz2.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/tarbz2.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/tarbz2.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/tarbz2.py index 02568d5b3..a98c6e811 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/tarbz2.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/tarbz2.py @@ -4,7 +4,7 @@ The tarbz2 SRC packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The tarbz2 SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/tarbz2.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/tarbz2.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/targz.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/targz.py similarity index 90% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/targz.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/targz.py index 09b17268b..d0c80dbfe 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/targz.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/targz.py @@ -4,7 +4,7 @@ The targz SRC packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The targz SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/targz.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/targz.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/scons/scons-local-2.4.1/SCons/Tool/packaging/zip.py b/scons/scons-local-2.5.0/SCons/Tool/packaging/zip.py similarity index 90% rename from scons/scons-local-2.4.1/SCons/Tool/packaging/zip.py rename to scons/scons-local-2.5.0/SCons/Tool/packaging/zip.py index bc263fb3d..0709ff162 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/packaging/zip.py +++ b/scons/scons-local-2.5.0/SCons/Tool/packaging/zip.py @@ -4,7 +4,7 @@ The zip SRC packager. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The zip SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/zip.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/zip.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/scons/scons-local-2.4.1/SCons/Tool/pdf.py b/scons/scons-local-2.5.0/SCons/Tool/pdf.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/pdf.py rename to scons/scons-local-2.5.0/SCons/Tool/pdf.py index b2d378e54..9475bda15 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/pdf.py +++ b/scons/scons-local-2.5.0/SCons/Tool/pdf.py @@ -6,7 +6,7 @@ Add an explicit action to run epstopdf to convert .eps files to .pdf """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Add an explicit action to run epstopdf to convert .eps files to .pdf # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdf.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdf.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Builder import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/pdflatex.py b/scons/scons-local-2.5.0/SCons/Tool/pdflatex.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/pdflatex.py rename to scons/scons-local-2.5.0/SCons/Tool/pdflatex.py index f4cb4ae5a..9f8973691 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/pdflatex.py +++ b/scons/scons-local-2.5.0/SCons/Tool/pdflatex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdflatex.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdflatex.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/pdftex.py b/scons/scons-local-2.5.0/SCons/Tool/pdftex.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/pdftex.py rename to scons/scons-local-2.5.0/SCons/Tool/pdftex.py index 84adf475d..815dc83bd 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/pdftex.py +++ b/scons/scons-local-2.5.0/SCons/Tool/pdftex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdftex.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdftex.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import SCons.Action diff --git a/scons/scons-local-2.4.1/SCons/Tool/qt.py b/scons/scons-local-2.5.0/SCons/Tool/qt.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/qt.py rename to scons/scons-local-2.5.0/SCons/Tool/qt.py index 923f719ef..4feb38eaa 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/qt.py +++ b/scons/scons-local-2.5.0/SCons/Tool/qt.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/qt.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/qt.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/rmic.py b/scons/scons-local-2.5.0/SCons/Tool/rmic.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/rmic.py rename to scons/scons-local-2.5.0/SCons/Tool/rmic.py index dbacda302..c05286db8 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/rmic.py +++ b/scons/scons-local-2.5.0/SCons/Tool/rmic.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rmic.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rmic.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/rpcgen.py b/scons/scons-local-2.5.0/SCons/Tool/rpcgen.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/rpcgen.py rename to scons/scons-local-2.5.0/SCons/Tool/rpcgen.py index eec6bf625..6c4116f5b 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/rpcgen.py +++ b/scons/scons-local-2.5.0/SCons/Tool/rpcgen.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rpcgen.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpcgen.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" from SCons.Builder import Builder import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/rpm.py b/scons/scons-local-2.5.0/SCons/Tool/rpm.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/rpm.py rename to scons/scons-local-2.5.0/SCons/Tool/rpm.py index 400639e95..fe63e2941 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/rpm.py +++ b/scons/scons-local-2.5.0/SCons/Tool/rpm.py @@ -11,7 +11,7 @@ tar.gz consisting of the source file and a specfile. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ tar.gz consisting of the source file and a specfile. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rpm.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpm.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import re diff --git a/scons/scons-local-2.4.1/SCons/Tool/rpmutils.py b/scons/scons-local-2.5.0/SCons/Tool/rpmutils.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/Tool/rpmutils.py rename to scons/scons-local-2.5.0/SCons/Tool/rpmutils.py index 82247bc68..aa6c6804b 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/rpmutils.py +++ b/scons/scons-local-2.5.0/SCons/Tool/rpmutils.py @@ -14,7 +14,7 @@ exact syntax. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -35,7 +35,7 @@ exact syntax. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/rpmutils.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpmutils.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import platform diff --git a/scons/scons-local-2.4.1/SCons/Tool/sgiar.py b/scons/scons-local-2.5.0/SCons/Tool/sgiar.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/sgiar.py rename to scons/scons-local-2.5.0/SCons/Tool/sgiar.py index 1e7a4bd1d..849520c9b 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sgiar.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sgiar.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgiar.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgiar.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/sgic++.py b/scons/scons-local-2.5.0/SCons/Tool/sgic++.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/sgic++.py rename to scons/scons-local-2.5.0/SCons/Tool/sgic++.py index 556009a43..ec1954ec7 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sgic++.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sgic++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgic++.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgic++.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/sgicc.py b/scons/scons-local-2.5.0/SCons/Tool/sgicc.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/sgicc.py rename to scons/scons-local-2.5.0/SCons/Tool/sgicc.py index f236b786c..474e6cdca 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sgicc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sgicc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgicc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgicc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import cc diff --git a/scons/scons-local-2.4.1/SCons/Tool/sgilink.py b/scons/scons-local-2.5.0/SCons/Tool/sgilink.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/sgilink.py rename to scons/scons-local-2.5.0/SCons/Tool/sgilink.py index b0249d249..491d293ff 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sgilink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sgilink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgilink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgilink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/sunar.py b/scons/scons-local-2.5.0/SCons/Tool/sunar.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/sunar.py rename to scons/scons-local-2.5.0/SCons/Tool/sunar.py index 6f7fe70c5..e453a7bbc 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sunar.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sunar.py @@ -2,7 +2,7 @@ Tool-specific initialization for Solaris (Forte) ar (library archive). If CC exists, static libraries should be built with it, so that template -instantians can be resolved. +instantiations can be resolved. There normally shouldn't be any need to import this module directly. It will usually be imported through the generic SCons.Tool.Tool() @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunar.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunar.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-2.4.1/SCons/Tool/sunc++.py b/scons/scons-local-2.5.0/SCons/Tool/sunc++.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Tool/sunc++.py rename to scons/scons-local-2.5.0/SCons/Tool/sunc++.py index 8dc4d23b1..cf0c95dc5 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sunc++.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sunc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunc++.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunc++.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons diff --git a/scons/scons-local-2.4.1/SCons/Tool/suncc.py b/scons/scons-local-2.5.0/SCons/Tool/suncc.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/suncc.py rename to scons/scons-local-2.5.0/SCons/Tool/suncc.py index b40a8d736..0110174e4 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/suncc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/suncc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/suncc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/suncc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/sunf77.py b/scons/scons-local-2.5.0/SCons/Tool/sunf77.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/sunf77.py rename to scons/scons-local-2.5.0/SCons/Tool/sunf77.py index a169c4fde..e3260c9e6 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sunf77.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sunf77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf77.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf77.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/sunf90.py b/scons/scons-local-2.5.0/SCons/Tool/sunf90.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/sunf90.py rename to scons/scons-local-2.5.0/SCons/Tool/sunf90.py index bb737f78d..63465e2f5 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sunf90.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sunf90.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf90.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf90.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/sunf95.py b/scons/scons-local-2.5.0/SCons/Tool/sunf95.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Tool/sunf95.py rename to scons/scons-local-2.5.0/SCons/Tool/sunf95.py index 52cbaa886..61bdf3742 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sunf95.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sunf95.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf95.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf95.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Util diff --git a/scons/scons-local-2.4.1/SCons/Tool/sunlink.py b/scons/scons-local-2.5.0/SCons/Tool/sunlink.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/sunlink.py rename to scons/scons-local-2.5.0/SCons/Tool/sunlink.py index 90f95bd9f..49deaf163 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/sunlink.py +++ b/scons/scons-local-2.5.0/SCons/Tool/sunlink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunlink.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunlink.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import os.path diff --git a/scons/scons-local-2.4.1/SCons/Tool/swig.py b/scons/scons-local-2.5.0/SCons/Tool/swig.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Tool/swig.py rename to scons/scons-local-2.5.0/SCons/Tool/swig.py index 74c5a8ee5..1d806ae6f 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/swig.py +++ b/scons/scons-local-2.5.0/SCons/Tool/swig.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/swig.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/swig.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re @@ -39,11 +39,12 @@ import subprocess import SCons.Action import SCons.Defaults -import SCons.Scanner import SCons.Tool import SCons.Util import SCons.Node +verbose = False + swigs = [ 'swig', 'swig3.0', 'swig2.0' ] SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR') @@ -140,9 +141,12 @@ def _get_swig_version(env, swig): if pipe.wait() != 0: return out = pipe.stdout.read() - match = re.search(r'SWIG Version\s+(\S+)$', out, re.MULTILINE) + match = re.search(r'SWIG Version\s+(\S+).*', out, re.MULTILINE) if match: + if verbose: print "Version is:%s"%match.group(1) return match.group(1) + else: + if verbose: print "Unable to detect version: [%s]"%out def generate(env): """Add Builders and construction variables for swig to an Environment.""" @@ -177,11 +181,6 @@ def generate(env): env['_SWIGINCFLAGS'] = '$( ${_concat(SWIGINCPREFIX, SWIGPATH, SWIGINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' env['SWIGCOM'] = '$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS} $SWIGFLAGS $SOURCES' - expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' - scanner = SCons.Scanner.ClassicCPP("SWIGScan", ".i", "SWIGPATH", expr) - - env.Append(SCANNERS = scanner) - def exists(env): swig = env.get('SWIG') or env.Detect(['swig']) return swig diff --git a/scons/scons-local-2.4.1/SCons/Tool/tar.py b/scons/scons-local-2.5.0/SCons/Tool/tar.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Tool/tar.py rename to scons/scons-local-2.5.0/SCons/Tool/tar.py index e96743866..c19d4916a 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/tar.py +++ b/scons/scons-local-2.5.0/SCons/Tool/tar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tar.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tar.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-2.4.1/SCons/Tool/tex.py b/scons/scons-local-2.5.0/SCons/Tool/tex.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/Tool/tex.py rename to scons/scons-local-2.5.0/SCons/Tool/tex.py index 92542d606..b4e457f64 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/tex.py +++ b/scons/scons-local-2.5.0/SCons/Tool/tex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tex.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tex.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import re @@ -700,12 +700,6 @@ def tex_emitter_core(target, source, env, graphics_extensions): content = source[0].get_text_contents() - # These variables are no longer used. - #idx_exists = os.path.isfile(targetbase + '.idx') - #nlo_exists = os.path.isfile(targetbase + '.nlo') - #glo_exists = os.path.isfile(targetbase + '.glo') - #acr_exists = os.path.isfile(targetbase + '.acn') - # set up list with the regular expressions # we use to find features used file_tests_search = [auxfile_re, diff --git a/scons/scons-local-2.4.1/SCons/Tool/textfile.py b/scons/scons-local-2.5.0/SCons/Tool/textfile.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/textfile.py rename to scons/scons-local-2.5.0/SCons/Tool/textfile.py index 87a3ad8f2..f0d028f92 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/textfile.py +++ b/scons/scons-local-2.5.0/SCons/Tool/textfile.py @@ -1,6 +1,6 @@ # -*- python -*- # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -40,11 +40,11 @@ Textfile/Substfile builder for SCons. expanded (its keys are not expanded). If a value of SUBST_DICT is a python callable function, it is called and the result is expanded as the value. Values are substituted in a "random" order; if any - substitution could be further expanded by another subsitition, it - is unpredictible whether the expansion will occur. + substitution could be further expanded by another substitution, it + is unpredictable whether the expansion will occur. """ -__revision__ = "src/engine/SCons/Tool/textfile.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/textfile.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons diff --git a/scons/scons-local-2.4.1/SCons/Tool/tlib.py b/scons/scons-local-2.5.0/SCons/Tool/tlib.py similarity index 91% rename from scons/scons-local-2.4.1/SCons/Tool/tlib.py rename to scons/scons-local-2.5.0/SCons/Tool/tlib.py index 4951bddfe..406697f3c 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/tlib.py +++ b/scons/scons-local-2.5.0/SCons/Tool/tlib.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tlib.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tlib.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Tool import SCons.Tool.bcc32 diff --git a/scons/scons-local-2.4.1/SCons/Tool/wix.py b/scons/scons-local-2.5.0/SCons/Tool/wix.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/wix.py rename to scons/scons-local-2.5.0/SCons/Tool/wix.py index 0fa3ea7e9..cc259edc1 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/wix.py +++ b/scons/scons-local-2.5.0/SCons/Tool/wix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/wix.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/wix.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import SCons.Builder import SCons.Action diff --git a/scons/scons-local-2.4.1/SCons/Tool/xgettext.py b/scons/scons-local-2.5.0/SCons/Tool/xgettext.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Tool/xgettext.py rename to scons/scons-local-2.5.0/SCons/Tool/xgettext.py index 4edd4aa80..153d71f74 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/xgettext.py +++ b/scons/scons-local-2.5.0/SCons/Tool/xgettext.py @@ -3,7 +3,7 @@ Tool specific initialization of `xgettext` tool. """ -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization of `xgettext` tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/xgettext.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/xgettext.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" ############################################################################# class _CmdRunner(object): @@ -76,7 +76,7 @@ def _update_pot_file(target, source, env): nop = lambda target, source, env : 0 # Save scons cwd and os cwd (NOTE: they may be different. After the job, we - # revert ech one to its original state). + # revert each one to its original state). save_cwd = env.fs.getcwd() save_os_cwd = os.getcwd() chdir = target[0].dir @@ -134,7 +134,7 @@ def _update_pot_file(target, source, env): explain = "new file" if needs_update: # Print message employing SCons.Action.Action for that. - msg = "Writting " + repr(str(target[0])) + " (" + explain + ")" + msg = "Writing " + repr(str(target[0])) + " (" + explain + ")" env.Execute(SCons.Action.Action(nop, msg)) f = open(str(target[0]),"w") f.write(new_content) @@ -142,7 +142,7 @@ def _update_pot_file(target, source, env): return 0 else: # Print message employing SCons.Action.Action for that. - msg = "Not writting " + repr(str(target[0])) + " (" + explain + ")" + msg = "Not writing " + repr(str(target[0])) + " (" + explain + ")" env.Execute(SCons.Action.Action(nop, msg)) return 0 ############################################################################# diff --git a/scons/scons-local-2.4.1/SCons/Tool/yacc.py b/scons/scons-local-2.5.0/SCons/Tool/yacc.py similarity index 87% rename from scons/scons-local-2.4.1/SCons/Tool/yacc.py rename to scons/scons-local-2.5.0/SCons/Tool/yacc.py index c05140f0f..6a089a147 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/yacc.py +++ b/scons/scons-local-2.5.0/SCons/Tool/yacc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/yacc.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/yacc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path @@ -61,7 +61,7 @@ def _yaccEmitter(target, source, env, ysuf, hsuf): base, ext = os.path.splitext(SCons.Util.to_String(source[0])) target.append(base + env.subst("$YACCVCGFILESUFFIX")) - # If -v is specirfied yacc will create the output debug file + # If -v is specified yacc will create the output debug file # which is not really source for any process, but should # be noted and also be cleaned # Bug #2558 @@ -118,14 +118,6 @@ def generate(env): env['YACCCOM'] = '$YACC $YACCFLAGS -o $TARGET $SOURCES' env['YACCHFILESUFFIX'] = '.h' - # Apparently, OS X now creates file.hpp like everybody else - # I have no idea when it changed; it was fixed in 10.4 - #if env['PLATFORM'] == 'darwin': - # # Bison on Mac OS X just appends ".h" to the generated target .cc - # # or .cpp file name. Hooray for delayed expansion of variables. - # env['YACCHXXFILESUFFIX'] = '${TARGET.suffix}.h' - #else: - # env['YACCHXXFILESUFFIX'] = '.hpp' env['YACCHXXFILESUFFIX'] = '.hpp' env['YACCVCGFILESUFFIX'] = '.vcg' diff --git a/scons/scons-local-2.4.1/SCons/Tool/zip.py b/scons/scons-local-2.5.0/SCons/Tool/zip.py similarity index 95% rename from scons/scons-local-2.4.1/SCons/Tool/zip.py rename to scons/scons-local-2.5.0/SCons/Tool/zip.py index 02999c2d4..5349cba33 100644 --- a/scons/scons-local-2.4.1/SCons/Tool/zip.py +++ b/scons/scons-local-2.5.0/SCons/Tool/zip.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/zip.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Tool/zip.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path diff --git a/scons/scons-local-2.4.1/SCons/Util.py b/scons/scons-local-2.5.0/SCons/Util.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Util.py rename to scons/scons-local-2.5.0/SCons/Util.py index be86831df..21ef53fed 100644 --- a/scons/scons-local-2.4.1/SCons/Util.py +++ b/scons/scons-local-2.5.0/SCons/Util.py @@ -3,7 +3,7 @@ Various utility functions go here. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Various utility functions go here. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Util.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Util.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import sys @@ -92,7 +92,7 @@ def splitext(path): def updrive(path): """ Make the drive letter (if any) upper case. - This is useful because Windows is inconsitent on the case + This is useful because Windows is inconsistent on the case of the drive letter, which can cause inconsistencies when calculating command signatures. """ @@ -167,7 +167,7 @@ class DisplayEngine(object): def set_mode(self, mode): self.print_it = mode -def render_tree(root, child_func, prune=0, margin=[0], visited={}): +def render_tree(root, child_func, prune=0, margin=[0], visited=None): """ Render a tree of nodes into an ASCII tree view. root - the root node of the tree @@ -181,6 +181,10 @@ def render_tree(root, child_func, prune=0, margin=[0], visited={}): rname = str(root) + # Initialize 'visited' dict, if required + if visited is None: + visited = {} + children = child_func(root) retval = "" for pipe in margin[:-1]: @@ -207,7 +211,7 @@ def render_tree(root, child_func, prune=0, margin=[0], visited={}): IDX = lambda N: N and 1 or 0 -def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): +def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): """ Print a tree of nodes. This is like render_tree, except it prints lines directly instead of creating a string representation in memory, @@ -224,6 +228,10 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): """ rname = str(root) + + # Initialize 'visited' dict, if required + if visited is None: + visited = {} if showtags: @@ -291,7 +299,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): # often too slow. # We are using the following trick to speed up these -# functions. Default arguments are used to take a snapshot of the +# functions. Default arguments are used to take a snapshot of # the global functions and constants used by these functions. This # transforms accesses to global variable into local variables # accesses (i.e. LOAD_FAST instead of LOAD_GLOBAL). @@ -301,11 +309,11 @@ ListTypes = (list, UserList) SequenceTypes = (list, tuple, UserList) # Note that profiling data shows a speed-up when comparing -# explicitely with str and unicode instead of simply comparing +# explicitly with str and unicode instead of simply comparing # with basestring. (at least on Python 2.5.1) StringTypes = (str, unicode, UserString) -# Empirically, it is faster to check explicitely for str and +# Empirically, it is faster to check explicitly for str and # unicode than for basestring. BaseStringTypes = (str, unicode) @@ -326,11 +334,11 @@ def is_String(obj, isinstance=isinstance, StringTypes=StringTypes): def is_Scalar(obj, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes): # Profiling shows that there is an impressive speed-up of 2x - # when explicitely checking for strings instead of just not + # when explicitly checking for strings instead of just not # sequence when the argument (i.e. obj) is already a string. # But, if obj is a not string then it is twice as fast to # check only for 'not sequence'. The following code therefore - # assumes that the obj argument is a string must of the time. + # assumes that the obj argument is a string most of the time. return isinstance(obj, StringTypes) or not isinstance(obj, SequenceTypes) def do_flatten(sequence, result, isinstance=isinstance, @@ -431,7 +439,7 @@ def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst, # # A special case is any object that has a __semi_deepcopy__() method, # which we invoke to create the copy. Currently only used by -# BuilderDict to actually prevent the copy operation (as invalid on that object) +# BuilderDict to actually prevent the copy operation (as invalid on that object). # # The dispatch table approach used here is a direct rip-off from the # normal Python copy module. @@ -571,6 +579,19 @@ except ImportError: pass RegError = _NoError +WinError = None +# Make sure we have a definition of WindowsError so we can +# run platform-independent tests of Windows functionality on +# platforms other than Windows. (WindowsError is, in fact, an +# OSError subclass on Windows.) +class PlainWindowsError(OSError): + pass +try: + WinError = WindowsError +except NameError: + WinError = PlainWindowsError + + if can_read_reg: HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE @@ -604,30 +625,16 @@ if can_read_reg: k = RegOpenKeyEx(root, keyp) return RegQueryValueEx(k,val) else: - try: - e = WindowsError - except NameError: - # Make sure we have a definition of WindowsError so we can - # run platform-independent tests of Windows functionality on - # platforms other than Windows. (WindowsError is, in fact, an - # OSError subclass on Windows.) - class WindowsError(OSError): - pass - import builtins - builtins.WindowsError = WindowsError - else: - del e - HKEY_CLASSES_ROOT = None HKEY_LOCAL_MACHINE = None HKEY_CURRENT_USER = None HKEY_USERS = None def RegGetValue(root, key): - raise WindowsError + raise WinError def RegOpenKeyEx(root, key): - raise WindowsError + raise WinError if sys.platform == 'win32': @@ -889,6 +896,28 @@ def AppendPath(oldpath, newpath, sep = os.pathsep, else: return sep.join(paths) +def AddPathIfNotExists(env_dict, key, path, sep=os.pathsep): + """This function will take 'key' out of the dictionary + 'env_dict', then add the path 'path' to that key if it is not + already there. This treats the value of env_dict[key] as if it + has a similar format to the PATH variable...a list of paths + separated by tokens. The 'path' will get added to the list if it + is not already there.""" + try: + is_list = 1 + paths = env_dict[key] + if not is_List(env_dict[key]): + paths = paths.split(sep) + is_list = 0 + if os.path.normcase(path) not in list(map(os.path.normcase, paths)): + paths = [ path ] + paths + if is_list: + env_dict[key] = paths + else: + env_dict[key] = sep.join(paths) + except KeyError: + env_dict[key] = path + if sys.platform == 'cygwin': def get_native_path(path): """Transforms an absolute path into a native path for the system. In @@ -1156,38 +1185,40 @@ def uniquer_hashables(seq): return result +# Recipe 19.11 "Reading Lines with Continuation Characters", +# by Alex Martelli, straight from the Python CookBook (2nd edition). +def logical_lines(physical_lines, joiner=''.join): + logical_line = [] + for line in physical_lines: + stripped = line.rstrip() + if stripped.endswith('\\'): + # a line which continues w/the next physical line + logical_line.append(stripped[:-1]) + else: + # a line which does not continue, end of logical line + logical_line.append(line) + yield joiner(logical_line) + logical_line = [] + if logical_line: + # end of sequence implies end of last logical line + yield joiner(logical_line) + -# Much of the logic here was originally based on recipe 4.9 from the -# Python CookBook, but we had to dumb it way down for Python 1.5.2. class LogicalLines(object): - + """ Wrapper class for the logical_lines method. + + Allows us to read all "logical" lines at once from a + given file object. + """ + def __init__(self, fileobj): self.fileobj = fileobj - def readline(self): - result = [] - while True: - line = self.fileobj.readline() - if not line: - break - if line[-2:] == '\\\n': - result.append(line[:-2]) - else: - result.append(line) - break - return ''.join(result) - def readlines(self): - result = [] - while True: - line = self.readline() - if not line: - break - result.append(line) + result = [l for l in logical_lines(self.fileobj)] return result - class UniqueList(UserList): def __init__(self, seq = []): UserList.__init__(self, seq) diff --git a/scons/scons-local-2.4.1/SCons/Variables/BoolVariable.py b/scons/scons-local-2.5.0/SCons/Variables/BoolVariable.py similarity index 93% rename from scons/scons-local-2.4.1/SCons/Variables/BoolVariable.py rename to scons/scons-local-2.5.0/SCons/Variables/BoolVariable.py index c7310a759..e6ad86bf8 100644 --- a/scons/scons-local-2.4.1/SCons/Variables/BoolVariable.py +++ b/scons/scons-local-2.5.0/SCons/Variables/BoolVariable.py @@ -12,7 +12,7 @@ Usage example: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ Usage example: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/BoolVariable.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Variables/BoolVariable.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __all__ = ['BoolVariable',] @@ -51,7 +51,7 @@ def _text2bool(val): will be returned. See '__true_strings' and '__false_strings' for values considered - 'true' or 'false respectivly. + 'true' or 'false respectively. This is usable as 'converter' for SCons' Variables. """ @@ -74,7 +74,7 @@ def _validator(key, val, env): def BoolVariable(key, help, default): """ - The input parameters describe a boolen option, thus they are + The input parameters describe a boolean option, thus they are returned with the correct converter and validator appended. The 'help' text will by appended by '(yes|no) to show the valid valued. The result is usable for input to opts.Add(). diff --git a/scons/scons-local-2.4.1/SCons/Variables/EnumVariable.py b/scons/scons-local-2.5.0/SCons/Variables/EnumVariable.py similarity index 94% rename from scons/scons-local-2.4.1/SCons/Variables/EnumVariable.py rename to scons/scons-local-2.5.0/SCons/Variables/EnumVariable.py index 734d48c18..5fd41013d 100644 --- a/scons/scons-local-2.4.1/SCons/Variables/EnumVariable.py +++ b/scons/scons-local-2.5.0/SCons/Variables/EnumVariable.py @@ -15,7 +15,7 @@ Usage example: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -37,7 +37,7 @@ Usage example: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/EnumVariable.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Variables/EnumVariable.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __all__ = ['EnumVariable',] @@ -52,7 +52,7 @@ def _validator(key, val, env, vals): def EnumVariable(key, help, default, allowed_values, map={}, ignorecase=0): """ - The input parameters describe a option with only certain values + The input parameters describe an option with only certain values allowed. They are returned with an appropriate converter and validator appended. The result is usable for input to Variables.Add(). @@ -65,7 +65,7 @@ def EnumVariable(key, help, default, allowed_values, map={}, ignorecase=0): for this option. The 'map'-dictionary may be used for converting the input value - into canonical values (eg. for aliases). + into canonical values (e.g. for aliases). 'ignorecase' defines the behaviour of the validator: diff --git a/scons/scons-local-2.4.1/SCons/Variables/ListVariable.py b/scons/scons-local-2.5.0/SCons/Variables/ListVariable.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Variables/ListVariable.py rename to scons/scons-local-2.5.0/SCons/Variables/ListVariable.py index 5541f303d..8e31d88e8 100644 --- a/scons/scons-local-2.4.1/SCons/Variables/ListVariable.py +++ b/scons/scons-local-2.5.0/SCons/Variables/ListVariable.py @@ -4,7 +4,7 @@ This file defines the option type for SCons implementing 'lists'. A 'list' option may either be 'all', 'none' or a list of names separated by comma. After the option has been processed, the option -value holds either the named list elements, all list elemens or no +value holds either the named list elements, all list elements or no list elements at all. Usage example: @@ -25,7 +25,7 @@ Usage example: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -46,9 +46,9 @@ Usage example: # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Variables/ListVariable.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Variables/ListVariable.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" -# Know Bug: This should behave like a Set-Type, but does not really, +# Known Bug: This should behave like a Set-Type, but does not really, # since elements can occur twice. __all__ = ['ListVariable',] @@ -106,14 +106,14 @@ def _converter(val, allowedElems, mapdict): ## def _validator(key, val, env): ## """ ## """ -## # todo: write validater for pgk list +## # todo: write validator for pgk list ## return 1 def ListVariable(key, help, default, names, map={}): """ The input parameters describe a 'package list' option, thus they - are returned with the correct converter and validater appended. The + are returned with the correct converter and validator appended. The result is usable for input to opts.Add() . A 'package list' option may either be 'all', 'none' or a list of diff --git a/scons/scons-local-2.4.1/SCons/Variables/PackageVariable.py b/scons/scons-local-2.5.0/SCons/Variables/PackageVariable.py similarity index 89% rename from scons/scons-local-2.4.1/SCons/Variables/PackageVariable.py rename to scons/scons-local-2.5.0/SCons/Variables/PackageVariable.py index a0244e4a3..44d87ccbb 100644 --- a/scons/scons-local-2.4.1/SCons/Variables/PackageVariable.py +++ b/scons/scons-local-2.5.0/SCons/Variables/PackageVariable.py @@ -11,7 +11,7 @@ Usage example: Examples: x11=no (disables X11 support) x11=yes (will search for the package installation dir) - x11=/usr/local/X11 (will check this path for existance) + x11=/usr/local/X11 (will check this path for existence) To replace autoconf's --with-xxx=yyy @@ -28,7 +28,7 @@ Usage example: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -50,7 +50,7 @@ Usage example: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/PackageVariable.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Variables/PackageVariable.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __all__ = ['PackageVariable',] @@ -70,10 +70,10 @@ def _converter(val): def _validator(key, val, env, searchfunc): - # NB: searchfunc is currenty undocumented and unsupported + # NB: searchfunc is currently undocumented and unsupported """ """ - # todo: write validator, check for path + # TODO write validator, check for path import os if env[key] is True: if searchfunc: @@ -84,14 +84,14 @@ def _validator(key, val, env, searchfunc): def PackageVariable(key, help, default, searchfunc=None): - # NB: searchfunc is currenty undocumented and unsupported + # NB: searchfunc is currently undocumented and unsupported """ The input parameters describe a 'package list' option, thus they are returned with the correct converter and validator appended. The result is usable for input to opts.Add() . A 'package list' option may either be 'all', 'none' or a list of - package names (seperated by space). + package names (separated by space). """ help = '\n '.join( (help, '( yes | no | /path/to/%s )' % key)) diff --git a/scons/scons-local-2.4.1/SCons/Variables/PathVariable.py b/scons/scons-local-2.5.0/SCons/Variables/PathVariable.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/Variables/PathVariable.py rename to scons/scons-local-2.5.0/SCons/Variables/PathVariable.py index a7c68a88a..081fee598 100644 --- a/scons/scons-local-2.4.1/SCons/Variables/PathVariable.py +++ b/scons/scons-local-2.5.0/SCons/Variables/PathVariable.py @@ -2,7 +2,7 @@ This file defines an option type for SCons implementing path settings. -To be used whenever a a user-specified path override should be allowed. +To be used whenever a user-specified path override should be allowed. Arguments to PathVariable are: option-name = name of this option on the command line (e.g. "prefix") @@ -22,7 +22,7 @@ Arguments to PathVariable are: is valid. The arguments to the validator function are: (key, val, env). The key is the name of the option, the val is the path specified for the option, - and the env is the env to which the Otions have been + and the env is the env to which the Options have been added. Usage example: @@ -46,7 +46,7 @@ Usage example: """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -68,7 +68,7 @@ Usage example: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/PathVariable.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Variables/PathVariable.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __all__ = ['PathVariable',] @@ -102,7 +102,7 @@ class _PathVariableClass(object): os.makedirs(val) def PathIsFile(self, key, val, env): - """validator to check if Path is a file""" + """Validator to check if Path is a file""" if not os.path.isfile(val): if os.path.isdir(val): m = 'File path for option %s is a directory: %s' @@ -111,13 +111,12 @@ class _PathVariableClass(object): raise SCons.Errors.UserError(m % (key, val)) def PathExists(self, key, val, env): - """validator to check if Path exists""" + """Validator to check if Path exists""" if not os.path.exists(val): m = 'Path for option %s does not exist: %s' raise SCons.Errors.UserError(m % (key, val)) def __call__(self, key, help, default, validator=None): - # NB: searchfunc is currenty undocumented and unsupported """ The input parameters describe a 'path list' option, thus they are returned with the correct converter and validator appended. The diff --git a/scons/scons-local-2.4.1/SCons/Variables/__init__.py b/scons/scons-local-2.5.0/SCons/Variables/__init__.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/Variables/__init__.py rename to scons/scons-local-2.5.0/SCons/Variables/__init__.py index 57447d79a..83ec1b267 100644 --- a/scons/scons-local-2.4.1/SCons/Variables/__init__.py +++ b/scons/scons-local-2.5.0/SCons/Variables/__init__.py @@ -5,7 +5,7 @@ customizable variables to an SCons build. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ customizable variables to an SCons build. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Variables/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Variables/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os.path import sys @@ -50,12 +50,17 @@ class Variables(object): Holds all the options, updates the environment with the variables, and renders the help text. """ - def __init__(self, files=[], args={}, is_global=1): + def __init__(self, files=None, args=None, is_global=1): """ files - [optional] List of option configuration files to load (backward compatibility) If a single string is passed it is automatically placed in a file list """ + # initialize arguments + if files is None: + files = [] + if args is None: + args = {} self.options = [] self.args = args if not SCons.Util.is_List(files): diff --git a/scons/scons-local-2.4.1/SCons/Warnings.py b/scons/scons-local-2.5.0/SCons/Warnings.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/Warnings.py rename to scons/scons-local-2.5.0/SCons/Warnings.py index 5edef279d..adf1eabd1 100644 --- a/scons/scons-local-2.4.1/SCons/Warnings.py +++ b/scons/scons-local-2.5.0/SCons/Warnings.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This file implements the warnings framework for SCons. """ -__revision__ = "src/engine/SCons/Warnings.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/Warnings.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import sys @@ -41,10 +41,12 @@ class WarningOnByDefault(Warning): # NOTE: If you add a new warning class, add it to the man page, too! - class TargetNotBuiltWarning(Warning): # Should go to OnByDefault pass +class CacheVersionWarning(WarningOnByDefault): + pass + class CacheWriteErrorWarning(Warning): pass diff --git a/scons/scons-local-2.4.1/SCons/__init__.py b/scons/scons-local-2.5.0/SCons/__init__.py similarity index 84% rename from scons/scons-local-2.4.1/SCons/__init__.py rename to scons/scons-local-2.5.0/SCons/__init__.py index d7ec281b2..bc557bf50 100644 --- a/scons/scons-local-2.4.1/SCons/__init__.py +++ b/scons/scons-local-2.5.0/SCons/__init__.py @@ -5,7 +5,7 @@ The main package for the SCons software construction utility. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,15 +27,15 @@ The main package for the SCons software construction utility. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/__init__.py rel_2.5.0:3544:95d356f188a3 2016/04/09 14:38:50 bdbaddog" -__version__ = "2.4.1" +__version__ = "2.5.0" -__build__ = "rel_2.4.1:3453:73fefd3ea0b0" +__build__ = "rel_2.5.0:3544:95d356f188a3[MODIFIED]" __buildsys__ = "ubuntu1404-32bit" -__date__ = "2015/11/09 03:25:05" +__date__ = "2016/04/09 14:38:50" __developer__ = "bdbaddog" diff --git a/scons/scons-local-2.4.1/SCons/compat/__init__.py b/scons/scons-local-2.5.0/SCons/compat/__init__.py similarity index 50% rename from scons/scons-local-2.4.1/SCons/compat/__init__.py rename to scons/scons-local-2.5.0/SCons/compat/__init__.py index 62f28f216..000b81faf 100644 --- a/scons/scons-local-2.4.1/SCons/compat/__init__.py +++ b/scons/scons-local-2.5.0/SCons/compat/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -35,9 +35,6 @@ the builtins namespace or the global module list so that the rest of our code can use the objects and names imported here regardless of Python version. -Simply enough, things that go in the builtins name space come from -our _scons_builtins module. - The rest of the things here will be in individual compatibility modules that are either: 1) suitably modified copies of the future modules that we want to use; or 2) backwards compatible re-implementations of the @@ -60,7 +57,7 @@ function defined below loads the module as the "real" name (without the rest of our code will find our pre-loaded compatibility module. """ -__revision__ = "src/engine/SCons/compat/__init__.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/compat/__init__.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import os import sys @@ -85,93 +82,8 @@ def rename_module(new, old): except ImportError: return False - -rename_module('builtins', '__builtin__') -import _scons_builtins - - -try: - import hashlib -except ImportError: - # Pre-2.5 Python has no hashlib module. - try: - import_as('_scons_hashlib', 'hashlib') - except ImportError: - # If we failed importing our compatibility module, it probably - # means this version of Python has no md5 module. Don't do - # anything and let the higher layer discover this fact, so it - # can fall back to using timestamp. - pass - -try: - set -except NameError: - # Pre-2.4 Python has no native set type - import_as('_scons_sets', 'sets') - import builtins, sets - builtins.set = sets.Set - - -try: - import collections -except ImportError: - # Pre-2.4 Python has no collections module. - import_as('_scons_collections', 'collections') -else: - try: - collections.UserDict - except AttributeError: - exec('from UserDict import UserDict as _UserDict') - collections.UserDict = _UserDict - del _UserDict - try: - collections.UserList - except AttributeError: - exec('from UserList import UserList as _UserList') - collections.UserList = _UserList - del _UserList - try: - collections.UserString - except AttributeError: - exec('from UserString import UserString as _UserString') - collections.UserString = _UserString - del _UserString - - -try: - import io -except ImportError: - # Pre-2.6 Python has no io module. - import_as('_scons_io', 'io') - - -try: - os.devnull -except AttributeError: - # Pre-2.4 Python has no os.devnull attribute - _names = sys.builtin_module_names - if 'posix' in _names: - os.devnull = '/dev/null' - elif 'nt' in _names: - os.devnull = 'nul' - os.path.devnull = os.devnull -try: - os.path.lexists -except AttributeError: - # Pre-2.4 Python has no os.path.lexists function - def lexists(path): - return os.path.exists(path) or os.path.islink(path) - os.path.lexists = lexists - - -# When we're using the '-3' option during regression tests, importing -# cPickle gives a warning no matter how it's done, so always use the -# real profile module, whether it's fast or not. -if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is None: - # Not a regression test with '-3', so try to use faster version. - # In 3.x, 'pickle' automatically loads the fast version if available. - rename_module('pickle', 'cPickle') - +# In 3.x, 'pickle' automatically loads the fast version if available. +rename_module('pickle', 'cPickle') # In 3.x, 'profile' automatically loads the fast version if available. rename_module('profile', 'cProfile') @@ -185,49 +97,40 @@ rename_module('queue', 'Queue') rename_module('winreg', '_winreg') -try: - import subprocess -except ImportError: - # Pre-2.4 Python has no subprocess module. - import_as('_scons_subprocess', 'subprocess') - +# Python 3 moved builtin intern() to sys package +# To make porting easier, make intern always live +# in sys package (for python 2.7.x) try: sys.intern except AttributeError: - # Pre-2.6 Python has no sys.intern() function. - import builtins - try: - sys.intern = builtins.intern - except AttributeError: - # Pre-2.x Python has no builtin intern() function. - def intern(x): - return x - sys.intern = intern - del intern + # We must be using python 2.7.x so monkey patch + # intern into the sys package + sys.intern = intern + + +# Preparing for 3.x. UserDict, UserList, UserString are in +# collections for 3.x, but standalone in 2.7.x +import collections try: - sys.maxsize + collections.UserDict except AttributeError: - # Pre-2.6 Python has no sys.maxsize attribute - # Wrapping sys in () is silly, but protects it from 2to3 renames fixer - sys.maxsize = (sys).maxint + exec('from UserDict import UserDict as _UserDict') + collections.UserDict = _UserDict + del _UserDict +try: + collections.UserList +except AttributeError: + exec('from UserList import UserList as _UserList') + collections.UserList = _UserList + del _UserList -if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: - # We can't apply the 'callable' fixer until the floor is 2.6, but the - # '-3' option to Python 2.6 and 2.7 generates almost ten thousand - # warnings. This hack allows us to run regression tests with the '-3' - # option by replacing the callable() built-in function with a hack - # that performs the same function but doesn't generate the warning. - # Note that this hack is ONLY intended to be used for regression - # testing, and should NEVER be used for real runs. - from types import ClassType - def callable(obj): - if hasattr(obj, '__call__'): return True - if isinstance(obj, (ClassType, type)): return True - return False - import builtins - builtins.callable = callable - del callable +try: + collections.UserString +except AttributeError: + exec('from UserString import UserString as _UserString') + collections.UserString = _UserString + del _UserString # Local Variables: diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_builtins.py b/scons/scons-local-2.5.0/SCons/compat/_scons_builtins.py similarity index 98% rename from scons/scons-local-2.4.1/SCons/compat/_scons_builtins.py rename to scons/scons-local-2.5.0/SCons/compat/_scons_builtins.py index b42fc2df7..cc97faf8f 100644 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_builtins.py +++ b/scons/scons-local-2.5.0/SCons/compat/_scons_builtins.py @@ -51,7 +51,7 @@ the FUNCTIONS or DATA output, that means those names are already built in to this version of Python and we don't need to add them from this module. """ -__revision__ = "src/engine/SCons/compat/_scons_builtins.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/compat/_scons_builtins.py rel_2.4.1:3480:df381b06597b 2015/11/21 07:35:35 bdbaddog" import builtins diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_dbm.py b/scons/scons-local-2.5.0/SCons/compat/_scons_dbm.py similarity index 90% rename from scons/scons-local-2.4.1/SCons/compat/_scons_dbm.py rename to scons/scons-local-2.5.0/SCons/compat/_scons_dbm.py index 080c424b9..0720956fb 100644 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_dbm.py +++ b/scons/scons-local-2.5.0/SCons/compat/_scons_dbm.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ that the whichdb.whichdb() implementstation in the various 2.X versions of Python won't blow up even if dbm wasn't compiled in. """ -__revision__ = "src/engine/SCons/compat/_scons_dbm.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/compat/_scons_dbm.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" class error(Exception): pass diff --git a/scons/scons-local-2.4.1/SCons/compat/_scons_hashlib.py b/scons/scons-local-2.5.0/SCons/compat/_scons_hashlib.py similarity index 97% rename from scons/scons-local-2.4.1/SCons/compat/_scons_hashlib.py rename to scons/scons-local-2.5.0/SCons/compat/_scons_hashlib.py index 626253019..e86078262 100644 --- a/scons/scons-local-2.4.1/SCons/compat/_scons_hashlib.py +++ b/scons/scons-local-2.5.0/SCons/compat/_scons_hashlib.py @@ -31,7 +31,7 @@ purposes, anyway). In fact, this module will raise an ImportError if the underlying md5 module isn't available. """ -__revision__ = "src/engine/SCons/compat/_scons_hashlib.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/compat/_scons_hashlib.py rel_2.4.1:3480:df381b06597b 2015/11/21 07:35:35 bdbaddog" import md5 from string import hexdigits diff --git a/scons/scons-local-2.4.1/SCons/cpp.py b/scons/scons-local-2.5.0/SCons/cpp.py similarity index 99% rename from scons/scons-local-2.4.1/SCons/cpp.py rename to scons/scons-local-2.5.0/SCons/cpp.py index 56bb003ab..46671afdb 100644 --- a/scons/scons-local-2.4.1/SCons/cpp.py +++ b/scons/scons-local-2.5.0/SCons/cpp.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/cpp.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/cpp.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" __doc__ = """ SCons C Pre-Processor module diff --git a/scons/scons-local-2.4.1/SCons/dblite.py b/scons/scons-local-2.5.0/SCons/dblite.py similarity index 96% rename from scons/scons-local-2.4.1/SCons/dblite.py rename to scons/scons-local-2.5.0/SCons/dblite.py index f4ba90a1f..707a4f88b 100644 --- a/scons/scons-local-2.4.1/SCons/dblite.py +++ b/scons/scons-local-2.5.0/SCons/dblite.py @@ -3,7 +3,6 @@ import SCons.compat -import builtins import os # compat layer imports "cPickle" for us if it's available. import pickle @@ -44,7 +43,7 @@ class dblite(object): # See the discussion at: # http://mail.python.org/pipermail/python-bugs-list/2003-March/016877.html - _open = builtins.open + _open = open _pickle_dump = staticmethod(pickle.dump) _os_chmod = os.chmod try: @@ -99,7 +98,10 @@ class dblite(object): if (len(p) > 0): try: self._dict = pickle.loads(p) - except (pickle.UnpicklingError, EOFError): + except (pickle.UnpicklingError, EOFError, KeyError): + # Note how we catch KeyErrors too here, which might happen + # when we don't have cPickle available (default pickle + # throws it). if (ignore_corrupt_dbfiles == 0): raise if (ignore_corrupt_dbfiles == 1): corruption_warning(self._file_name) diff --git a/scons/scons-local-2.4.1/SCons/exitfuncs.py b/scons/scons-local-2.5.0/SCons/exitfuncs.py similarity index 92% rename from scons/scons-local-2.4.1/SCons/exitfuncs.py rename to scons/scons-local-2.5.0/SCons/exitfuncs.py index ae07ec0c0..a20f049b3 100644 --- a/scons/scons-local-2.4.1/SCons/exitfuncs.py +++ b/scons/scons-local-2.5.0/SCons/exitfuncs.py @@ -5,7 +5,7 @@ Register functions which are executed when SCons exits for any reason. """ # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Register functions which are executed when SCons exits for any reason. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/exitfuncs.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/engine/SCons/exitfuncs.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import atexit diff --git a/scons/scons-local-2.4.1/scons-2.4.1-py2.7.egg-info b/scons/scons-local-2.5.0/scons-2.5.0-py2.7.egg-info similarity index 96% rename from scons/scons-local-2.4.1/scons-2.4.1-py2.7.egg-info rename to scons/scons-local-2.5.0/scons-2.5.0-py2.7.egg-info index 9e50367c6..1742cf89d 100644 --- a/scons/scons-local-2.4.1/scons-2.4.1-py2.7.egg-info +++ b/scons/scons-local-2.5.0/scons-2.5.0-py2.7.egg-info @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: scons -Version: 2.4.1 +Version: 2.5.0 Summary: Open Source next-generation build tool. Home-page: http://www.scons.org/ Author: Steven Knight diff --git a/scons/scons-time.py b/scons/scons-time.py index 054e73ebe..2e63ef211 100755 --- a/scons/scons-time.py +++ b/scons/scons-time.py @@ -9,7 +9,7 @@ # # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ from __future__ import division from __future__ import nested_scopes -__revision__ = "src/script/scons-time.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/script/scons-time.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog" import getopt import glob @@ -43,53 +43,10 @@ import sys import tempfile import time -try: - sorted -except NameError: - # Pre-2.4 Python has no sorted() function. - # - # The pre-2.4 Python list.sort() method does not support - # list.sort(key=) nor list.sort(reverse=) keyword arguments, so - # we must implement the functionality of those keyword arguments - # by hand instead of passing them to list.sort(). - def sorted(iterable, cmp=None, key=None, reverse=False): - if key is not None: - result = [(key(x), x) for x in iterable] - else: - result = iterable[:] - if cmp is None: - # Pre-2.3 Python does not support list.sort(None). - result.sort() - else: - result.sort(cmp) - if key is not None: - result = [t1 for t0,t1 in result] - if reverse: - result.reverse() - return result - -if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: - # We can't apply the 'callable' fixer until the floor is 2.6, but the - # '-3' option to Python 2.6 and 2.7 generates almost ten thousand - # warnings. This hack allows us to run regression tests with the '-3' - # option by replacing the callable() built-in function with a hack - # that performs the same function but doesn't generate the warning. - # Note that this hack is ONLY intended to be used for regression - # testing, and should NEVER be used for real runs. - from types import ClassType - def callable(obj): - if hasattr(obj, '__call__'): return True - if isinstance(obj, (ClassType, type)): return True - return False - def make_temp_file(**kw): try: result = tempfile.mktemp(**kw) - try: - result = os.path.realpath(result) - except AttributeError: - # Python 2.1 has no os.path.realpath() method. - pass + result = os.path.realpath(result) except TypeError: try: save_template = tempfile.template diff --git a/scons/scons.py b/scons/scons.py index e2f66bd82..2cae192af 100755 --- a/scons/scons.py +++ b/scons/scons.py @@ -2,7 +2,7 @@ # # SCons - a Software Constructor # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,15 +23,15 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/script/scons.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/script/scons.py rel_2.5.0:3544:95d356f188a3 2016/04/09 14:38:50 bdbaddog" -__version__ = "2.4.1" +__version__ = "2.5.0" -__build__ = "rel_2.4.1:3453:73fefd3ea0b0" +__build__ = "rel_2.5.0:3544:95d356f188a3[MODIFIED]" __buildsys__ = "ubuntu1404-32bit" -__date__ = "2015/11/09 03:25:05" +__date__ = "2016/04/09 14:38:50" __developer__ = "bdbaddog" @@ -188,8 +188,8 @@ sys.path = libs + sys.path if __name__ == "__main__": try: import SCons.Script - except: - print("Import failed. Unable to find SCons files in:") + except ImportError: + print("SCons import failed. Unable to find engine files in:") for path in libs: print(" %s" % path) raise diff --git a/scons/sconsign.py b/scons/sconsign.py index 775f23b05..38a217a54 100755 --- a/scons/sconsign.py +++ b/scons/sconsign.py @@ -2,7 +2,7 @@ # # SCons - a Software Constructor # -# Copyright (c) 2001 - 2015 The SCons Foundation +# Copyright (c) 2001 - 2016 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,15 +23,15 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/script/sconsign.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" +__revision__ = "src/script/sconsign.py rel_2.5.0:3544:95d356f188a3 2016/04/09 14:38:50 bdbaddog" -__version__ = "2.4.1" +__version__ = "2.5.0" -__build__ = "rel_2.4.1:3453:73fefd3ea0b0" +__build__ = "rel_2.5.0:3544:95d356f188a3[MODIFIED]" __buildsys__ = "ubuntu1404-32bit" -__date__ = "2015/11/09 03:25:05" +__date__ = "2016/04/09 14:38:50" __developer__ = "bdbaddog" @@ -54,6 +54,14 @@ import sys # followed by generic) so we pick up the right version of the build # engine modules if they're in either directory. + +if sys.version_info >= (3,0,0): + msg = "sconsign: *** Version %s does not run under Python version %s.\n\ +Python 3 is not yet supported.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) + + script_dir = sys.path[0] if script_dir in sys.path: @@ -64,6 +72,11 @@ libs = [] if "SCONS_LIB_DIR" in os.environ: libs.append(os.environ["SCONS_LIB_DIR"]) +# - running from source takes priority (since 2.3.2), excluding SCONS_LIB_DIR settings +script_path = os.path.abspath(os.path.dirname(__file__)) +source_path = os.path.join(script_path, '..', 'engine') +libs.append(source_path) + local_version = 'scons-local-' + __version__ local = 'scons-local' if script_dir: @@ -463,12 +476,22 @@ for o, a in opts: elif o in ('-e', '--entry'): Print_Entries.append(a) elif o in ('-f', '--format'): + # Try to map the given DB format to a known module + # name, that we can then try to import... Module_Map = {'dblite' : 'SCons.dblite', 'sconsign' : None} dbm_name = Module_Map.get(a, a) if dbm_name: try: - dbm = my_import(dbm_name) + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 except: sys.stderr.write("sconsign: illegal file format `%s'\n" % a) print helpstr @@ -500,7 +523,15 @@ else: dbm_name = whichdb.whichdb(a) if dbm_name: Map_Module = {'SCons.dblite' : 'dblite'} - dbm = my_import(dbm_name) + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) else: Do_SConsignDir(a) diff --git a/scripts/appveyor-system-info.ps1 b/scripts/appveyor-system-info.ps1 new file mode 100644 index 000000000..586ef2de2 --- /dev/null +++ b/scripts/appveyor-system-info.ps1 @@ -0,0 +1,84 @@ +$PSVersionTable +$PSVersionTable.PSVersion + +$comp_name = $env:COMPUTERNAME +$user_name = $env:USERNAME +Write-Host $comp_name $user_name + +$on_appveyor = $false +if($comp_name -like 'APPVYR*' -And $user_name -eq "appveyor"){ + $on_appveyor = $true +} + + +$SystemManaged = Get-WmiObject -Class Win32_ComputerSystem | % {$_.AutomaticManagedPagefile} +$total_physicalmem = gwmi Win32_ComputerSystem | % {[Math]::round($_.TotalPhysicalMemory/1MB,0)} +$physical_mem = get-ciminstance -class 'cim_physicalmemory' | % { $_.Capacity/1024/1024} + +$PF =gwmi Win32_PageFileUsage +$PageFileLocation = $PF.Name; +$PageFileSize = $PF.AllocatedBaseSize + +Write-Host "physical memory : "$physical_mem +Write-Host "total physical memory : "$total_physicalmem +Write-Host "page file system managed : "$SystemManaged +Write-Host "page file location : "$PageFileLocation +Write-Host "page file size : "$PageFileSize +Write-Host "InitialSize : "${CurrentPageFile}.InitialSize +Write-Host "MaximumSize : "$CurrentPageFile.MaximumSize + +if($on_appveyor -eq $true){ + + Write-Host !!!!!!! on AppVeyor: changing page file settings !!!!!!!!!! + + $dirs = ( + "C:\qt", + "C:\Users\appveyor\AppData\Local\Microsoft\Web Platform Installer", + "C:\Program Files\Microsoft SQL Server", + "C:\ProgramData\Package Cache" + ) + Foreach($dir in $dirs){ + if(Test-Path $dir) { + Write-Host found $dir + Remove-Item $dir -Force -Recurse + } else { + Write-Host not found $dir + } + } + + #disable automatically managed page file settings + $c = Get-WmiObject Win32_computersystem -EnableAllPrivileges + if($c.AutomaticManagedPagefile){ + Write-Host disabling managed page file settings + $c.AutomaticManagedPagefile = $false + $c.Put() | Out-Null + } + + $new_page_size=18000 + $CurrentPageFile = Get-WmiObject -Class Win32_PageFileSetting + if($CurrentPageFile.InitialSize -ne $new_page_size){ + Write-Host "setting new page file size to $new_page_size" + $CurrentPageFile.InitialSize=$new_page_size + $CurrentPageFile.MaximumSize=$new_page_size + $CurrentPageFile.Put() | Out-Null + } + + Write-Host "new ------------ " + Write-Host "system managed:" (Get-WmiObject -Class Win32_ComputerSystem | % {$_.AutomaticManagedPagefile}) + Write-Host "page file size:" (gwmi Win32_PageFileUsage).AllocatedBaseSize + Write-Host "InitialSize: "${CurrentPageFile}.InitialSize + Write-Host "MaximumSize: "$CurrentPageFile.MaximumSize +} else { + Write-Host not on AppVeyor, leaving page file as is +} + +#list drives +Get-WmiObject -Class Win32_LogicalDisk | + Where-Object {$_.DriveType -ne 5} | + Sort-Object -Property Name | + Select-Object Name, VolumeName, FileSystem, Description, VolumeDirty, ` + @{"Label"="DiskSize(GB)";"Expression"={"{0:N}" -f ($_.Size/1GB) -as [float]}}, ` + @{"Label"="FreeSpace(GB)";"Expression"={"{0:N}" -f ($_.FreeSpace/1GB) -as [float]}}, ` + @{"Label"="%Free";"Expression"={"{0:N}" -f ($_.FreeSpace/$_.Size*100) -as [float]}} | + Format-Table -AutoSize + diff --git a/scripts/build-appveyor.bat b/scripts/build-appveyor.bat index 0cadb5ef8..84088d4cb 100644 --- a/scripts/build-appveyor.bat +++ b/scripts/build-appveyor.bat @@ -5,12 +5,13 @@ SET EL=0 ECHO =========== %~f0 =========== ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS% -ECHO RAM [MB]^: -powershell "get-ciminstance -class 'cim_physicalmemory' | %% { $_.Capacity/1024/1024}" +powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force +IF %ERRORLEVEL% NEQ 0 GOTO ERROR +powershell .\scripts\appveyor-system-info.ps1 IF %ERRORLEVEL% NEQ 0 GOTO ERROR ::only build on AppVeyor, if explicitly stated -ECHO APPVEYOR_REPO_COMMIT_MESSAGE^: %APPVEYOR_REPO_COMMIT_MESSAGE% +ECHO APPVEYOR_REPO_COMMIT_MESSAGE^: "%APPVEYOR_REPO_COMMIT_MESSAGE%" ::SET BUILD_ON_APPVEYOR=0 ::for /F "tokens=1 usebackq" %%i in (`powershell .\scripts\parse-commit-message.ps1 '[build appveyor]'`) DO SET BUILD_ON_APPVEYOR=%%i ::IF %BUILD_ON_APPVEYOR% EQU 0 ECHO not building, commit with [build appveyor] && GOTO DONE @@ -21,32 +22,27 @@ ECHO msvs_toolset^: %msvs_toolset% SET BUILD_TYPE=%configuration% SET BUILDPLATFORM=%platform% SET TOOLS_VERSION=%msvs_toolset%.0 +SET ICU_VERSION=56.1 +ECHO ICU_VERSION^: %ICU_VERSION% IF DEFINED APPVEYOR (ECHO on AppVeyor) ELSE (ECHO NOT on AppVeyor) ECHO ======== SET PATH=C:\Python27;%PATH% SET PATH=C:\Program Files\7-Zip;%PATH% -:: *nix style find command comes with git: -ECHO checking for unix style 'find' -find %USERPROFILE% -name "*.blabla" -IF %ERRORLEVEL% EQU 0 GOTO NIX_FIND_FOUND - -IF DEFINED GIT_INSTALL_ROOT SET TEMP_GIT_DIR=%GIT_INSTALL_ROOT%&& GOTO TEST_FIND_AGAIN -IF EXIST "C:\Program Files (x86)\Git" SET TEMP_GIT_DIR=C:\Program Files (x86)\Git&& GOTO TEST_FIND_AGAIN -IF EXIST "C:\Program Files\Git" SET TEMP_GIT_DIR=C:\Program Files\Git&& GOTO TEST_FIND_AGAIN - -:TEST_FIND_AGAIN -SET PATH=%TEMP_GIT_DIR%\bin;%PATH% -SET PATH=%TEMP_GIT_DIR%\usr\bin;%PATH% -ECHO %PATH% -::check again -find %USERPROFILE% -name "*.blabla" -IF %ERRORLEVEL% NEQ 0 (ECHO unix style find not found && GOTO ERROR) +::update submodules (variant + test data) +git submodule update --init +IF %ERRORLEVEL% NEQ 0 GOTO ERROR -:NIX_FIND_FOUND -ECHO find was found +::python bindings, including test data +IF NOT EXIST bindings\python git clone --recursive https://github.com/mapnik/python-mapnik.git bindings/python +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + +CD bindings\python & IF %ERRORLEVEL% NEQ 0 GOTO ERROR +git fetch & IF %ERRORLEVEL% NEQ 0 GOTO ERROR +git pull & IF %ERRORLEVEL% NEQ 0 GOTO ERROR +CD ..\.. & IF %ERRORLEVEL% NEQ 0 GOTO ERROR ::cloning mapnik-gyp if EXIST mapnik-gyp ECHO mapnik-gyp already cloned && GOTO MAPNIK_GYP_ALREADY_HERE diff --git a/scripts/build-local.bat b/scripts/build-local.bat index 5d9affc7f..306e10c86 100644 --- a/scripts/build-local.bat +++ b/scripts/build-local.bat @@ -8,14 +8,37 @@ SET APPVEYOR_REPO_COMMIT_MESSAGE=this is a [build appveyor] test SET APPVEYOR=true ::comment this to get complete AppVeyor behaviour SET LOCAL_BUILD_DONT_SKIP_TESTS=true - -SET MAPNIK_GIT=3.0.5 -SET BOOST_VERSION=59 SET FASTBUILD=1 + +FOR /F "tokens=1 usebackq" %%i in (`powershell .\scripts\parse-appveyor-yml.ps1`) DO SET BOOST_VERSION=%%i +ECHO BOOST_VERSION found in appveyor.yml^: %BOOST_VERSION% +IF "%BOOST_VERSION%"=="0" ECHO BOOST_VERSION not valid && SET ERRORLEVEL=1 && GOTO ERROR + + +:: OVERRIDE PARAMETERS >>>>>>>> +:NEXT-ARG + +IF '%1'=='' GOTO ARGS-DONE +ECHO setting %1 +SET %1 +SHIFT +GOTO NEXT-ARG + +:ARGS-DONE +::<<<<< OVERRIDE PARAMETERS + + SET configuration=Release SET msvs_toolset=14 SET platform=x64 SET APPVEYOR_BUILD_FOLDER=%CD% + +ECHO pulling test data +CALL git submodule update --init +IF %ERRORLEVEL% NEQ 0 GOTO ERROR +ECHO pulling test data, DONE + +SET TIME_START_LOCAL_BUILD=%TIME% CALL scripts\build-appveyor.bat IF %ERRORLEVEL% NEQ 0 GOTO ERROR @@ -28,5 +51,7 @@ SET EL=%ERRORLEVEL% :DONE ECHO =========== DONE %~f0 =========== +ECHO build started^: %TIME_START_LOCAL_BUILD% +ECHO build finished^: %TIME% EXIT /b %EL% diff --git a/scripts/msbuild-force-mp-and-buildinparallel.props b/scripts/msbuild-force-mp-and-buildinparallel.props new file mode 100644 index 000000000..1b06765c2 --- /dev/null +++ b/scripts/msbuild-force-mp-and-buildinparallel.props @@ -0,0 +1,9 @@ + + + + + true + true + + + \ No newline at end of file diff --git a/scripts/parse-appveyor-yml.ps1 b/scripts/parse-appveyor-yml.ps1 new file mode 100644 index 000000000..f87ae7e3a --- /dev/null +++ b/scripts/parse-appveyor-yml.ps1 @@ -0,0 +1,7 @@ +$ErrorActionPreference = 'Stop' +$boost_version='0' +Get-Content .\appveyor.yml | + foreach { + if ($_ -match "BOOST_VERSION: "){ $boost_version = $_.split()[-1] } + } +Write-Host $boost_version diff --git a/scripts/time-header b/scripts/time-header new file mode 100755 index 000000000..97c3c6977 --- /dev/null +++ b/scripts/time-header @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +CXXFLAGS="$(./utils/mapnik-config/mapnik-config --cflags)" +CXX="$(./utils/mapnik-config/mapnik-config --cxx)" +echo "Time taken to compile '$(basename $1)':" +time ${CXX} $1 -I./test -I./deps/agg/include -Ideps -I./include $CXXFLAGS -o /tmp/header.out \ No newline at end of file diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh new file mode 100644 index 000000000..40d18374e --- /dev/null +++ b/scripts/travis-common.sh @@ -0,0 +1,119 @@ +#! /bin/bash + +# enabled VALUE +# - if VALUE is empty or falsy, returns 1 (false) +# - otherwise returns 0 (true) +# enabled VALUE COMMAND ... +# - if VALUE is empty or falsy, returns 0 (true) +# - otherwise runs COMMAND and returns its result +enabled () { + local value="$1"; shift + case $value in + ''|'0'|[Ff]alse|[Nn]o) test $# -ne 0;; + *) test $# -eq 0 || "$@";; + esac +} + +# on NAME +# - if NAME == $TRAVIS_OS_NAME, returns 0 (true) +# - otherwise returns 1 (false) +# on NAME COMMAND ... +# - if NAME == $TRAVIS_OS_NAME, runs COMMAND and returns its result +# - otherwise returns 0 (true) +on () { + local name="$1"; shift + case $name in + $TRAVIS_OS_NAME) test $# -eq 0 || "$@";; + *) test $# -ne 0;; + esac +} + +git_submodule_update () { + git submodule update "$@" && return + # failed, search pull requests for matching commits + git submodule foreach \ + ' + test "$sha1" = "`git rev-parse HEAD`" || + git ls-remote origin "refs/pull/*/head" | + while read hash ref; do + if test "$hash" = "$sha1"; then + git config --add remote.origin.fetch "+$ref:$ref"; + fi + done + ' + # try again with added fetch refs + git submodule update "$@" +} + +# install and call pip +pip () { + if ! which pip >/dev/null; then + easy_install --user pip && \ + export PATH="$HOME/Library/Python/2.7/bin:$PATH" + fi + command pip "$@" +} + +# commit_message_contains TEXT +# - returns 0 (true) if TEXT is found in commit message +# - case-insensitive, plain-text search, not regex +commit_message_contains () { + git log -1 --pretty='%B' "$TRAVIS_COMMIT" | grep -qiFe "$*" +} + +commit_message_parse () { + if commit_message_contains '[skip tests]'; then + config_override "CPP_TESTS = False" + fi + if commit_message_contains '[skip utils]'; then + config_override "MAPNIK_INDEX = False" + config_override "MAPNIK_RENDER = False" + config_override "PGSQL2SQLITE = False" + config_override "SHAPEINDEX = False" + config_override "SVG2PNG = False" + fi +} + +config_override () { + echo "Appending to config.py:" "$@" + echo "$@" >> ./config.py +} + +configure () { + if enabled ${COVERAGE}; then + ./configure "$@" PREFIX=${PREFIX} PGSQL2SQLITE=False SVG2PNG=False SVG_RENDERER=False \ + COVERAGE=True DEBUG=True WARNING_CXXFLAGS="-Wno-unknown-warning-option" + else + ./configure "$@" PREFIX=${PREFIX} WARNING_CXXFLAGS="-Wno-unknown-warning-option" + fi + # print final config values, sorted and indented + sort -sk1,1 ./config.py | sed -e 's/^/ /' +} + +coverage () { + ./mason_packages/.link/bin/cpp-coveralls \ + --gcov ${LLVM_COV} \ + --exclude mason_packages \ + --exclude .sconf_temp --exclude benchmark --exclude deps \ + --exclude scons --exclude test --exclude demo --exclude docs \ + --exclude fonts \ + > /dev/null +} + +trigger_downstream() { + body="{ + \"request\": { + \"message\": \"Triggered build: Mapnik core commit ${TRAVIS_COMMIT}\", + \"branch\":\"master\" + } + } + " + + curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Travis-API-Version: 3" \ + -H "Authorization: token ${TRAVIS_TRIGGER_TOKEN}" \ + -d "$body" \ + https://api.travis-ci.org/repo/mapnik%2Fpython-mapnik/requests +} diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index 74e3c935b..f144ceaad 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -43,7 +43,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_color_rgba.h" @@ -53,9 +55,12 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_span_image_filter_rgba.h" +#pragma GCC diagnostic pop -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop // stl #include @@ -121,11 +126,11 @@ struct setup_agg_bg_visitor mode_(mode), opacity_(opacity) {} - void operator() (marker_null const&) {} + void operator() (marker_null const&) const {} - void operator() (marker_svg const&) {} + void operator() (marker_svg const&) const {} - void operator() (marker_rgba8 const& marker) + void operator() (marker_rgba8 const& marker) const { mapnik::image_rgba8 const& bg_image = marker.get_data(); std::size_t w = bg_image.width(); @@ -361,9 +366,9 @@ struct agg_render_marker_visitor opacity_(opacity), comp_op_(comp_op) {} - void operator() (marker_null const&) {} + void operator() (marker_null const&) const {} - void operator() (marker_svg const& marker) + void operator() (marker_svg const& marker) const { using color_type = agg::rgba8; using order_type = agg::order_rgba; @@ -414,7 +419,7 @@ struct agg_render_marker_visitor svg_renderer.render(*ras_ptr_, sl, renb, mtx, opacity_, bbox); } - void operator() (marker_rgba8 const& marker) + void operator() (marker_rgba8 const& marker) const { using color_type = agg::rgba8; using order_type = agg::order_rgba; diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index aabba778d..d27b68b7c 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -33,10 +33,12 @@ #include #include #include + // stl #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_color_rgba.h" @@ -45,6 +47,7 @@ #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" #include "agg_conv_stroke.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_debug_symbolizer.cpp b/src/agg/process_debug_symbolizer.cpp index c56add951..3c3f898f8 100644 --- a/src/agg/process_debug_symbolizer.cpp +++ b/src/agg/process_debug_symbolizer.cpp @@ -33,7 +33,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_color_rgba.h" @@ -41,6 +42,7 @@ #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" #include "agg_conv_stroke.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -165,12 +167,12 @@ struct RingRenderer { }; template -struct render_ring_visitor { - +struct render_ring_visitor +{ render_ring_visitor(RingRenderer & renderer) : renderer_(renderer) {} - void operator()(mapnik::geometry::multi_polygon const& geom) + void operator()(mapnik::geometry::multi_polygon const& geom) const { for (auto const& poly : geom) { @@ -178,7 +180,7 @@ struct render_ring_visitor { } } - void operator()(mapnik::geometry::polygon const& geom) + void operator()(mapnik::geometry::polygon const& geom) const { agg::rgba8 red(255,0,0,255); agg::rgba8 green(0,255,255,255); @@ -199,7 +201,7 @@ struct render_ring_visitor { } template - void operator()(GeomType const&) {} + void operator()(GeomType const&) const {} RingRenderer & renderer_; }; diff --git a/src/agg/process_dot_symbolizer.cpp b/src/agg/process_dot_symbolizer.cpp index cc375862d..cfb58c6e9 100644 --- a/src/agg/process_dot_symbolizer.cpp +++ b/src/agg/process_dot_symbolizer.cpp @@ -33,7 +33,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_ellipse.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -41,6 +42,7 @@ #include "agg_renderer_scanline.h" #include "agg_color_rgba.h" #include "agg_renderer_base.h" +#pragma GCC diagnostic pop namespace mapnik { namespace detail { diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index f2c8adf48..6ba5605dc 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -25,22 +25,20 @@ #include #include #include -#include #include -#include #include -#include -#include -#include #include -#include #include +#include #include #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -55,7 +53,7 @@ template struct thunk_renderer; template <> -struct thunk_renderer +struct thunk_renderer : render_thunk_list_dispatch { using renderer_type = agg_renderer; using buffer_type = renderer_type::buffer_type; @@ -64,12 +62,13 @@ struct thunk_renderer thunk_renderer(renderer_type &ren, std::unique_ptr const& ras_ptr, buffer_type *buf, - renderer_common &common, - pixel_position const &offset) - : ren_(ren), ras_ptr_(ras_ptr), buf_(buf), common_(common), offset_(offset) + renderer_common &common) + : ren_(ren), ras_ptr_(ras_ptr), buf_(buf), common_(common), + tex_(*buf, HALO_RASTERIZER_FULL, src_over, src_over, + common.scale_factor_, common.font_manager_.get_stroker()) {} - void operator()(vector_marker_render_thunk const &thunk) const + virtual void operator()(vector_marker_render_thunk const& thunk) { using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender using buf_type = agg::rendering_buffer; @@ -95,7 +94,7 @@ struct thunk_renderer render_vector_marker(svg_renderer, *ras_ptr_, renb, thunk.src_->bounding_box(), offset_tr, thunk.opacity_, thunk.snap_to_pixels_); } - void operator()(raster_marker_render_thunk const &thunk) const + virtual void operator()(raster_marker_render_thunk const& thunk) { using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender using buf_type = agg::rendering_buffer; @@ -113,32 +112,25 @@ struct thunk_renderer render_raster_marker(renb, *ras_ptr_, thunk.src_, offset_tr, thunk.opacity_, common_.scale_factor_, thunk.snap_to_pixels_); } - void operator()(text_render_thunk const &thunk) const + virtual void operator()(text_render_thunk const& thunk) { - text_renderer_type ren(*buf_, thunk.halo_rasterizer_, thunk.comp_op_, thunk.comp_op_, - common_.scale_factor_, common_.font_manager_.get_stroker()); + tex_.set_comp_op(thunk.comp_op_); + tex_.set_halo_comp_op(thunk.comp_op_); + tex_.set_halo_rasterizer(thunk.halo_rasterizer_); - render_offset_placements( - thunk.placements_, - offset_, - [&] (glyph_positions_ptr const& glyphs) + for (auto const& glyphs : thunk.placements_) + { + scoped_glyph_positions_offset tmp_off(*glyphs, offset_); + + if (auto const& mark = glyphs->get_marker()) { - marker_info_ptr mark = glyphs->get_marker(); - if (mark) - { - ren_.render_marker(glyphs->marker_pos(), - *mark->marker_, - mark->transform_, - thunk.opacity_, thunk.comp_op_); - } - ren.render(*glyphs); - }); - } - - template - void operator()(T const &) const - { - throw std::runtime_error("Rendering of this data type is not supported currently by the renderer"); + ren_.render_marker(glyphs->marker_pos(), + *mark->marker_, + mark->transform_, + thunk.opacity_, thunk.comp_op_); + } + tex_.render(*glyphs); + } } private: @@ -146,7 +138,7 @@ private: std::unique_ptr const& ras_ptr_; buffer_type *buf_; renderer_common &common_; - pixel_position offset_; + text_renderer_type tex_; }; template @@ -154,16 +146,11 @@ void agg_renderer::process(group_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + thunk_renderer ren(*this, ras_ptr, current_buffer_, common_); + render_group_symbolizer( sym, feature, common_.vars_, prj_trans, clipping_extent(common_), common_, - [&](render_thunk_list const& thunks, pixel_position const& render_offset) - { - thunk_renderer ren(*this, ras_ptr, current_buffer_, common_, render_offset); - for (render_thunk_ptr const& thunk : thunks) - { - util::apply_visitor(ren, *thunk); - } - }); + ren); } template void agg_renderer::process(group_symbolizer const&, diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 17ec5bbf0..dbbb7f26d 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -37,7 +37,10 @@ #include #include #include -// agg + + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_pixfmt_rgba.h" #include "agg_color_rgba.h" @@ -50,6 +53,7 @@ #include "agg_span_allocator.h" #include "agg_span_pattern_rgba.h" #include "agg_renderer_outline_image.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -71,9 +75,9 @@ struct agg_renderer_process_visitor_l feature_(feature), prj_trans_(prj_trans) {} - void operator() (marker_null const&) {} + void operator() (marker_null const&) const {} - void operator() (marker_svg const& marker) + void operator() (marker_svg const& marker) const { using color = agg::rgba8; using order = agg::order_rgba; @@ -88,7 +92,7 @@ struct agg_renderer_process_visitor_l value_double opacity = get(sym_, feature_, common_.vars_); agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*ras_ptr_, marker, image_tr, 1.0, image); @@ -147,7 +151,7 @@ struct agg_renderer_process_visitor_l mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry()); } - void operator() (marker_rgba8 const& marker) + void operator() (marker_rgba8 const& marker) const { using color = agg::rgba8; using order = agg::order_rgba; @@ -214,7 +218,7 @@ struct agg_renderer_process_visitor_l using apply_vertex_converter_type = detail::apply_vertex_converter; using vertex_processor_type = geometry::vertex_processor; apply_vertex_converter_type apply(converter, ras); - mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry()); + mapnik::util::apply_visitor(vertex_processor_type(apply), feature_.get_geometry()); } private: diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index b3a01c7e8..9bace2539 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -32,7 +32,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -45,6 +47,7 @@ #include "agg_conv_dash.h" #include "agg_renderer_outline_aa.h" #include "agg_rasterizer_outline_aa.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index cb9428260..3fc122dcb 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -24,23 +24,17 @@ #include #include #include - -#include -#include -#include -#include -#include -#include #include #include #include #include #include #include -#include -#include #include -// agg +#include + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_renderer_base.h" #include "agg_renderer_scanline.h" @@ -51,115 +45,64 @@ #include "agg_scanline_u.h" #include "agg_path_storage.h" #include "agg_conv_transform.h" - - -// boost -#include +#pragma GCC diagnostic pop namespace mapnik { namespace detail { -template -struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch +template +struct agg_markers_renderer_context : markers_renderer_context { using renderer_base = typename SvgRenderer::renderer_base; using vertex_source_type = typename SvgRenderer::vertex_source_type; using attribute_source_type = typename SvgRenderer::attribute_source_type; using pixfmt_type = typename renderer_base::pixfmt_type; - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - - vector_markers_rasterizer_dispatch(svg_path_ptr const& src, - vertex_source_type & path, - svg_attribute_type const& attrs, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) -: vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - buf_(std::get<0>(renderer_context)), + agg_markers_renderer_context(symbolizer_base const& sym, + feature_impl const& feature, + attributes const& vars, + BufferType & buf, + RasterizerType & ras) + : buf_(buf), pixf_(buf_), renb_(pixf_), - svg_renderer_(path, attrs), - ras_(std::get<1>(renderer_context)), - snap_to_pixels_(snap_to_pixels) + ras_(ras) { - pixf_.comp_op(static_cast(get(sym, feature, vars))); + auto comp_op = get(sym, feature, vars); + pixf_.comp_op(static_cast(comp_op)); } - ~vector_markers_rasterizer_dispatch() {} - - void render_marker(agg::trans_affine const& marker_tr, double opacity) + virtual void render_marker(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) { - render_vector_marker(svg_renderer_, ras_, renb_, this->src_->bounding_box(), - marker_tr, opacity, snap_to_pixels_); + SvgRenderer svg_renderer(path, attrs); + render_vector_marker(svg_renderer, ras_, renb_, src->bounding_box(), + marker_tr, params.opacity, params.snap_to_pixels); + } + + + virtual void render_marker(image_rgba8 const& src, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) + { + // In the long term this should be a visitor pattern based on the type of + // render src provided that converts the destination pixel type required. + render_raster_marker(renb_, ras_, src, marker_tr, params.opacity, + params.scale_factor, params.snap_to_pixels); } private: BufferType & buf_; pixfmt_type pixf_; renderer_base renb_; - SvgRenderer svg_renderer_; RasterizerType & ras_; - bool snap_to_pixels_; }; -template -struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch -{ - using BufferType = typename std::remove_reference::type>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - - using color_type = agg::rgba8; - using order_type = agg::order_rgba; - using pixel_type = agg::pixel32_type; - using blender_type = agg::comp_op_adaptor_rgba_pre; // comp blender - using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; - using renderer_base = agg::renderer_base; - - raster_markers_rasterizer_dispatch(image_rgba8 const& src, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - RendererContext const& renderer_context, - bool snap_to_pixels = false) - : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - ras_(std::get<1>(renderer_context)), - snap_to_pixels_(snap_to_pixels) - { - pixf_.comp_op(static_cast(get(sym, feature, vars))); - } - - ~raster_markers_rasterizer_dispatch() {} - - void render_marker(agg::trans_affine const& marker_tr, double opacity) - { - // In the long term this should be a visitor pattern based on the type of render this->src_ provided that converts - // the destination pixel type required. - render_raster_marker(renb_, ras_, this->src_, marker_tr, opacity, this->scale_factor_, snap_to_pixels_); - } - -private: - BufferType & buf_; - pixfmt_comp_type pixf_; - renderer_base renb_; - RasterizerType & ras_; - bool snap_to_pixels_; -}; - -} +} // namespace detail template void agg_renderer::process(markers_symbolizer const& sym, @@ -194,16 +137,16 @@ void agg_renderer::process(markers_symbolizer const& sym, buf_type render_buffer(current_buffer_->bytes(), current_buffer_->width(), current_buffer_->height(), current_buffer_->row_size()); box2d clip_box = clipping_extent(common_); - auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_); - using context_type = decltype(renderer_context); - using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch; - using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch; + using context_type = detail::agg_markers_renderer_context; + context_type renderer_context(sym, feature, common_.vars_, render_buffer, *ras_ptr); - render_markers_symbolizer( + render_markers_symbolizer( sym, feature, prj_trans, common_, clip_box, renderer_context); } template void agg_renderer::process(markers_symbolizer const&, mapnik::feature_impl &, proj_transform const&); -} +} // namespace mapnik diff --git a/src/agg/process_point_symbolizer.cpp b/src/agg/process_point_symbolizer.cpp index 8dc40f1af..bb54db51c 100644 --- a/src/agg/process_point_symbolizer.cpp +++ b/src/agg/process_point_symbolizer.cpp @@ -30,13 +30,14 @@ #include #include #include -#include #include #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index fb00b2a00..f2a0159d1 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -39,7 +39,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -52,6 +54,7 @@ #include "agg_span_pattern_rgba.h" #include "agg_image_accessors.h" #include "agg_conv_clip_polygon.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -75,13 +78,13 @@ struct agg_renderer_process_visitor_p feature_(feature), prj_trans_(prj_trans) {} - void operator() (marker_null const&) {} + void operator() (marker_null const&) const {} - void operator() (marker_svg const& marker) + void operator() (marker_svg const& marker) const { agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(*ras_ptr_, marker, image_tr, 1.0, image); @@ -180,7 +183,7 @@ struct agg_renderer_process_visitor_p agg::render_scanlines(*ras_ptr_, sl, rp); } - void operator() (marker_rgba8 const& marker) + void operator() (marker_rgba8 const& marker) const { using color = agg::rgba8; using order = agg::order_rgba; diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 9af6d4ac5..bd2d2bc15 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -32,7 +32,9 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" @@ -40,6 +42,7 @@ #include "agg_renderer_scanline.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index 0105e9bc3..746a5cc2b 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -38,9 +38,11 @@ // stl #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index b3794bcf5..685b66c95 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -63,7 +63,7 @@ void agg_renderer::process(text_symbolizer const& sym, if (halo_transform) { agg::trans_affine halo_affine_transform; - evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform); + evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform, common_.scale_factor_); ren.set_halo_transform(halo_affine_transform); } diff --git a/src/box2d.cpp b/src/box2d.cpp index 26e69293c..407c054ba 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * Copyright (C) 2016 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,465 +21,12 @@ *****************************************************************************/ // mapnik -#include -#include +#include -// stl -#include -#include -#include - -#include - -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - -// agg -#include "agg_trans_affine.h" - -BOOST_FUSION_ADAPT_TPL_ADT( - (T), - (mapnik::box2d)(T), - (T, T, obj.minx(), obj.set_minx(mapnik::safe_cast(val))) - (T, T, obj.miny(), obj.set_miny(mapnik::safe_cast(val))) - (T, T, obj.maxx(), obj.set_maxx(mapnik::safe_cast(val))) - (T, T, obj.maxy(), obj.set_maxy(mapnik::safe_cast(val)))) - -namespace mapnik -{ -template -box2d::box2d() - :minx_( std::numeric_limits::max()), - miny_( std::numeric_limits::max()), - maxx_(-std::numeric_limits::max()), - maxy_(-std::numeric_limits::max()) {} - -template -box2d::box2d(T minx,T miny,T maxx,T maxy) -{ - init(minx,miny,maxx,maxy); -} - -template -box2d::box2d(coord const& c0, coord const& c1) -{ - init(c0.x,c0.y,c1.x,c1.y); -} - -template -box2d::box2d(box2d_type const& rhs) - : minx_(rhs.minx_), - miny_(rhs.miny_), - maxx_(rhs.maxx_), - maxy_(rhs.maxy_) {} - -template -box2d::box2d(box2d_type && rhs) - : minx_(std::move(rhs.minx_)), - miny_(std::move(rhs.miny_)), - maxx_(std::move(rhs.maxx_)), - maxy_(std::move(rhs.maxy_)) {} - -template -box2d& box2d::operator=(box2d_type other) -{ - swap(*this, other); - return *this; -} - -template -box2d::box2d(box2d_type const& rhs, agg::trans_affine const& tr) -{ - double x0 = rhs.minx_, y0 = rhs.miny_; - double x1 = rhs.maxx_, y1 = rhs.miny_; - double x2 = rhs.maxx_, y2 = rhs.maxy_; - double x3 = rhs.minx_, y3 = rhs.maxy_; - tr.transform(&x0, &y0); - tr.transform(&x1, &y1); - tr.transform(&x2, &y2); - tr.transform(&x3, &y3); - init(static_cast(x0), static_cast(y0), - static_cast(x2), static_cast(y2)); - expand_to_include(static_cast(x1), static_cast(y1)); - expand_to_include(static_cast(x3), static_cast(y3)); -} - -template -bool box2d::operator==(box2d const& other) const -{ - return minx_==other.minx_ && - miny_==other.miny_ && - maxx_==other.maxx_ && - maxy_==other.maxy_; -} - -template -T box2d::minx() const -{ - return minx_; -} - -template -T box2d::maxx() const -{ - return maxx_; -} - -template -T box2d::miny() const -{ - return miny_; -} - -template -T box2d::maxy() const -{ - return maxy_; -} - -template -void box2d::set_minx(T v) -{ - minx_ = v; -} - -template -void box2d::set_miny(T v) -{ - miny_ = v; -} - -template -void box2d::set_maxx(T v) -{ - maxx_ = v; -} - -template -void box2d::set_maxy(T v) -{ - maxy_ = v; -} - -template -T box2d::width() const -{ - return maxx_-minx_; -} - -template -T box2d::height() const -{ - return maxy_-miny_; -} - -template -void box2d::width(T w) -{ - T cx=center().x; - minx_=static_cast(cx-w*0.5); - maxx_=static_cast(cx+w*0.5); -} - -template -void box2d::height(T h) -{ - T cy=center().y; - miny_=static_cast(cy-h*0.5); - maxy_=static_cast(cy+h*0.5); -} - -template -coord box2d::center() const -{ - return coord(static_cast(0.5*(minx_+maxx_)), - static_cast(0.5*(miny_+maxy_))); -} - -template -void box2d::expand_to_include(coord const& c) -{ - expand_to_include(c.x,c.y); -} - -template -void box2d::expand_to_include(T x,T y) -{ - if (xmaxx_) maxx_=x; - if (ymaxy_) maxy_=y; -} - -template -void box2d::expand_to_include(box2d const& other) -{ - if (other.minx_maxx_) maxx_=other.maxx_; - if (other.miny_maxy_) maxy_=other.maxy_; -} - -template -bool box2d::contains(coord const& c) const -{ - return contains(c.x,c.y); -} - -template -bool box2d::contains(T x,T y) const -{ - return x>=minx_ && x<=maxx_ && y>=miny_ && y<=maxy_; -} - -template -bool box2d::contains(box2d const& other) const -{ - return other.minx_>=minx_ && - other.maxx_<=maxx_ && - other.miny_>=miny_ && - other.maxy_<=maxy_; -} - -template -bool box2d::intersects(coord const& c) const -{ - return intersects(c.x,c.y); -} - -template -bool box2d::intersects(T x,T y) const -{ - return !(x>maxx_ || xmaxy_ || y -bool box2d::intersects(box2d const& other) const -{ - return !(other.minx_>maxx_ || other.maxx_maxy_ || other.maxy_ -box2d box2d::intersect(box2d_type const& other) const -{ - if (intersects(other)) - { - T x0=std::max(minx_,other.minx_); - T y0=std::max(miny_,other.miny_); - T x1=std::min(maxx_,other.maxx_); - T y1=std::min(maxy_,other.maxy_); - return box2d(x0,y0,x1,y1); - } - else - { - return box2d(); - } -} - -template -void box2d::re_center(T cx,T cy) -{ - T dx=cx-center().x; - T dy=cy-center().y; - minx_+=dx; - miny_+=dy; - maxx_+=dx; - maxy_+=dy; -} - -template -void box2d::re_center(coord const& c) -{ - re_center(c.x,c.y); -} - -template -void box2d::init(T x0,T y0,T x1,T y1) -{ - if (x0 -void box2d::clip(box2d_type const& other) -{ - minx_ = std::max(minx_,other.minx()); - miny_ = std::max(miny_,other.miny()); - maxx_ = std::min(maxx_,other.maxx()); - maxy_ = std::min(maxy_,other.maxy()); -} - -template -void box2d::pad(T padding) -{ - minx_ -= padding; - miny_ -= padding; - maxx_ += padding; - maxy_ += padding; -} - - -template -bool box2d::from_string(std::string const& str) -{ - boost::spirit::qi::lit_type lit; - boost::spirit::qi::double_type double_; - boost::spirit::ascii::space_type space; - bool r = boost::spirit::qi::phrase_parse(str.begin(), - str.end(), - double_ >> -lit(',') >> double_ >> -lit(',') - >> double_ >> -lit(',') >> double_, - space, - *this); - return r; -} - -template -bool box2d::valid() const -{ - return (minx_ <= maxx_ && miny_ <= maxy_) ; -} - -template -void box2d::move(T x, T y) -{ - minx_ += x; - maxx_ += x; - miny_ += y; - maxy_ += y; -} - -template -std::string box2d::to_string() const -{ - std::ostringstream s; - s << "box2d(" << std::fixed << std::setprecision(16) - << minx_ << ',' << miny_ << ',' - << maxx_ << ',' << maxy_ << ')'; - return s.str(); -} - - -template -box2d& box2d::operator+=(box2d const& other) -{ - expand_to_include(other); - return *this; -} - -template -box2d box2d::operator+ (T other) const -{ - return box2d(minx_ - other, miny_ - other, maxx_ + other, maxy_ + other); -} - -template -box2d& box2d::operator+= (T other) -{ - minx_ -= other; - miny_ -= other; - maxx_ += other; - maxy_ += other; - return *this; -} - - -template -box2d& box2d::operator*=(T t) -{ - coord c = center(); - T sx = static_cast(0.5 * width() * t); - T sy = static_cast(0.5 * height() * t); - minx_ = c.x - sx; - maxx_ = c.x + sx; - miny_ = c.y - sy; - maxy_ = c.y + sy; - return *this; -} - -template -box2d& box2d::operator/=(T t) -{ - coord c = center(); - T sx = static_cast(0.5 * width() / t); - T sy = static_cast(0.5 * height() / t); - minx_ = c.x - sx; - maxx_ = c.x + sx; - miny_ = c.y - sy; - maxy_ = c.y + sy; - return *this; -} - -template -T box2d::operator[] (int index) const -{ - switch(index) - { - case 0: - return minx_; - case 1: - return miny_; - case 2: - return maxx_; - case 3: - return maxy_; - case -4: - return minx_; - case -3: - return miny_; - case -2: - return maxx_; - case -1: - return maxy_; - default: - throw std::out_of_range("index out of range, max value is 3, min value is -4 "); - } -} - -template -box2d box2d::operator*(agg::trans_affine const& tr) const -{ - return box2d(*this, tr); -} - -template -box2d& box2d::operator*=(agg::trans_affine const& tr) -{ - double x0 = minx_, y0 = miny_; - double x1 = maxx_, y1 = miny_; - double x2 = maxx_, y2 = maxy_; - double x3 = minx_, y3 = maxy_; - tr.transform(&x0, &y0); - tr.transform(&x1, &y1); - tr.transform(&x2, &y2); - tr.transform(&x3, &y3); - init(static_cast(x0), static_cast(y0), - static_cast(x2), static_cast(y2)); - expand_to_include(static_cast(x1), static_cast(y1)); - expand_to_include(static_cast(x3), static_cast(y3)); - return *this; -} +namespace mapnik { template class box2d; +template class box2d; template class box2d; } diff --git a/src/build.py b/src/build.py index bdc343803..6dd0f24a9 100644 --- a/src/build.py +++ b/src/build.py @@ -62,6 +62,10 @@ system = 'boost_system%s' % env['BOOST_APPEND'] lib_env['LIBS'] = [filesystem, regex] +if env['COVERAGE']: + lib_env.Append(LINKFLAGS='--coverage') + lib_env.Append(CXXFLAGS='--coverage') + if env['HAS_CAIRO']: lib_env.Append(LIBS=env['CAIRO_ALL_LIBS']) @@ -154,7 +158,7 @@ source = Split( well_known_srs.cpp params.cpp image_filter_types.cpp - miniz_png.cpp + image_filter_grammar.cpp color.cpp conversions.cpp image_copy.cpp @@ -201,6 +205,7 @@ source = Split( rule.cpp save_map.cpp wkb.cpp + twkb.cpp projection.cpp proj_transform.cpp scale_denominator.cpp @@ -221,6 +226,7 @@ source = Split( warp.cpp css_color_grammar.cpp vertex_cache.cpp + vertex_adapters.cpp text/font_library.cpp text/text_layout.cpp text/text_line.cpp @@ -252,9 +258,12 @@ source = Split( config_error.cpp color_factory.cpp renderer_common.cpp + renderer_common/render_group_symbolizer.cpp + renderer_common/render_markers_symbolizer.cpp renderer_common/render_pattern.cpp - renderer_common/process_group_symbolizer.cpp + renderer_common/render_thunk_extractor.cpp math.cpp + value.cpp """ ) diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index c8ba13c8a..cb9216df4 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -304,6 +304,12 @@ void cairo_context::paint() check_object_status_and_throw_exception(*this); } +void cairo_context::paint(double opacity) +{ + cairo_paint_with_alpha(cairo_.get(), opacity); + check_object_status_and_throw_exception(*this); +} + void cairo_context::set_pattern(cairo_pattern const& pattern) { cairo_set_source(cairo_.get(), pattern.pattern()); @@ -489,6 +495,18 @@ void cairo_context::add_text(glyph_positions const& pos, } +void cairo_context::push_group() +{ + cairo_push_group(cairo_.get()); + check_object_status_and_throw_exception(*this); +} + +void cairo_context::pop_group() +{ + cairo_pop_group_to_source(cairo_.get()); + check_object_status_and_throw_exception(*this); +} + cairo_face_manager::cairo_face_manager(std::shared_ptr font_library) : font_library_(font_library) { diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index 17723071c..2f845a53a 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -36,6 +36,7 @@ #include #include #include +#include // agg #include "agg/include/agg_trans_affine.h" // for trans_affine, etc @@ -58,7 +59,8 @@ cairo_renderer::cairo_renderer(Map const& m, m_(m), context_(cairo), common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor), - face_manager_(common_.shared_font_library_) + face_manager_(common_.shared_font_library_), + style_level_compositing_(false) { setup(m); } @@ -75,7 +77,9 @@ cairo_renderer::cairo_renderer(Map const& m, m_(m), context_(cairo), common_(m, req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor), - face_manager_(common_.shared_font_library_) + face_manager_(common_.shared_font_library_), + style_level_compositing_(false) + { setup(m); } @@ -91,7 +95,9 @@ cairo_renderer::cairo_renderer(Map const& m, m_(m), context_(cairo), common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor, detector), - face_manager_(common_.shared_font_library_) + face_manager_(common_.shared_font_library_), + style_level_compositing_(false) + { setup(m); } @@ -104,10 +110,10 @@ struct setup_marker_visitor setup_marker_visitor(cairo_context & context, renderer_common const& common) : context_(context), common_(common) {} - void operator() (marker_null const &) {} - void operator() (marker_svg const &) {} + void operator() (marker_null const &) const{} + void operator() (marker_svg const &) const {} - void operator() (marker_rgba8 const& marker) + void operator() (marker_rgba8 const& marker) const { mapnik::image_rgba8 const& bg_image = marker.get_data(); std::size_t w = bg_image.width(); @@ -191,15 +197,30 @@ void cairo_renderer::end_layer_processing(layer const&) } template -void cairo_renderer::start_style_processing(feature_type_style const&) +void cairo_renderer::start_style_processing(feature_type_style const & st) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:start style processing"; + + style_level_compositing_ = st.comp_op() || st.get_opacity() < 1; + + if (style_level_compositing_) + { + context_.push_group(); + } } template -void cairo_renderer::end_style_processing(feature_type_style const&) +void cairo_renderer::end_style_processing(feature_type_style const & st) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:end style processing"; + + if (style_level_compositing_) + { + context_.pop_group(); + composite_mode_e comp_op = st.comp_op() ? *st.comp_op() : src_over; + context_.set_operator(comp_op); + context_.paint(st.get_opacity()); + } } struct cairo_render_marker_visitor diff --git a/src/cairo/process_group_symbolizer.cpp b/src/cairo/process_group_symbolizer.cpp index a2dc4abbe..0c35ba0ec 100644 --- a/src/cairo/process_group_symbolizer.cpp +++ b/src/cairo/process_group_symbolizer.cpp @@ -25,13 +25,12 @@ // mapnik #include #include -#include #include #include #include // mapnik symbolizer generics -#include +#include namespace mapnik { @@ -47,20 +46,19 @@ namespace { // to render it, and the boxes themselves should already be // in the detector from the placement_finder. template -struct thunk_renderer +struct thunk_renderer : render_thunk_list_dispatch { using renderer_type = cairo_renderer; thunk_renderer(renderer_type & ren, cairo_context & context, cairo_face_manager & face_manager, - renderer_common & common, - pixel_position const& offset) + renderer_common & common) : ren_(ren), context_(context), face_manager_(face_manager), - common_(common), offset_(offset) + common_(common) {} - void operator()(vector_marker_render_thunk const &thunk) const + virtual void operator()(vector_marker_render_thunk const& thunk) { cairo_save_restore guard(context_); context_.set_operator(thunk.comp_op_); @@ -78,7 +76,7 @@ struct thunk_renderer thunk.opacity_); } - void operator()(raster_marker_render_thunk const& thunk) const + virtual void operator()(raster_marker_render_thunk const& thunk) { cairo_save_restore guard(context_); context_.set_operator(thunk.comp_op_); @@ -88,32 +86,24 @@ struct thunk_renderer context_.add_image(offset_tr, thunk.src_, thunk.opacity_); } - void operator()(text_render_thunk const &thunk) const + virtual void operator()(text_render_thunk const& thunk) { cairo_save_restore guard(context_); context_.set_operator(thunk.comp_op_); - render_offset_placements( - thunk.placements_, - offset_, - [&] (glyph_positions_ptr const& glyphs) - { - marker_info_ptr mark = glyphs->get_marker(); - if (mark) - { - ren_.render_marker(glyphs->marker_pos(), - *mark->marker_, - mark->transform_, - thunk.opacity_, thunk.comp_op_); - } - context_.add_text(*glyphs, face_manager_, src_over, src_over, common_.scale_factor_); - }); - } + for (auto const& glyphs : thunk.placements_) + { + scoped_glyph_positions_offset tmp_off(*glyphs, offset_); - template - void operator()(T0 const &) const - { - throw std::runtime_error("Rendering of this type is not supported by the cairo renderer."); + if (auto const& mark = glyphs->get_marker()) + { + ren_.render_marker(glyphs->marker_pos(), + *mark->marker_, + mark->transform_, + thunk.opacity_, thunk.comp_op_); + } + context_.add_text(*glyphs, face_manager_, src_over, src_over, common_.scale_factor_); + } } private: @@ -121,7 +111,6 @@ private: cairo_context & context_; cairo_face_manager & face_manager_; renderer_common & common_; - pixel_position offset_; }; } // anonymous namespace @@ -131,16 +120,11 @@ void cairo_renderer::process(group_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + thunk_renderer ren(*this, context_, face_manager_, common_); + render_group_symbolizer( sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, - [&](render_thunk_list const& thunks, pixel_position const& render_offset) - { - thunk_renderer ren(*this, context_, face_manager_, common_, render_offset); - for (render_thunk_ptr const& thunk : thunks) - { - util::apply_visitor(ren, *thunk); - } - }); + ren); } template void cairo_renderer::process(group_symbolizer const&, diff --git a/src/cairo/process_line_pattern_symbolizer.cpp b/src/cairo/process_line_pattern_symbolizer.cpp index 7aa85ab41..f53d850a6 100644 --- a/src/cairo/process_line_pattern_symbolizer.cpp +++ b/src/cairo/process_line_pattern_symbolizer.cpp @@ -62,7 +62,7 @@ struct cairo_renderer_process_visitor_l mapnik::rasterizer ras; agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); mapnik::box2d const& bbox_image = marker.get_data()->bounding_box() * image_tr; mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height()); render_pattern(ras, marker, image_tr, 1.0, image); diff --git a/src/cairo/process_markers_symbolizer.cpp b/src/cairo/process_markers_symbolizer.cpp index faffd3d6a..73b84ecb7 100644 --- a/src/cairo/process_markers_symbolizer.cpp +++ b/src/cairo/process_markers_symbolizer.cpp @@ -25,90 +25,46 @@ // mapnik #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// agg -#include "agg/include/agg_array.h" // for pod_bvector -#include "agg/include/agg_trans_affine.h" // for trans_affine, etc +#include +#include namespace mapnik { -class feature_impl; -class proj_transform; - namespace detail { -template -struct vector_markers_dispatch_cairo : public vector_markers_dispatch +struct cairo_markers_renderer_context : markers_renderer_context { - vector_markers_dispatch_cairo(svg_path_ptr const& src, - svg::svg_path_adapter & path, - svg_attribute_type const& attrs, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - mapnik::attributes const& vars, - bool /* snap_to_pixels */, // only used in agg renderer currently - RendererContext const& renderer_context) - : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - path_(path), - attr_(attrs), - ctx_(std::get<0>(renderer_context)) + explicit cairo_markers_renderer_context(cairo_context & ctx) + : ctx_(ctx) {} - void render_marker(agg::trans_affine const& marker_tr, double opacity) + virtual void render_marker(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) { render_vector_marker(ctx_, - path_, - attr_, - this->src_->bounding_box(), + path, + attrs, + src->bounding_box(), marker_tr, - opacity); + params.opacity); } -private: - svg::svg_path_adapter & path_; - svg_attribute_type const& attr_; - cairo_context & ctx_; -}; - -template -struct raster_markers_dispatch_cairo : public raster_markers_dispatch -{ - raster_markers_dispatch_cairo(image_rgba8 const& src, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - mapnik::attributes const& vars, - RendererContext const& renderer_context) - : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - ctx_(std::get<0>(renderer_context)) {} - - ~raster_markers_dispatch_cairo() {} - - void render_marker(agg::trans_affine const& marker_tr, double opacity) + virtual void render_marker(image_rgba8 const& src, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) { - ctx_.add_image(marker_tr, this->src_, opacity); + ctx_.add_image(marker_tr, src, params.opacity); } private: cairo_context & ctx_; }; -} +} // namespace detail template void cairo_renderer::process(markers_symbolizer const& sym, @@ -120,17 +76,10 @@ void cairo_renderer::process(markers_symbolizer const& sym, context_.set_operator(comp_op); box2d clip_box = common_.query_extent_; - auto renderer_context = std::tie(context_); + using context_type = detail::cairo_markers_renderer_context; + context_type renderer_context(context_); - using RendererContextType = decltype(renderer_context); - using vector_dispatch_type = detail::vector_markers_dispatch_cairo; - - using raster_dispatch_type = detail::raster_markers_dispatch_cairo; - - - render_markers_symbolizer( + render_markers_symbolizer( sym, feature, prj_trans, common_, clip_box, renderer_context); } @@ -139,6 +88,6 @@ template void cairo_renderer::process(markers_symbolizer const&, mapnik::feature_impl &, proj_transform const&); -} +} // namespace mapnik #endif // HAVE_CAIRO diff --git a/src/cairo/process_polygon_pattern_symbolizer.cpp b/src/cairo/process_polygon_pattern_symbolizer.cpp index aa7b0ca12..4e21234b8 100644 --- a/src/cairo/process_polygon_pattern_symbolizer.cpp +++ b/src/cairo/process_polygon_pattern_symbolizer.cpp @@ -96,7 +96,7 @@ void cairo_renderer::process(polygon_pattern_symbolizer const& sym, value_double opacity = get(sym, feature, common_.vars_); agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform, common_.scale_factor_); cairo_save_restore guard(context_); context_.set_operator(comp_op); @@ -124,8 +124,7 @@ void cairo_renderer::process(polygon_pattern_symbolizer const& sym, agg::trans_affine tr; auto geom_transform = get_optional(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - using vertex_converter_type = vertex_converter< - clip_poly_tag, + using vertex_converter_type = vertex_converter #include -// agg -#include "agg_color_rgba.h" - #pragma GCC diagnostic push #include #include -#include -#include -#include -#include -#include #pragma GCC diagnostic pop -// stl -#include - namespace mapnik { color::color(std::string const& str, bool premultiplied) @@ -52,22 +41,23 @@ color::color(std::string const& str, bool premultiplied) std::string color::to_string() const { namespace karma = boost::spirit::karma; - boost::spirit::karma::_1_type _1; boost::spirit::karma::eps_type eps; boost::spirit::karma::double_type double_; - boost::spirit::karma::string_type kstring; - boost::spirit::karma::uint_generator color_generator; + boost::spirit::karma::uint_generator color_; std::string str; std::back_insert_iterator sink(str); - karma::generate(sink, + karma::generate(sink, eps(alpha() < 255) // begin grammar - kstring[ boost::phoenix::if_(alpha()==255) [_1="rgb("].else_[_1="rgba("]] - << color_generator[_1 = red()] << ',' - << color_generator[_1 = green()] << ',' - << color_generator[_1 = blue()] - << kstring[ boost::phoenix::if_(alpha()==255) [_1 = ')'].else_[_1 =',']] - << eps(alpha()<255) << double_ [_1 = alpha()/255.0] - << ')' + << "rgba(" + << color_(red()) << ',' + << color_(green()) << ',' + << color_(blue()) << ',' + << double_(alpha()/255.0) << ')' + | + "rgb(" + << color_(red()) << ',' + << color_(green()) << ',' + << color_(blue()) << ')' // end grammar ); return str; @@ -76,7 +66,6 @@ std::string color::to_string() const std::string color::to_hex_string() const { namespace karma = boost::spirit::karma; - boost::spirit::karma::_1_type _1; boost::spirit::karma::hex_type hex; boost::spirit::karma::eps_type eps; boost::spirit::karma::right_align_type right_align; @@ -85,23 +74,34 @@ std::string color::to_hex_string() const karma::generate(sink, // begin grammar '#' - << right_align(2,'0')[hex[_1 = red()]] - << right_align(2,'0')[hex[_1 = green()]] - << right_align(2,'0')[hex[_1 = blue()]] - << eps(alpha() < 255) << right_align(2,'0')[hex [_1 = alpha()]] + << right_align(2,'0')[hex(red())] + << right_align(2,'0')[hex(green())] + << right_align(2,'0')[hex(blue())] + << eps(alpha() < 255) << right_align(2,'0')[hex(alpha())] // end grammar ); return str; } +namespace { + +static std::uint8_t multiply(std::uint8_t c, std::uint8_t a) +{ + std::uint32_t t = c * a + 128; + return std::uint8_t(((t >> 8) + t) >> 8); +} + +} + bool color::premultiply() { if (premultiplied_) return false; - agg::rgba8 pre_c = agg::rgba8(red_,green_,blue_,alpha_); - pre_c.premultiply(); - red_ = pre_c.r; - green_ = pre_c.g; - blue_ = pre_c.b; + if (alpha_ != 255) + { + red_ = multiply(red_, alpha_); + green_ = multiply(green_, alpha_); + blue_ = multiply(blue_, alpha_); + } premultiplied_ = true; return true; } @@ -109,13 +109,23 @@ bool color::premultiply() bool color::demultiply() { if (!premultiplied_) return false; - agg::rgba8 pre_c = agg::rgba8(red_,green_,blue_,alpha_); - pre_c.demultiply(); - red_ = pre_c.r; - green_ = pre_c.g; - blue_ = pre_c.b; + if (alpha_ < 255) + { + if (alpha_ == 0) + { + red_ = green_ = blue_ = 0; + } + else + { + std::uint32_t r = (std::uint32_t(red_) * 255) / alpha_; + std::uint32_t g = (std::uint32_t(green_) * 255) / alpha_; + std::uint32_t b = (std::uint32_t(blue_) * 255) / alpha_; + red_ = (r > 255) ? 255 : r; + green_ = (g > 255) ? 255 : g; + blue_ = (b > 255) ? 255 : b; + } + } premultiplied_ = false; return true; } - } diff --git a/src/dasharray_parser.cpp b/src/dasharray_parser.cpp index 760caea25..963a2905a 100644 --- a/src/dasharray_parser.cpp +++ b/src/dasharray_parser.cpp @@ -36,7 +36,29 @@ namespace mapnik { namespace util { -bool parse_dasharray(std::string const& value, std::vector& dasharray) +namespace { +inline bool setup_dashes(std::vector & buf, dash_array & dash) +{ + if (buf.empty()) return false; + size_t size = buf.size(); + if (size % 2 == 1) + { + buf.insert(buf.end(),buf.begin(),buf.end()); + } + std::vector::const_iterator pos = buf.begin(); + while (pos != buf.end()) + { + if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0 + { + dash.emplace_back(*pos,*(pos + 1)); + } + pos +=2; + } + return !buf.empty(); +} +} + +bool parse_dasharray(std::string const& value, dash_array & dash) { using namespace boost::spirit; qi::double_type double_; @@ -49,18 +71,19 @@ bool parse_dasharray(std::string const& value, std::vector& dasharray) // dasharray ::= (length | percentage) (comma-wsp dasharray)? // no support for 'percentage' as viewport is unknown at load_map // + std::vector buf; auto first = value.begin(); auto last = value.end(); bool r = qi::phrase_parse(first, last, - (double_[boost::phoenix::push_back(boost::phoenix::ref(dasharray), _1)] % + (double_[boost::phoenix::push_back(boost::phoenix::ref(buf), _1)] % no_skip[char_(", ")] | lit("none")), space); - if (first != last) + if (r && first == last) { - return false; + return setup_dashes(buf, dash); } - return r; + return false; } } // end namespace util diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index c712f4adb..3759a6ceb 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -65,7 +65,7 @@ datasource_cache::~datasource_cache() datasource_ptr datasource_cache::create(parameters const& params) { boost::optional type = params.get("type"); - if ( ! type) + if (!type) { throw config_error(std::string("Could not create datasource. Required ") + "parameter 'type' is missing"); @@ -88,7 +88,7 @@ datasource_ptr datasource_cache::create(parameters const& params) #ifdef MAPNIK_THREADSAFE std::lock_guard lock(instance_mutex_); #endif - itr=plugins_.find(*type); + itr = plugins_.find(*type); if (itr == plugins_.end()) { std::string s("Could not create datasource for type: '"); @@ -105,7 +105,7 @@ datasource_ptr datasource_cache::create(parameters const& params) } } - if (! itr->second->valid()) + if (!itr->second->valid()) { throw std::runtime_error(std::string("Cannot load library: ") + itr->second->get_error()); @@ -117,7 +117,7 @@ datasource_ptr datasource_cache::create(parameters const& params) #endif create_ds create_datasource = reinterpret_cast(itr->second->get_symbol("create")); - if (! create_datasource) + if (!create_datasource) { throw std::runtime_error(std::string("Cannot load symbols: ") + itr->second->get_error()); diff --git a/src/debug.cpp b/src/debug.cpp index 169272f09..d1ae15fa4 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include // stl #include @@ -74,14 +75,7 @@ logger::severity_type logger::severity_level_ { logger::severity_map logger::object_severity_level_ = logger::severity_map(); - -// format - -#define __xstr__(s) __str__(s) -#define __str__(s) #s -std::string logger::format_ = __xstr__(MAPNIK_LOG_FORMAT); -#undef __xstr__ -#undef __str__ +std::string logger::format_ = MAPNIK_STRINGIFY(MAPNIK_LOG_FORMAT); std::string logger::str() { diff --git a/src/expression_node.cpp b/src/expression_node.cpp index 377d091c9..549f4c891 100644 --- a/src/expression_node.cpp +++ b/src/expression_node.cpp @@ -37,6 +37,14 @@ namespace mapnik { +#if defined(BOOST_REGEX_HAS_ICU) +static void fromUTF32toUTF8(std::basic_string const& src, std::string & dst) +{ + int32_t len = safe_cast(src.length()); + value_unicode_string::fromUTF32(src.data(), len).toUTF8String(dst); +} +#endif + struct _regex_match_impl : util::noncopyable { #if defined(BOOST_REGEX_HAS_ICU) _regex_match_impl(value_unicode_string const& ustr) : @@ -94,10 +102,7 @@ std::string regex_match_node::to_string() const str_ +=".match('"; auto const& pattern = impl_.get()->pattern_; #if defined(BOOST_REGEX_HAS_ICU) - std::string utf8; - value_unicode_string ustr = value_unicode_string::fromUTF32( &pattern.str()[0], safe_cast(pattern.str().length())); - to_utf8(ustr,utf8); - str_ += utf8; + fromUTF32toUTF8(pattern.str(), str_); #else str_ += pattern.str(); #endif @@ -125,9 +130,9 @@ value regex_replace_node::apply(value const& v) const auto const& pattern = impl_.get()->pattern_; auto const& format = impl_.get()->format_; #if defined(BOOST_REGEX_HAS_ICU) - return boost::u32regex_replace(v.to_unicode(),pattern,format); + return boost::u32regex_replace(v.to_unicode(), pattern, format); #else - std::string repl = boost::regex_replace(v.to_string(),pattern,format); + std::string repl = boost::regex_replace(v.to_string(), pattern, format); transcoder tr_("utf8"); return tr_.transcode(repl.c_str()); #endif @@ -141,13 +146,9 @@ std::string regex_replace_node::to_string() const auto const& pattern = impl_.get()->pattern_; auto const& format = impl_.get()->format_; #if defined(BOOST_REGEX_HAS_ICU) - std::string utf8; - value_unicode_string ustr = value_unicode_string::fromUTF32( &pattern.str()[0], safe_cast(pattern.str().length())); - to_utf8(ustr,utf8); - str_ += utf8; + fromUTF32toUTF8(pattern.str(), str_); str_ +="','"; - to_utf8(format ,utf8); - str_ += utf8; + format.toUTF8String(str_); #else str_ += pattern.str(); str_ +="','"; diff --git a/src/feature_kv_iterator.cpp b/src/feature_kv_iterator.cpp index 8fdba826b..4ae384254 100644 --- a/src/feature_kv_iterator.cpp +++ b/src/feature_kv_iterator.cpp @@ -22,7 +22,11 @@ #include #include + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index b0f137473..9721d70bf 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -27,18 +27,12 @@ #include #include #include -#include #include #pragma GCC diagnostic push #include #include #include -#pragma GCC diagnostic pop - -// stl -#include -#include // freetype2 extern "C" @@ -48,6 +42,11 @@ extern "C" #include FT_STROKER_H #include FT_MODULE_H } +#pragma GCC diagnostic pop + +// stl +#include +#include namespace mapnik @@ -76,7 +75,7 @@ unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char * if (count <= 0) return 0; FILE * file = static_cast(stream->descriptor.pointer); std::fseek (file , offset , SEEK_SET); - return std::fread ((char*)buffer, 1, count, file); + return std::fread(reinterpret_cast(buffer), 1, count, file); } bool freetype_engine::register_font(std::string const& file_name) @@ -94,7 +93,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, { MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name; mapnik::util::file file(file_name); - if (!file.open()) return false; + if (!file) return false; FT_Face face = 0; FT_Open_Args args; @@ -106,7 +105,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, streamRec.size = file.size(); streamRec.descriptor.pointer = file.get(); streamRec.read = ft_read_cb; - streamRec.close = NULL; + streamRec.close = nullptr; args.flags = FT_OPEN_STREAM; args.stream = &streamRec; int num_faces = 0; @@ -259,7 +258,7 @@ bool freetype_engine::can_open(std::string const& face_name, } if (!found_font_file) return false; mapnik::util::file file(itr->second.second); - if (!file.open()) return false; + if (!file) return false; FT_Face face = 0; FT_Open_Args args; FT_StreamRec streamRec; @@ -270,7 +269,7 @@ bool freetype_engine::can_open(std::string const& face_name, streamRec.size = file.size(); streamRec.descriptor.pointer = file.get(); streamRec.read = ft_read_cb; - streamRec.close = NULL; + streamRec.close = nullptr; args.flags = FT_OPEN_STREAM; args.stream = &streamRec; // -1 is used to quickly check if the font file appears valid without iterating each face @@ -333,7 +332,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name, if (found_font_file) { mapnik::util::file file(itr->second.second); - if (file.open()) + if (file) { #ifdef MAPNIK_THREADSAFE std::lock_guard lock(mutex_); @@ -361,7 +360,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name, face_manager::face_manager(font_library & library, freetype_engine::font_file_mapping_type const& font_file_mapping, freetype_engine::font_memory_cache_type const& font_cache) - : face_ptr_cache_(), + : face_cache_(new face_cache()), library_(library), font_file_mapping_(font_file_mapping), font_memory_cache_(font_cache) @@ -376,8 +375,8 @@ face_manager::face_manager(font_library & library, face_ptr face_manager::get_face(std::string const& name) { - auto itr = face_ptr_cache_.find(name); - if (itr != face_ptr_cache_.end()) + auto itr = face_cache_->find(name); + if (itr != face_cache_->end()) { return itr->second; } @@ -391,7 +390,7 @@ face_ptr face_manager::get_face(std::string const& name) freetype_engine::get_cache()); if (face) { - face_ptr_cache_.emplace(name,face); + face_cache_->emplace(name, face); } return face; } diff --git a/src/fs.cpp b/src/fs.cpp index 9c87d97be..640345396 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -24,9 +24,12 @@ #include #include -// boost + +#pragma GCC diagnostic push +#include #include // for absolute, exists, etc #include // for path, operator/ +#pragma GCC diagnostic pop // stl #include diff --git a/src/geometry_envelope.cpp b/src/geometry_envelope.cpp index 0aa3466f1..bb79f59ad 100644 --- a/src/geometry_envelope.cpp +++ b/src/geometry_envelope.cpp @@ -23,28 +23,21 @@ #include #include #include -namespace mapnik { -namespace geometry { + +namespace mapnik { namespace geometry { template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); -template MAPNIK_DECL mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry_empty const& geom); +// single template MAPNIK_DECL mapnik::box2d envelope(point const& geom); template MAPNIK_DECL mapnik::box2d envelope(line_string const& geom); template MAPNIK_DECL mapnik::box2d envelope(polygon const& geom); +template MAPNIK_DECL mapnik::box2d envelope(linear_ring const& geom); +// multi template MAPNIK_DECL mapnik::box2d envelope(multi_point const& geom); template MAPNIK_DECL mapnik::box2d envelope(multi_line_string const& geom); template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); +// collection template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry const& geom); -template MAPNIK_DECL mapnik::box2d envelope(point const& geom); -template MAPNIK_DECL mapnik::box2d envelope(line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(polygon const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_point const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_line_string const& geom); -template MAPNIK_DECL mapnik::box2d envelope(multi_polygon const& geom); -template MAPNIK_DECL mapnik::box2d envelope(geometry_collection const& geom); - } // end ns geometry } // end ns mapnik diff --git a/src/gradient.cpp b/src/gradient.cpp index 037cf8fc7..0c9c6b8fa 100644 --- a/src/gradient.cpp +++ b/src/gradient.cpp @@ -26,24 +26,6 @@ namespace mapnik { -static const char * gradient_strings[] = { - "no-gradient", - "linear", - "radial", - "" -}; - -IMPLEMENT_ENUM( gradient_e, gradient_strings ) - -static const char * gradient_unit_strings[] = { - "user-space-on-use", - "user-space-on-use-bounding-box", - "object-bounding-box", - "" -}; - -IMPLEMENT_ENUM( gradient_unit_e, gradient_unit_strings ) - gradient::gradient() : transform_(), x1_(0), diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index 33d10ee6a..fd970f580 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -47,11 +47,15 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index e6649da53..13ee8d442 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -39,11 +39,13 @@ // stl #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_conv_stroke.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_group_symbolizer.cpp b/src/grid/process_group_symbolizer.cpp index f73118969..ba7f48ece 100644 --- a/src/grid/process_group_symbolizer.cpp +++ b/src/grid/process_group_symbolizer.cpp @@ -29,28 +29,18 @@ #include #include #include -#include -#include -#include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include -#include -#include -#include - -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -61,7 +51,7 @@ namespace mapnik { * in the detector from the placement_finder. */ template -struct thunk_renderer +struct thunk_renderer : render_thunk_list_dispatch { using renderer_type = grid_renderer; using buffer_type = typename renderer_type::buffer_type; @@ -71,13 +61,13 @@ struct thunk_renderer grid_rasterizer &ras, buffer_type &pixmap, renderer_common &common, - feature_impl &feature, - pixel_position const &offset) + feature_impl &feature) : ren_(ren), ras_(ras), pixmap_(pixmap), - common_(common), feature_(feature), offset_(offset) + common_(common), feature_(feature), + tex_(pixmap, src_over, common.scale_factor_) {} - void operator()(vector_marker_render_thunk const &thunk) const + virtual void operator()(vector_marker_render_thunk const& thunk) { using buf_type = grid_rendering_buffer; using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; @@ -106,7 +96,7 @@ struct thunk_renderer pixmap_.add_feature(feature_); } - void operator()(raster_marker_render_thunk const &thunk) const + virtual void operator()(raster_marker_render_thunk const& thunk) { using buf_type = grid_rendering_buffer; using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; @@ -122,34 +112,28 @@ struct thunk_renderer pixmap_.add_feature(feature_); } - void operator()(text_render_thunk const &thunk) const + virtual void operator()(text_render_thunk const &thunk) { - text_renderer_type ren(pixmap_, thunk.comp_op_, common_.scale_factor_); + tex_.set_comp_op(thunk.comp_op_); + value_integer feature_id = feature_.id(); - render_offset_placements( - thunk.placements_, - offset_, - [&] (glyph_positions_ptr const& glyphs) - { - marker_info_ptr mark = glyphs->get_marker(); - if (mark) - { - ren_.render_marker(feature_, - glyphs->marker_pos(), - *mark->marker_, - mark->transform_, - thunk.opacity_, thunk.comp_op_); - } - ren.render(*glyphs, feature_id); - }); - pixmap_.add_feature(feature_); - } + for (auto const& glyphs : thunk.placements_) + { + scoped_glyph_positions_offset tmp_off(*glyphs, offset_); - template - void operator()(T1 const &) const - { - // TODO: warning if unimplemented? + if (auto const& mark = glyphs->get_marker()) + { + ren_.render_marker(feature_, + glyphs->marker_pos(), + *mark->marker_, + mark->transform_, + thunk.opacity_, thunk.comp_op_); + } + tex_.render(*glyphs, feature_id); + } + + pixmap_.add_feature(feature_); } private: @@ -158,7 +142,7 @@ private: buffer_type &pixmap_; renderer_common &common_; feature_impl &feature_; - pixel_position offset_; + text_renderer_type tex_; }; template @@ -166,16 +150,11 @@ void grid_renderer::process(group_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + thunk_renderer ren(*this, *ras_ptr, pixmap_, common_, feature); + render_group_symbolizer( sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, - [&](render_thunk_list const& thunks, pixel_position const& render_offset) - { - thunk_renderer ren(*this, *ras_ptr, pixmap_, common_, feature, render_offset); - for (render_thunk_ptr const& thunk : thunks) - { - util::apply_visitor(ren, *thunk); - } - }); + ren); } template void grid_renderer::process(group_symbolizer const&, diff --git a/src/grid/process_line_pattern_symbolizer.cpp b/src/grid/process_line_pattern_symbolizer.cpp index dc370f73c..af54ac5b6 100644 --- a/src/grid/process_line_pattern_symbolizer.cpp +++ b/src/grid/process_line_pattern_symbolizer.cpp @@ -35,12 +35,15 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_conv_stroke.h" #include "agg_conv_dash.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_line_symbolizer.cpp b/src/grid/process_line_symbolizer.cpp index c569f6b2c..b65dd8502 100644 --- a/src/grid/process_line_symbolizer.cpp +++ b/src/grid/process_line_symbolizer.cpp @@ -32,12 +32,15 @@ #include #include #include -// agg + +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" #include "agg_conv_stroke.h" #include "agg_conv_dash.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index b79807ec0..380923211 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -44,146 +44,94 @@ porting notes --> */ // mapnik -#include -#include -#include #include #include #include #include #include - -#include -#include -#include -#include -#include #include #include #include #include -#include -#include +#include -// agg +#pragma GCC diagnostic push +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_rasterizer_scanline_aa.h" - -// boost -#include - -// stl -#include -#include +#pragma GCC diagnostic pop namespace mapnik { namespace detail { -template -struct vector_markers_rasterizer_dispatch : public vector_markers_dispatch +template +struct grid_markers_renderer_context : markers_renderer_context { using renderer_base = typename SvgRenderer::renderer_base; using vertex_source_type = typename SvgRenderer::vertex_source_type; using attribute_source_type = typename SvgRenderer::attribute_source_type; using pixfmt_type = typename renderer_base::pixfmt_type; - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - using PixMapType = typename std::tuple_element<2,RendererContext>::type; - - vector_markers_rasterizer_dispatch(svg_path_ptr const& src, - vertex_source_type & path, - svg_attribute_type const& attrs, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - mapnik::feature_impl & feature, - attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - buf_(std::get<0>(renderer_context)), + grid_markers_renderer_context(feature_impl const& feature, + BufferType & buf, + RasterizerType & ras, + PixMapType & pixmap) + : feature_(feature), + buf_(buf), pixf_(buf_), renb_(pixf_), - svg_renderer_(path, attrs), - ras_(std::get<1>(renderer_context)), - pixmap_(std::get<2>(renderer_context)), + ras_(ras), + pixmap_(pixmap), placed_(false) {} - void render_marker(agg::trans_affine const& marker_tr, double opacity) + virtual void render_marker(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) { + SvgRenderer svg_renderer_(path, attrs); agg::scanline_bin sl_; - svg_renderer_.render_id(ras_, sl_, renb_, this->feature_.id(), marker_tr, opacity, this->src_->bounding_box()); + svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), marker_tr, + params.opacity, src->bounding_box()); + place_feature(); + } + + virtual void render_marker(image_rgba8 const& src, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) + { + // In the long term this should be a visitor pattern based on the type of + // render src provided that converts the destination pixel type required. + render_raster_marker(ScanlineRenderer(renb_), ras_, src, feature_, + marker_tr, params.opacity); + place_feature(); + } + + void place_feature() + { if (!placed_) { - pixmap_.add_feature(this->feature_); + pixmap_.add_feature(feature_); placed_ = true; } } private: + feature_impl const& feature_; BufferType & buf_; pixfmt_type pixf_; renderer_base renb_; - SvgRenderer svg_renderer_; RasterizerType & ras_; PixMapType & pixmap_; bool placed_; }; -template -struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch -{ - using pixfmt_type = typename RendererBase::pixfmt_type; - using color_type = typename RendererBase::pixfmt_type::color_type; - - using BufferType = typename std::tuple_element<0,RendererContext>::type; - using RasterizerType = typename std::tuple_element<1,RendererContext>::type; - using PixMapType = typename std::tuple_element<2,RendererContext>::type; - - raster_markers_rasterizer_dispatch(image_rgba8 const& src, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - mapnik::feature_impl & feature, - attributes const& vars, - RendererContext const& renderer_context) - : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - buf_(std::get<0>(renderer_context)), - pixf_(buf_), - renb_(pixf_), - ras_(std::get<1>(renderer_context)), - pixmap_(std::get<2>(renderer_context)), - placed_(false) - {} - - void render_marker(agg::trans_affine const& marker_tr, double opacity) - { - // In the long term this should be a visitor pattern based on the type of render this->src_ provided that converts - // the destination pixel type required. - render_raster_marker(RendererType(renb_), ras_, this->src_, this->feature_, marker_tr, opacity); - if (!placed_) - { - pixmap_.add_feature(this->feature_); - placed_ = true; - } - } - -private: - BufferType & buf_; - pixfmt_type pixf_; - RendererBase renb_; - RasterizerType & ras_; - PixMapType & pixmap_; - bool placed_; -}; - -} +} // namespace detail template void grid_renderer::process(markers_symbolizer const& sym, @@ -193,7 +141,6 @@ void grid_renderer::process(markers_symbolizer const& sym, using buf_type = grid_rendering_buffer; using pixfmt_type = typename grid_renderer_base_type::pixfmt_type; using renderer_type = agg::renderer_scanline_bin_solid; - using detector_type = label_collision_detector4; using namespace mapnik::svg; using svg_attribute_type = agg::pod_bvector; @@ -206,22 +153,20 @@ void grid_renderer::process(markers_symbolizer const& sym, ras_ptr->reset(); box2d clip_box = common_.query_extent_; - auto renderer_context = std::tie(render_buf,*ras_ptr,pixmap_); - using context_type = decltype(renderer_context); - using vector_dispatch_type = detail::vector_markers_rasterizer_dispatch; - using raster_dispatch_type = detail::raster_markers_rasterizer_dispatch; - render_markers_symbolizer( - sym, feature, prj_trans, common_, clip_box,renderer_context); + using context_type = detail::grid_markers_renderer_context; + context_type renderer_context(feature, render_buf, *ras_ptr, pixmap_); + + render_markers_symbolizer( + sym, feature, prj_trans, common_, clip_box, renderer_context); } template void grid_renderer::process(markers_symbolizer const&, mapnik::feature_impl &, proj_transform const&); -} +} // namespace mapnik #endif diff --git a/src/grid/process_point_symbolizer.cpp b/src/grid/process_point_symbolizer.cpp index 731291d78..60328009d 100644 --- a/src/grid/process_point_symbolizer.cpp +++ b/src/grid/process_point_symbolizer.cpp @@ -30,15 +30,16 @@ #include #include -#include #include #include #include #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_polygon_pattern_symbolizer.cpp b/src/grid/process_polygon_pattern_symbolizer.cpp index 06408a801..03e27c65d 100644 --- a/src/grid/process_polygon_pattern_symbolizer.cpp +++ b/src/grid/process_polygon_pattern_symbolizer.cpp @@ -36,10 +36,12 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" +#pragma GCC diagnostic pop // stl #include @@ -76,7 +78,12 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); } - using vertex_converter_type = vertex_converter; + using vertex_converter_type = vertex_converter; + vertex_converter_type converter(common_.query_extent_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set(); diff --git a/src/grid/process_polygon_symbolizer.cpp b/src/grid/process_polygon_symbolizer.cpp index 3e1f08932..ab8526252 100644 --- a/src/grid/process_polygon_symbolizer.cpp +++ b/src/grid/process_polygon_symbolizer.cpp @@ -34,10 +34,12 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_scanline_bin.h" +#pragma GCC diagnostic pop // stl #include diff --git a/src/grid/process_shield_symbolizer.cpp b/src/grid/process_shield_symbolizer.cpp index 50bc8209f..0463bee8e 100644 --- a/src/grid/process_shield_symbolizer.cpp +++ b/src/grid/process_shield_symbolizer.cpp @@ -33,8 +33,11 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#include "agg_gamma_functions.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 7fe0ff377..d1b6a17b4 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -60,7 +60,7 @@ void grid_renderer::process(text_symbolizer const& sym, if (halo_transform) { agg::trans_affine halo_affine_transform; - evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform); + evaluate_transform(halo_affine_transform, feature, common_.vars_, *halo_transform, common_.scale_factor_); ren.set_halo_transform(halo_affine_transform); } diff --git a/src/group/group_layout_manager.cpp b/src/group/group_layout_manager.cpp index fe00e7d02..ad9aaad7c 100644 --- a/src/group/group_layout_manager.cpp +++ b/src/group/group_layout_manager.cpp @@ -34,19 +34,21 @@ namespace mapnik // This visitor will process offsets for the given layout struct process_layout { + using bound_box = box2d; + // The vector containing the existing, centered item bounding boxes - vector const& member_boxes_; + std::vector const& member_boxes_; // The vector to populate with item offsets - vector & member_offsets_; + std::vector & member_offsets_; // The origin point of the member boxes // i.e. The member boxes are positioned around input_origin, // and the offset values should position them around (0,0) pixel_position const& input_origin_; - process_layout(vector const& member_bboxes, - vector &member_offsets, + process_layout(std::vector const& member_bboxes, + std::vector &member_offsets, pixel_position const& input_origin) : member_boxes_(member_bboxes), member_offsets_(member_offsets), @@ -54,9 +56,12 @@ struct process_layout { } - // arrange group memebers in centered, horizontal row + // arrange group members in centered, horizontal row void operator()(simple_row_layout const& layout) const { + member_offsets_.clear(); + member_offsets_.reserve(member_boxes_.size()); + double total_width = (member_boxes_.size() - 1) * layout.get_item_margin(); for (auto const& box : member_boxes_) { @@ -66,7 +71,7 @@ struct process_layout double x_offset = -(total_width / 2.0); for (auto const& box : member_boxes_) { - member_offsets_.push_back(pixel_position(x_offset - box.minx(), -input_origin_.y)); + member_offsets_.emplace_back(x_offset - box.minx(), -input_origin_.y); x_offset += box.width() + layout.get_item_margin(); } } @@ -150,7 +155,7 @@ private: } }; -bound_box group_layout_manager::offset_box_at(size_t i) +box2d group_layout_manager::offset_box_at(size_t i) { handle_update(); pixel_position const& offset = member_offsets_.at(i); diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index 12633cbc2..d6c8a3333 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -33,7 +33,8 @@ #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" @@ -41,7 +42,7 @@ #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" #include "agg_color_rgba.h" - +#pragma GCC diagnostic pop namespace mapnik { @@ -190,7 +191,20 @@ struct composite_visitor dy_(dy) {} template - void operator() (T & dst); + void operator() (T & dst) const + { + throw std::runtime_error("Error: Composite with " + std::string(typeid(dst).name()) + " is not supported"); + } + + void operator()(image_rgba8 & dst) const + { + composite(dst, util::get(src_), mode_, opacity_, dx_, dy_); + } + + void operator() (image_gray32f & dst) const + { + composite(dst, util::get(src_), mode_, opacity_, dx_, dy_); + } private: image_any const& src_; @@ -198,26 +212,9 @@ struct composite_visitor float opacity_; int dx_; int dy_; + }; -template -void composite_visitor::operator() (T & dst) -{ - throw std::runtime_error("Error: Composite with " + std::string(typeid(dst).name()) + " is not supported"); -} - -template <> -void composite_visitor::operator() (image_rgba8 & dst) -{ - composite(dst, util::get(src_), mode_, opacity_, dx_, dy_); -} - -template <> -void composite_visitor::operator() (image_gray32f & dst) -{ - composite(dst, util::get(src_), mode_, opacity_, dx_, dy_); -} - } // end ns template <> diff --git a/src/image_copy.cpp b/src/image_copy.cpp index 01225c25b..04fa75c32 100644 --- a/src/image_copy.cpp +++ b/src/image_copy.cpp @@ -37,7 +37,7 @@ struct visitor_image_copy { using dst_type = typename T0::pixel_type; - T0 operator() (image_null const&) + T0 operator() (image_null const&) const { throw std::runtime_error("Can not cast a null image"); } @@ -48,7 +48,7 @@ struct visitor_image_copy } template - T0 operator() (T1 const& src) + T0 operator() (T1 const& src) const { T0 dst(safe_cast(src.width()), safe_cast(src.height()), false); for (std::size_t y = 0; y < dst.height(); ++y) @@ -75,7 +75,7 @@ struct visitor_image_copy_so throw std::runtime_error("Can not cast a null image"); } - T0 operator() (T0 const& src) + T0 operator() (T0 const& src) const { if (offset_ == src.get_offset() && scaling_ == src.get_scaling()) { @@ -91,7 +91,7 @@ struct visitor_image_copy_so } template - T0 operator() (T1 const& src) + T0 operator() (T1 const& src) const { double src_offset = src.get_offset(); double src_scaling = src.get_scaling(); diff --git a/src/image_filter_grammar.cpp b/src/image_filter_grammar.cpp new file mode 100644 index 000000000..9a4bea35a --- /dev/null +++ b/src/image_filter_grammar.cpp @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include +#include +#include + +template struct mapnik::image_filter_grammar>; diff --git a/src/image_filter_types.cpp b/src/image_filter_types.cpp index 6755757ec..d30804378 100644 --- a/src/image_filter_types.cpp +++ b/src/image_filter_types.cpp @@ -22,7 +22,6 @@ // mapnik #include #include -#include #pragma GCC diagnostic push #include diff --git a/src/image_scaling.cpp b/src/image_scaling.cpp index f0cc450e6..413948c64 100644 --- a/src/image_scaling.cpp +++ b/src/image_scaling.cpp @@ -25,14 +25,14 @@ #include #include -// boost #pragma GCC diagnostic push #include #include #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_image_accessors.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" @@ -47,6 +47,7 @@ #include "agg_span_interpolator_linear.h" #include "agg_trans_affine.h" #include "agg_image_filters.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/image_util.cpp b/src/image_util.cpp index 79d7e0af1..1fec8b130 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -38,13 +38,14 @@ #include #ifdef SSE_MATH #include - #endif -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_color_rgba.h" +#pragma GCC diagnostic pop // stl #include @@ -111,7 +112,7 @@ MAPNIK_DECL void save_to_stream(T const& image, { std::string t = type; std::transform(t.begin(), t.end(), t.begin(), ::tolower); - if (t == "png" || boost::algorithm::starts_with(t, "png")) + if (boost::algorithm::starts_with(t, "png")) { png_saver_pal visitor(stream, t, palette); mapnik::util::apply_visitor(visitor, image); @@ -141,7 +142,7 @@ MAPNIK_DECL void save_to_stream(image_rgba8 const& image, { std::string t = type; std::transform(t.begin(), t.end(), t.begin(), ::tolower); - if (t == "png" || boost::algorithm::starts_with(t, "png")) + if (boost::algorithm::starts_with(t, "png")) { png_saver_pal visitor(stream, t, palette); visitor(image); @@ -172,7 +173,7 @@ MAPNIK_DECL void save_to_stream(image_view_rgba8 const& image, { std::string t = type; std::transform(t.begin(), t.end(), t.begin(), ::tolower); - if (t == "png" || boost::algorithm::starts_with(t, "png")) + if (boost::algorithm::starts_with(t, "png")) { png_saver_pal visitor(stream, t, palette); visitor(image); @@ -200,7 +201,7 @@ MAPNIK_DECL void save_to_stream(T const& image, { std::string t = type; std::transform(t.begin(), t.end(), t.begin(), ::tolower); - if (t == "png" || boost::algorithm::starts_with(t, "png")) + if (boost::algorithm::starts_with(t, "png")) { png_saver visitor(stream, t); util::apply_visitor(visitor, image); @@ -236,7 +237,7 @@ MAPNIK_DECL void save_to_stream(image_rgba8 const& image, { std::string t = type; std::transform(t.begin(), t.end(), t.begin(), ::tolower); - if (t == "png" || boost::algorithm::starts_with(t, "png")) + if (boost::algorithm::starts_with(t, "png")) { png_saver visitor(stream, t); visitor(image); @@ -276,7 +277,7 @@ MAPNIK_DECL void save_to_stream(image_view_rgba8 const& image, { std::string t = type; std::transform(t.begin(), t.end(), t.begin(), ::tolower); - if (t == "png" || boost::algorithm::starts_with(t, "png")) + if (boost::algorithm::starts_with(t, "png")) { png_saver visitor(stream, t); visitor(image); @@ -2087,7 +2088,7 @@ struct visitor_view_to_stream : os_(os) {} template - void operator() (T const& view) + void operator() (T const& view) const { for (std::size_t i=0;i Z_BEST_COMPRESSION) + if (opts.compression > Z_BEST_COMPRESSION) { throw image_writer_exception("invalid compression value: (only -1 through 9 are valid)"); } diff --git a/src/jpeg_reader.cpp b/src/jpeg_reader.cpp index 84c805ee8..6b6e1b127 100644 --- a/src/jpeg_reader.cpp +++ b/src/jpeg_reader.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include #include // jpeg @@ -30,16 +31,10 @@ extern "C" #include } -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - // std #include #include +#include namespace mapnik { @@ -49,7 +44,7 @@ class jpeg_reader : public image_reader { public: using source_type = T; - using input_stream = boost::iostreams::stream; + using input_stream = std::iostream; const static unsigned BUF_SIZE = 4096; private: struct jpeg_stream_wrapper @@ -77,7 +72,7 @@ private: unsigned width_; unsigned height_; public: - explicit jpeg_reader(std::string const& file_name); + explicit jpeg_reader(std::string const& filename); explicit jpeg_reader(char const* data, size_t size); ~jpeg_reader(); unsigned width() const final; @@ -99,14 +94,14 @@ private: namespace { -image_reader* create_jpeg_reader(std::string const& file) +image_reader* create_jpeg_reader(std::string const& filename) { - return new jpeg_reader(file); + return new jpeg_reader(filename); } image_reader* create_jpeg_reader2(char const* data, size_t size) { - return new jpeg_reader(data, size); + return new jpeg_reader(data, size); } const bool registered = register_image_reader("jpeg",create_jpeg_reader); @@ -115,20 +110,21 @@ const bool registered2 = register_image_reader("jpeg",create_jpeg_reader2); // ctors template -jpeg_reader::jpeg_reader(std::string const& file_name) - : source_(file_name,std::ios_base::in | std::ios_base::binary), - stream_(source_), +jpeg_reader::jpeg_reader(std::string const& filename) + : source_(), + stream_(&source_), width_(0), height_(0) { - if (!stream_) throw image_reader_exception("cannot open image file "+ file_name); + source_.open(filename, std::ios_base::in | std::ios_base::binary); + if (!stream_) throw image_reader_exception("cannot open image file "+ filename); init(); } template jpeg_reader::jpeg_reader(char const* data, size_t size) : source_(data, size), - stream_(source_), + stream_(&source_), width_(0), height_(0) { diff --git a/src/json/mapnik_geometry_to_geojson.cpp b/src/json/mapnik_geometry_to_geojson.cpp new file mode 100644 index 000000000..ab2618093 --- /dev/null +++ b/src/json/mapnik_geometry_to_geojson.cpp @@ -0,0 +1,37 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include + +namespace mapnik { namespace util { + +bool to_geojson(std::string & json, mapnik::geometry::geometry const& geom) +{ + using sink_type = std::back_insert_iterator; + static const mapnik::json::geometry_generator_grammar > grammar; + sink_type sink(json); + return boost::spirit::karma::generate(sink, grammar, geom); +} + +}} diff --git a/src/json/mapnik_json_geometry_parser.cpp b/src/json/mapnik_json_geometry_parser.cpp new file mode 100644 index 000000000..278d2c4be --- /dev/null +++ b/src/json/mapnik_json_geometry_parser.cpp @@ -0,0 +1,43 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + + +#include +#include + +// boost +#include +#include + +namespace mapnik { namespace json { + +bool from_geojson(std::string const& json, mapnik::geometry::geometry & geom) +{ + using namespace boost::spirit; + static const geometry_grammar g; + standard::space_type space; + char const* start = json.c_str(); + char const* end = start + json.length(); + return qi::phrase_parse(start, end, g, space, geom); +} + +}} diff --git a/src/json/mapnik_json_positions_grammar.cpp b/src/json/mapnik_json_positions_grammar.cpp new file mode 100644 index 000000000..a13f0e313 --- /dev/null +++ b/src/json/mapnik_json_positions_grammar.cpp @@ -0,0 +1,27 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include + +using iterator_type = char const*; +template struct mapnik::json::positions_grammar; diff --git a/src/load_map.cpp b/src/load_map.cpp index 6e15ba2fb..bf6324d20 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -59,18 +59,22 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include #include #include #include #include +#pragma GCC diagnostic pop // stl #include -// agg +#pragma GCC diagnostic push +#include #include "agg_trans_affine.h" +#pragma GCC diagnostic pop using boost::tokenizer; @@ -196,7 +200,7 @@ void map_parser::parse_map(Map & map, xml_node const& node, std::string const& b { map.set_background(*bgcolor); } - + optional image_filename = map_node.get_opt_attr("background-image"); if (image_filename) { @@ -751,7 +755,7 @@ void map_parser::parse_layer(Map & map, xml_node const& node) } catch (...) { - throw config_error("Unknown exception occured attempting to create datasoure for layer '" + lyr.name() + "'"); + throw config_error("Unknown exception occurred attempting to create datasoure for layer '" + lyr.name() + "'"); } } } @@ -887,7 +891,7 @@ void map_parser::parse_symbolizer_base(symbolizer_base &sym, xml_node const& nod { set_symbolizer_property(sym, keys::simplify_tolerance, node); set_symbolizer_property(sym, keys::smooth, node); - set_symbolizer_property(sym, keys::clip, node); + set_symbolizer_property(sym, keys::clip, node); set_symbolizer_property(sym, keys::comp_op, node); set_symbolizer_property(sym, keys::geometry_transform, node); set_symbolizer_property(sym, keys::simplify_algorithm, node); @@ -903,8 +907,8 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & node) point_symbolizer sym; parse_symbolizer_base(sym, node); set_symbolizer_property(sym, keys::opacity, node); - set_symbolizer_property(sym, keys::allow_overlap, node); - set_symbolizer_property(sym, keys::ignore_placement, node); + set_symbolizer_property(sym, keys::allow_overlap, node); + set_symbolizer_property(sym, keys::ignore_placement, node); set_symbolizer_property(sym, keys::point_placement_type, node); set_symbolizer_property(sym, keys::image_transform, node); if (file && !file->empty()) @@ -1007,9 +1011,9 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node) set_symbolizer_property(sym, keys::offset, node); set_symbolizer_property(sym, keys::width, node); set_symbolizer_property(sym, keys::height, node); - set_symbolizer_property(sym, keys::allow_overlap, node); - set_symbolizer_property(sym, keys::avoid_edges, node); - set_symbolizer_property(sym, keys::ignore_placement, node); + set_symbolizer_property(sym, keys::allow_overlap, node); + set_symbolizer_property(sym, keys::avoid_edges, node); + set_symbolizer_property(sym, keys::ignore_placement, node); set_symbolizer_property(sym, keys::fill, node); set_symbolizer_property(sym, keys::image_transform, node); set_symbolizer_property(sym, keys::markers_placement_type, node); @@ -1168,7 +1172,7 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& node) set_symbolizer_property(sym, keys::shield_dx, node); set_symbolizer_property(sym, keys::shield_dy, node); set_symbolizer_property(sym, keys::opacity, node); - set_symbolizer_property(sym, keys::unlock_image, node); + set_symbolizer_property(sym, keys::unlock_image, node); std::string file = node.get_attr("file"); if (file.empty()) @@ -1339,7 +1343,7 @@ void map_parser::parse_raster_symbolizer(rule & rule, xml_node const & node) // premultiplied status of image optional premultiplied = node.get_opt_attr("premultiplied"); - if (premultiplied) put(raster_sym, keys::premultiplied, *premultiplied); + if (premultiplied) put(raster_sym, keys::premultiplied, bool(*premultiplied)); bool found_colorizer = false; for ( auto const& css : node) diff --git a/src/map.cpp b/src/map.cpp index c44735ce4..ec0d9f83e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -307,7 +307,7 @@ bool Map::load_fonts() continue; } mapnik::util::file file(file_path); - if (file.open()) + if (file) { auto item = font_memory_cache_.emplace(file_path, std::make_pair(file.data(),file.size())); if (item.second) result = true; @@ -695,7 +695,7 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const { if (!current_extent_.valid()) { - throw std::runtime_error("query_point: map extent is not intialized, you need to set a valid extent before querying"); + throw std::runtime_error("query_point: map extent is not initialized, you need to set a valid extent before querying"); } if (!current_extent_.intersects(x,y)) { @@ -746,7 +746,7 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const else s << " (map has no layers)"; throw std::out_of_range(s.str()); } - return featureset_ptr(); + return mapnik::make_invalid_featureset(); } featureset_ptr Map::query_map_point(unsigned index, double x, double y) const diff --git a/src/mapped_memory_cache.cpp b/src/mapped_memory_cache.cpp index db4fce897..f35a379af 100644 --- a/src/mapped_memory_cache.cpp +++ b/src/mapped_memory_cache.cpp @@ -37,6 +37,8 @@ namespace mapnik { +template class singleton; + void mapped_memory_cache::clear() { #ifdef MAPNIK_THREADSAFE @@ -58,6 +60,7 @@ boost::optional mapped_memory_cache::find(std::string const& #ifdef MAPNIK_THREADSAFE std::lock_guard lock(mutex_); #endif + using iterator_type = std::unordered_map::const_iterator; boost::optional result; iterator_type itr = cache_.find(uri); @@ -76,7 +79,7 @@ boost::optional mapped_memory_cache::find(std::string const& result.reset(region); if (update_cache) { - cache_.emplace(uri,*result); + cache_.emplace(uri, *result); } return result; } diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 664121854..059280c6b 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -39,9 +39,11 @@ #include #pragma GCC diagnostic pop -// agg +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -118,19 +120,19 @@ namespace detail struct visitor_create_marker { - marker operator() (image_rgba8 & data) + marker operator() (image_rgba8 & data) const { mapnik::premultiply_alpha(data); return mapnik::marker(mapnik::marker_rgba8(data)); } - marker operator() (image_null &) + marker operator() (image_null &) const { throw std::runtime_error("Can not make marker from null image data type"); } template - marker operator() (T &) + marker operator() (T &) const { throw std::runtime_error("Can not make marker from this data type"); } @@ -265,7 +267,7 @@ std::shared_ptr marker_cache::find(std::string const& uri, } else { - MAPNIK_LOG_ERROR(marker_cache) << "could not intialize reader for: '" << uri << "'"; + MAPNIK_LOG_ERROR(marker_cache) << "could not initialize reader for: '" << uri << "'"; return std::make_shared(mapnik::marker_null()); } } diff --git a/src/marker_helpers.cpp b/src/marker_helpers.cpp index cf37cdbe4..eb0202169 100644 --- a/src/marker_helpers.cpp +++ b/src/marker_helpers.cpp @@ -23,9 +23,13 @@ // mapnik #include #include +#include +#pragma GCC diagnostic push +#include #include "agg_ellipse.h" #include "agg_color_rgba.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -33,6 +37,7 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a { double width = 0.0; double height = 0.0; + double half_stroke_width = 0.0; if (has_key(sym,keys::width) && has_key(sym,keys::height)) { width = get(sym, keys::width, feature, vars, 0.0); @@ -46,6 +51,10 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a { width = height = get(sym, keys::height, feature, vars, 0.0); } + if (has_key(sym,keys::stroke_width)) + { + half_stroke_width = get(sym, keys::stroke_width, feature, vars, 0.0) / 2.0; + } svg::svg_converter_type styled_svg(svg_path, marker_ellipse.attributes()); styled_svg.push_attr(); styled_svg.begin_path(); @@ -55,6 +64,10 @@ void build_ellipse(symbolizer_base const& sym, mapnik::feature_impl & feature, a styled_svg.pop_attr(); double lox,loy,hix,hiy; styled_svg.bounding_rect(&lox, &loy, &hix, &hiy); + lox -= half_stroke_width; + loy -= half_stroke_width; + hix += half_stroke_width; + hiy += half_stroke_width; styled_svg.set_dimensions(width,height); marker_ellipse.set_dimensions(width,height); marker_ellipse.set_bounding_box(lox,loy,hix,hiy); @@ -158,5 +171,142 @@ void setup_transform_scaling(agg::trans_affine & tr, } } +template +void apply_markers_single(vertex_converter_type & converter, Processor & proc, + geometry::geometry const& geom, geometry::geometry_types type) +{ + if (type == geometry::geometry_types::Point) + { + geometry::point_vertex_adapter va(geom.get>()); + converter.apply(va, proc); + } + else if (type == geometry::geometry_types::LineString) + { + geometry::line_string_vertex_adapter va(geom.get>()); + converter.apply(va, proc); + } + else if (type == geometry::geometry_types::Polygon) + { + geometry::polygon_vertex_adapter va(geom.get>()); + converter.apply(va, proc); + } + else if (type == geometry::geometry_types::MultiPoint) + { + for (auto const& pt : geom.get>()) + { + geometry::point_vertex_adapter va(pt); + converter.apply(va, proc); + } + } + else if (type == geometry::geometry_types::MultiLineString) + { + for (auto const& line : geom.get>()) + { + geometry::line_string_vertex_adapter va(line); + converter.apply(va, proc); + } + } + else if (type == geometry::geometry_types::MultiPolygon) + { + for (auto const& poly : geom.get>()) + { + geometry::polygon_vertex_adapter va(poly); + converter.apply(va, proc); + } + } +} + +template +void apply_markers_multi(feature_impl const& feature, attributes const& vars, + vertex_converter_type & converter, Processor & proc, symbolizer_base const& sym) +{ + auto const& geom = feature.get_geometry(); + geometry::geometry_types type = geometry::geometry_type(geom); + + if (type == geometry::geometry_types::Point + || + type == geometry::geometry_types::LineString + || + type == geometry::geometry_types::Polygon) + { + apply_markers_single(converter, proc, geom, type); + } + else + { + + marker_multi_policy_enum multi_policy = get(sym, feature, vars); + marker_placement_enum placement = get(sym, feature, vars); + + if (placement == MARKER_POINT_PLACEMENT && + multi_policy == MARKER_WHOLE_MULTI) + { + geometry::point pt; + // test if centroid is contained by bounding box + if (geometry::centroid(geom, pt) && converter.disp_.args_.bbox.contains(pt.x, pt.y)) + { + // unset any clipping since we're now dealing with a point + converter.template unset(); + geometry::point_vertex_adapter va(pt); + converter.apply(va, proc); + } + } + else if ((placement == MARKER_POINT_PLACEMENT || placement == MARKER_INTERIOR_PLACEMENT) && + multi_policy == MARKER_LARGEST_MULTI) + { + // Only apply to path with largest envelope area + // TODO: consider using true area for polygon types + if (type == geometry::geometry_types::MultiPolygon) + { + geometry::multi_polygon const& multi_poly = mapnik::util::get >(geom); + double maxarea = 0; + geometry::polygon const* largest = 0; + for (geometry::polygon const& poly : multi_poly) + { + box2d bbox = geometry::envelope(poly); + double area = bbox.width() * bbox.height(); + if (area > maxarea) + { + maxarea = area; + largest = &poly; + } + } + if (largest) + { + geometry::polygon_vertex_adapter va(*largest); + converter.apply(va, proc); + } + } + else + { + MAPNIK_LOG_WARN(marker_symbolizer) << "TODO: if you get here -> open an issue"; + } + } + else + { + if (multi_policy != MARKER_EACH_MULTI && placement != MARKER_POINT_PLACEMENT) + { + MAPNIK_LOG_WARN(marker_symbolizer) << "marker_multi_policy != 'each' has no effect with marker_placement != 'point'"; + } + if (type == geometry::geometry_types::GeometryCollection) + { + for (auto const& g : geom.get>()) + { + apply_markers_single(converter, proc, g, geometry::geometry_type(g)); + } + } + else + { + apply_markers_single(converter, proc, geom, type); + } + } + } +} +template void apply_markers_multi(feature_impl const& feature, attributes const& vars, + vertex_converter_type & converter, vector_dispatch_type & proc, + symbolizer_base const& sym); + +template void apply_markers_multi(feature_impl const& feature, attributes const& vars, + vertex_converter_type & converter, raster_dispatch_type & proc, + symbolizer_base const& sym); } // end namespace mapnik diff --git a/src/memory_datasource.cpp b/src/memory_datasource.cpp index f7bd61d4e..3c182207b 100644 --- a/src/memory_datasource.cpp +++ b/src/memory_datasource.cpp @@ -73,7 +73,8 @@ memory_datasource::memory_datasource(parameters const& params) desc_(memory_datasource::name(), *params.get("encoding","utf-8")), type_(datasource::Vector), - bbox_check_(*params.get("bbox_check", true)) {} + bbox_check_(*params.get("bbox_check", true)), + type_set_(false) {} memory_datasource::~memory_datasource() {} @@ -81,6 +82,30 @@ void memory_datasource::push(feature_ptr feature) { // TODO - collect attribute descriptors? //desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer)); + if (feature->get_raster()) + { + // if a feature has a raster_ptr set it must be of raster type. + if (!type_set_) + { + type_ = datasource::Raster; + type_set_ = true; + } + else if (type_ == datasource::Vector) + { + throw std::runtime_error("Can not add a raster feature to a memory datasource that contains vectors"); + } + } + else + { + if (!type_set_) + { + type_set_ = true; + } + else if (type_ == datasource::Raster) + { + throw std::runtime_error("Can not add a vector feature to a memory datasource that contains rasters"); + } + } features_.push_back(feature); dirty_extent_ = true; } @@ -107,6 +132,7 @@ featureset_ptr memory_datasource::features_at_point(coord2d const& pt, double to void memory_datasource::set_envelope(box2d const& box) { extent_ = box; + dirty_extent_ = false; } box2d memory_datasource::envelope() const diff --git a/src/miniz.c b/src/miniz.c deleted file mode 100644 index c45bb42fd..000000000 --- a/src/miniz.c +++ /dev/null @@ -1,4834 +0,0 @@ -/* miniz.c v1.14 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing - See "unlicense" statement at the end of this file. - Rich Geldreich , last updated May 20, 2012 - Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt - - Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define - MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). - - * Change History - 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). - 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. - Eliminated a bunch of warnings when compiling with GCC 32-bit/64. - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly - "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). - 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. - level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. - 5/28/11 v1.11 - Added statement from unlicense.org - 5/27/11 v1.10 - Substantial compressor optimizations: - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. - Refactored the compression code for better readability and maintainability. - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large - drop in throughput on some files). - 5/15/11 v1.09 - Initial stable release. - - * Low-level Deflate/Inflate implementation notes: - - Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or - greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses - approximately as well as zlib. - - Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function - coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory - block large enough to hold the entire file. - - The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. - - * zlib-style API notes: - - miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in - zlib replacement in many apps: - The z_stream struct, optional memory allocation callbacks - deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound - inflateInit/inflateInit2/inflate/inflateEnd - compress, compress2, compressBound, uncompress - CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. - Supports raw deflate streams or standard zlib streams with adler-32 checking. - - Limitations: - The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. - I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but - there are no guarantees that miniz.c pulls this off perfectly. - - * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by - Alex Evans. Supports 1-4 bytes/pixel images. - - * ZIP archive API notes: - - The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to - get the job done with minimal fuss. There are simple API's to retrieve file information, read files from - existing archives, create new archives, append new files to existing archives, or clone archive data from - one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), - or you can specify custom file read/write callbacks. - - - Archive reading: Just call this function to read a single file from a disk archive: - - void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, - size_t *pSize, mz_uint zip_flags); - - For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central - directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. - - - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: - - int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); - - The locate operation can optionally check file comments too, which (as one example) can be used to identify - multiple versions of the same file in an archive. This function uses a simple linear search through the central - directory, so it's not very fast. - - Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and - retrieve detailed info on each file by calling mz_zip_reader_file_stat(). - - - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data - to disk and builds an exact image of the central directory in memory. The central directory image is written - all at once at the end of the archive file when the archive is finalized. - - The archive writer can optionally align each file's local header and file data to any power of 2 alignment, - which can be useful when the archive will be read from optical media. Also, the writer supports placing - arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still - readable by any ZIP tool. - - - Archive appending: The simple way to add a single file to an archive is to call this function: - - mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, - const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); - - The archive will be created if it doesn't already exist, otherwise it'll be appended to. - Note the appending is done in-place and is not an atomic operation, so if something goes wrong - during the operation it's possible the archive could be left without a central directory (although the local - file headers and file data will be fine, so the archive will be recoverable). - - For more complex archive modification scenarios: - 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to - preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the - compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and - you're done. This is safe but requires a bunch of temporary disk space or heap memory. - - 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), - append new files as needed, then finalize the archive which will write an updated central directory to the - original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a - possibility that the archive's central directory could be lost with this method if anything goes wrong, though. - - - ZIP archive support limitations: - No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files. - Requires streams capable of seeking. - - * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the - below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. - - * Important: For best perf. be sure to customize the below macros for your target platform: - #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 - #define MINIZ_LITTLE_ENDIAN 1 - #define MINIZ_HAS_64BIT_REGISTERS 1 -*/ - -#ifndef MINIZ_HEADER_INCLUDED -#define MINIZ_HEADER_INCLUDED - -#include - -#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) -#include -#endif - -// Defines to completely disable specific portions of miniz.c: -// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. - -// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. -//#define MINIZ_NO_STDIO - -// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or -// get/set file times. -//#define MINIZ_NO_TIME - -// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. -//#define MINIZ_NO_ARCHIVE_APIS - -// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's. -//#define MINIZ_NO_ARCHIVE_WRITING_APIS - -// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. -//#define MINIZ_NO_ZLIB_APIS - -// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. -//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES - -// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. -// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc -// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user -// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. -//#define MINIZ_NO_MALLOC - -#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) -// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. -#define MINIZ_X86_OR_X64_CPU 1 -#endif - -#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU -// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. -#define MINIZ_LITTLE_ENDIAN 1 -#endif - -#if MINIZ_X86_OR_X64_CPU -// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. -#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 -#endif - -#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) -// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). -#define MINIZ_HAS_64BIT_REGISTERS 1 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// ------------------- zlib-style API Definitions. - -// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! -typedef unsigned long mz_ulong; - -// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. -void mz_free(void *p); - -#define MZ_ADLER32_INIT (1) -// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); - -#define MZ_CRC32_INIT (0) -// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. -mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); - -// Compression strategies. -enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; - -// Method -#define MZ_DEFLATED 8 - -#ifndef MINIZ_NO_ZLIB_APIS - -// Heap allocation callbacks. -// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. -typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); -typedef void (*mz_free_func)(void *opaque, void *address); -typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); - -#define MZ_VERSION "9.1.14" -#define MZ_VERNUM 0x91E0 -#define MZ_VER_MAJOR 9 -#define MZ_VER_MINOR 1 -#define MZ_VER_REVISION 14 -#define MZ_VER_SUBREVISION 0 - -// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). -enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; - -// Return status codes. MZ_PARAM_ERROR is non-standard. -enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; - -// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. -enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; - -// Window bits -#define MZ_DEFAULT_WINDOW_BITS 15 - -struct mz_internal_state; - -// Compression/decompression stream struct. -typedef struct mz_stream_s -{ - const unsigned char *next_in; // pointer to next byte to read - unsigned int avail_in; // number of bytes available at next_in - mz_ulong total_in; // total number of bytes consumed so far - - unsigned char *next_out; // pointer to next byte to write - unsigned int avail_out; // number of bytes that can be written to next_out - mz_ulong total_out; // total number of bytes produced so far - - char *msg; // error msg (unused) - struct mz_internal_state *state; // internal state, allocated by zalloc/zfree - - mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) - mz_free_func zfree; // optional heap free function (defaults to free) - void *opaque; // heap alloc function user pointer - - int data_type; // data_type (unused) - mz_ulong adler; // adler32 of the source or uncompressed data - mz_ulong reserved; // not used -} mz_stream; - -typedef mz_stream *mz_streamp; - -// Returns the version string of miniz.c. -const char *mz_version(void); - -// mz_deflateInit() initializes a compressor with default options: -// Parameters: -// pStream must point to an initialized mz_stream struct. -// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. -// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. -// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) -// Return values: -// MZ_OK on success. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_PARAM_ERROR if the input parameters are bogus. -// MZ_MEM_ERROR on out of memory. -int mz_deflateInit(mz_streamp pStream, int level); - -// mz_deflateInit2() is like mz_deflate(), except with more control: -// Additional parameters: -// method must be MZ_DEFLATED -// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) -// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) -int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); - -// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). -int mz_deflateReset(mz_streamp pStream); - -// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. -// Parameters: -// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. -// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. -// Return values: -// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). -// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_PARAM_ERROR if one of the parameters is invalid. -// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) -int mz_deflate(mz_streamp pStream, int flush); - -// mz_deflateEnd() deinitializes a compressor: -// Return values: -// MZ_OK on success. -// MZ_STREAM_ERROR if the stream is bogus. -int mz_deflateEnd(mz_streamp pStream); - -// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); - -// Single-call compression functions mz_compress() and mz_compress2(): -// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); - -// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). -mz_ulong mz_compressBound(mz_ulong source_len); - -// Initializes a decompressor. -int mz_inflateInit(mz_streamp pStream); - -// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: -// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). -int mz_inflateInit2(mz_streamp pStream, int window_bits); - -// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. -// Parameters: -// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. -// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. -// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). -// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. -// Return values: -// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. -// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_DATA_ERROR if the deflate stream is invalid. -// MZ_PARAM_ERROR if one of the parameters is invalid. -// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again -// with more input data, or with more room in the output buffer (except when using single call decompression, described above). -int mz_inflate(mz_streamp pStream, int flush); - -// Deinitializes a decompressor. -int mz_inflateEnd(mz_streamp pStream); - -// Single-call decompression. -// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); - -// Returns a string description of the specified error code, or NULL if the error code is invalid. -const char *mz_error(int err); - -// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. -// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. -#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES - typedef unsigned char Byte; - typedef unsigned int uInt; - typedef mz_ulong uLong; - typedef Byte Bytef; - typedef uInt uIntf; - typedef char charf; - typedef int intf; - typedef void *voidpf; - typedef uLong uLongf; - typedef void *voidp; - typedef void *const voidpc; - #define Z_NULL 0 - #define Z_NO_FLUSH MZ_NO_FLUSH - #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH - #define Z_SYNC_FLUSH MZ_SYNC_FLUSH - #define Z_FULL_FLUSH MZ_FULL_FLUSH - #define Z_FINISH MZ_FINISH - #define Z_BLOCK MZ_BLOCK - #define Z_OK MZ_OK - #define Z_STREAM_END MZ_STREAM_END - #define Z_NEED_DICT MZ_NEED_DICT - #define Z_ERRNO MZ_ERRNO - #define Z_STREAM_ERROR MZ_STREAM_ERROR - #define Z_DATA_ERROR MZ_DATA_ERROR - #define Z_MEM_ERROR MZ_MEM_ERROR - #define Z_BUF_ERROR MZ_BUF_ERROR - #define Z_VERSION_ERROR MZ_VERSION_ERROR - #define Z_PARAM_ERROR MZ_PARAM_ERROR - #define Z_NO_COMPRESSION MZ_NO_COMPRESSION - #define Z_BEST_SPEED MZ_BEST_SPEED - #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION - #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION - #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY - #define Z_FILTERED MZ_FILTERED - #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY - #define Z_RLE MZ_RLE - #define Z_FIXED MZ_FIXED - #define Z_DEFLATED MZ_DEFLATED - #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS - #define alloc_func mz_alloc_func - #define free_func mz_free_func - #define internal_state mz_internal_state - #define z_stream mz_stream - #define deflateInit mz_deflateInit - #define deflateInit2 mz_deflateInit2 - #define deflateReset mz_deflateReset - #define deflate mz_deflate - #define deflateEnd mz_deflateEnd - #define deflateBound mz_deflateBound - #define compress mz_compress - #define compress2 mz_compress2 - #define compressBound mz_compressBound - #define inflateInit mz_inflateInit - #define inflateInit2 mz_inflateInit2 - #define inflate mz_inflate - #define inflateEnd mz_inflateEnd - #define uncompress mz_uncompress - #define crc32 mz_crc32 - #define adler32 mz_adler32 - #define MAX_WBITS 15 - #define MAX_MEM_LEVEL 9 - #define zError mz_error - #define ZLIB_VERSION MZ_VERSION - #define ZLIB_VERNUM MZ_VERNUM - #define ZLIB_VER_MAJOR MZ_VER_MAJOR - #define ZLIB_VER_MINOR MZ_VER_MINOR - #define ZLIB_VER_REVISION MZ_VER_REVISION - #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION - #define zlibVersion mz_version - #define zlib_version mz_version() -#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES - -#endif // MINIZ_NO_ZLIB_APIS - -// ------------------- Types and macros - -typedef unsigned char mz_uint8; -typedef signed short mz_int16; -typedef unsigned short mz_uint16; -typedef unsigned int mz_uint32; -typedef unsigned int mz_uint; -typedef long long mz_int64; -typedef unsigned long long mz_uint64; -typedef int mz_bool; - -#define MZ_FALSE (0) -#define MZ_TRUE (1) - -// Works around MSVC's spammy "warning C4127: conditional expression is constant" message. -#ifdef _MSC_VER - #define MZ_MACRO_END while (0, 0) -#else - #define MZ_MACRO_END while (0) -#endif - -// ------------------- ZIP archive reading/writing - -#ifndef MINIZ_NO_ARCHIVE_APIS - -enum -{ - MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, - MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, - MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 -}; - -typedef struct -{ - mz_uint32 m_file_index; - mz_uint32 m_central_dir_ofs; - mz_uint16 m_version_made_by; - mz_uint16 m_version_needed; - mz_uint16 m_bit_flag; - mz_uint16 m_method; -#ifndef MINIZ_NO_TIME - time_t m_time; -#endif - mz_uint32 m_crc32; - mz_uint64 m_comp_size; - mz_uint64 m_uncomp_size; - mz_uint16 m_internal_attr; - mz_uint32 m_external_attr; - mz_uint64 m_local_header_ofs; - mz_uint32 m_comment_size; - char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; - char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; -} mz_zip_archive_file_stat; - -typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); -typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); - -struct mz_zip_internal_state_tag; -typedef struct mz_zip_internal_state_tag mz_zip_internal_state; - -typedef enum -{ - MZ_ZIP_MODE_INVALID = 0, - MZ_ZIP_MODE_READING = 1, - MZ_ZIP_MODE_WRITING = 2, - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 -} mz_zip_mode; - -typedef struct -{ - mz_uint64 m_archive_size; - mz_uint64 m_central_directory_file_ofs; - mz_uint m_total_files; - mz_zip_mode m_zip_mode; - - mz_uint m_file_offset_alignment; - - mz_alloc_func m_pAlloc; - mz_free_func m_pFree; - mz_realloc_func m_pRealloc; - void *m_pAlloc_opaque; - - mz_file_read_func m_pRead; - mz_file_write_func m_pWrite; - void *m_pIO_opaque; - - mz_zip_internal_state *m_pState; - -} mz_zip_archive; - -typedef enum -{ - MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, - MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, - MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 -} mz_zip_flags; - -// ZIP archive reading - -// Inits a ZIP archive reader. -// These functions read and validate the archive's central directory. -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); -#endif - -// Returns the total number of files in the archive. -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); - -// Returns detailed information about an archive file entry. -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); - -// Determines if an archive file entry is a directory entry. -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); - -// Retrieves the filename of an archive file entry. -// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); - -// Attempts to locates a file in the archive's central directory. -// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH -// Returns -1 if the file cannot be found. -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); - -// Extracts a archive file to a memory buffer using no memory allocation. -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); - -// Extracts a archive file to a memory buffer. -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); - -// Extracts a archive file to a dynamically allocated heap buffer. -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); - -// Extracts a archive file using a callback function to output the file's data. -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); - -#ifndef MINIZ_NO_STDIO -// Extracts a archive file to a disk file and sets its last accessed and modified times. -// This function only extracts files, not archive directory records. -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); -#endif - -// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. -mz_bool mz_zip_reader_end(mz_zip_archive *pZip); - -// ZIP archive writing - -#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -// Inits a ZIP archive writer. -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); -#endif - -// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. -// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. -// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). -// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. -// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before -// the archive is finalized the file's central directory will be hosed. -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); - -// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. -// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); - -#ifndef MINIZ_NO_STDIO -// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); -#endif - -// Adds a file to an archive by fully cloning the data from another archive. -// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); - -// Finalizes the archive by writing the central directory records followed by the end of central directory record. -// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). -// An archive must be manually finalized by calling this function for it to be valid. -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); - -// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. -// Note for the archive to be valid, it must have been finalized before ending. -mz_bool mz_zip_writer_end(mz_zip_archive *pZip); - -// Misc. high-level helper functions: - -// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); - -// Reads a single file from an archive into a heap block. -// Returns NULL on failure. -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); - -#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -#endif // #ifndef MINIZ_NO_ARCHIVE_APIS - -// ------------------- Low-level Decompression API Definitions - -// Decompression flags used by tinfl_decompress(). -// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. -// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. -// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). -// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. -enum -{ - TINFL_FLAG_PARSE_ZLIB_HEADER = 1, - TINFL_FLAG_HAS_MORE_INPUT = 2, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, - TINFL_FLAG_COMPUTE_ADLER32 = 8 -}; - -// High level decompression functions: -// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. -// On return: -// Function returns a pointer to the decompressed data, or NULL on failure. -// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must call mz_free() on the returned block when it's no longer needed. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); - -// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. -// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. -#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); - -// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. -// Returns 1 on success or 0 on failure. -typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; - -// Max size of LZ dictionary. -#define TINFL_LZ_DICT_SIZE 32768 - -// Return status. -typedef enum -{ - TINFL_STATUS_BAD_PARAM = -3, - TINFL_STATUS_ADLER32_MISMATCH = -2, - TINFL_STATUS_FAILED = -1, - TINFL_STATUS_DONE = 0, - TINFL_STATUS_NEEDS_MORE_INPUT = 1, - TINFL_STATUS_HAS_MORE_OUTPUT = 2 -} tinfl_status; - -// Initializes the decompressor to its initial state. -#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END -#define tinfl_get_adler32(r) (r)->m_check_adler32 - -// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. -// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); - -// Internal/private bits follow. -enum -{ - TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, - TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS -}; - -typedef struct -{ - mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; - mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; -} tinfl_huff_table; - -#if MINIZ_HAS_64BIT_REGISTERS - #define TINFL_USE_64BIT_BITBUF 1 -#endif - -#if TINFL_USE_64BIT_BITBUF - typedef mz_uint64 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (64) -#else - typedef mz_uint32 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (32) -#endif - -struct tinfl_decompressor_tag -{ - mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; - tinfl_bit_buf_t m_bit_buf; - size_t m_dist_from_out_buf_start; - tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; - mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; -}; - -// ------------------- Low-level Compression API Definitions - -// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). -#define TDEFL_LESS_MEMORY 0 - -// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): -// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). -enum -{ - TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF -}; - -// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. -// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). -// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. -// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). -// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) -// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. -// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. -// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. -enum -{ - TDEFL_WRITE_ZLIB_HEADER = 0x01000, - TDEFL_COMPUTE_ADLER32 = 0x02000, - TDEFL_GREEDY_PARSING_FLAG = 0x04000, - TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, - TDEFL_RLE_MATCHES = 0x10000, - TDEFL_FILTER_MATCHES = 0x20000, - TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, - TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 -}; - -// High level compression functions: -// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of source block to compress. -// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must free() the returned block when it's no longer needed. -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); - -// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. -// Returns 0 on failure. -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); - -// Compresses an image to a compressed PNG file in memory. -// On entry: -// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. -// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pLen_out will be set to the size of the PNG image file. -// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); - -// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. -typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, size_t len, void *pUser); - -// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; - -// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). -#if TDEFL_LESS_MEMORY -enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#else -enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#endif - -// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. -typedef enum -{ - TDEFL_STATUS_BAD_PARAM = -2, - TDEFL_STATUS_PUT_BUF_FAILED = -1, - TDEFL_STATUS_OKAY = 0, - TDEFL_STATUS_DONE = 1, -} tdefl_status; - -// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums -typedef enum -{ - TDEFL_NO_FLUSH = 0, - TDEFL_SYNC_FLUSH = 2, - TDEFL_FULL_FLUSH = 3, - TDEFL_FINISH = 4 -} tdefl_flush; - -// tdefl's compression state structure. -struct tdefl_compressor -{ - tdefl_put_buf_func_ptr m_pPut_buf_func; - void *m_pPut_buf_user; - mz_uint m_flags, m_max_probes[2]; - int m_greedy_parsing; - mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; - mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; - mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; - mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; - tdefl_status m_prev_return_status; - const void *m_pIn_buf; - void *m_pOut_buf; - size_t *m_pIn_buf_size, *m_pOut_buf_size; - tdefl_flush m_flush; - const mz_uint8 *m_pSrc; - size_t m_src_buf_left, m_out_buf_ofs; - mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; - mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; - mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; - mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; - mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; -}; - -// Initializes the compressor. -// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. -// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. -// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. -// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); - -// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); - -// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. -// tdefl_compress_buffer() always consumes the entire input buffer. -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); -mz_uint32 tdefl_get_adler32(tdefl_compressor *d); - -// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. -#ifndef MINIZ_NO_ZLIB_APIS -// Create tdefl_compress() flags given zlib-style compression parameters. -// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) -// window_bits may be -15 (raw deflate) or 15 (zlib) -// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED -mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); -#endif // #ifndef MINIZ_NO_ZLIB_APIS - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_INCLUDED - -// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) - -#ifndef MINIZ_HEADER_FILE_ONLY - -typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; -typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; -typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; - -#include -#include - -#define MZ_ASSERT(x) assert(x) - -#ifdef MINIZ_NO_MALLOC - #define MZ_MALLOC(x) NULL - #define MZ_FREE(x) (void)x, ((void)0) - #define MZ_REALLOC(p, x) NULL -#else - #define MZ_MALLOC(x) malloc(x) - #define MZ_FREE(x) free(x) - #define MZ_REALLOC(p, x) realloc(p, x) -#endif - -#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) -#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) -#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) - #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) -#else - #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) - #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) -#endif - -#ifdef _MSC_VER - #define MZ_FORCEINLINE __forceinline -#elif defined(__GNUC__) - #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) -#else - #define MZ_FORCEINLINE inline -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -// ------------------- zlib-style API's - -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) -{ - mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; - if (!ptr) return MZ_ADLER32_INIT; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - return (s2 << 16) + s1; -} - -// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) -{ - static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; - mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) return MZ_CRC32_INIT; - crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } - return ~crcu32; -} - -void mz_free(void *p) -{ - MZ_FREE(p); -} - -#ifndef MINIZ_NO_ZLIB_APIS - -static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } -static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } -//static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } - -const char *mz_version(void) -{ - return MZ_VERSION; -} - -int mz_deflateInit(mz_streamp pStream, int level) -{ - return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); -} - -int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) -{ - tdefl_compressor *pComp; - mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); - - if (!pStream) return MZ_STREAM_ERROR; - if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = MZ_ADLER32_INIT; - pStream->msg = NULL; - pStream->reserved = 0; - pStream->total_in = 0; - pStream->total_out = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; - - pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *)pComp; - - if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) - { - mz_deflateEnd(pStream); - return MZ_PARAM_ERROR; - } - - return MZ_OK; -} - -int mz_deflateReset(mz_streamp pStream) -{ - if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; - pStream->total_in = pStream->total_out = 0; - tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); - return MZ_OK; -} - -int mz_deflate(mz_streamp pStream, int flush) -{ - size_t in_bytes, out_bytes; - mz_ulong orig_total_in, orig_total_out; - int mz_status = MZ_OK; - - if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; - if (!pStream->avail_out) return MZ_BUF_ERROR; - - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - - if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) - return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; - - orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; - for ( ; ; ) - { - tdefl_status defl_status; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; - - defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); - - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; - pStream->total_out += (mz_uint)out_bytes; - - if (defl_status < 0) - { - mz_status = MZ_STREAM_ERROR; - break; - } - else if (defl_status == TDEFL_STATUS_DONE) - { - mz_status = MZ_STREAM_END; - break; - } - else if (!pStream->avail_out) - break; - else if ((!pStream->avail_in) && (flush != MZ_FINISH)) - { - if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) - break; - return MZ_BUF_ERROR; // Can't make forward progress without some input. - } - } - return mz_status; -} - -int mz_deflateEnd(mz_streamp pStream) -{ - if (!pStream) return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} - -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) -{ - (void)pStream; - // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) - return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); -} - -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) -{ - int status; - mz_stream stream; - memset(&stream, 0, sizeof(stream)); - - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; - - status = mz_deflateInit(&stream, level); - if (status != MZ_OK) return status; - - status = mz_deflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_deflateEnd(&stream); - return (status == MZ_OK) ? MZ_BUF_ERROR : status; - } - - *pDest_len = stream.total_out; - return mz_deflateEnd(&stream); -} - -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) -{ - return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); -} - -mz_ulong mz_compressBound(mz_ulong source_len) -{ - return mz_deflateBound(NULL, source_len); -} - -typedef struct -{ - tinfl_decompressor m_decomp; - mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; - mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; - tinfl_status m_last_status; -} inflate_state; - -int mz_inflateInit2(mz_streamp pStream, int window_bits) -{ - inflate_state *pDecomp; - if (!pStream) return MZ_STREAM_ERROR; - if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = 0; - pStream->msg = NULL; - pStream->total_in = 0; - pStream->total_out = 0; - pStream->reserved = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; - - pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); - if (!pDecomp) return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *)pDecomp; - - tinfl_init(&pDecomp->m_decomp); - pDecomp->m_dict_ofs = 0; - pDecomp->m_dict_avail = 0; - pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; - pDecomp->m_first_call = 1; - pDecomp->m_has_flushed = 0; - pDecomp->m_window_bits = window_bits; - - return MZ_OK; -} - -int mz_inflateInit(mz_streamp pStream) -{ - return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); -} - -int mz_inflate(mz_streamp pStream, int flush) -{ - inflate_state* pState; - mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; - size_t in_bytes, out_bytes, orig_avail_in; - tinfl_status status; - - if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - - pState = (inflate_state*)pStream->state; - if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; - orig_avail_in = pStream->avail_in; - - first_call = pState->m_first_call; pState->m_first_call = 0; - if (pState->m_last_status < 0) return MZ_DATA_ERROR; - - if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - pState->m_has_flushed |= (flush == MZ_FINISH); - - if ((flush == MZ_FINISH) && (first_call)) - { - // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. - decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); - pState->m_last_status = status; - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; - pStream->adler = tinfl_get_adler32(&pState->m_decomp); - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; - - if (status < 0) - return MZ_DATA_ERROR; - else if (status != TINFL_STATUS_DONE) - { - pState->m_last_status = TINFL_STATUS_FAILED; - return MZ_BUF_ERROR; - } - return MZ_STREAM_END; - } - // flush != MZ_FINISH then we must assume there's more input. - if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; - - if (pState->m_dict_avail) - { - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; - } - - for ( ; ; ) - { - in_bytes = pStream->avail_in; - out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; - - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); - pState->m_last_status = status; - - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); - - pState->m_dict_avail = (mz_uint)out_bytes; - - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - - if (status < 0) - return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). - else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) - return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. - else if (flush == MZ_FINISH) - { - // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. - if (status == TINFL_STATUS_DONE) - return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; - // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. - else if (!pStream->avail_out) - return MZ_BUF_ERROR; - } - else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) - break; - } - - return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; -} - -int mz_inflateEnd(mz_streamp pStream) -{ - if (!pStream) - return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} - -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) -{ - mz_stream stream; - int status; - memset(&stream, 0, sizeof(stream)); - - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; - - status = mz_inflateInit(&stream); - if (status != MZ_OK) - return status; - - status = mz_inflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_inflateEnd(&stream); - return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; - } - *pDest_len = stream.total_out; - - return mz_inflateEnd(&stream); -} - -const char *mz_error(int err) -{ - static struct { int m_err; const char *m_pDesc; } s_error_descs[] = - { - { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, - { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } - }; - mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; - return NULL; -} - -#endif //MINIZ_NO_ZLIB_APIS - -// ------------------- Low-level Decompression (completely independent from all compression API's) - -#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) -#define TINFL_MEMSET(p, c, l) memset(p, c, l) - -#define TINFL_CR_BEGIN switch(r->m_state) { case 0: -#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END -#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END -#define TINFL_CR_FINISH } - -// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never -// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. -#define TINFL_GET_BYTE(state_index, c) do { \ - if (pIn_buf_cur >= pIn_buf_end) { \ - for ( ; ; ) { \ - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ - TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ - if (pIn_buf_cur < pIn_buf_end) { \ - c = *pIn_buf_cur++; \ - break; \ - } \ - } else { \ - c = 0; \ - break; \ - } \ - } \ - } else c = *pIn_buf_cur++; } MZ_MACRO_END - -#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) -#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END -#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END - -// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. -// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a -// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the -// bit buffer contains >=15 bits (deflate's max. Huffman code size). -#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ - do { \ - temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ - if (temp >= 0) { \ - code_len = temp >> 9; \ - if ((code_len) && (num_bits >= code_len)) \ - break; \ - } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ - code_len = TINFL_FAST_LOOKUP_BITS; \ - do { \ - temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ - } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ - } while (num_bits < 15); - -// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read -// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully -// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. -// The slow path is only executed at the very end of the input buffer. -#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ - int temp; mz_uint code_len, c; \ - if (num_bits < 15) { \ - if ((pIn_buf_end - pIn_buf_cur) < 2) { \ - TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ - } else { \ - bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ - } \ - } \ - if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ - code_len = temp >> 9, temp &= 511; \ - else { \ - code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ - } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END - -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) -{ - static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; - static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - static const int s_min_table_sizes[3] = { 257, 1, 4 }; - - tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; - size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; - - // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). - if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } - - num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; - TINFL_CR_BEGIN - - bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); - counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); - if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } - } - - do - { - TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; - if (r->m_type == 0) - { - TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } - if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } - while ((counter) && (num_bits)) - { - TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)dist; - counter--; - } - while (counter) - { - size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } - while (pIn_buf_cur >= pIn_buf_end) - { - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) - { - TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); - } - else - { - TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); - } - } - n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); - TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; - } - } - else if (r->m_type == 3) - { - TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); - } - else - { - if (r->m_type == 1) - { - mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; - r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; - } - else - { - for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } - MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } - r->m_table_sizes[2] = 19; - } - for ( ; (int)r->m_type >= 0; r->m_type--) - { - int tree_next, tree_cur; tinfl_huff_table *pTable; - mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; - used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } - if ((65536 != total) && (used_syms > 1)) - { - TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); - } - for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) - { - mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; - cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } - if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } - rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) - { - tree_cur -= ((rev_code >>= 1) & 1); - if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; - } - tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; - } - if (r->m_type == 2) - { - for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) - { - mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } - if ((dist == 16) && (!counter)) - { - TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); - } - num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; - TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; - } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) - { - TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); - } - TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); - } - } - for ( ; ; ) - { - mz_uint8 *pSrc; - for ( ; ; ) - { - if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) - { - TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); - if (counter >= 256) - break; - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)counter; - } - else - { - int sym2; mz_uint code_len; -#if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } -#else - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - counter = sym2; bit_buf >>= code_len; num_bits -= code_len; - if (counter & 256) - break; - -#if !TINFL_USE_64BIT_BITBUF - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); - } - bit_buf >>= code_len; num_bits -= code_len; - - pOut_buf_cur[0] = (mz_uint8)counter; - if (sym2 & 256) - { - pOut_buf_cur++; - counter = sym2; - break; - } - pOut_buf_cur[1] = (mz_uint8)sym2; - pOut_buf_cur += 2; - } - } - if ((counter &= 511) == 256) break; - - num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } - - TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); - num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } - - dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) - { - TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); - } - - pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); - - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) - { - while (counter--) - { - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; - } - continue; - } -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) - { - const mz_uint8 *pSrc_end = pSrc + (counter & ~7); - do - { - ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; - ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; - pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) - { - if (counter) - { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - continue; - } - } -#endif - do - { - pOut_buf_cur[0] = pSrc[0]; - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur[2] = pSrc[2]; - pOut_buf_cur += 3; pSrc += 3; - } while ((int)(counter -= 3) > 2); - if ((int)counter > 0) - { - pOut_buf_cur[0] = pSrc[0]; - if ((int)counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - } - } - } while (!(r->m_final & 1)); - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } - } - TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); - TINFL_CR_FINISH - -common_exit: - r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; - *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) - { - const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; - mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; - while (buf_len) - { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) - { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; - } - return status; -} - -// Higher level helper functions. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; - *pOut_len = 0; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - src_buf_ofs += src_buf_size; - *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) break; - new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; - pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; - } - return pBuf; -} - -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); - status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; -} - -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - int result = 0; - tinfl_decompressor decomp; - mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) - return TINFL_STATUS_FAILED; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); - in_buf_ofs += in_buf_size; - if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) - break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) - { - result = (status == TINFL_STATUS_DONE); - break; - } - dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); - } - MZ_FREE(pDict); - *pIn_buf_size = in_buf_ofs; - return result; -} - -// ------------------- Low-level Compression (independent from all decompression API's) - -// Purposely making these tables static for faster init and thread safety. -static const mz_uint16 s_tdefl_len_sym[256] = { - 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, - 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, - 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, - 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, - 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, - 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; - -static const mz_uint8 s_tdefl_len_extra[256] = { - 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; - -static const mz_uint8 s_tdefl_small_dist_sym[512] = { - 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; - -static const mz_uint8 s_tdefl_small_dist_extra[512] = { - 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7 }; - -static const mz_uint8 s_tdefl_large_dist_sym[128] = { - 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, - 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; - -static const mz_uint8 s_tdefl_large_dist_extra[128] = { - 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; - -// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. -typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; -static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) -{ - mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); - for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } - while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) - { - const mz_uint32* pHist = &hist[pass << 8]; - mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } - for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; - { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } - } - return pCur_syms; -} - -// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. -static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) -{ - int root, leaf, next, avbl, used, dpth; - if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } - A[0].m_key += A[1].m_key; root = 0; leaf = 2; - for (next=1; next < n-1; next++) - { - if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; - avbl = 1; used = dpth = 0; root = n-2; next = n-1; - while (avbl>0) - { - while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } - while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } - avbl = 2*used; dpth++; used = 0; - } -} - -// Limits canonical Huffman code table's max code size. -enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; -static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) -{ - int i; mz_uint32 total = 0; if (code_list_len <= 1) return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) - { - pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } - total--; - } -} - -static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) -{ - int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); - if (static_table) - { - for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; - } - else - { - tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; - int num_used_syms = 0; - const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } - - pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - - for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; - - tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); - - MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); - } - - next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); - - for (i = 0; i < table_len; i++) - { - mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; - code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); - d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; - } -} - -#define TDEFL_PUT_BITS(b, l) do { \ - mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ - d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ - while (d->m_bits_in >= 8) { \ - if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ - *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ - d->m_bit_buffer >>= 8; \ - d->m_bits_in -= 8; \ - } \ -} MZ_MACRO_END - -#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ - if (rle_repeat_count < 3) { \ - d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ - while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ - } else { \ - d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ -} rle_repeat_count = 0; } } - -#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ - if (rle_z_count < 3) { \ - d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ - } else if (rle_z_count <= 10) { \ - d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ - } else { \ - d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ -} rle_z_count = 0; } } - -static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - -static void tdefl_start_dynamic_block(tdefl_compressor *d) -{ - int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; - mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; - - d->m_huff_count[0][256] = 1; - - tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); - tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); - - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; - - memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); - memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); - total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; - - memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) - { - mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } - } - else - { - TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; - } - else if (++rle_repeat_count == 6) - { - TDEFL_RLE_PREV_CODE_SIZE(); - } - } - prev_code_size = code_size; - } - if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } - - tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); - - TDEFL_PUT_BITS(2, 2); - - TDEFL_PUT_BITS(num_lit_codes - 257, 5); - TDEFL_PUT_BITS(num_dist_codes - 1, 5); - - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; - num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); - - for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) - { - mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); - TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); - if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); - } -} - -static void tdefl_start_static_block(tdefl_compressor *d) -{ - mz_uint i; - mz_uint8 *p = &d->m_huff_code_sizes[0][0]; - - for (i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; - - memset(d->m_huff_code_sizes[1], 5, 32); - - tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); - tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); - - TDEFL_PUT_BITS(1, 2); -} - -static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - mz_uint8 *pOutput_buf = d->m_pOutput_buf; - mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; - mz_uint64 bit_buffer = d->m_bit_buffer; - mz_uint bits_in = d->m_bits_in; - -#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - - if (flags & 1) - { - mz_uint s0, s1, n0, n1, sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - // This sequence coaxes MSVC into using cmov's vs. jmp's. - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - n0 = s_tdefl_small_dist_extra[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[match_dist >> 8]; - n1 = s_tdefl_large_dist_extra[match_dist >> 8]; - sym = (match_dist < 512) ? s0 : s1; - num_extra_bits = (match_dist < 512) ? n0 : n1; - - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - } - - if (pOutput_buf >= d->m_pOutput_buf_end) - return MZ_FALSE; - - *(mz_uint64*)pOutput_buf = bit_buffer; - pOutput_buf += (bits_in >> 3); - bit_buffer >>= (bits_in & ~7); - bits_in &= 7; - } - -#undef TDEFL_PUT_BITS_FAST - - d->m_pOutput_buf = pOutput_buf; - d->m_bits_in = 0; - d->m_bit_buffer = 0; - - while (bits_in) - { - mz_uint32 n = MZ_MIN(bits_in, 16); - TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); - bit_buffer >>= n; - bits_in -= n; - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#else -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - if (flags & 1) - { - mz_uint sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - if (match_dist < 512) - { - sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; - } - else - { - sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; - } - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS - -static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) -{ - if (static_block) - tdefl_start_static_block(d); - else - tdefl_start_dynamic_block(d); - return tdefl_compress_lz_codes(d); -} - -static int tdefl_flush_block(tdefl_compressor *d, int flush) -{ - mz_uint saved_bit_buf, saved_bits_in; - mz_uint8 *pSaved_output_buf; - mz_bool comp_block_succeeded = MZ_FALSE; - int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; - mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; - - d->m_pOutput_buf = pOutput_buf_start; - d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - - MZ_ASSERT(!d->m_output_flush_remaining); - d->m_output_flush_ofs = 0; - d->m_output_flush_remaining = 0; - - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); - d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) - { - TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); - } - - TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - - pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; - - if (!use_raw_block) - comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); - - // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. - if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && - ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) - { - mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) - { - TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); - } - for (i = 0; i < d->m_total_lz_bytes; ++i) - { - TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); - } - } - // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. - else if (!comp_block_succeeded) - { - d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - tdefl_compress_block(d, MZ_TRUE); - } - - if (flush) - { - if (flush == TDEFL_FINISH) - { - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } - } - else - { - mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } - } - } - - MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); - - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; - - if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) - { - if (d->m_pPut_buf_func) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) - return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); - } - else if (pOutput_buf_start == d->m_output_buf) - { - int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); - d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) - { - d->m_output_flush_ofs = bytes_to_copy; - d->m_output_flush_remaining = n; - } - } - else - { - d->m_out_buf_ofs += n; - } - } - - return d->m_output_flush_remaining; -} - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES -#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; - mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - if (!probe_len) - { - *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; - } - else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; - c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); - } - } -} -#else -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint8 *s = d->m_dict + pos, *p, *q; - mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; - if (probe_len > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; - c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; - } - } -} -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -static mz_bool tdefl_compress_fast(tdefl_compressor *d) -{ - // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. - mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; - mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; - mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) - { - const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; - mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); - d->m_src_buf_left -= num_bytes_to_process; - lookahead_size += num_bytes_to_process; - - while (num_bytes_to_process) - { - mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); - memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); - d->m_pSrc += n; - dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; - num_bytes_to_process -= n; - } - - dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); - if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; - - while (lookahead_size >= 4) - { - mz_uint cur_match_dist, cur_match_len = 1; - mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; - mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; - mz_uint probe_pos = d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16)lookahead_pos; - - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) - { - const mz_uint16 *p = (const mz_uint16 *)pCur_dict; - const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); - mz_uint32 probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); - if (!probe_len) - cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) - { - cur_match_len = 1; - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - else - { - mz_uint32 s0, s1; - cur_match_len = MZ_MIN(cur_match_len, lookahead_size); - - MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); - - cur_match_dist--; - - pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); - *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; - pLZ_code_buf += 3; - *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); - - s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; - s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; - d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; - - d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; - } - } - else - { - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - total_lz_bytes += cur_match_len; - lookahead_pos += cur_match_len; - dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; - MZ_ASSERT(lookahead_size >= cur_match_len); - lookahead_size -= cur_match_len; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - - while (lookahead_size) - { - mz_uint8 lit = d->m_dict[cur_pos]; - - total_lz_bytes++; - *pLZ_code_buf++ = lit; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - d->m_huff_count[0][lit]++; - - lookahead_pos++; - dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - lookahead_size--; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - } - - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - return MZ_TRUE; -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - -static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) -{ - d->m_total_lz_bytes++; - *d->m_pLZ_code_buf++ = lit; - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - d->m_huff_count[0][lit]++; -} - -static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) -{ - mz_uint32 s0, s1; - - MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); - - d->m_total_lz_bytes += match_len; - - d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); - - match_dist -= 1; - d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); - d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; - - *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - - s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; - d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - - if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; -} - -static mz_bool tdefl_compress_normal(tdefl_compressor *d) -{ - const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; - tdefl_flush flush = d->m_flush; - - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) - { - mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; - // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. - if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) - { - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; - mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); - const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; - src_buf_left -= num_bytes_to_process; - d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) - { - mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; - } - } - else - { - while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - { - mz_uint8 c = *pSrc++; - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - src_buf_left--; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) - { - mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; - mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - } - } - } - d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - break; - - // Simple lazy/greedy parsing state machine. - len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) - { - if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) - { - mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; - cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; - } - } - else - { - tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); - } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) - { - cur_match_dist = cur_match_len = 0; - } - if (d->m_saved_match_len) - { - if (cur_match_len > d->m_saved_match_len) - { - tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); - if (cur_match_len >= 128) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - d->m_saved_match_len = 0; len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - } - else - { - tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); - len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; - } - } - else if (!cur_match_dist) - tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - // Move the lookahead forward by len_to_move bytes. - d->m_lookahead_pos += len_to_move; - MZ_ASSERT(d->m_lookahead_size >= len_to_move); - d->m_lookahead_size -= len_to_move; - d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); - // Check if it's time to flush the current LZ codes to the internal output buffer. - if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || - ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) - { - int n; - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - } - } - - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - return MZ_TRUE; -} - -static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) -{ - if (d->m_pIn_buf_size) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - } - - if (d->m_pOut_buf_size) - { - size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); - d->m_output_flush_ofs += (mz_uint)n; - d->m_output_flush_remaining -= (mz_uint)n; - d->m_out_buf_ofs += n; - - *d->m_pOut_buf_size = d->m_out_buf_ofs; - } - - return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) -{ - if (!d) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return TDEFL_STATUS_BAD_PARAM; - } - - d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; - d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; - d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; - d->m_out_buf_ofs = 0; - d->m_flush = flush; - - if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || - (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); - } - d->m_wants_to_finish |= (flush == TDEFL_FINISH); - - if ((d->m_output_flush_remaining) || (d->m_finished)) - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && - ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && - ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) - { - if (!tdefl_compress_fast(d)) - return d->m_prev_return_status; - } - else -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - { - if (!tdefl_compress_normal(d)) - return d->m_prev_return_status; - } - - if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) - d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); - - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) - { - if (tdefl_flush_block(d, flush) < 0) - return d->m_prev_return_status; - d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } - } - - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); -} - -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) -{ - MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); -} - -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; - d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; - d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); - d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; - d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; - d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; - d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; - d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; - d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; - d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - return TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) -{ - return d->m_prev_return_status; -} - -mz_uint32 tdefl_get_adler32(tdefl_compressor *d) -{ - return d->m_adler32; -} - -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; - pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; - succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); - succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); - MZ_FREE(pComp); return succeeded; -} - -struct tdefl_output_buffer -{ - size_t m_size, m_capacity; - mz_uint8 *m_pBuf; - mz_bool m_expandable; -}; - -static mz_bool tdefl_output_buffer_putter(const void *pBuf, size_t len, void *pUser) -{ - tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; - size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) - { - size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; - do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); - pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; - p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; - } - memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; - return MZ_TRUE; -} - -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; - out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; - *pOut_len = out_buf.m_size; return out_buf.m_pBuf; -} - -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) return 0; - out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; - return out_buf.m_size; -} - -#ifndef MINIZ_NO_ZLIB_APIS -static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; - -// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). -mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) -{ - mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; - - if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; - else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; - - return comp_flags; -} -#endif //MINIZ_NO_ZLIB_APIS - -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) -#endif - -// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at -// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) -{ - tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; - if (!pComp) return NULL; - MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } - // write dummy header - for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); - // compress image data - tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, TDEFL_DEFAULT_MAX_PROBES | TDEFL_WRITE_ZLIB_HEADER); - for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + y * bpl, bpl, TDEFL_NO_FLUSH); } - if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - // write real header - *pLen_out = out_buf.m_size-41; - { - mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, - 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8, (mz_uint8)"\0\0\04\02\06"[num_chans],0,0,0,0,0,0,0, - (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; - c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); - memcpy(out_buf.m_pBuf, pnghdr, 41); - } - // write footer (IDAT CRC-32, followed by IEND chunk) - if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); - // compute final size of file, grab compressed data buffer and return - *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; -} - -#ifdef _MSC_VER -#pragma warning (pop) -#endif - -// ------------------- .ZIP archive reading - -#ifndef MINIZ_NO_ARCHIVE_APIS - -#ifdef MINIZ_NO_STDIO - #define MZ_FILE void * -#else - #include - #include - - #if defined(_MSC_VER) - static FILE *mz_fopen(const char *pFilename, const char *pMode) - { - FILE* pFile = NULL; - fopen_s(&pFile, pFilename, pMode); - return pFile; - } - static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) - { - FILE* pFile = NULL; - if (freopen_s(&pFile, pPath, pMode, pStream)) - return NULL; - return pFile; - } - #else - static FILE *mz_fopen(const char *pFilename, const char *pMode) - { - return fopen(pFilename, pMode); - } - static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) - { - return freopen(pPath, pMode, pStream); - } - #endif // #if defined(_MSC_VER) - - #if defined(_MSC_VER) || defined(__MINGW64__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 _ftelli64 - #define MZ_FSEEK64 _fseeki64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #elif defined(__MINGW32__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello64 - #define MZ_FSEEK64 fseeko64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #elif defined(__TINYC__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftell - #define MZ_FSEEK64 fseek - #define MZ_FILE_STAT_STRUCT stat - #define MZ_FILE_STAT stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #else - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello - #define MZ_FSEEK64 fseeko - #define MZ_FILE_STAT_STRUCT stat - #define MZ_FILE_STAT stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #endif // #ifdef _MSC_VER -#endif // #ifdef MINIZ_NO_STDIO - -#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) - -// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. -enum -{ - // ZIP archive identifiers and record sizes - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, - // Central directory header record offsets - MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, - MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, - MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, - MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, - // Local directory header offsets - MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, - MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, - MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, - // End of central directory offsets - MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, - MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, -}; - -typedef struct -{ - void *m_p; - size_t m_size, m_capacity; - mz_uint m_element_size; -} mz_zip_array; - -struct mz_zip_internal_state_tag -{ - mz_zip_array m_central_dir; - mz_zip_array m_central_dir_offsets; - mz_zip_array m_sorted_central_dir_offsets; - MZ_FILE *m_pFile; - void *m_pMem; - size_t m_mem_size; - size_t m_mem_capacity; -}; - -#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size -#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] - -static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) -{ - pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); - memset(pArray, 0, sizeof(mz_zip_array)); -} - -static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) -{ - void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; - if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } - if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; - pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) -{ - if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) -{ - if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } - pArray->m_size = new_size; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) -{ - return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) -{ - size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; - memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); - return MZ_TRUE; -} - -#ifndef MINIZ_NO_TIME -static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) -{ - struct tm tm; - memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; - tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; - tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; - return mktime(&tm); -} - -static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) -{ -#ifdef _MSC_VER - struct tm tm_struct; - struct tm *tm = &tm_struct; - errno_t err = localtime_s(tm, &time); - if (err) - { - *pDOS_date = 0; *pDOS_time = 0; - return; - } -#else - struct tm *tm = localtime(&time); -#endif - *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); - *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); -} -#endif - -#ifndef MINIZ_NO_STDIO -static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) -{ -#ifdef MINIZ_NO_TIME - (void)pFilename; *pDOS_date = *pDOS_time = 0; -#else - struct MZ_FILE_STAT_STRUCT file_stat; if (MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE; - mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); -#endif // #ifdef MINIZ_NO_TIME - return MZ_TRUE; -} - -static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) -{ -#ifndef MINIZ_NO_TIME - struct utimbuf t; t.actime = access_time; t.modtime = modified_time; - return !utime(pFilename, &t); -#else - (void)pFilename, (void)access_time, (void)modified_time; - return MZ_TRUE; -#endif // #ifndef MINIZ_NO_TIME -} -#endif - -static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) -{ - (void)flags; - if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; - - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - - pZip->m_zip_mode = MZ_ZIP_MODE_READING; - pZip->m_archive_size = 0; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) -{ - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (l_len < r_len) : (l < r); -} - -#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END - -// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) -static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - int start = (size - 2) >> 1, end; - while (start >= 0) - { - int child, root = start; - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= size) - break; - child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - start--; - } - - end = size - 1; - while (end > 0) - { - int child, root = 0; - MZ_SWAP_UINT32(pIndices[end], pIndices[0]); - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= end) - break; - child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - end--; - } -} - -static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) -{ - mz_uint cdir_size, num_this_disk, cdir_disk_index; - mz_uint64 cdir_ofs; - mz_int64 cur_file_ofs; - const mz_uint8 *p; - mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; - // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - // Find the end of central directory record by scanning the file from the end towards the beginning. - cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); - for ( ; ; ) - { - int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) - return MZ_FALSE; - for (i = n - 4; i >= 0; --i) - if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) - break; - if (i >= 0) - { - cur_file_ofs += i; - break; - } - if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) - return MZ_FALSE; - cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); - } - // Read and verify the end of central directory record. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || - ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) - return MZ_FALSE; - - num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); - cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); - if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) - return MZ_FALSE; - - if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - - cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); - if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) - return MZ_FALSE; - - pZip->m_central_directory_file_ofs = cdir_ofs; - - if (pZip->m_total_files) - { - mz_uint i, n; - // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. - if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || - (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) || - (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) - return MZ_FALSE; - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) - return MZ_FALSE; - - // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). - p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; - for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) - { - mz_uint total_header_size, comp_size, decomp_size, disk_index; - if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) - return MZ_FALSE; - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) - return MZ_FALSE; - disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index != num_this_disk) && (disk_index != 1)) - return MZ_FALSE; - if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) - return MZ_FALSE; - if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) - return MZ_FALSE; - n -= total_header_size; p += total_header_size; - } - } - - if ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) - mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); - - return MZ_TRUE; -} - -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) -{ - if ((!pZip) || (!pZip->m_pRead)) - return MZ_FALSE; - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} - -static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); - memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); - return s; -} - -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) -{ - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - pZip->m_pRead = mz_zip_mem_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pMem = (void *)pMem; - pZip->m_pState->m_mem_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) -{ - mz_uint64 file_size; - MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); - if (!pFile) - return MZ_FALSE; - if (MZ_FSEEK64(pFile, 0, SEEK_END)) - return MZ_FALSE; - file_size = MZ_FTELL64(pFile); - if (!mz_zip_reader_init_internal(pZip, flags)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - pZip->m_pRead = mz_zip_file_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pFile = pFile; - pZip->m_archive_size = file_size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) -{ - return pZip ? pZip->m_total_files : 0; -} - -static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) -{ - if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return NULL; - return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); -} - -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) -{ - mz_uint m_bit_flag; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - return (m_bit_flag & 1); -} - -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) -{ - mz_uint filename_len, internal_attr, external_attr; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - - internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); - external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - if ((!internal_attr) && ((external_attr & 0x10) != 0)) - return MZ_TRUE; - - filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_len) - { - if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') - return MZ_TRUE; - } - - return MZ_FALSE; -} - -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) -{ - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if ((!p) || (!pStat)) - return MZ_FALSE; - - // Unpack the central directory record. - pStat->m_file_index = file_index; - pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); - pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); - pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); - pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); -#ifndef MINIZ_NO_TIME - pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); -#endif - pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); - pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); - pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - - // Copy as much of the filename and comment as possible. - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); - memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; - - n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); - pStat->m_comment_size = n; - memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; - - return MZ_TRUE; -} - -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) -{ - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_buf_size) - { - n = MZ_MIN(n, filename_buf_size - 1); - memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); - pFilename[n] = '\0'; - } - return n + 1; -} - -static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) -{ - mz_uint i; - if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) - return 0 == memcmp(pA, pB, len); - for (i = 0; i < len; ++i) - if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) - return MZ_FALSE; - return MZ_TRUE; -} - -static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) -{ - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (int)(l_len - r_len) : (l - r); -} - -static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) -{ - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - const mz_uint filename_len = (mz_uint)strlen(pFilename); - int l = 0, h = size - 1; - while (l <= h) - { - int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); - if (!comp) - return file_index; - else if (comp < 0) - l = m + 1; - else - h = m - 1; - } - return -1; -} - -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) -{ - mz_uint file_index; size_t name_len, comment_len; - if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return -1; - if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_p)) - return mz_zip_reader_locate_file_binary_search(pZip, pName); - name_len = strlen(pName); if (name_len > 0xFFFF) return -1; - comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; - for (file_index = 0; file_index < pZip->m_total_files; file_index++) - { - const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); - mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); - const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - if (filename_len < name_len) - continue; - if (comment_len) - { - mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); - const char *pFile_comment = pFilename + filename_len + file_extra_len; - if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) - continue; - } - if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) - { - int ofs = filename_len - 1; - do - { - if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) - break; - } while (--ofs >= 0); - ofs++; - pFilename += ofs; filename_len -= ofs; - } - if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) - return file_index; - } - return -1; -} - -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) -{ - int status = TINFL_STATUS_DONE; - mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; - mz_zip_archive_file_stat file_stat; - void *pRead_buf; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - tinfl_decompressor inflator; - - if ((buf_size) && (!pBuf)) - return MZ_FALSE; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - if (!file_stat.m_comp_size) - return MZ_TRUE; - - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; - - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; - - // Ensure supplied output buffer is large enough. - needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; - if (buf_size < needed_size) - return MZ_FALSE; - - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) - return MZ_FALSE; - return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); - } - - // Decompress the file either directly from memory or from a file input buffer. - tinfl_init(&inflator); - - if (pZip->m_pState->m_pMem) - { - // Read directly from the archive in memory. - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else if (pUser_read_buf) - { - // Use a user provided read buffer. - if (!user_read_buf_size) - return MZ_FALSE; - pRead_buf = (mz_uint8 *)pUser_read_buf; - read_buf_size = user_read_buf_size; - read_buf_avail = 0; - comp_remaining = file_stat.m_uncomp_size; - } - else - { - // Temporarily allocate a read buffer. - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) -#endif - return MZ_FALSE; - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - do - { - size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - out_buf_ofs += out_buf_size; - } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); - - if (status == TINFL_STATUS_DONE) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } - - if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); -} - -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) -{ - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); -} - -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) -{ - return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); -} - -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) -{ - mz_uint64 comp_size, uncomp_size, alloc_size; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - void *pBuf; - - if (pSize) - *pSize = 0; - if (!p) - return NULL; - - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - - alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) -#endif - return NULL; - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) - return NULL; - - if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return NULL; - } - - if (pSize) *pSize = (size_t)alloc_size; - return pBuf; -} - -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - { - if (pSize) *pSize = 0; - return MZ_FALSE; - } - return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); -} - -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) -{ - int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; - mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; - mz_zip_archive_file_stat file_stat; - void *pRead_buf = NULL; void *pWrite_buf = NULL; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - if (!file_stat.m_comp_size) - return MZ_TRUE; - - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; - - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; - - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; - - // Decompress the file either directly from memory or from a file input buffer. - if (pZip->m_pState->m_pMem) - { - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pState->m_pMem) - { -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) -#endif - return MZ_FALSE; - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) - status = TINFL_STATUS_FAILED; - else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); - cur_file_ofs += file_stat.m_comp_size; - out_buf_ofs += file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - while (comp_remaining) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - - if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); - - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - out_buf_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - } - } - } - else - { - tinfl_decompressor inflator; - tinfl_init(&inflator); - - if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) - status = TINFL_STATUS_FAILED; - else - { - do - { - mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - - if (out_buf_size) - { - if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) - { - status = TINFL_STATUS_FAILED; - break; - } - file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); - if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) - { - status = TINFL_STATUS_FAILED; - break; - } - } - } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); - } - } - - if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } - - if (!pZip->m_pState->m_pMem) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - if (pWrite_buf) - pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) -{ - (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); -} - -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) -{ - mz_bool status; - mz_zip_archive_file_stat file_stat; - MZ_FILE *pFile; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - pFile = MZ_FOPEN(pDst_filename, "wb"); - if (!pFile) - return MZ_FALSE; - status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); - if (MZ_FCLOSE(pFile) == EOF) - return MZ_FALSE; -#ifndef MINIZ_NO_TIME - if (status) - mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); -#endif - return status; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_reader_end(mz_zip_archive *pZip) -{ - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - - if (pZip->m_pState) - { - mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -#ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } -#endif // #ifndef MINIZ_NO_STDIO - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - } - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); -} -#endif - -// ------------------- .ZIP archive writing - -#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } -static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } -#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) -#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) - -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) -{ - if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; - - if (pZip->m_file_offset_alignment) - { - // Ensure user specified file offset alignment is a power of 2. - if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) - return MZ_FALSE; - } - - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_archive_size = existing_size; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; -} - -static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); -#ifdef _MSC_VER - if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) -#else - if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) -#endif - return 0; - if (new_size > pState->m_mem_capacity) - { - void *pNew_block; - size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; - if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) - return 0; - pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; - } - memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); - pState->m_mem_size = (size_t)new_size; - return n; -} - -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) -{ - pZip->m_pWrite = mz_zip_heap_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) - { - if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_mem_capacity = initial_allocation_size; - } - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) -{ - MZ_FILE *pFile; - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_pFile = pFile; - if (size_to_reserve_at_beginning) - { - mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); - do - { - size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - cur_ofs += n; size_to_reserve_at_beginning -= n; - } while (size_to_reserve_at_beginning); - } - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) -{ - mz_zip_internal_state *pState; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - // No sense in trying to write to an archive that's already at the support max size - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - pState = pZip->m_pState; - - if (pState->m_pFile) - { -#ifdef MINIZ_NO_STDIO - pFilename; return MZ_FALSE; -#else - // Archive is being read from stdio - try to reopen as writable. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - if (!pFilename) - return MZ_FALSE; - pZip->m_pWrite = mz_zip_file_write_func; - if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) - { - // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. - mz_zip_reader_end(pZip); - return MZ_FALSE; - } -#endif // #ifdef MINIZ_NO_STDIO - } - else if (pState->m_pMem) - { - // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - pState->m_mem_capacity = pState->m_mem_size; - pZip->m_pWrite = mz_zip_heap_write_func; - } - // Archive is being read via a user provided read function - make sure the user has specified a write function too. - else if (!pZip->m_pWrite) - return MZ_FALSE; - - // Start writing new files at the archive's current central directory location. - pZip->m_archive_size = pZip->m_central_directory_file_ofs; - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_central_directory_file_ofs = 0; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) -{ - return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); -} - -typedef struct -{ - mz_zip_archive *m_pZip; - mz_uint64 m_cur_archive_file_ofs; - mz_uint64 m_comp_size; -} mz_zip_writer_add_state; - -static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) -{ - mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; - if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) - return MZ_FALSE; - pState->m_cur_archive_file_ofs += len; - pState->m_comp_size += len; - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) -{ - (void)pZip; - memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) -{ - (void)pZip; - memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) -{ - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; - size_t orig_central_dir_size = pState->m_central_dir.m_size; - mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - - // No zip64 support yet - if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) - return MZ_FALSE; - - if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) - { - // Try to push the central directory array back into its original state. - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) -{ - // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. - if (*pArchive_name == '/') - return MZ_FALSE; - while (*pArchive_name) - { - if ((*pArchive_name == '\\') || (*pArchive_name == ':')) - return MZ_FALSE; - pArchive_name++; - } - return MZ_TRUE; -} - -static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) -{ - mz_uint32 n; - if (!pZip->m_file_offset_alignment) - return 0; - n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); - return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); -} - -static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) -{ - char buf[4096]; - memset(buf, 0, MZ_MIN(sizeof(buf), n)); - while (n) - { - mz_uint32 s = MZ_MIN(sizeof(buf), n); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) - return MZ_FALSE; - cur_file_ofs += s; n -= s; - } - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) -{ - mz_uint16 method = 0, dos_time = 0, dos_date = 0; - mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - tdefl_compressor *pComp = NULL; - mz_bool store_data_uncompressed; - mz_zip_internal_state *pState; - - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - - pState = pZip->m_pState; - - if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) - return MZ_FALSE; - // No zip64 support yet - if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - -#ifndef MINIZ_NO_TIME - { - time_t cur_time; time(&cur_time); - mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); - } -#endif // #ifndef MINIZ_NO_TIME - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) - { - // Set DOS Subdirectory attribute bit. - ext_attributes |= 0x10; - // Subdirectories cannot contain data. - if ((buf_size) || (uncomp_size)) - return MZ_FALSE; - } - - // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) - if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) - return MZ_FALSE; - - if ((!store_data_uncompressed) && (buf_size)) - { - if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) - return MZ_FALSE; - } - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; - - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - { - uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); - uncomp_size = buf_size; - if (uncomp_size <= 3) - { - level = 0; - store_data_uncompressed = MZ_TRUE; - } - } - - if (store_data_uncompressed) - { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - - cur_archive_file_ofs += buf_size; - comp_size = buf_size; - - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - method = MZ_DEFLATED; - } - else if (buf_size) - { - mz_zip_writer_add_state state; - - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; - - if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || - (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - - method = MZ_DEFLATED; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pComp = NULL; - - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; - - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) -{ - mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; - mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - MZ_FILE *pSrc_file = NULL; - - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) - return MZ_FALSE; - - pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); - if (!pSrc_file) - return MZ_FALSE; - MZ_FSEEK64(pSrc_file, 0, SEEK_END); - uncomp_size = MZ_FTELL64(pSrc_file); - MZ_FSEEK64(pSrc_file, 0, SEEK_SET); - - if (uncomp_size > 0xFFFFFFFF) - { - // No zip64 support yet - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - if (uncomp_size <= 3) - level = 0; - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - return MZ_FALSE; - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; - - if (uncomp_size) - { - mz_uint64 uncomp_remaining = uncomp_size; - void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); - if (!pRead_buf) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - if (!level) - { - while (uncomp_remaining) - { - mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); - uncomp_remaining -= n; - cur_archive_file_ofs += n; - } - comp_size = uncomp_size; - } - else - { - mz_bool result = MZ_FALSE; - mz_zip_writer_add_state state; - tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; - - if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - for ( ; ; ) - { - size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); - tdefl_status status; - - if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) - break; - - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); - uncomp_remaining -= in_buf_size; - - status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); - if (status == TDEFL_STATUS_DONE) - { - result = MZ_TRUE; - break; - } - else if (status != TDEFL_STATUS_OKAY) - break; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - - if (!result) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - - method = MZ_DEFLATED; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - } - - MZ_FCLOSE(pSrc_file); pSrc_file = NULL; - - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; - - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) -{ - mz_uint n, bit_flags, num_alignment_padding_bytes; - mz_uint64 comp_bytes_remaining, local_dir_header_ofs; - mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - size_t orig_central_dir_size; - mz_zip_internal_state *pState; - void *pBuf; const mz_uint8 *pSrc_central_header; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) - return MZ_FALSE; - pState = pZip->m_pState; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - cur_dst_file_ofs = pZip->m_archive_size; - - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) - return MZ_FALSE; - cur_dst_file_ofs += num_alignment_padding_bytes; - local_dir_header_ofs = cur_dst_file_ofs; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) - return MZ_FALSE; - - while (comp_bytes_remaining) - { - n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_src_file_ofs += n; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_dst_file_ofs += n; - - comp_bytes_remaining -= n; - } - - bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); - if (bit_flags & 8) - { - // Copy data descriptor - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - - n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - - cur_src_file_ofs += n; - cur_dst_file_ofs += n; - } - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - - // no zip64 support yet - if (cur_dst_file_ofs > 0xFFFFFFFF) - return MZ_FALSE; - - orig_central_dir_size = pState->m_central_dir.m_size; - - memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) - return MZ_FALSE; - - n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - if (pState->m_central_dir.m_size > 0xFFFFFFFF) - return MZ_FALSE; - n = (mz_uint32)pState->m_central_dir.m_size; - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - pZip->m_total_files++; - pZip->m_archive_size = cur_dst_file_ofs; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState; - mz_uint64 central_dir_ofs, central_dir_size; - mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - - pState = pZip->m_pState; - - // no zip64 support yet - if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - central_dir_ofs = 0; - central_dir_size = 0; - if (pZip->m_total_files) - { - // Write central directory - central_dir_ofs = pZip->m_archive_size; - central_dir_size = pState->m_central_dir.m_size; - pZip->m_central_directory_file_ofs = central_dir_ofs; - if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) - return MZ_FALSE; - pZip->m_archive_size += central_dir_size; - } - - // Write end of central directory record - MZ_CLEAR_OBJ(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) - return MZ_FALSE; -#ifndef MINIZ_NO_STDIO - if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) - return MZ_FALSE; -#endif // #ifndef MINIZ_NO_STDIO - - pZip->m_archive_size += sizeof(hdr); - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) -{ - if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) - return MZ_FALSE; - if (pZip->m_pWrite != mz_zip_heap_write_func) - return MZ_FALSE; - if (!mz_zip_writer_finalize_archive(pZip)) - return MZ_FALSE; - - *pBuf = pZip->m_pState->m_pMem; - *pSize = pZip->m_pState->m_mem_size; - pZip->m_pState->m_pMem = NULL; - pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_end(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState; - mz_bool status = MZ_TRUE; - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) - return MZ_FALSE; - - pState = pZip->m_pState; - pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -#ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } -#endif // #ifndef MINIZ_NO_STDIO - - if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); - pState->m_pMem = NULL; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - return status; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) -{ - mz_bool status, created_new_archive = MZ_FALSE; - mz_zip_archive zip_archive; - struct MZ_FILE_STAT_STRUCT file_stat; - MZ_CLEAR_OBJ(zip_archive); - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) - { - // Create a new archive. - if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) - return MZ_FALSE; - created_new_archive = MZ_TRUE; - } - else - { - // Append to an existing archive. - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return MZ_FALSE; - if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) - { - mz_zip_reader_end(&zip_archive); - return MZ_FALSE; - } - } - status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); - // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) - if (!mz_zip_writer_finalize_archive(&zip_archive)) - status = MZ_FALSE; - if (!mz_zip_writer_end(&zip_archive)) - status = MZ_FALSE; - if ((!status) && (created_new_archive)) - { - // It's a new archive and something went wrong, so just delete it. - int ignoredStatus = MZ_DELETE_FILE(pZip_filename); - (void)ignoredStatus; - } - return status; -} - -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) -{ - int file_index; - mz_zip_archive zip_archive; - void *p = NULL; - - if (pSize) - *pSize = 0; - - if ((!pZip_filename) || (!pArchive_name)) - return NULL; - - MZ_CLEAR_OBJ(zip_archive); - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return NULL; - - if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) - p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); - - mz_zip_reader_end(&zip_archive); - return p; -} - -#endif // #ifndef MINIZ_NO_STDIO - -#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -#endif // #ifndef MINIZ_NO_ARCHIVE_APIS - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_FILE_ONLY - -/* - This is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - - In jurisdictions that recognize copyright laws, the author or authors - of this software dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the benefit - of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - For more information, please refer to -*/ diff --git a/src/miniz_png.cpp b/src/miniz_png.cpp deleted file mode 100644 index 746cffa9d..000000000 --- a/src/miniz_png.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -// mapnik -#include -#include -#include -#include - -// miniz -#define MINIZ_NO_ARCHIVE_APIS -#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES - -#pragma GCC diagnostic push -#include -extern "C" { -#include "miniz.c" -} -#pragma GCC diagnostic pop - -// zlib -#include - -// stl -#include -#include -#include - -namespace mapnik { namespace MiniZ { - -PNGWriter::PNGWriter(int level, int strategy) -{ - buffer = nullptr; - compressor = nullptr; - - if (level == -1) - { - level = MZ_DEFAULT_LEVEL; // 6 - } - else if (level < 0 || level > 10) - { - throw std::runtime_error("compression level must be between 0 and 10"); - } - mz_uint flags = s_tdefl_num_probes[level] | TDEFL_WRITE_ZLIB_HEADER; - if (level <= 3) - { - flags |= TDEFL_GREEDY_PARSING_FLAG; - } - if (strategy == Z_FILTERED) flags |= TDEFL_FILTER_MATCHES; - else if (strategy == Z_HUFFMAN_ONLY) flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == Z_RLE) flags |= TDEFL_RLE_MATCHES; - else if (strategy == Z_FIXED) flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - - buffer = (tdefl_output_buffer *)MZ_MALLOC(sizeof(tdefl_output_buffer)); - if (buffer == nullptr) - { - throw std::bad_alloc(); - } - - buffer->m_pBuf = nullptr; - buffer->m_capacity = 8192; - buffer->m_expandable = MZ_TRUE; - buffer->m_pBuf = (mz_uint8 *)MZ_MALLOC(buffer->m_capacity); - if (buffer->m_pBuf == nullptr) - { - throw std::bad_alloc(); - } - - compressor = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); - if (compressor == nullptr) - { - throw std::bad_alloc(); - } - - // Reset output buffer. - buffer->m_size = 0; - tdefl_status tdstatus = tdefl_init(compressor, tdefl_output_buffer_putter, buffer, flags); - if (tdstatus != TDEFL_STATUS_OKAY) - { - throw std::runtime_error("tdefl_init failed"); - } - - // Write preamble. - mz_bool status = tdefl_output_buffer_putter(preamble, 8, buffer); - if (status != MZ_TRUE) - { - throw std::bad_alloc(); - } -} - -PNGWriter::~PNGWriter() -{ - if (compressor) - { - MZ_FREE(compressor); - } - if (buffer) - { - if (buffer->m_pBuf) - { - MZ_FREE(buffer->m_pBuf); - } - MZ_FREE(buffer); - } -} - -inline void PNGWriter::writeUInt32BE(mz_uint8 *target, mz_uint32 value) -{ - target[0] = (value >> 24) & 0xFF; - target[1] = (value >> 16) & 0xFF; - target[2] = (value >> 8) & 0xFF; - target[3] = value & 0xFF; -} - -size_t PNGWriter::startChunk(const mz_uint8 header[], size_t length) -{ - size_t start = buffer->m_size; - mz_bool status = tdefl_output_buffer_putter(header, length, buffer); - if (status != MZ_TRUE) - { - throw std::bad_alloc(); - } - return start; -} - -void PNGWriter::finishChunk(size_t start) -{ - // Write chunk length at the beginning of the chunk. - size_t payloadLength = buffer->m_size - start - 4 - 4; - writeUInt32BE(buffer->m_pBuf + start, static_cast(payloadLength)); - // Write CRC32 checksum. Don't include the 4-byte length, but /do/ include - // the 4-byte chunk name. - mz_uint32 crc = mz_crc32(MZ_CRC32_INIT, buffer->m_pBuf + start + 4, payloadLength + 4); - mz_uint8 checksum[] = { static_cast(crc >> 24), - static_cast(crc >> 16), - static_cast(crc >> 8), - static_cast(crc) }; - mz_bool status = tdefl_output_buffer_putter(checksum, 4, buffer); - if (status != MZ_TRUE) - { - throw std::bad_alloc(); - } -} - -void PNGWriter::writeIHDR(mz_uint32 width, mz_uint32 height, mz_uint8 pixel_depth) -{ - // Write IHDR chunk. - size_t IHDR = startChunk(IHDR_tpl, 21); - writeUInt32BE(buffer->m_pBuf + IHDR + 8, width); - writeUInt32BE(buffer->m_pBuf + IHDR + 12, height); - - if (pixel_depth == 32) - { - // Alpha full color image. - buffer->m_pBuf[IHDR + 16] = 8; // bit depth - buffer->m_pBuf[IHDR + 17] = 6; // color type (6 == true color with alpha) - } - else if (pixel_depth == 24) - { - // Full color image. - buffer->m_pBuf[IHDR + 16] = 8; // bit depth - buffer->m_pBuf[IHDR + 17] = 2; // color type (2 == true color without alpha) - } - else - { - // Paletted image. - buffer->m_pBuf[IHDR + 16] = pixel_depth; // bit depth - buffer->m_pBuf[IHDR + 17] = 3; // color type (3 == indexed color) - } - - buffer->m_pBuf[IHDR + 18] = 0; // compression method - buffer->m_pBuf[IHDR + 19] = 0; // filter method - buffer->m_pBuf[IHDR + 20] = 0; // interlace method - finishChunk(IHDR); -} - -void PNGWriter::writePLTE(std::vector const& palette) -{ - // Write PLTE chunk. - size_t PLTE = startChunk(PLTE_tpl, 8); - const mz_uint8 *colors = reinterpret_cast(&palette[0]); - mz_bool status = tdefl_output_buffer_putter(colors, palette.size() * 3, buffer); - if (status != MZ_TRUE) - { - throw std::bad_alloc(); - } - finishChunk(PLTE); -} - -void PNGWriter::writetRNS(std::vector const& alpha) -{ - if (alpha.size() == 0) - { - return; - } - - std::vector transparency(alpha.size()); - unsigned char transparencySize = 0; // Stores position of biggest to nonopaque value. - for(unsigned i = 0; i < alpha.size(); i++) - { - transparency[i] = alpha[i]; - if (alpha[i] < 255) - { - transparencySize = i + 1; - } - } - if (transparencySize > 0) - { - // Write tRNS chunk. - size_t tRNS = startChunk(tRNS_tpl, 8); - mz_bool status = tdefl_output_buffer_putter(&transparency[0], transparencySize, buffer); - if (status != MZ_TRUE) - { - throw std::bad_alloc(); - } - finishChunk(tRNS); - } -} - -template -void PNGWriter::writeIDAT(T const& image) -{ - // Write IDAT chunk. - size_t IDAT = startChunk(IDAT_tpl, 8); - mz_uint8 filter_type = 0; - tdefl_status status; - - int bytes_per_pixel = sizeof(typename T::pixel_type); - int stride = image.width() * bytes_per_pixel; - - for (unsigned int y = 0; y < image.height(); y++) - { - // Write filter_type - status = tdefl_compress_buffer(compressor, &filter_type, 1, TDEFL_NO_FLUSH); - if (status != TDEFL_STATUS_OKAY) - { - throw std::runtime_error("failed to compress image"); - } - - // Write scanline - status = tdefl_compress_buffer(compressor, (mz_uint8 *)image.get_row(y), stride, TDEFL_NO_FLUSH); - if (status != TDEFL_STATUS_OKAY) - { - throw std::runtime_error("failed to compress image"); - } - } - - status = tdefl_compress_buffer(compressor, nullptr, 0, TDEFL_FINISH); - if (status != TDEFL_STATUS_DONE) - { - throw std::runtime_error("failed to compress image"); - } - - finishChunk(IDAT); -} - -template -void PNGWriter::writeIDATStripAlpha(T const& image) { - // Write IDAT chunk. - size_t IDAT = startChunk(IDAT_tpl, 8); - mz_uint8 filter_type = 0; - tdefl_status status; - - size_t stride = image.width() * 3; - size_t i, j; - mz_uint8 *scanline = (mz_uint8 *)MZ_MALLOC(stride); - - for (unsigned int y = 0; y < image.height(); y++) { - // Write filter_type - status = tdefl_compress_buffer(compressor, &filter_type, 1, TDEFL_NO_FLUSH); - if (status != TDEFL_STATUS_OKAY) - { - MZ_FREE(scanline); - throw std::runtime_error("failed to compress image"); - } - - // Strip alpha bytes from scanline - mz_uint8 *row = (mz_uint8 *)image.get_row(y); - for (i = 0, j = 0; j < stride; i += 4, j += 3) { - scanline[j] = row[i]; - scanline[j+1] = row[i+1]; - scanline[j+2] = row[i+2]; - } - - // Write scanline - status = tdefl_compress_buffer(compressor, scanline, stride, TDEFL_NO_FLUSH); - if (status != TDEFL_STATUS_OKAY) { - MZ_FREE(scanline); - throw std::runtime_error("failed to compress image"); - } - } - - MZ_FREE(scanline); - - status = tdefl_compress_buffer(compressor, nullptr, 0, TDEFL_FINISH); - if (status != TDEFL_STATUS_DONE) throw std::runtime_error("failed to compress image"); - - finishChunk(IDAT); -} - -void PNGWriter::writeIEND() -{ - // Write IEND chunk. - size_t IEND = startChunk(IEND_tpl, 8); - finishChunk(IEND); -} - -void PNGWriter::toStream(std::ostream& stream) -{ - stream.write((char *)buffer->m_pBuf, buffer->m_size); -} - -const mz_uint8 PNGWriter::preamble[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a -}; - -const mz_uint8 PNGWriter::IHDR_tpl[] = { - 0x00, 0x00, 0x00, 0x0D, // chunk length - 'I', 'H', 'D', 'R', // "IHDR" - 0x00, 0x00, 0x00, 0x00, // image width (4 bytes) - 0x00, 0x00, 0x00, 0x00, // image height (4 bytes) - 0x00, // bit depth (1 byte) - 0x00, // color type (1 byte) - 0x00, // compression method (1 byte), has to be 0 - 0x00, // filter method (1 byte) - 0x00 // interlace method (1 byte) -}; - -const mz_uint8 PNGWriter::PLTE_tpl[] = { - 0x00, 0x00, 0x00, 0x00, // chunk length - 'P', 'L', 'T', 'E' // "IDAT" -}; - -const mz_uint8 PNGWriter::tRNS_tpl[] = { - 0x00, 0x00, 0x00, 0x00, // chunk length - 't', 'R', 'N', 'S' // "IDAT" -}; - -const mz_uint8 PNGWriter::IDAT_tpl[] = { - 0x00, 0x00, 0x00, 0x00, // chunk length - 'I', 'D', 'A', 'T' // "IDAT" -}; - -const mz_uint8 PNGWriter::IEND_tpl[] = { - 0x00, 0x00, 0x00, 0x00, // chunk length - 'I', 'E', 'N', 'D' // "IEND" -}; - -template void PNGWriter::writeIDAT(image_gray8 const& image); -template void PNGWriter::writeIDAT(image_view_gray8 const& image); -template void PNGWriter::writeIDAT(image_rgba8 const& image); -template void PNGWriter::writeIDAT(image_view_rgba8 const& image); -template void PNGWriter::writeIDATStripAlpha(image_rgba8 const& image); -template void PNGWriter::writeIDATStripAlpha(image_view_rgba8 const& image); - -}} diff --git a/src/palette.cpp b/src/palette.cpp index 54e4346b5..1fc5b8b21 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -37,8 +37,8 @@ rgb::rgb(rgba const& c) // ordering by mean(a,r,g,b), a, r, g, b bool rgba::mean_sort_cmp::operator() (const rgba& x, const rgba& y) const { - int t1 = (int)x.a + x.r + x.g + x.b; - int t2 = (int)y.a + y.r + y.g + y.b; + int t1 = x.a + x.r + x.g + x.b; + int t2 = y.a + y.r + y.g + y.b; if (t1 != t2) return t1 < t2; // https://github.com/mapnik/mapnik/issues/1087 @@ -65,16 +65,6 @@ rgba_palette::rgba_palette() #endif } -const std::vector& rgba_palette::palette() const -{ - return rgb_pal_; -} - -const std::vector& rgba_palette::alphaTable() const -{ - return alpha_pal_; -} - bool rgba_palette::valid() const { return colors_ > 0; @@ -97,9 +87,9 @@ std::string rgba_palette::to_string() const str << std::hex << std::setfill('0'); for (unsigned i = 0; i < length; i++) { str << " #"; - str << std::setw(2) << (unsigned)rgb_pal_[i].r; - str << std::setw(2) << (unsigned)rgb_pal_[i].g; - str << std::setw(2) << (unsigned)rgb_pal_[i].b; + str << std::setw(2) << static_cast(rgb_pal_[i].r); + str << std::setw(2) << static_cast(rgb_pal_[i].g); + str << std::setw(2) << static_cast(rgb_pal_[i].b); if (i < alphaLength) str << std::setw(2) << alpha_pal_[i]; } str << "]"; diff --git a/src/plugin.cpp b/src/plugin.cpp index 7b057284e..b2186304d 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -58,16 +58,24 @@ PluginInfo::PluginInfo(std::string const& filename, if (module_) module_->dl = LoadLibraryA(filename.c_str()); if (module_ && module_->dl) { - name_func name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); + callable_returning_string name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); if (name) name_ = name(); + callable_returning_void init_once = reinterpret_cast(dlsym(module_->dl, "on_plugin_load")); + if (init_once) { + init_once(); + } } #else #ifdef MAPNIK_HAS_DLCFN if (module_) module_->dl = dlopen(filename.c_str(),RTLD_LAZY); if (module_ && module_->dl) { - name_func name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); + callable_returning_string name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); if (name) name_ = name(); + callable_returning_void init_once = reinterpret_cast(dlsym(module_->dl, "on_plugin_load")); + if (init_once) { + init_once(); + } } #else throw std::runtime_error("no support for loading dynamic objects (Mapnik not compiled with -DMAPNIK_HAS_DLCFN)"); @@ -93,7 +101,9 @@ PluginInfo::~PluginInfo() */ if (module_->dl && name_ != "gdal" && name_ != "ogr") { +#ifndef MAPNIK_NO_DLCLOSE dlclose(module_->dl),module_->dl=0; +#endif } #endif delete module_; @@ -106,7 +116,7 @@ void * PluginInfo::get_symbol(std::string const& sym_name) const #ifdef MAPNIK_SUPPORTS_DLOPEN return static_cast(dlsym(module_->dl, sym_name.c_str())); #else - return NULL; + return nullptr; #endif } diff --git a/src/png_reader.cpp b/src/png_reader.cpp index 30b470fd6..8c58b2238 100644 --- a/src/png_reader.cpp +++ b/src/png_reader.cpp @@ -23,22 +23,17 @@ // mapnik #include #include +#include extern "C" { #include } -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - // stl #include #include +#include namespace mapnik { @@ -47,7 +42,7 @@ template class png_reader : public image_reader { using source_type = T; - using input_stream = boost::iostreams::stream; + using input_stream = std::istream; struct png_struct_guard { @@ -73,7 +68,7 @@ private: int color_type_; bool has_alpha_; public: - explicit png_reader(std::string const& file_name); + explicit png_reader(std::string const& filename); png_reader(char const* data, std::size_t size); ~png_reader(); unsigned width() const final; @@ -90,14 +85,14 @@ private: namespace { -image_reader* create_png_reader(std::string const& file) +image_reader* create_png_reader(std::string const& filename) { - return new png_reader(file); + return new png_reader(filename); } image_reader* create_png_reader2(char const * data, std::size_t size) { - return new png_reader(data, size); + return new png_reader(data, size); } const bool registered = register_image_reader("png",create_png_reader); @@ -128,31 +123,30 @@ void png_reader::png_read_data(png_structp png_ptr, png_bytep data, png_size_ } template -png_reader::png_reader(std::string const& file_name) - : source_(file_name,std::ios_base::in | std::ios_base::binary), - stream_(source_), +png_reader::png_reader(std::string const& filename) + : source_(), + stream_(&source_), width_(0), height_(0), bit_depth_(0), color_type_(0), has_alpha_(false) { - if (!source_.is_open()) throw image_reader_exception("PNG reader: cannot open file '"+ file_name + "'"); - if (!stream_) throw image_reader_exception("PNG reader: cannot open file '"+ file_name + "'"); + source_.open(filename, std::ios_base::in | std::ios_base::binary); + if (!source_.is_open()) throw image_reader_exception("PNG reader: cannot open file '"+ filename + "'"); init(); } template png_reader::png_reader(char const* data, std::size_t size) : source_(data,size), - stream_(source_), + stream_(&source_), width_(0), height_(0), bit_depth_(0), color_type_(0), has_alpha_(false) { - if (!stream_) throw image_reader_exception("PNG reader: cannot open image stream"); init(); } diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index a08b4d7dd..9c23d805a 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef MAPNIK_USE_PROJ4 // proj4 @@ -124,7 +125,7 @@ unsigned int proj_transform::forward (geometry::line_string & ls) const geometry::point * ptr = ls.data(); double * x = reinterpret_cast(ptr); double * y = x + 1; - double * z = NULL; + double * z = nullptr; if(!forward(x, y, z, size, 2)) { return size; @@ -199,20 +200,21 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co #ifdef MAPNIK_USE_PROJ4 if (is_dest_longlat_) { - int i; - for(i=0; i & ls) const geometry::point * ptr = ls.data(); double * x = reinterpret_cast(ptr); double * y = x + 1; - double * z = NULL; - if(!backward(x, y, z, size, 2)) + double * z = nullptr; + if (!backward(x, y, z, size, 2)) { return size; } @@ -311,31 +313,24 @@ bool proj_transform::backward (box2d & box) const if (is_source_equal_dest_) return true; - double llx = box.minx(); - double ulx = box.minx(); - double lly = box.miny(); - double lry = box.miny(); - double lrx = box.maxx(); - double urx = box.maxx(); - double uly = box.maxy(); - double ury = box.maxy(); - double z = 0.0; - if (!backward(llx,lly,z)) + double x[4], y[4]; + x[0] = box.minx(); // llx 0 + y[0] = box.miny(); // lly 1 + x[1] = box.maxx(); // lrx 2 + y[1] = box.miny(); // lry 3 + x[2] = box.minx(); // ulx 4 + y[2] = box.maxy(); // uly 5 + x[3] = box.maxx(); // urx 6 + y[3] = box.maxy(); // ury 7 + + if (!backward(x, y, nullptr, 4, 1)) return false; - if (!backward(lrx,lry,z)) - return false; - if (!backward(ulx,uly,z)) - return false; - if (!backward(urx,ury,z)) - return false; - double minx = std::min(ulx, llx); - double miny = std::min(lly, lry); - double maxx = std::max(urx, lrx); - double maxy = std::max(ury, uly); - box.init(minx, - miny, - maxx, - maxy); + + double minx = std::min(x[0], x[2]); + double miny = std::min(y[0], y[1]); + double maxx = std::max(x[1], x[3]); + double maxy = std::max(y[2], y[3]); + box.init(minx, miny, maxx, maxy); return true; } @@ -370,21 +365,6 @@ void envelope_points(std::vector< coord > & coords, box2d& env } } -// determine if an ordered sequence of coordinates is in clockwise order -bool is_clockwise(const std::vector< coord > & coords) -{ - int n = coords.size(); - coord c1, c2; - double a = 0.0; - - for (int i=0; i calculate_bbox(std::vector > & points) { std::vector >::iterator it = points.begin(); std::vector >::iterator it_end = points.end(); @@ -425,7 +405,7 @@ bool proj_transform::backward(box2d& env, int points) const } box2d result = calculate_bbox(coords); - if (is_source_longlat_ && !is_clockwise(coords)) + if (is_source_longlat_ && !util::is_clockwise(coords)) { // we've gone to a geographic CS, and our clockwise envelope has // changed into an anticlockwise one. This means we've crossed the antimeridian, and @@ -439,7 +419,6 @@ bool proj_transform::backward(box2d& env, int points) const env.re_center(result.center().x, result.center().y); env.height(result.height()); env.width(result.width()); - return true; } @@ -466,7 +445,7 @@ bool proj_transform::forward(box2d& env, int points) const box2d result = calculate_bbox(coords); - if (is_dest_longlat_ && !is_clockwise(coords)) + if (is_dest_longlat_ && !util::is_clockwise(coords)) { // we've gone to a geographic CS, and our clockwise envelope has // changed into an anticlockwise one. This means we've crossed the antimeridian, and diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp index c0a631f69..94e829405 100644 --- a/src/rapidxml_loader.cpp +++ b/src/rapidxml_loader.cpp @@ -28,12 +28,16 @@ #include #include #include -#include #include #include #include #include +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + // stl #include #include diff --git a/src/raster_colorizer.cpp b/src/raster_colorizer.cpp index 22d3ee88a..2c43df6b6 100644 --- a/src/raster_colorizer.cpp +++ b/src/raster_colorizer.cpp @@ -149,7 +149,7 @@ void raster_colorizer::colorize(image_rgba8 & out, T const& in, inline unsigned interpolate(unsigned start, unsigned end, float fraction) { - return static_cast(fraction * ((float)end - (float)start) + start); + return static_cast(fraction * (static_cast(end) - static_cast(start)) + static_cast(start)); } unsigned raster_colorizer::get_color(float value) const diff --git a/src/renderer_common.cpp b/src/renderer_common.cpp index 37223e35d..d45e3a03c 100644 --- a/src/renderer_common.cpp +++ b/src/renderer_common.cpp @@ -29,10 +29,24 @@ namespace mapnik { +// copy constructor exclusively for virtual_renderer_common +renderer_common::renderer_common(renderer_common const& other) + : width_(other.width_), + height_(other.height_), + scale_factor_(other.scale_factor_), + vars_(other.vars_), + shared_font_library_(other.shared_font_library_), + font_library_(other.font_library_), + font_manager_(other.font_manager_), + query_extent_(other.query_extent_), + t_(other.t_), + detector_(other.detector_) +{} + renderer_common::renderer_common(Map const& map, unsigned width, unsigned height, double scale_factor, attributes const& vars, view_transform && t, - std::shared_ptr detector) + detector_ptr detector) : width_(width), height_(height), scale_factor_(scale_factor), @@ -57,7 +71,7 @@ renderer_common::renderer_common(Map const &m, attributes const& vars, unsigned renderer_common::renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor, - std::shared_ptr detector) + detector_ptr detector) : renderer_common(m, width, height, scale_factor, vars, view_transform(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y), @@ -74,4 +88,10 @@ renderer_common::renderer_common(Map const &m, request const &req, attributes co req.width() + req.buffer_size() ,req.height() + req.buffer_size()))) {} +renderer_common::~renderer_common() +{ + // defined in .cpp to make this destructible elsewhere without + // having to #include +} + } diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp deleted file mode 100644 index ebef9149f..000000000 --- a/src/renderer_common/process_group_symbolizer.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -// mapnik -#include -#include -#include - -namespace mapnik { - -vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src, - svg_attribute_type const& attrs, - agg::trans_affine const& marker_trans, - double opacity, - composite_mode_e comp_op, - bool snap_to_pixels) - : src_(src), attrs_(attrs), tr_(marker_trans), opacity_(opacity), - comp_op_(comp_op), snap_to_pixels_(snap_to_pixels) -{} - -vector_marker_render_thunk::vector_marker_render_thunk(vector_marker_render_thunk && rhs) - : src_(std::move(rhs.src_)), - attrs_(std::move(rhs.attrs_)), - tr_(std::move(rhs.tr_)), - opacity_(std::move(rhs.opacity_)), - comp_op_(std::move(rhs.comp_op_)), - snap_to_pixels_(std::move(rhs.snap_to_pixels_)) {} - - -raster_marker_render_thunk::raster_marker_render_thunk(image_rgba8 const& src, - agg::trans_affine const& marker_trans, - double opacity, - composite_mode_e comp_op, - bool snap_to_pixels) - : src_(src), tr_(marker_trans), opacity_(opacity), comp_op_(comp_op), - snap_to_pixels_(snap_to_pixels) -{} - -raster_marker_render_thunk::raster_marker_render_thunk(raster_marker_render_thunk && rhs) - : src_(rhs.src_), - tr_(std::move(rhs.tr_)), - opacity_(std::move(rhs.opacity_)), - comp_op_(std::move(rhs.comp_op_)), - snap_to_pixels_(std::move(rhs.snap_to_pixels_)) {} - - -text_render_thunk::text_render_thunk(helper_ptr && helper, - double opacity, composite_mode_e comp_op, - halo_rasterizer_enum halo_rasterizer) - : helper_(std::move(helper)), - placements_(helper_->get()), - opacity_(opacity), - comp_op_(comp_op), - halo_rasterizer_(halo_rasterizer) -{} - -text_render_thunk::text_render_thunk(text_render_thunk && rhs) - : helper_(std::move(rhs.helper_)), - placements_(std::move(rhs.placements_)), - opacity_(std::move(rhs.opacity_)), - comp_op_(std::move(rhs.comp_op_)), - halo_rasterizer_(std::move(rhs.halo_rasterizer_)) {} - -namespace detail { - -template -struct vector_marker_thunk_dispatch : public vector_markers_dispatch -{ - vector_marker_thunk_dispatch(svg_path_ptr const& src, - svg_path_adapter & path, - svg_attribute_type const& attrs, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - : vector_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - attrs_(attrs), comp_op_(get(sym, feature, vars)), - snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context)) - {} - - ~vector_marker_thunk_dispatch() {} - - void render_marker(agg::trans_affine const& marker_tr, double opacity) - { - vector_marker_render_thunk thunk(this->src_, this->attrs_, marker_tr, opacity, comp_op_, snap_to_pixels_); - thunks_.push_back(std::make_unique(std::move(thunk))); - } - -private: - svg_attribute_type const& attrs_; - composite_mode_e comp_op_; - bool snap_to_pixels_; - render_thunk_list & thunks_; -}; - -template -struct raster_marker_thunk_dispatch : public raster_markers_dispatch -{ - raster_marker_thunk_dispatch(image_rgba8 const& src, - agg::trans_affine const& marker_trans, - symbolizer_base const& sym, - Detector & detector, - double scale_factor, - feature_impl & feature, - attributes const& vars, - RendererContext const& renderer_context, - bool snap_to_pixels = false) - : raster_markers_dispatch(src, marker_trans, sym, detector, scale_factor, feature, vars), - comp_op_(get(sym, feature, vars)), - snap_to_pixels_(snap_to_pixels), thunks_(std::get<0>(renderer_context)) - {} - - ~raster_marker_thunk_dispatch() {} - - void render_marker(agg::trans_affine const& marker_tr, double opacity) - { - raster_marker_render_thunk thunk(this->src_, marker_tr, opacity, comp_op_, snap_to_pixels_); - thunks_.push_back(std::make_unique(std::move(thunk))); - } - -private: - composite_mode_e comp_op_; - bool snap_to_pixels_; - render_thunk_list & thunks_; -}; - -} // end detail ns - -render_thunk_extractor::render_thunk_extractor(box2d & box, - render_thunk_list & thunks, - feature_impl & feature, - attributes const& vars, - proj_transform const& prj_trans, - virtual_renderer_common & common, - box2d const& clipping_extent) - : box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans), - common_(common), clipping_extent_(clipping_extent) -{} - -void render_thunk_extractor::operator()(markers_symbolizer const& sym) const -{ - auto renderer_context = std::tie(thunks_); - using context_type = decltype(renderer_context); - using vector_dispatch_type = detail::vector_marker_thunk_dispatch; - using raster_dispatch_type = detail::raster_marker_thunk_dispatch; - - render_markers_symbolizer( - sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context); - - update_box(); -} - -void render_thunk_extractor::operator()(text_symbolizer const& sym) const -{ - box2d clip_box = clipping_extent_; - helper_ptr helper = std::make_unique( - sym, feature_, vars_, prj_trans_, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - clip_box, agg::trans_affine()); - - extract_text_thunk(std::move(helper), sym); -} - -void render_thunk_extractor::operator()(shield_symbolizer const& sym) const -{ - box2d clip_box = clipping_extent_; - helper_ptr helper = std::make_unique( - sym, feature_, vars_, prj_trans_, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - clip_box, agg::trans_affine()); - - extract_text_thunk(std::move(helper), sym); -} - -void render_thunk_extractor::extract_text_thunk(helper_ptr && helper, text_symbolizer const& sym) const -{ - double opacity = get(sym, keys::opacity, feature_, common_.vars_, 1.0); - composite_mode_e comp_op = get(sym, keys::comp_op, feature_, common_.vars_, src_over); - halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL); - - text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer); - thunks_.push_back(std::make_unique(std::move(thunk))); - - update_box(); -} - -void render_thunk_extractor::update_box() const -{ - label_collision_detector4 & detector = *common_.detector_; - - for (auto const& label : detector) - { - if (box_.width() > 0 && box_.height() > 0) - { - box_.expand_to_include(label.get().box); - } - else - { - box_ = label.get().box; - } - } - - detector.clear(); -} - -} // namespace mapnik diff --git a/src/renderer_common/render_group_symbolizer.cpp b/src/renderer_common/render_group_symbolizer.cpp new file mode 100644 index 000000000..9892dfc8d --- /dev/null +++ b/src/renderer_common/render_group_symbolizer.cpp @@ -0,0 +1,194 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik { + +void render_group_symbolizer(group_symbolizer const& sym, + feature_impl & feature, + attributes const& vars, + proj_transform const& prj_trans, + box2d const& clipping_extent, + renderer_common & common, + render_thunk_list_dispatch & render_thunks) +{ + // find all column names referenced in the group rules and symbolizers + std::set columns; + group_attribute_collector column_collector(columns, false); + column_collector(sym); + + auto props = get(sym, keys::group_properties); + + // create a new context for the sub features of this group + context_ptr sub_feature_ctx = std::make_shared(); + + // populate new context with column names referenced in the group rules and symbolizers + for (auto const& col_name : columns) + { + sub_feature_ctx->push(col_name); + } + + // keep track of the sub features that we'll want to symbolize + // along with the group rules that they matched + std::vector< std::pair > matches; + + // create a copied 'virtual' common renderer for processing sub feature symbolizers + // create an empty detector for it, so we are sure we won't hit anything + virtual_renderer_common virtual_renderer(common); + + // keep track of which lists of render thunks correspond to + // entries in the group_layout_manager. + std::vector layout_thunks; + + // layout manager to store and arrange bboxes of matched features + group_layout_manager layout_manager(props->get_layout()); + layout_manager.set_input_origin(common.width_ * 0.5, common.height_ * 0.5); + + // run feature or sub feature through the group rules & symbolizers + // for each index value in the range + value_integer start = get(sym, keys::start_column); + value_integer end = start + get(sym, keys::num_columns); + for (value_integer col_idx = start; col_idx < end; ++col_idx) + { + // create sub feature with indexed column values + feature_ptr sub_feature = feature_factory::create(sub_feature_ctx, col_idx); + + // copy the necessary columns to sub feature + for(auto const& col_name : columns) + { + if (col_name.find('%') != std::string::npos) + { + if (col_name.size() == 1) + { + // column name is '%' by itself, so give the index as the value + sub_feature->put(col_name, col_idx); + } + else + { + // indexed column + std::string col_idx_str; + if (mapnik::util::to_string(col_idx_str,col_idx)) + { + std::string col_idx_name = col_name; + boost::replace_all(col_idx_name, "%", col_idx_str); + sub_feature->put(col_name, feature.get(col_idx_name)); + } + } + } + else + { + // non-indexed column + sub_feature->put(col_name, feature.get(col_name)); + } + } + + // add a single point geometry at pixel origin + double x = common.width_ / 2.0, y = common.height_ / 2.0, z = 0.0; + common.t_.backward(&x, &y); + prj_trans.forward(x, y, z); + // note that we choose a point in the middle of the screen to + // try to ensure that we don't get edge artefacts due to any + // symbolizers with avoid-edges set: only the avoid-edges of + // the group symbolizer itself should matter. + geometry::point origin_pt(x,y); + sub_feature->set_geometry(origin_pt); + // get the layout for this set of properties + for (auto const& rule : props->get_rules()) + { + if (util::apply_visitor(evaluate(*sub_feature,common.vars_), + *(rule->get_filter())).to_bool()) + { + // add matched rule and feature to the list of things to draw + matches.emplace_back(rule, sub_feature); + + // construct a bounding box around all symbolizers for the matched rule + box2d bounds; + render_thunk_list thunks; + render_thunk_extractor extractor(bounds, thunks, *sub_feature, common.vars_, prj_trans, + virtual_renderer, clipping_extent); + + for (auto const& _sym : *rule) + { + // TODO: construct layout and obtain bounding box + util::apply_visitor(extractor, _sym); + } + + // add the bounding box to the layout manager + layout_manager.add_member_bound_box(bounds); + layout_thunks.emplace_back(std::move(thunks)); + break; + } + } + } + + // create a symbolizer helper + group_symbolizer_helper helper(sym, feature, vars, prj_trans, + common.width_, common.height_, + common.scale_factor_, common.t_, + *common.detector_, clipping_extent); + + for (size_t i = 0; i < matches.size(); ++i) + { + group_rule_ptr match_rule = matches[i].first; + feature_ptr match_feature = matches[i].second; + value_unicode_string rpt_key_value = ""; + + // get repeat key from matched group rule + expression_ptr rpt_key_expr = match_rule->get_repeat_key(); + + // if no repeat key was defined, use default from group symbolizer + if (!rpt_key_expr) + { + rpt_key_expr = get(sym, keys::repeat_key); + } + + // evaluate the repeat key with the matched sub feature if we have one + if (rpt_key_expr) + { + rpt_key_value = util::apply_visitor(evaluate(*match_feature,common.vars_), + *rpt_key_expr).to_unicode(); + } + helper.add_box_element(layout_manager.offset_box_at(i), rpt_key_value); + } + + pixel_position_list const& positions = helper.get(); + for (pixel_position const& pos : positions) + { + for (size_t layout_i = 0; layout_i < layout_thunks.size(); ++layout_i) + { + pixel_position const& offset = layout_manager.offset_at(layout_i); + pixel_position render_offset = pos + offset; + render_thunks.render_list(layout_thunks[layout_i], render_offset); + } + } +} + +} // namespace mapnik diff --git a/src/renderer_common/render_markers_symbolizer.cpp b/src/renderer_common/render_markers_symbolizer.cpp new file mode 100644 index 000000000..6706cb1cd --- /dev/null +++ b/src/renderer_common/render_markers_symbolizer.cpp @@ -0,0 +1,265 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik { + +namespace detail { + +template +struct render_marker_symbolizer_visitor +{ + using vector_dispatch_type = vector_markers_dispatch; + using raster_dispatch_type = raster_markers_dispatch; + + render_marker_symbolizer_visitor(std::string const& filename, + markers_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans, + RendererType const& common, + box2d const& clip_box, + ContextType & renderer_context) + : filename_(filename), + sym_(sym), + feature_(feature), + prj_trans_(prj_trans), + common_(common), + clip_box_(clip_box), + renderer_context_(renderer_context) {} + + svg_attribute_type const& get_marker_attributes(svg_path_ptr const& stock_marker, + svg_attribute_type & custom_attr) const + { + auto const& stock_attr = stock_marker->attributes(); + if (push_explicit_style(stock_attr, custom_attr, sym_, feature_, common_.vars_)) + return custom_attr; + else + return stock_attr; + } + + template + void render_marker(Marker const& mark, Dispatch & rasterizer_dispatch) const + { + auto const& vars = common_.vars_; + + agg::trans_affine geom_tr; + if (auto geometry_transform = get_optional(sym_, keys::geometry_transform)) + { + evaluate_transform(geom_tr, feature_, vars, *geometry_transform, common_.scale_factor_); + } + + vertex_converter_type converter(clip_box_, + sym_, + common_.t_, + prj_trans_, + geom_tr, + feature_, + vars, + common_.scale_factor_); + + bool clip = get(sym_, feature_, vars); + double offset = get(sym_, feature_, vars); + double simplify_tolerance = get(sym_, feature_, vars); + double smooth = get(sym_, feature_, vars); + + if (clip) + { + geometry::geometry_types type = geometry::geometry_type(feature_.get_geometry()); + switch (type) + { + case geometry::geometry_types::Polygon: + case geometry::geometry_types::MultiPolygon: + converter.template set(); + break; + case geometry::geometry_types::LineString: + case geometry::geometry_types::MultiLineString: + converter.template set(); + break; + default: + // silence warning: 4 enumeration values not handled in switch + break; + } + } + + converter.template set(); //always transform + if (std::fabs(offset) > 0.0) converter.template set(); // parallel offset + converter.template set(); // optional affine transform + if (simplify_tolerance > 0.0) converter.template set(); // optional simplify converter + if (smooth > 0.0) converter.template set(); // optional smooth converter + + apply_markers_multi(feature_, vars, converter, rasterizer_dispatch, sym_); + } + + void operator() (marker_null const&) const {} + + void operator() (marker_svg const& mark) const + { + using namespace mapnik::svg; + + // https://github.com/mapnik/mapnik/issues/1316 + bool snap_to_pixels = !mapnik::marker_cache::instance().is_uri(filename_); + + agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); + + boost::optional const& stock_vector_marker = mark.get_data(); + svg_path_ptr marker_ptr = *stock_vector_marker; + bool is_ellipse = false; + + svg_attribute_type s_attributes; + auto const& r_attributes = get_marker_attributes(*stock_vector_marker, s_attributes); + + // special case for simple ellipse markers + // to allow for full control over rx/ry dimensions + if (filename_ == "shape://ellipse" + && (has_key(sym_,keys::width) || has_key(sym_,keys::height))) + { + marker_ptr = std::make_shared(); + is_ellipse = true; + } + else + { + box2d const& bbox = mark.bounding_box(); + setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature_, common_.vars_, sym_); + } + + vertex_stl_adapter stl_storage(marker_ptr->source()); + svg_path_adapter svg_path(stl_storage); + + if (is_ellipse) + { + build_ellipse(sym_, feature_, common_.vars_, *marker_ptr, svg_path); + } + + if (auto image_transform = get_optional(sym_, keys::image_transform)) + { + evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); + } + + vector_dispatch_type rasterizer_dispatch(marker_ptr, + svg_path, + r_attributes, + image_tr, + sym_, + *common_.detector_, + common_.scale_factor_, + feature_, + common_.vars_, + snap_to_pixels, + renderer_context_); + + render_marker(mark, rasterizer_dispatch); + } + + void operator() (marker_rgba8 const& mark) const + { + agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); + + setup_transform_scaling(image_tr, mark.width(), mark.height(), feature_, common_.vars_, sym_); + auto image_transform = get_optional(sym_, keys::image_transform); + if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform, common_.scale_factor_); + box2d const& bbox = mark.bounding_box(); + mapnik::image_rgba8 const& marker = mark.get_data(); + // - clamp sizes to > 4 pixels of interactivity + coord2d center = bbox.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine marker_trans = recenter * image_tr; + raster_dispatch_type rasterizer_dispatch(marker, + marker_trans, + sym_, + *common_.detector_, + common_.scale_factor_, + feature_, + common_.vars_, + renderer_context_); + + render_marker(mark, rasterizer_dispatch); + } + + private: + std::string const& filename_; + markers_symbolizer const& sym_; + mapnik::feature_impl & feature_; + proj_transform const& prj_trans_; + RendererType const& common_; + box2d const& clip_box_; + ContextType & renderer_context_; +}; + +} // namespace detail + +markers_dispatch_params::markers_dispatch_params(box2d const& size, + agg::trans_affine const& tr, + symbolizer_base const& sym, + feature_impl const& feature, + attributes const& vars, + double scale, + bool snap) + : placement_params{ + size, + tr, + get(sym, feature, vars), + get(sym, feature, vars), + get(sym, feature, vars), + get(sym, feature, vars), + get(sym, feature, vars)} + , placement_method(get(sym, feature, vars)) + , ignore_placement(get(sym, feature, vars)) + , snap_to_pixels(snap) + , scale_factor(scale) + , opacity(get(sym, feature, vars)) +{ + placement_params.spacing *= scale; +} + +void render_markers_symbolizer(markers_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans, + renderer_common const& common, + box2d const& clip_box, + markers_renderer_context & renderer_context) +{ + using Detector = label_collision_detector4; + using RendererType = renderer_common; + using ContextType = markers_renderer_context; + using VisitorType = detail::render_marker_symbolizer_visitor; + + std::string filename = get(sym, keys::file, feature, common.vars_, "shape://ellipse"); + if (!filename.empty()) + { + auto mark = mapnik::marker_cache::instance().find(filename, true); + VisitorType visitor(filename, sym, feature, prj_trans, common, clip_box, + renderer_context); + util::apply_visitor(visitor, *mark); + } +} + +} // namespace mapnik diff --git a/src/renderer_common/render_pattern.cpp b/src/renderer_common/render_pattern.cpp index 06477d460..5e6f95820 100644 --- a/src/renderer_common/render_pattern.cpp +++ b/src/renderer_common/render_pattern.cpp @@ -28,12 +28,15 @@ #include #include +#pragma GCC diagnostic push +#include #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_pixfmt_gray.h" #include "agg_color_rgba.h" #include "agg_color_gray.h" #include "agg_scanline_u.h" +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/renderer_common/render_thunk_extractor.cpp b/src/renderer_common/render_thunk_extractor.cpp new file mode 100644 index 000000000..c437262da --- /dev/null +++ b/src/renderer_common/render_thunk_extractor.cpp @@ -0,0 +1,155 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include +#include +#include + +namespace mapnik { + +virtual_renderer_common::virtual_renderer_common(renderer_common const& other) + : renderer_common(other) +{ + // replace collision detector with my own so that I don't pollute the original + detector_ = std::make_shared(other.detector_->extent()); +} + +namespace detail { + +struct thunk_markers_renderer_context : markers_renderer_context +{ + thunk_markers_renderer_context(symbolizer_base const& sym, + feature_impl const& feature, + attributes const& vars, + render_thunk_list & thunks) + : comp_op_(get(sym, feature, vars)) + , thunks_(thunks) + {} + + virtual void render_marker(svg_path_ptr const& src, + svg_path_adapter & path, + svg_attribute_type const& attrs, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) + { + vector_marker_render_thunk thunk(src, attrs, marker_tr, params.opacity, + comp_op_, params.snap_to_pixels); + thunks_.push_back(std::make_unique(std::move(thunk))); + } + + virtual void render_marker(image_rgba8 const& src, + markers_dispatch_params const& params, + agg::trans_affine const& marker_tr) + { + raster_marker_render_thunk thunk(src, marker_tr, params.opacity, + comp_op_, params.snap_to_pixels); + thunks_.push_back(std::make_unique(std::move(thunk))); + } + +private: + composite_mode_e comp_op_; + render_thunk_list & thunks_; +}; + +} // namespace detail + +render_thunk_extractor::render_thunk_extractor(box2d & box, + render_thunk_list & thunks, + feature_impl & feature, + attributes const& vars, + proj_transform const& prj_trans, + virtual_renderer_common & common, + box2d const& clipping_extent) + : box_(box), thunks_(thunks), feature_(feature), vars_(vars), prj_trans_(prj_trans), + common_(common), clipping_extent_(clipping_extent) +{} + +void render_thunk_extractor::operator()(markers_symbolizer const& sym) const +{ + using context_type = detail::thunk_markers_renderer_context; + context_type renderer_context(sym, feature_, vars_, thunks_); + + render_markers_symbolizer( + sym, feature_, prj_trans_, common_, clipping_extent_, renderer_context); + + update_box(); +} + +void render_thunk_extractor::operator()(text_symbolizer const& sym) const +{ + auto helper = std::make_unique( + sym, feature_, vars_, prj_trans_, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + clipping_extent_, agg::trans_affine::identity); + + extract_text_thunk(std::move(helper), sym); +} + +void render_thunk_extractor::operator()(shield_symbolizer const& sym) const +{ + auto helper = std::make_unique( + sym, feature_, vars_, prj_trans_, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + clipping_extent_, agg::trans_affine::identity); + + extract_text_thunk(std::move(helper), sym); +} + +void render_thunk_extractor::extract_text_thunk(text_render_thunk::helper_ptr && helper, + text_symbolizer const& sym) const +{ + double opacity = get(sym, keys::opacity, feature_, common_.vars_, 1.0); + composite_mode_e comp_op = get(sym, keys::comp_op, feature_, common_.vars_, src_over); + halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, feature_, common_.vars_, HALO_RASTERIZER_FULL); + + text_render_thunk thunk(std::move(helper), opacity, comp_op, halo_rasterizer); + thunks_.push_back(std::make_unique(std::move(thunk))); + + update_box(); +} + +void render_thunk_extractor::update_box() const +{ + label_collision_detector4 & detector = *common_.detector_; + + for (auto const& label : detector) + { + if (box_.width() > 0 && box_.height() > 0) + { + box_.expand_to_include(label.get().box); + } + else + { + box_ = label.get().box; + } + } + + detector.clear(); +} + +} // namespace mapnik diff --git a/src/save_map.cpp b/src/save_map.cpp index b8db98a78..f3d89153c 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -47,7 +47,6 @@ #include #include #include - #pragma GCC diagnostic push #include #include @@ -105,7 +104,7 @@ void serialize_raster_colorizer(ptree & sym_node, raster_colorizer dfl; if (colorizer->get_default_mode() != dfl.get_default_mode() || explicit_defaults) { - set_attr(col_node, "default-mode", colorizer->get_default_mode()); + set_attr(col_node, "default-mode", colorizer->get_default_mode().as_string()); } if (colorizer->get_default_color() != dfl.get_default_color() || explicit_defaults) { @@ -404,7 +403,7 @@ void serialize_style( ptree & map_node, std::string const& name, feature_type_st filter_mode_e filter_mode = style.get_filter_mode(); if (filter_mode != dfl.get_filter_mode() || explicit_defaults) { - set_attr(style_node, "filter-mode", filter_mode); + set_attr(style_node, "filter-mode", filter_mode.as_string()); } double opacity = style.get_opacity(); diff --git a/src/svg/output/svg_renderer.cpp b/src/svg/output/svg_renderer.cpp index c110e5e8c..569164645 100644 --- a/src/svg/output/svg_renderer.cpp +++ b/src/svg/output/svg_renderer.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index 5885e8d9e..2483bae56 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -29,10 +29,15 @@ #include #include #include +#include + +#pragma GCC diagnostic push +#include #include "agg_ellipse.h" #include "agg_rounded_rect.h" #include "agg_span_gradient.h" #include "agg_color_rgba.h" +#pragma GCC diagnostic pop #pragma GCC diagnostic push #include @@ -123,7 +128,7 @@ template double parse_double(T & error_messages, const char* str) { using namespace boost::spirit::qi; - qi::double_type double_; + double_type double_; double val = 0.0; if (!parse(str, str + std::strlen(str),double_,val)) { @@ -132,24 +137,40 @@ double parse_double(T & error_messages, const char* str) return val; } - -// parse a double that might end with a % -// if it does then set the ref bool true and divide the result by 100 - -template -double parse_double_optional_percent(T & error_messages, const char* str, bool &percent) +// https://www.w3.org/TR/SVG/coords.html#Units +template +double parse_svg_value(T & error_messages, const char* str, bool & percent) { - using namespace boost::spirit::qi; + using skip_type = boost::spirit::ascii::space_type; using boost::phoenix::ref; - qi::_1_type _1; qi::double_type double_; - qi::char_type char_; - + qi::lit_type lit; + qi::_1_type _1; double val = 0.0; - if (!parse(str, str + std::strlen(str),double_[ref(val)=_1, ref(percent) = false] - >> -char_('%')[ref(val) /= 100.0, ref(percent) = true])) + qi::symbols units; + units.add + ("px", 1.0) + ("pt", DPI/72.0) + ("pc", DPI/6.0) + ("mm", DPI/25.4) + ("cm", DPI/2.54) + ("in", static_cast(DPI)) + ; + const char* cur = str; // phrase_parse modifies the first iterator + const char* end = str + std::strlen(str); + if (!qi::phrase_parse(cur, end, + double_[ref(val) = _1][ref(percent) = false] + > - (units[ ref(val) *= _1] + | + lit('%')[ref(val) *= 0.01][ref(percent) = true]), + skip_type())) { - error_messages.emplace_back("Failed to parse double (optional %) from " + std::string(str)); + error_messages.emplace_back("Failed to parse SVG value: '" + std::string(str) + "'"); + } + else if (cur != end) + { + error_messages.emplace_back("Failed to parse SVG value: '" + std::string(str) + + "', trailing garbage: '" + cur + "'"); } return val; } @@ -159,9 +180,9 @@ bool parse_double_list(T & error_messages, const char* str, double* list) { using namespace boost::spirit::qi; using boost::phoenix::ref; - qi::_1_type _1; - qi::double_type double_; - qi::lit_type lit; + _1_type _1; + double_type double_; + lit_type lit; using skip_type = boost::spirit::ascii::space_type; if (!phrase_parse(str, str + std::strlen(str), @@ -411,7 +432,8 @@ void parse_attr(svg_parser & parser, char const* name, char const* value ) } else if (std::strcmp(name, "stroke-width") == 0) { - parser.path_.stroke_width(parse_double(parser.error_messages_, value)); + bool percent; + parser.path_.stroke_width(parse_svg_value(parser.error_messages_, value, percent)); } else if (std::strcmp(name, "stroke-opacity") == 0) { @@ -439,7 +461,19 @@ void parse_attr(svg_parser & parser, char const* name, char const* value ) { parser.path_.miter_limit(parse_double(parser.error_messages_,value)); } - + else if (std::strcmp(name,"stroke-dasharray") == 0) + { + dash_array dash; + if (util::parse_dasharray(value, dash)) + { + parser.path_.dash_array(std::move(dash)); + } + } + else if (std::strcmp(name,"stroke-dashoffset") == 0) + { + double offset = parse_double(parser.error_messages_, value); + parser.path_.dash_offset(offset); + } else if(std::strcmp(name, "opacity") == 0) { double opacity = parse_double(parser.error_messages_, value); @@ -455,7 +489,6 @@ void parse_attr(svg_parser & parser, char const* name, char const* value ) } } - void parse_attr(svg_parser & parser, rapidxml::xml_node const* node) { for (rapidxml::xml_attribute const* attr = node->first_attribute(); @@ -493,12 +526,12 @@ void parse_dimensions(svg_parser & parser, rapidxml::xml_node const* node) auto const* width_attr = node->first_attribute("width"); if (width_attr) { - width = parse_double_optional_percent(parser.error_messages_, width_attr->value(), has_percent_width); + width = parse_svg_value(parser.error_messages_, width_attr->value(), has_percent_width); } auto const* height_attr = node->first_attribute("height"); if (height_attr) { - height = parse_double_optional_percent(parser.error_messages_, height_attr->value(), has_percent_height); + height = parse_svg_value(parser.error_messages_, height_attr->value(), has_percent_height); } auto const* viewbox_attr = node->first_attribute("viewBox"); if (viewbox_attr) @@ -589,18 +622,18 @@ void parse_line(svg_parser & parser, rapidxml::xml_node const* node) double y1 = 0.0; double x2 = 0.0; double y2 = 0.0; - + bool percent; auto const* x1_attr = node->first_attribute("x1"); - if (x1_attr) x1 = parse_double(parser.error_messages_, x1_attr->value()); + if (x1_attr) x1 = parse_svg_value(parser.error_messages_, x1_attr->value(), percent); auto const* y1_attr = node->first_attribute("y1"); - if (y1_attr) y1 = parse_double(parser.error_messages_, y1_attr->value()); + if (y1_attr) y1 = parse_svg_value(parser.error_messages_, y1_attr->value(), percent); auto const* x2_attr = node->first_attribute("x2"); - if (x2_attr) x2 = parse_double(parser.error_messages_, x2_attr->value()); + if (x2_attr) x2 = parse_svg_value(parser.error_messages_, x2_attr->value(), percent); auto const* y2_attr = node->first_attribute("y2"); - if (y2_attr) y2 = parse_double(parser.error_messages_, y2_attr->value()); + if (y2_attr) y2 = parse_svg_value(parser.error_messages_, y2_attr->value(), percent); parser.path_.begin_path(); parser.path_.move_to(x1, y1); @@ -613,23 +646,23 @@ void parse_circle(svg_parser & parser, rapidxml::xml_node const* node) double cx = 0.0; double cy = 0.0; double r = 0.0; - + bool percent; auto * attr = node->first_attribute("cx"); if (attr != nullptr) { - cx = parse_double(parser.error_messages_, attr->value()); + cx = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("cy"); if (attr != nullptr) { - cy = parse_double(parser.error_messages_, attr->value()); + cy = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("r"); if (attr != nullptr) { - r = parse_double(parser.error_messages_, attr->value()); + r = parse_svg_value(parser.error_messages_, attr->value(), percent); } parser.path_.begin_path(); @@ -654,29 +687,29 @@ void parse_ellipse(svg_parser & parser, rapidxml::xml_node const * node) double cy = 0.0; double rx = 0.0; double ry = 0.0; - + bool percent; auto * attr = node->first_attribute("cx"); if (attr != nullptr) { - cx = parse_double(parser.error_messages_, attr->value()); + cx = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("cy"); if (attr) { - cy = parse_double(parser.error_messages_, attr->value()); + cy = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("rx"); if (attr != nullptr) { - rx = parse_double(parser.error_messages_, attr->value()); + rx = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("ry"); if (attr != nullptr) { - ry = parse_double(parser.error_messages_, attr->value()); + ry = parse_svg_value(parser.error_messages_, attr->value(), percent); } if (rx != 0.0 && ry != 0.0) @@ -709,35 +742,35 @@ void parse_rect(svg_parser & parser, rapidxml::xml_node const* node) double h = 0.0; double rx = 0.0; double ry = 0.0; - + bool percent; auto * attr = node->first_attribute("x"); if (attr != nullptr) { - x = parse_double(parser.error_messages_, attr->value()); + x = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("y"); if (attr != nullptr) { - y = parse_double(parser.error_messages_, attr->value()); + y = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("width"); if (attr != nullptr) { - w = parse_double(parser.error_messages_, attr->value()); + w = parse_svg_value(parser.error_messages_, attr->value(), percent); } attr = node->first_attribute("height"); if (attr) { - h = parse_double(parser.error_messages_, attr->value()); + h = parse_svg_value(parser.error_messages_, attr->value(), percent); } bool rounded = true; attr = node->first_attribute("rx"); if (attr != nullptr) { - rx = parse_double(parser.error_messages_, attr->value()); + rx = parse_svg_value(parser.error_messages_, attr->value(), percent); if ( rx > 0.5 * w ) rx = 0.5 * w; } else rounded = false; @@ -745,7 +778,7 @@ void parse_rect(svg_parser & parser, rapidxml::xml_node const* node) attr = node->first_attribute("ry"); if (attr != nullptr) { - ry = parse_double(parser.error_messages_, attr->value()); + ry = parse_svg_value(parser.error_messages_, attr->value(), percent); if ( ry > 0.5 * h ) ry = 0.5 * h; if (!rounded) { @@ -924,19 +957,19 @@ void parse_radial_gradient(svg_parser & parser, rapidxml::xml_node const* auto * attr = node->first_attribute("cx"); if (attr != nullptr) { - cx = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + cx = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } attr = node->first_attribute("cy"); if (attr != nullptr) { - cy = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + cy = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } attr = node->first_attribute("fx"); if (attr != nullptr) { - fx = parse_double_optional_percent(parser.error_messages_,attr->value(), has_percent); + fx = parse_svg_value(parser.error_messages_,attr->value(), has_percent); } else fx = cx; @@ -944,7 +977,7 @@ void parse_radial_gradient(svg_parser & parser, rapidxml::xml_node const* attr = node->first_attribute("fy"); if (attr != nullptr) { - fy = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + fy = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } else fy = cy; @@ -952,7 +985,7 @@ void parse_radial_gradient(svg_parser & parser, rapidxml::xml_node const* attr = node->first_attribute("r"); if (attr != nullptr) { - r = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + r = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } // this logic for detecting %'s will not support mixed coordinates. if (has_percent && parser.temporary_gradient_.second.get_units() == USER_SPACE_ON_USE) @@ -981,25 +1014,25 @@ void parse_linear_gradient(svg_parser & parser, rapidxml::xml_node const* auto * attr = node->first_attribute("x1"); if (attr != nullptr) { - x1 = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + x1 = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } attr = node->first_attribute("x2"); if (attr != nullptr) { - x2 = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + x2 = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } attr = node->first_attribute("y1"); if (attr != nullptr) { - y1 = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + y1 = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } attr = node->first_attribute("y2"); if (attr != nullptr) { - y2 = parse_double_optional_percent(parser.error_messages_, attr->value(), has_percent); + y2 = parse_svg_value(parser.error_messages_, attr->value(), has_percent); } // this logic for detecting %'s will not support mixed coordinates. if (has_percent && parser.temporary_gradient_.second.get_units() == USER_SPACE_ON_USE) diff --git a/src/svg/svg_path_parser.cpp b/src/svg/svg_path_parser.cpp index ba0ce07aa..52f95ef6e 100644 --- a/src/svg/svg_path_parser.cpp +++ b/src/svg/svg_path_parser.cpp @@ -21,32 +21,29 @@ *****************************************************************************/ // mapnik -#include + #include -#include -#include - -// agg -#include "agg_path_storage.h" - +#include // stl -#include #include +#include -namespace mapnik { namespace svg { +namespace mapnik { +namespace svg { - template - bool parse_path(const char* wkt, PathType & p) - { - using namespace boost::spirit; - using iterator_type = const char*; - using skip_type = ascii::space_type; - svg_path_grammar g(p); - iterator_type first = wkt; - iterator_type last = wkt + std::strlen(wkt); - return qi::phrase_parse(first, last, g, skip_type()); - } +template +bool parse_path(const char* wkt, PathType& p) +{ + using namespace boost::spirit; + using iterator_type = const char*; + using skip_type = ascii::space_type; + static const svg_path_grammar g; + iterator_type first = wkt; + iterator_type last = wkt + std::strlen(wkt); + bool status = qi::phrase_parse(first, last, (g)(boost::phoenix::ref(p)), skip_type()); + return (status && (first == last)); +} +template bool MAPNIK_DECL parse_path(const char*, svg_converter_type&); - template bool parse_path(const char*, svg_converter_type&); - - }} +} // namespace svg +} // namespace mapnik diff --git a/src/svg/svg_points_parser.cpp b/src/svg/svg_points_parser.cpp index 99de4c905..3e292ba70 100644 --- a/src/svg/svg_points_parser.cpp +++ b/src/svg/svg_points_parser.cpp @@ -22,26 +22,27 @@ // mapnik #include -#include -#include +#include // stl #include #include -namespace mapnik { namespace svg { +namespace mapnik { +namespace svg { - template - bool parse_points(const char* wkt, PathType & p) - { - using namespace boost::spirit; - using iterator_type = const char* ; - using skip_type = ascii::space_type; - svg_points_grammar g(p); - iterator_type first = wkt; - iterator_type last = wkt + std::strlen(wkt); - return qi::phrase_parse(first, last, g, skip_type()); - } +template +bool parse_points(const char* wkt, PathType& p) +{ + using namespace boost::spirit; + using iterator_type = const char*; + using skip_type = ascii::space_type; + static const svg_points_grammar g; + iterator_type first = wkt; + iterator_type last = wkt + std::strlen(wkt); + return qi::phrase_parse(first, last, (g)(boost::phoenix::ref(p)), skip_type()); +} - template bool parse_points(const char*, svg_converter_type&); +template bool parse_points(const char*, svg_converter_type&); - }} +} // namespace svg +} // namespace mapnik diff --git a/src/svg/svg_transform_parser.cpp b/src/svg/svg_transform_parser.cpp index f41b7b11e..7b90ca4cb 100644 --- a/src/svg/svg_transform_parser.cpp +++ b/src/svg/svg_transform_parser.cpp @@ -21,27 +21,28 @@ *****************************************************************************/ // mapnik -#include -#include +#include +#include // stl #include #include -namespace mapnik { namespace svg { +namespace mapnik { +namespace svg { - template - bool parse_svg_transform(const char * wkt, TransformType & p) - { - using namespace boost::spirit; - using iterator_type = const char *; - using skip_type = ascii::space_type; - // TODO - make it possible for this to be static const - // by avoiding ctor taking arg - https://github.com/mapnik/mapnik/pull/2231 - svg_transform_grammar g(p); - iterator_type first = wkt; - iterator_type last = wkt + std::strlen(wkt); - return qi::phrase_parse(first, last, g, skip_type()); - } +template +bool parse_svg_transform(const char* wkt, TransformType& tr) +{ + using namespace boost::spirit; + using iterator_type = const char*; + using skip_type = ascii::space_type; + static const svg_transform_grammar g; + iterator_type first = wkt; + iterator_type last = wkt + std::strlen(wkt); + return qi::phrase_parse(first, last, (g)(boost::phoenix::ref(tr)), skip_type()); +} - template MAPNIK_DECL bool parse_svg_transform(const char*, agg::trans_affine&); -}} +template bool MAPNIK_DECL parse_svg_transform(const char*, agg::trans_affine&); + +} // namespace svg +} // namespace mapnik diff --git a/src/text/face.cpp b/src/text/face.cpp index 79f35d8fe..1d3ad7820 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -23,11 +23,16 @@ #include #include +#pragma GCC diagnostic push +#include + extern "C" { #include FT_GLYPH_H } +#pragma GCC diagnostic pop + namespace mapnik { @@ -36,7 +41,7 @@ font_face::font_face(FT_Face face) bool font_face::set_character_sizes(double size) { - return (FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0) == 0); + return (FT_Set_Char_Size(face_,0,static_cast(size * (1<<6)),0,0) == 0); } bool font_face::set_unscaled_character_sizes() @@ -108,7 +113,7 @@ void font_face_set::set_unscaled_character_sizes() void stroker::init(double radius) { - FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)), + FT_Stroker_Set(s_, static_cast(radius * (1<<6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); diff --git a/src/text/font_library.cpp b/src/text/font_library.cpp index 2bdb4ba48..37fd6a43b 100644 --- a/src/text/font_library.cpp +++ b/src/text/font_library.cpp @@ -28,6 +28,9 @@ #include #include +#pragma GCC diagnostic push +#include + // freetype2 extern "C" { @@ -36,6 +39,8 @@ extern "C" #include FT_MODULE_H } +#pragma GCC diagnostic pop + namespace { void* _Alloc_Func(FT_Memory, long size) diff --git a/src/text/formatting/format.cpp b/src/text/formatting/format.cpp index 8e0fef52d..8a6a8cc9d 100644 --- a/src/text/formatting/format.cpp +++ b/src/text/formatting/format.cpp @@ -30,9 +30,11 @@ #include #include -//boost +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop namespace mapnik { namespace formatting { diff --git a/src/text/formatting/layout.cpp b/src/text/formatting/layout.cpp index 19da033fc..9a5ca10aa 100644 --- a/src/text/formatting/layout.cpp +++ b/src/text/formatting/layout.cpp @@ -35,8 +35,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { namespace formatting { @@ -73,9 +75,9 @@ node_ptr layout_node::from_xml(xml_node const& xml, fontset_map const& fontsets) if (xml.has_attribute("text-ratio")) set_property_from_xml(n->text_ratio, "text-ratio", xml); if (xml.has_attribute("wrap-width")) set_property_from_xml(n->wrap_width, "wrap-width", xml); if (xml.has_attribute("wrap-character")) set_property_from_xml(n->wrap_char, "wrap-character", xml); - if (xml.has_attribute("wrap-before")) set_property_from_xml(n->wrap_before, "wrap-before", xml); - if (xml.has_attribute("repeat-wrap-character")) set_property_from_xml(n->repeat_wrap_char, "repeat-wrap-character", xml); - if (xml.has_attribute("rotate-displacement")) set_property_from_xml(n->rotate_displacement, "rotate-displacement", xml); + if (xml.has_attribute("wrap-before")) set_property_from_xml(n->wrap_before, "wrap-before", xml); + if (xml.has_attribute("repeat-wrap-character")) set_property_from_xml(n->repeat_wrap_char, "repeat-wrap-character", xml); + if (xml.has_attribute("rotate-displacement")) set_property_from_xml(n->rotate_displacement, "rotate-displacement", xml); if (xml.has_attribute("orientation")) set_property_from_xml(n->orientation, "orientation", xml); if (xml.has_attribute("horizontal-alignment")) set_property_from_xml(n->halign, "horizontal-alignment", xml); if (xml.has_attribute("vertical-alignment")) set_property_from_xml(n->valign, "vertical-alignment", xml); diff --git a/src/text/formatting/list.cpp b/src/text/formatting/list.cpp index 89e9d2373..4bf7c4d2d 100644 --- a/src/text/formatting/list.cpp +++ b/src/text/formatting/list.cpp @@ -25,8 +25,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { using boost::property_tree::ptree; diff --git a/src/text/formatting/text.cpp b/src/text/formatting/text.cpp index c24aab123..3158f20e2 100644 --- a/src/text/formatting/text.cpp +++ b/src/text/formatting/text.cpp @@ -30,8 +30,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/text/glyph_positions.cpp b/src/text/glyph_positions.cpp index da3b30084..fdcb3a811 100644 --- a/src/text/glyph_positions.cpp +++ b/src/text/glyph_positions.cpp @@ -74,7 +74,7 @@ void glyph_positions::set_marker(marker_info_ptr mark, pixel_position const& mar marker_pos_ = marker_pos; } -marker_info_ptr glyph_positions::get_marker() const +marker_info_ptr const& glyph_positions::get_marker() const { return marker_info_; } diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index 04a290757..e4adddf3e 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -39,6 +39,41 @@ namespace mapnik { +namespace { +box2d get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot) +{ + /* + + (0/ymax) (width/ymax) + *************** + * * + (0/0)* * + * * + *************** + (0/ymin) (width/ymin) + Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)! + */ + double width = layout.cluster_width(glyph.char_index); + if (glyph.advance() <= 0) width = -width; + pixel_position tmp, tmp2; + tmp.set(0, glyph.ymax()); + tmp = tmp.rotate(rot); + tmp2.set(width, glyph.ymax()); + tmp2 = tmp2.rotate(rot); + box2d bbox(tmp.x, -tmp.y, + tmp2.x, -tmp2.y); + tmp.set(width, glyph.ymin()); + tmp = tmp.rotate(rot); + bbox.expand_to_include(tmp.x, -tmp.y); + tmp.set(0, glyph.ymin()); + tmp = tmp.rotate(rot); + bbox.expand_to_include(tmp.x, -tmp.y); + pixel_position pos2 = pos + pixel_position(0, glyph.offset.y).rotate(rot); + bbox.move(pos2.x , -pos2.y); + return bbox; +} +} // anonymous namespace + placement_finder::placement_finder(feature_impl const& feature, attributes const& attr, DetectorType &detector, @@ -432,37 +467,4 @@ bool placement_finder::add_marker(glyph_positions_ptr & glyphs, pixel_position c return true; } -box2d placement_finder::get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot) -{ - /* - - (0/ymax) (width/ymax) - *************** - * * - (0/0)* * - * * - *************** - (0/ymin) (width/ymin) - Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)! - */ - double width = layout.cluster_width(glyph.char_index); - if (glyph.advance() <= 0) width = -width; - pixel_position tmp, tmp2; - tmp.set(0, glyph.ymax()); - tmp = tmp.rotate(rot); - tmp2.set(width, glyph.ymax()); - tmp2 = tmp2.rotate(rot); - box2d bbox(tmp.x, -tmp.y, - tmp2.x, -tmp2.y); - tmp.set(width, glyph.ymin()); - tmp = tmp.rotate(rot); - bbox.expand_to_include(tmp.x, -tmp.y); - tmp.set(0, glyph.ymin()); - tmp = tmp.rotate(rot); - bbox.expand_to_include(tmp.x, -tmp.y); - pixel_position pos2 = pos + pixel_position(0, glyph.offset.y).rotate(rot); - bbox.move(pos2.x , -pos2.y); - return bbox; -} - }// ns mapnik diff --git a/src/text/placements/list.cpp b/src/text/placements/list.cpp index 65c729b84..7d609f2c4 100644 --- a/src/text/placements/list.cpp +++ b/src/text/placements/list.cpp @@ -24,8 +24,10 @@ #include #include -//boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/text/renderer.cpp b/src/text/renderer.cpp index 227c35dbe..163d11c6f 100644 --- a/src/text/renderer.cpp +++ b/src/text/renderer.cpp @@ -60,7 +60,9 @@ void text_renderer::prepare_glyphs(glyph_positions const& positions) FT_Vector pen; FT_Error error; + glyphs_.clear(); glyphs_.reserve(positions.size()); + for (auto const& glyph_pos : positions) { glyph_info const& glyph = glyph_pos.glyph; @@ -121,7 +123,6 @@ agg_text_renderer::agg_text_renderer (pixmap_type & pixmap, template void agg_text_renderer::render(glyph_positions const& pos) { - glyphs_.clear(); prepare_glyphs(pos); FT_Error error; FT_Vector start; @@ -232,7 +233,6 @@ void agg_text_renderer::render(glyph_positions const& pos) template void grid_text_renderer::render(glyph_positions const& pos, value_integer feature_id) { - glyphs_.clear(); prepare_glyphs(pos); FT_Error error; FT_Vector start; diff --git a/src/text/scrptrun.cpp b/src/text/scrptrun.cpp index 37a02e7c8..0cbb2c839 100644 --- a/src/text/scrptrun.cpp +++ b/src/text/scrptrun.cpp @@ -14,8 +14,11 @@ * http://source.icu-project.org/repos/icu/icu/trunk/license.html */ +#pragma GCC diagnostic push +#include #include #include +#pragma GCC diagnostic pop #include diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index 1d0fe48d2..fe5568ad2 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -41,8 +41,39 @@ #include #include +namespace mapnik { +namespace geometry { -namespace mapnik { namespace detail { +struct envelope_impl +{ + template + box2d operator() (T const& ref) const + { + return envelope(ref); + } +}; + +mapnik::box2d envelope(mapnik::base_symbolizer_helper::geometry_cref const& geom) +{ + return mapnik::util::apply_visitor(envelope_impl(), geom); +} + +struct geometry_type_impl +{ + template + auto operator() (T const& ref) const -> decltype(geometry_type(ref)) + { + return geometry_type(ref); + } +}; + +mapnik::geometry::geometry_types geometry_type(mapnik::base_symbolizer_helper::geometry_cref const& geom) +{ + return mapnik::util::apply_visitor(geometry_type_impl(), geom); +} + +} // geometry +namespace detail { template struct apply_vertex_placement @@ -389,7 +420,7 @@ bool text_symbolizer_helper::next_point_placement() const return true; } //No placement for this point. Keep it in points_ for next try. - point_itr_++; + ++point_itr_; } return false; } @@ -434,7 +465,7 @@ void text_symbolizer_helper::init_marker() const if (marker->is()) return; agg::trans_affine trans; auto image_transform = get_optional(sym_, keys::image_transform); - if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform); + if (image_transform) evaluate_transform(trans, feature_, vars_, *image_transform, scale_factor_); double width = marker->width(); double height = marker->height(); double px0 = - 0.5 * width; @@ -460,7 +491,6 @@ void text_symbolizer_helper::init_marker() const finder_.set_marker(std::make_shared(marker, trans), bbox, unlock_image, marker_displacement); } - template text_symbolizer_helper::text_symbolizer_helper( text_symbolizer const& sym, feature_impl const& feature, diff --git a/src/text/text_layout.cpp b/src/text/text_layout.cpp index ff37d28e2..3a3818c1f 100644 --- a/src/text/text_layout.cpp +++ b/src/text/text_layout.cpp @@ -29,8 +29,11 @@ #include #include -// ICU +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop + #include namespace mapnik diff --git a/src/text/text_line.cpp b/src/text/text_line.cpp index f228e5b93..2d0516731 100644 --- a/src/text/text_line.cpp +++ b/src/text/text_line.cpp @@ -51,7 +51,7 @@ text_line::text_line(text_line && rhs) void text_line::add_glyph(glyph_info && glyph, double scale_factor_) { - line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing); + line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing * scale_factor_); double advance = glyph.advance(); if (glyphs_.empty()) { diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 4b08c106b..73210d109 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -34,8 +34,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { @@ -101,9 +103,9 @@ void text_symbolizer_properties::text_properties_from_xml(xml_node const& node) set_property_from_xml(expressions.label_position_tolerance, "label-position-tolerance", node); set_property_from_xml(expressions.minimum_padding, "minimum-padding", node); set_property_from_xml(expressions.minimum_path_length, "minimum-path-length", node); - set_property_from_xml(expressions.avoid_edges, "avoid-edges", node); - set_property_from_xml(expressions.allow_overlap, "allow-overlap", node); - set_property_from_xml(expressions.largest_bbox_only, "largest-bbox-only", node); + set_property_from_xml(expressions.avoid_edges, "avoid-edges", node); + set_property_from_xml(expressions.allow_overlap, "allow-overlap", node); + set_property_from_xml(expressions.largest_bbox_only, "largest-bbox-only", node); set_property_from_xml(expressions.max_char_angle_delta, "max-char-angle-delta", node); set_property_from_xml(expressions.upright, "upright", node); } @@ -213,9 +215,9 @@ void text_layout_properties::from_xml(xml_node const &node, fontset_map const& f set_property_from_xml(text_ratio, "text-ratio", node); set_property_from_xml(wrap_width, "wrap-width", node); set_property_from_xml(wrap_char, "wrap-character", node); - set_property_from_xml(wrap_before, "wrap-before", node); - set_property_from_xml(repeat_wrap_char, "repeat-wrap-character", node); - set_property_from_xml(rotate_displacement, "rotate-displacement", node); + set_property_from_xml(wrap_before, "wrap-before", node); + set_property_from_xml(repeat_wrap_char, "repeat-wrap-character", node); + set_property_from_xml(rotate_displacement, "rotate-displacement", node); set_property_from_xml(orientation, "orientation", node); set_property_from_xml(valign, "vertical-alignment", node); set_property_from_xml(halign, "horizontal-alignment", node); diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index 37e59b556..157e4d0cb 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -23,21 +23,15 @@ // mapnik #include #include - +#include extern "C" { #include } -#pragma GCC diagnostic push -#include -#include -#include -#include -#pragma GCC diagnostic pop - // stl #include +#include namespace mapnik { namespace impl { @@ -106,7 +100,7 @@ class tiff_reader : public image_reader { using tiff_ptr = std::shared_ptr; using source_type = T; - using input_stream = boost::iostreams::stream; + using input_stream = std::istream; struct tiff_closer { @@ -145,7 +139,7 @@ public: stripped, tiled }; - explicit tiff_reader(std::string const& file_name); + explicit tiff_reader(std::string const& filename); tiff_reader(char const* data, std::size_t size); virtual ~tiff_reader(); unsigned width() const final; @@ -183,14 +177,14 @@ private: namespace { -image_reader* create_tiff_reader(std::string const& file) +image_reader* create_tiff_reader(std::string const& filename) { - return new tiff_reader(file); + return new tiff_reader(filename); } image_reader* create_tiff_reader2(char const * data, std::size_t size) { - return new tiff_reader(data, size); + return new tiff_reader(data, size); } const bool registered = register_image_reader("tiff",create_tiff_reader); @@ -199,9 +193,9 @@ const bool registered2 = register_image_reader("tiff", create_tiff_reader2); } template -tiff_reader::tiff_reader(std::string const& file_name) - : source_(file_name, std::ios_base::in | std::ios_base::binary), - stream_(source_), +tiff_reader::tiff_reader(std::string const& filename) + : source_(), + stream_(&source_), tif_(nullptr), read_method_(generic), rows_per_strip_(0), @@ -218,14 +212,15 @@ tiff_reader::tiff_reader(std::string const& file_name) has_alpha_(false), is_tiled_(false) { - if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ file_name); + source_.open(filename, std::ios_base::in | std::ios_base::binary); + if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ filename); init(); } template tiff_reader::tiff_reader(char const* data, std::size_t size) : source_(data, size), - stream_(source_), + stream_(&source_), tif_(nullptr), read_method_(generic), rows_per_strip_(0), @@ -243,8 +238,6 @@ tiff_reader::tiff_reader(char const* data, std::size_t size) is_tiled_(false) { if (!stream_) throw image_reader_exception("TIFF reader: cannot open image stream "); - stream_.rdbuf()->pubsetbuf(0, 0); - stream_.seekg(0, std::ios::beg); init(); } @@ -598,13 +591,9 @@ image_any tiff_reader::read(unsigned x, unsigned y, unsigned width, unsigned } template -void tiff_reader::read_generic(std::size_t, std::size_t, image_rgba8& image) +void tiff_reader::read_generic(std::size_t, std::size_t, image_rgba8&) { - TIFF* tif = open(stream_); - if (tif) - { - throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled"); - } + throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled"); } template diff --git a/src/twkb.cpp b/src/twkb.cpp new file mode 100644 index 000000000..f1928e5a6 --- /dev/null +++ b/src/twkb.cpp @@ -0,0 +1,387 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + + +// mapnik +#include +#include +#include +#include +#include +#include + +namespace mapnik { namespace detail { + +struct twkb_reader : mapnik::util::noncopyable +{ +private: + const char *twkb_; + size_t size_; + unsigned int pos_; + // Metadata on the geometry we are parsing + uint8_t twkb_type_; + uint8_t has_bbox_; + uint8_t has_size_; + uint8_t has_idlist_; + uint8_t has_z_; + uint8_t has_m_; + uint8_t is_empty_; + // Precision factors to convert ints to double + double factor_xy_; + double factor_z_; + double factor_m_; + // An array to keep delta values from 4 dimensions + int64_t coord_x_; + int64_t coord_y_; + int64_t coord_z_; + int64_t coord_m_; + +public: + enum twkbGeometryType : std::uint8_t + { + twkbPoint = 1, + twkbLineString = 2, + twkbPolygon = 3, + twkbMultiPoint = 4, + twkbMultiLineString = 5, + twkbMultiPolygon = 6, + twkbGeometryCollection = 7 + }; + + twkb_reader(char const* twkb, size_t size) + : twkb_(twkb), size_(size), pos_(0), twkb_type_(0), // Geometry type + has_bbox_(0), // Bounding box? + has_size_(0), // Size attribute? + has_idlist_(0), // Presence of X/Y + has_z_(0), // Presence of Z + has_m_(0), // Presence of M + is_empty_(0), // Empty? + factor_xy_(0.0), // Expansion factor for X/Y + factor_z_(0.0), // Expansion factor for Z + factor_m_(0.0) // Expansion factor for M + {} + + mapnik::geometry::geometry read() + { + mapnik::geometry::geometry geom = mapnik::geometry::geometry_empty(); + // Read the metadata bytes, populating all the + // information about optional fields, extended (z/m) dimensions + // expansion factors and so on + read_header(); + + // Each new read call has to reset the coordinate accumulators + coord_x_ = 0; // Accumulation register (x) + coord_y_ = 0; // Accumulation register (y) + coord_z_ = 0; // Accumulation register (z) + coord_m_ = 0; // Accumulation register (m) + + // If the geometry is empty, add nothing to the paths array + if (is_empty_) + return geom; + + // Read the [optional] size information + if (has_size_) + size_ = read_unsigned_integer(); + + // Read the [optional] bounding box information + if (has_bbox_) read_bbox(); + + switch (twkb_type_) + { + case twkbPoint: + geom = read_point(); + break; + case twkbLineString: + geom = read_linestring(); + break; + case twkbPolygon: + geom = read_polygon(); + break; + case twkbMultiPoint: + geom = read_multipoint(); + break; + case twkbMultiLineString: + geom = read_multilinestring(); + break; + case twkbMultiPolygon: + geom = read_multipolygon(); + break; + case twkbGeometryCollection: + geom = read_collection(); + default: + break; + } + return geom; + } + +private: + int64_t unzigzag64(uint64_t val) + { + if (val & 0x01) + return -1 * (int64_t)((val + 1) >> 1); + else + return (int64_t)(val >> 1); + } + + int32_t unzigzag32(uint32_t val) + { + if (val & 0x01) return -1 * (int32_t)((val + 1) >> 1); + else return (int32_t)(val >> 1); + } + + int8_t unzigzag8(uint8_t val) + { + if (val & 0x01) return -1 * (int8_t)((val + 1) >> 1); + else return (int8_t)(val >> 1); + } + + // Read from signed 64bit varint + int64_t read_signed_integer() { return unzigzag64(read_unsigned_integer()); } + + // Read from unsigned 64bit varint + uint64_t read_unsigned_integer() + { + uint64_t nVal = 0; + int nShift = 0; + uint8_t nByte; + + // Check so we don't read beyond the twkb + while (pos_ < size_) + { + nByte = twkb_[pos_]; + // We get here when there is more to read in the input varInt + // Here we take the least significant 7 bits of the read + // byte and put it in the most significant place in the result variable. + nVal |= ((uint64_t)(nByte & 0x7f)) << nShift; + // move the "cursor" of the input buffer step (8 bits) + pos_++; + // move the cursor in the resulting variable (7 bits) + nShift += 7; + // Hibit isn't set, so this is the last byte + if (!(nByte & 0x80)) { + return nVal; + } + } + return 0; + } + + // Every TWKB geometry starts with a metadata header + // + // type_and_dims byte + // metadata_header byte + // [extended_dims] byte + // [size] uvarint + // [bounds] bbox + // + void read_header() + { + uint8_t type_precision = twkb_[pos_++]; + uint8_t metadata = twkb_[pos_++]; + twkb_type_ = type_precision & 0x0F; + int8_t precision = unzigzag8((type_precision & 0xF0) >> 4); + factor_xy_ = std::pow(10, static_cast(precision)); + has_bbox_ = metadata & 0x01; + has_size_ = (metadata & 0x02) >> 1; + has_idlist_ = (metadata & 0x04) >> 2; + uint8_t zm = (metadata & 0x08) >> 3; + is_empty_ = (metadata & 0x10) >> 4; + + // Flag for higher dimensions means read a third byte + // of extended dimension information + if (zm) + { + zm = twkb_[pos_++]; + // Strip Z/M presence and precision from ext byte + has_z_ = (zm & 0x01); + has_m_ = (zm & 0x02) >> 1; + // Convert the precision into factor + int8_t precision_z = (zm & 0x1C) >> 2; + int8_t precision_m = (zm & 0xE0) >> 5; + factor_z_ = pow(10, (double)precision_z); + factor_m_ = pow(10, (double)precision_m); + } + } + + void read_bbox() + { + // we have nowhere to store this box information + // for now, so we'll just move the read head forward + // an appropriate number of times + if (has_bbox_) + { + read_signed_integer(); // uint64_t xmin + read_signed_integer(); // uint64_t xdelta + read_signed_integer(); // uint64_t ymin + read_signed_integer(); // uint64_t ydelta + if (has_z_) + { + read_signed_integer(); // uint64_t zmin + read_signed_integer(); // uint64_t zdelta + } + if (has_m_) + { + read_signed_integer(); // uint64_t mmin + read_signed_integer(); // uint64_t mdelta + } + } + } + + void read_idlist(unsigned int num_ids) + { + // we have nowhere to store this id information + // for now, so we'll just move the read head + // forward an appropriate number of times + if (has_idlist_) + { + for (unsigned int i = 0; i < num_ids; ++i) + { + read_signed_integer(); // uint64_t id + } + } + } + + template + void read_coords(Ring & ring, std::size_t num_points) + { + for (std::size_t i = 0; i < num_points; ++i) + { + coord_x_ += read_signed_integer(); + coord_y_ += read_signed_integer(); + ring.emplace_back( coord_x_ / factor_xy_, coord_y_ / factor_xy_); + // Skip Z and M + if (has_z_) coord_z_ += read_signed_integer(); + if (has_m_) coord_m_ += read_signed_integer(); + } + } + + mapnik::geometry::point read_point() + { + coord_x_ += read_signed_integer(); + coord_y_ += read_signed_integer(); + double x = coord_x_ / factor_xy_; + double y = coord_y_ / factor_xy_; + return mapnik::geometry::point(x, y); + } + + mapnik::geometry::multi_point read_multipoint() + { + mapnik::geometry::multi_point multi_point; + unsigned int num_points = read_unsigned_integer(); + if (has_idlist_) read_idlist(num_points); + + if (num_points > 0) + { + multi_point.reserve(num_points); + for (unsigned int i = 0; i < num_points; ++i) + { + multi_point.emplace_back(read_point()); + } + } + return multi_point; + } + + mapnik::geometry::line_string read_linestring() + { + mapnik::geometry::line_string line; + unsigned int num_points = read_unsigned_integer(); + if (num_points > 0) + { + line.reserve(num_points); + read_coords>(line, num_points); + } + return line; + } + + mapnik::geometry::multi_line_string read_multilinestring() + { + mapnik::geometry::multi_line_string multi_line; + unsigned int num_lines = read_unsigned_integer(); + if (has_idlist_) read_idlist(num_lines); + multi_line.reserve(num_lines); + for (unsigned int i = 0; i < num_lines; ++i) + { + multi_line.push_back(read_linestring()); + } + return multi_line; + } + + mapnik::geometry::polygon read_polygon() + { + unsigned int num_rings = read_unsigned_integer(); + mapnik::geometry::polygon poly; + if (num_rings > 1) + { + poly.interior_rings.reserve(num_rings - 1); + } + + for (unsigned int i = 0; i < num_rings; ++i) + { + mapnik::geometry::linear_ring ring; + unsigned int num_points = read_unsigned_integer(); + if (num_points > 0) + { + ring.reserve(num_points); + read_coords>(ring, num_points); + } + if ( i == 0) poly.set_exterior_ring(std::move(ring)); + else poly.add_hole(std::move(ring)); + } + return poly; + } + + mapnik::geometry::multi_polygon read_multipolygon() + { + mapnik::geometry::multi_polygon multi_poly; + unsigned int num_polys = read_unsigned_integer(); + if (has_idlist_) read_idlist(num_polys); + for (unsigned int i = 0; i < num_polys; ++i) + { + multi_poly.push_back(read_polygon()); + } + return multi_poly; + } + + mapnik::geometry::geometry_collection read_collection() + { + unsigned int num_geometries = read_unsigned_integer(); + mapnik::geometry::geometry_collection collection; + if (has_idlist_) read_idlist(num_geometries); + for (unsigned int i = 0; i < num_geometries; ++i) + { + collection.push_back(read()); + } + return collection; + } +}; + +} // namespace detail + +mapnik::geometry::geometry geometry_utils::from_twkb(const char* wkb, std::size_t size) +{ + detail::twkb_reader reader(wkb, size); + mapnik::geometry::geometry geom(reader.read()); + // note: this will only be applied to polygons + mapnik::geometry::correct(geom); + return geom; +} + +} // namespace mapnik diff --git a/src/unicode.cpp b/src/unicode.cpp index dac9b29d7..c96c58914 100644 --- a/src/unicode.cpp +++ b/src/unicode.cpp @@ -27,8 +27,10 @@ // std #include -// icu +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { @@ -60,4 +62,12 @@ transcoder::~transcoder() { if (conv_) ucnv_close(conv_); } + + +void to_utf8(mapnik::value_unicode_string const& input, std::string & target) +{ + target.clear(); // mimic previous target.assign(...) semantics + input.toUTF8String(target); // this appends to target +} + } diff --git a/src/value.cpp b/src/value.cpp new file mode 100644 index 000000000..b5ad606c7 --- /dev/null +++ b/src/value.cpp @@ -0,0 +1,928 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include +#include + +// stl +#include +#include +#include +// icu +#include +#include + +namespace mapnik { + +namespace detail { + +namespace { +template +struct both_arithmetic : std::integral_constant::value && + std::is_arithmetic::value> {}; + +struct equals +{ + static bool apply(value_null, value_unicode_string const& rhs) + { + return false; + } + + template + static auto apply(T const& lhs, T const& rhs) + -> decltype(lhs == rhs) + { + return lhs == rhs; + } +}; + +struct not_equal +{ + // back compatibility shim to equate empty string with null for != test + // https://github.com/mapnik/mapnik/issues/1859 + // TODO - consider removing entire specialization at Mapnik 3.1.x + static bool apply(value_null, value_unicode_string const& rhs) + { + if (rhs.isEmpty()) return false; + return true; + } + + template + static auto apply(T const& lhs, T const& rhs) + -> decltype(lhs != rhs) + { + return lhs != rhs; + } +}; + +struct greater_than +{ + static bool apply(value_null, value_unicode_string const& rhs) + { + return false; + } + + template + static auto apply(T const& lhs, T const& rhs) + -> decltype(lhs > rhs) + { + return lhs > rhs; + } +}; + +struct greater_or_equal +{ + static bool apply(value_null, value_unicode_string const& rhs) + { + return false; + } + + template + static auto apply(T const& lhs, T const& rhs) + -> decltype(lhs >= rhs) + { + return lhs >= rhs; + } +}; + +struct less_than +{ + static bool apply(value_null, value_unicode_string const& rhs) + { + return false; + } + + template + static auto apply(T const& lhs, T const& rhs) + -> decltype(lhs < rhs) + { + return lhs < rhs; + } +}; + +struct less_or_equal +{ + static bool apply(value_null, value_unicode_string const& rhs) + { + return false; + } + + template + static auto apply(T const& lhs, T const& rhs) + -> decltype(lhs <= rhs) + { + return lhs <= rhs; + } +}; +} + +template +struct comparison +{ + // special case for unicode_strings (fixes MSVC C4800) + bool operator()(value_unicode_string const& lhs, + value_unicode_string const& rhs) const + { + return Op::apply(lhs, rhs) ? true : false; + } + + ////////////////////////////////////////////////////////////////////////// + // special case for unicode_string and value_null + ////////////////////////////////////////////////////////////////////////// + + bool operator()(value_null const& lhs, value_unicode_string const& rhs) const + { + return Op::apply(lhs, rhs); + } + ////////////////////////////////////////////////////////////////////////// + + // same types + template + bool operator()(T lhs, T rhs) const + { + return Op::apply(lhs, rhs); + } + + // both types are arithmetic - promote to the common type + template ::value, int>::type = 0> + bool operator()(T const& lhs, U const& rhs) const + { + using common_type = typename std::common_type::type; + return Op::apply(static_cast(lhs), static_cast(rhs)); + } + + // + template ::value, int>::type = 0> + bool operator()(T const& lhs, U const& rhs) const + { + return default_result; + } +}; + +template +struct add +{ + using value_type = V; + value_type operator()(value_unicode_string const& lhs, + value_unicode_string const& rhs) const + { + return lhs + rhs; + } + + value_type operator()(value_null const& lhs, + value_null const& rhs) const + { + return lhs; + } + + value_type operator()(value_unicode_string const& lhs, value_null) const + { + return lhs; + } + + value_type operator()(value_null, value_unicode_string const& rhs) const + { + return rhs; + } + + template + value_type operator()(L const& lhs, value_null const&) const + { + return lhs; + } + + template + value_type operator()(value_null const&, R const& rhs) const + { + return rhs; + } + + template + value_type operator()(L const& lhs, value_unicode_string const& rhs) const + { + std::string val; + if (util::to_string(val, lhs)) + return value_unicode_string(val.c_str()) + rhs; + return rhs; + } + + template + value_type operator()(value_unicode_string const& lhs, R const& rhs) const + { + std::string val; + if (util::to_string(val, rhs)) + return lhs + value_unicode_string(val.c_str()); + return lhs; + } + + template + value_type operator()(T1 const& lhs, T2 const& rhs) const + { + return typename std::common_type::type{lhs + rhs}; + } + + value_type operator()(value_bool lhs, value_bool rhs) const + { + return value_integer(lhs + rhs); + } +}; + +template +struct sub +{ + using value_type = V; + + value_type operator()(value_null const& lhs, + value_null const& rhs) const + { + return lhs; + } + + value_type operator()(value_null, value_unicode_string const& rhs) const + { + return rhs; + } + value_type operator()(value_unicode_string const& lhs, value_null) const + { + return lhs; + } + + template + value_type operator()(value_unicode_string const& lhs, R const&) const + { + return lhs; + } + + template + value_type operator()(L const&, value_unicode_string const& rhs) const + { + return rhs; + } + + template + value_type operator()(L const& lhs, value_null const&) const + { + return lhs; + } + + template + value_type operator()(value_null const&, R const& rhs) const + { + return rhs; + } + + template + value_type operator()(T lhs, T rhs) const + { + return lhs - rhs; + } + + value_type operator()(value_unicode_string const&, + value_unicode_string const&) const + { + return value_type(); + } + + template + value_type operator()(T1 const& lhs, T2 const& rhs) const + { + return typename std::common_type::type{lhs - rhs}; + } + + value_type operator()(value_bool lhs, value_bool rhs) const + { + return value_integer(lhs - rhs); + } +}; + +template +struct mult +{ + using value_type = V; + + value_type operator()(value_null const& lhs, + value_null const& rhs) const + { + return lhs; + } + + value_type operator()(value_unicode_string const& lhs, value_null) const + { + return lhs; + } + + value_type operator()(value_null, value_unicode_string const& rhs) const + { + return rhs; + } + + template + value_type operator()(L const& lhs, value_null const&) const + { + return lhs; + } + + template + value_type operator()(value_null const&, R const& rhs) const + { + return rhs; + } + + template + value_type operator()(value_unicode_string const& lhs, R const&) const + { + return lhs; + } + + template + value_type operator()(L const&, value_unicode_string const& rhs) const + { + return rhs; + } + + template + value_type operator()(T lhs, T rhs) const + { + return lhs * rhs; + } + + value_type operator()(value_unicode_string const&, + value_unicode_string const&) const + { + return value_type(); + } + + template + value_type operator()(T1 const& lhs, T2 const& rhs) const + { + return typename std::common_type::type{lhs * rhs}; + } + + value_type operator()(value_bool lhs, value_bool rhs) const + { + return value_integer(lhs * rhs); + } +}; + +template +struct div +{ + using value_type = V; + + value_type operator()(value_null const& lhs, + value_null const& rhs) const + { + return lhs; + } + + value_type operator()(value_unicode_string const& lhs, value_null) const + { + return lhs; + } + + value_type operator()(value_null, value_unicode_string const& rhs) const + { + return rhs; + } + + template + value_type operator()(L const& lhs, value_null const&) const + { + return lhs; + } + + template + value_type operator()(value_null const&, R const& rhs) const + { + return rhs; + } + + template + value_type operator()(T lhs, T rhs) const + { + if (rhs == 0) return value_type(); + return lhs / rhs; + } + + value_type operator()(value_bool lhs, value_bool rhs) const + { + if (rhs == 0) return lhs; + return value_integer(lhs) / value_integer(rhs); + } + + value_type operator()(value_unicode_string const&, + value_unicode_string const&) const + { + return value_type(); + } + + template + value_type operator()(value_unicode_string const& lhs, R const&) const + { + return lhs; + } + + template + value_type operator()(L const&, value_unicode_string const& rhs) const + { + return rhs; + } + + template + value_type operator()(T1 const& lhs, T2 const& rhs) const + { + if (rhs == 0) return value_type(); + using common_type = typename std::common_type::type; + return common_type(lhs) / common_type(rhs); + } +}; + +template +struct mod +{ + using value_type = V; + + template + value_type operator()(T1 const& lhs, T2 const&) const + { + return lhs; + } + + template + value_type operator()(T lhs, T rhs) const + { + return lhs % rhs; + } + + value_type operator()(value_unicode_string const&, + value_unicode_string const&) const + { + return value_type(); + } + + value_type operator()(value_bool, + value_bool) const + { + return false; + } + + value_type operator()(value_double lhs, value_integer rhs) const + { + return std::fmod(lhs, static_cast(rhs)); + } + + value_type operator()(value_integer lhs, value_double rhs) const + { + return std::fmod(static_cast(lhs), rhs); + } + + value_type operator()(value_double lhs, value_double rhs) const + { + return std::fmod(lhs, rhs); + } +}; + +template +struct negate +{ + using value_type = V; + + template + value_type operator()(T val) const + { + return -val; + } + + value_type operator()(value_null val) const + { + return val; + } + + value_type operator()(value_bool val) const + { + return val ? value_integer(-1) : value_integer(0); + } + + value_type operator()(value_unicode_string const&) const + { + return value_type(); + } +}; + +// converters +template +struct convert +{ +}; + +template <> +struct convert +{ + value_bool operator()(value_bool val) const + { + return val; + } + + value_bool operator()(value_unicode_string const& ustr) const + { + return !ustr.isEmpty(); + } + + value_bool operator()(value_null const&) const + { + return false; + } + + template + value_bool operator()(T val) const + { + return val > 0 ? true : false; + } +}; + +template <> +struct convert +{ + value_double operator()(value_double val) const + { + return val; + } + + value_double operator()(value_integer val) const + { + return static_cast(val); + } + + value_double operator()(value_bool val) const + { + return static_cast(val); + } + + value_double operator()(std::string const& val) const + { + value_double result; + if (util::string2double(val, result)) + return result; + return 0; + } + + value_double operator()(value_unicode_string const& val) const + { + std::string utf8; + val.toUTF8String(utf8); + return operator()(utf8); + } + + value_double operator()(value_null const&) const + { + return 0.0; + } +}; + +template <> +struct convert +{ + value_integer operator()(value_integer val) const + { + return val; + } + + value_integer operator()(value_double val) const + { + return static_cast(rint(val)); + } + + value_integer operator()(value_bool val) const + { + return static_cast(val); + } + + value_integer operator()(std::string const& val) const + { + value_integer result; + if (util::string2int(val, result)) + return result; + return value_integer(0); + } + + value_integer operator()(value_unicode_string const& val) const + { + std::string utf8; + val.toUTF8String(utf8); + return operator()(utf8); + } + + value_integer operator()(value_null const&) const + { + return value_integer(0); + } +}; + +template <> +struct convert +{ + template + std::string operator()(T val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + // specializations + std::string operator()(value_unicode_string const& val) const + { + std::string utf8; + val.toUTF8String(utf8); + return utf8; + } + + std::string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); // TODO set precision(16) + return str; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_null const&) const + { + return std::string(""); + } +}; + +struct to_unicode_impl +{ + + template + value_unicode_string operator()(T val) const + { + std::string str; + util::to_string(str, val); + return value_unicode_string(str.c_str()); + } + + // specializations + value_unicode_string const& operator()(value_unicode_string const& val) const + { + return val; + } + + value_unicode_string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); + return value_unicode_string(str.c_str()); + } + + value_unicode_string operator()(value_bool val) const + { + return value_unicode_string(val ? "true" : "false"); + } + + value_unicode_string operator()(value_null const&) const + { + return value_unicode_string(""); + } +}; + +struct to_expression_string_impl +{ + struct EscapingByteSink : U_NAMESPACE_QUALIFIER ByteSink + { + std::string dest_; + char quote_; + + explicit EscapingByteSink(char quote) + : quote_(quote) + { + } + + virtual void Append(const char* data, int32_t n) + { + // reserve enough room to hold the appended chunk and quotes; + // if another chunk follows, or any character needs escaping, + // the string will grow naturally + if (dest_.empty()) + { + dest_.reserve(2 + static_cast(n)); + dest_.append(1, quote_); + } + else + { + dest_.reserve(dest_.size() + n + 1); + } + + for (auto end = data + n; data < end; ++data) + { + if (*data == '\\' || *data == quote_) + dest_.append(1, '\\'); + dest_.append(1, *data); + } + } + + virtual void Flush() + { + if (dest_.empty()) + dest_.append(2, quote_); + else + dest_.append(1, quote_); + } + }; + + explicit to_expression_string_impl(char quote = '\'') + : quote_(quote) {} + + std::string operator()(value_unicode_string const& val) const + { + // toUTF8(sink) doesn't Flush() the sink if the source string + // is empty -- we must return a pair of quotes in that case + // https://github.com/mapnik/mapnik/issues/3362 + if (val.isEmpty()) + { + return std::string(2, quote_); + } + EscapingByteSink sink(quote_); + val.toUTF8(sink); + return sink.dest_; + } + + std::string operator()(value_integer val) const + { + std::string output; + util::to_string(output, val); + return output; + } + + std::string operator()(value_double val) const + { + std::string output; + util::to_string(output, val); // TODO precision(16) + return output; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_null const&) const + { + return "null"; + } + + const char quote_; +}; + +} // ns detail + +namespace value_adl_barrier { + +bool value::operator==(value const& other) const +{ + return util::apply_visitor(detail::comparison(), *this, other); +} + +bool value::operator!=(value const& other) const +{ + return util::apply_visitor(detail::comparison(), *this, other); +} + +bool value::operator>(value const& other) const +{ + return util::apply_visitor(detail::comparison(), *this, other); +} + +bool value::operator>=(value const& other) const +{ + return util::apply_visitor(detail::comparison(), *this, other); +} + +bool value::operator<(value const& other) const +{ + return util::apply_visitor(detail::comparison(), *this, other); +} + +bool value::operator<=(value const& other) const +{ + return util::apply_visitor(detail::comparison(), *this, other); +} + +value value::operator-() const +{ + return util::apply_visitor(detail::negate(), *this); +} + +value_bool value::to_bool() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +std::string value::to_expression_string(char quote) const +{ + return util::apply_visitor(detail::to_expression_string_impl(quote), *this); +} + +std::string value::to_string() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +value_unicode_string value::to_unicode() const +{ + return util::apply_visitor(detail::to_unicode_impl(), *this); +} + +value_double value::to_double() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +value_integer value::to_int() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +bool value::is_null() const +{ + return util::apply_visitor(mapnik::detail::is_null_visitor(), *this); +} + +template <> +value_double value::convert() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +template <> +value_integer value::convert() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +template <> +value_bool value::convert() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +template <> +std::string value::convert() const +{ + return util::apply_visitor(detail::convert(), *this); +} + +// +value operator+(value const& p1, value const& p2) +{ + return value(util::apply_visitor(detail::add(), p1, p2)); +} + +value operator-(value const& p1, value const& p2) +{ + return value(util::apply_visitor(detail::sub(), p1, p2)); +} + +value operator*(value const& p1, value const& p2) +{ + return value(util::apply_visitor(detail::mult(), p1, p2)); +} + +value operator/(value const& p1, value const& p2) +{ + return value(util::apply_visitor(detail::div(), p1, p2)); +} + +value operator%(value const& p1, value const& p2) +{ + return value(util::apply_visitor(detail::mod(), p1, p2)); +} + +} // namespace value_adl_barrier +} // namespace mapnik diff --git a/src/vertex_adapters.cpp b/src/vertex_adapters.cpp new file mode 100644 index 000000000..e96a9e25e --- /dev/null +++ b/src/vertex_adapters.cpp @@ -0,0 +1,213 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include +#include + +namespace mapnik { namespace geometry { + +// point adapter +template +point_vertex_adapter::point_vertex_adapter(point const& pt) + : pt_(pt), + first_(true) {} + +template +unsigned point_vertex_adapter::vertex(coord_type * x, coord_type * y) const +{ + if (first_) + { + *x = pt_.x; + *y = pt_.y; + first_ = false; + return mapnik::SEG_MOVETO; + } + return mapnik::SEG_END; +} + +template +void point_vertex_adapter::rewind(unsigned) const +{ + first_ = true; +} + +template +geometry_types point_vertex_adapter::type () const +{ + return geometry_types::Point; +} + +// line_string adapter +template +line_string_vertex_adapter::line_string_vertex_adapter(line_string const& line) + : line_(line), + current_index_(0), + end_index_(line.size()) +{} + +template +unsigned line_string_vertex_adapter::vertex(coord_type * x, coord_type * y) const +{ + if (current_index_ != end_index_) + { + point const& coord = line_[current_index_++]; + *x = coord.x; + *y = coord.y; + if (current_index_ == 1) + { + return mapnik::SEG_MOVETO; + } + else + { + return mapnik::SEG_LINETO; + } + } + return mapnik::SEG_END; +} + +template +void line_string_vertex_adapter::rewind(unsigned) const +{ + current_index_ = 0; +} + +template +geometry_types line_string_vertex_adapter::type() const +{ + return geometry_types::LineString; +} + +template +polygon_vertex_adapter::polygon_vertex_adapter(polygon const& poly) + : poly_(poly), + rings_itr_(0), + rings_end_(poly_.interior_rings.size() + 1), + current_index_(0), + end_index_((rings_itr_ < rings_end_) ? poly_.exterior_ring.size() : 0), + start_loop_(true) {} + +template +void polygon_vertex_adapter::rewind(unsigned) const +{ + rings_itr_ = 0; + rings_end_ = poly_.interior_rings.size() + 1; + current_index_ = 0; + end_index_ = (rings_itr_ < rings_end_) ? poly_.exterior_ring.size() : 0; + start_loop_ = true; +} +template +unsigned polygon_vertex_adapter::vertex(coord_type * x, coord_type * y) const +{ + if (rings_itr_ == rings_end_) + { + return mapnik::SEG_END; + } + if (current_index_ < end_index_) + { + point const& coord = (rings_itr_ == 0) ? + poly_.exterior_ring[current_index_++] : poly_.interior_rings[rings_itr_- 1][current_index_++]; + *x = coord.x; + *y = coord.y; + if (start_loop_) + { + start_loop_= false; + return mapnik::SEG_MOVETO; + } + if (current_index_ == end_index_) + { + *x = 0; + *y = 0; + return mapnik::SEG_CLOSE; + } + return mapnik::SEG_LINETO; + } + else if (++rings_itr_ != rings_end_) + { + current_index_ = 0; + end_index_ = poly_.interior_rings[rings_itr_ - 1].size(); + point const& coord = poly_.interior_rings[rings_itr_ - 1][current_index_++]; + *x = coord.x; + *y = coord.y; + return mapnik::SEG_MOVETO; + } + return mapnik::SEG_END; +} + +template +geometry_types polygon_vertex_adapter::type () const +{ + return geometry_types::Polygon; +} + +// ring adapter +template +ring_vertex_adapter::ring_vertex_adapter(linear_ring const& ring) + : ring_(ring), + current_index_(0), + end_index_(ring_.size()), + start_loop_(true) {} + +template +void ring_vertex_adapter::rewind(unsigned) const +{ + current_index_ = 0; + end_index_ = ring_.size(); + start_loop_ = true; +} + +template +unsigned ring_vertex_adapter::vertex(coord_type * x, coord_type * y) const +{ + if (current_index_ < end_index_) + { + auto const& coord = ring_[current_index_++]; + *x = coord.x; + *y = coord.y; + if (start_loop_) + { + start_loop_= false; + return mapnik::SEG_MOVETO; + } + if (current_index_ == end_index_) + { + *x = 0; + *y = 0; + return mapnik::SEG_CLOSE; + } + return mapnik::SEG_LINETO; + } + return mapnik::SEG_END; +} +template +geometry_types ring_vertex_adapter::type () const +{ + return geometry_types::Polygon; +} + +template struct point_vertex_adapter; +template struct line_string_vertex_adapter; +template struct polygon_vertex_adapter; +template struct ring_vertex_adapter; + +}} diff --git a/src/warp.cpp b/src/warp.cpp index b250d6e39..29cfa44cc 100644 --- a/src/warp.cpp +++ b/src/warp.cpp @@ -31,7 +31,8 @@ #include #include -// agg +#pragma GCC diagnostic push +#include #include "agg_image_filters.h" #include "agg_trans_bilinear.h" #include "agg_span_interpolator_linear.h" @@ -45,6 +46,7 @@ #include "agg_span_allocator.h" #include "agg_image_accessors.h" #include "agg_renderer_scanline.h" +#pragma GCC diagnostic pop namespace mapnik { @@ -181,10 +183,10 @@ struct warp_image_visitor nodata_value_(nodata_value) {} - void operator() (image_null const&) {} + void operator() (image_null const&) const {} template - void operator() (T const& source) + void operator() (T const& source) const { using image_type = T; //source and target image data types must match diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp index c806df9c1..ca611aeef 100644 --- a/src/webp_reader.cpp +++ b/src/webp_reader.cpp @@ -33,9 +33,6 @@ extern "C" #include } -#include -#include -#include #pragma GCC diagnostic pop // stl diff --git a/src/well_known_srs.cpp b/src/well_known_srs.cpp index d3296effa..445d84aee 100644 --- a/src/well_known_srs.cpp +++ b/src/well_known_srs.cpp @@ -25,8 +25,10 @@ #include #include -// boost +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop namespace mapnik { diff --git a/src/wkb.cpp b/src/wkb.cpp index 19b31ca5c..94c1fccde 100644 --- a/src/wkb.cpp +++ b/src/wkb.cpp @@ -103,13 +103,13 @@ public: switch (format_) { case wkbSpatiaLite: - byteOrder_ = (wkbByteOrder) wkb_[1]; + byteOrder_ = static_cast(wkb_[1]); pos_ = 39; break; case wkbGeneric: default: - byteOrder_ = (wkbByteOrder) wkb_[0]; + byteOrder_ = static_cast(wkb_[0]); pos_ = 1; break; } @@ -124,8 +124,12 @@ public: switch (type) { case wkbPoint: - geom = read_point(); + { + auto pt = read_point(); + if (!std::isnan(pt.x) && !std::isnan(pt.y)) + geom = std::move(pt); break; + } case wkbLineString: geom = read_linestring(); break; @@ -146,11 +150,19 @@ public: break; case wkbPointZ: case wkbPointM: - geom = read_point(); + { + auto pt = read_point(); + if (!std::isnan(pt.x) && !std::isnan(pt.y)) + geom = std::move(pt); break; + } case wkbPointZM: - geom = read_point(); + { + auto pt = read_point(); + if (!std::isnan(pt.x) && !std::isnan(pt.y)) + geom = std::move(pt); break; + } case wkbLineStringZ: case wkbLineStringM: geom = read_linestring(); diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index e342e6861..2e2a7df8e 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -69,11 +69,10 @@ DEFINE_NAME_TRAIT( double, "double") DEFINE_NAME_TRAIT( float, "float") DEFINE_NAME_TRAIT( unsigned, "unsigned") DEFINE_NAME_TRAIT( int, "int") +DEFINE_NAME_TRAIT( bool, "bool") DEFINE_NAME_TRAIT( boolean_type, "boolean_type") #ifdef BIGINT DEFINE_NAME_TRAIT( mapnik::value_integer, "long long" ) -#else -DEFINE_NAME_TRAIT( mapnik::value_integer, "int" ) #endif DEFINE_NAME_TRAIT( std::string, "string" ) DEFINE_NAME_TRAIT( color, "color" ) @@ -413,10 +412,13 @@ std::string xml_node::line_to_string() const #define compile_get_value(T) template T xml_node::get_value() const compile_get_opt_attr(boolean_type); +compile_get_opt_attr(mapnik::value_bool); compile_get_opt_attr(std::string); compile_get_opt_attr(int); compile_get_opt_attr(unsigned); +#ifdef BIGINT compile_get_opt_attr(mapnik::value_integer); +#endif compile_get_opt_attr(float); compile_get_opt_attr(double); compile_get_opt_attr(color); diff --git a/test/build.py b/test/build.py index c600d01bc..78fd9342a 100644 --- a/test/build.py +++ b/test/build.py @@ -9,6 +9,8 @@ test_env = env.Clone() if not env['CPP_TESTS']: for cpp_test_bin in glob.glob('./*/*-bin'): os.unlink(cpp_test_bin) + if os.path.exists('./unit/run'): os.unlink('./unit/run') + if os.path.exists('./visual/run'): os.unlink('./visual/run') else: test_env['LIBS'] = [env['MAPNIK_NAME']] test_env.AppendUnique(LIBS='mapnik-wkt') diff --git a/test/catch.hpp b/test/catch.hpp index 5b616a2b6..b7ac69633 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.1 build 1 (master branch) - * Generated: 2015-03-27 18:00:16.346230 + * Catch v1.3.2 + * Generated: 2015-12-28 15:07:07.166291 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -13,9 +13,13 @@ #define TWOBLUECUBES_CATCH_HPP_INCLUDED -// #included from: internal/catch_suppress_warnings.h +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif -#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED +// #included from: internal/catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro @@ -30,6 +34,8 @@ # pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" @@ -37,7 +43,6 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif - #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL #endif @@ -69,16 +74,42 @@ // #included from: catch_compiler_capabilities.h #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED -// Much of the following code is based on Boost (1.53) +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 #ifdef __clang__ # if __has_feature(cxx_nullptr) -# define CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif # if __has_feature(cxx_noexcept) -# define CATCH_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif #endif // __clang__ @@ -87,52 +118,30 @@ // Borland #ifdef __BORLANDC__ -#if (__BORLANDC__ > 0x582 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - #endif // __BORLANDC__ //////////////////////////////////////////////////////////////////////////////// // EDG #ifdef __EDG_VERSION__ -#if (__EDG_VERSION__ > 238 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - #endif // __EDG_VERSION__ //////////////////////////////////////////////////////////////////////////////// // Digital Mars #ifdef __DMC__ -#if (__DMC__ > 0x840 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - #endif // __DMC__ //////////////////////////////////////////////////////////////////////////////// // GCC #ifdef __GNUC__ -#if __GNUC__ < 3 - -#if (__GNUC_MINOR__ >= 96 ) -//#define CATCH_CONFIG_SFINAE +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR #endif -#elif __GNUC__ >= 3 - -// #define CATCH_CONFIG_SFINAE // Taking this out completely for now - -#endif // __GNUC__ < 3 - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) - -#define CATCH_CONFIG_CPP11_NULLPTR -#endif +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below #endif // __GNUC__ @@ -141,36 +150,101 @@ #ifdef _MSC_VER #if (_MSC_VER >= 1600) -#define CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif -#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) -//#define CATCH_CONFIG_SFINAE // Not confirmed +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #endif #endif // _MSC_VER +//////////////////////////////////////////////////////////////////////////////// + // Use variadic macros if the compiler supports them #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ ( defined __GNUC__ && __GNUC__ >= 3 ) || \ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) -#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS -#define CATCH_CONFIG_VARIADIC_MACROS -#endif +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS #endif //////////////////////////////////////////////////////////////////////////////// // C++ language feature support -// detect language version: -#if (__cplusplus == 201103L) -# define CATCH_CPP11 -# define CATCH_CPP11_OR_GREATER -#elif (__cplusplus >= 201103L) +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + # define CATCH_CPP11_OR_GREATER + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR #endif // noexcept support: @@ -182,10 +256,38 @@ # define CATCH_NOEXCEPT_IS(x) #endif +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + namespace Catch { + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + class NonCopyable { -#ifdef CATCH_CPP11_OR_GREATER +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; @@ -248,7 +350,7 @@ namespace Catch { SourceLineInfo(); SourceLineInfo( char const* _file, std::size_t _line ); SourceLineInfo( SourceLineInfo const& other ); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; @@ -270,6 +372,9 @@ namespace Catch { void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as @@ -355,7 +460,7 @@ namespace Catch { template class Ptr { public: - Ptr() : m_p( NULL ){} + Ptr() : m_p( CATCH_NULL ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); @@ -371,7 +476,7 @@ namespace Catch { void reset() { if( m_p ) m_p->release(); - m_p = NULL; + m_p = CATCH_NULL; } Ptr& operator = ( T* p ){ Ptr temp( p ); @@ -384,12 +489,11 @@ namespace Catch { return *this; } void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() { return m_p; } - const T* get() const{ return m_p; } + T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } - bool operator !() const { return m_p == NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } private: T* m_p; @@ -486,9 +590,13 @@ namespace Catch { struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector const& getAllTests() const = 0; - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const = 0; - + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + } namespace Catch { @@ -521,27 +629,32 @@ struct NameAndDesc { const char* description; }; +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + struct AutoReg { - AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); template - AutoReg( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - registerTestCase( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - void registerTestCase( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } ~AutoReg(); @@ -550,6 +663,11 @@ private: void operator= ( AutoReg const& ); }; +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS @@ -573,6 +691,10 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ @@ -594,6 +716,9 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); #endif // #included from: internal/catch_capture.hpp @@ -637,11 +762,11 @@ namespace Catch { // ResultDisposition::Flags enum struct ResultDisposition { enum Flags { - Normal = 0x00, + Normal = 0x01, - ContinueOnFailure = 0x01, // Failures fail test, but execution continues - FalseTest = 0x02, // Prefix expression with ! - SuppressFail = 0x04 // Failures are reported but do not fail the test + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test }; }; inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { @@ -689,7 +814,7 @@ namespace Catch { AssertionResult(); AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); ~AssertionResult(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionResult( AssertionResult const& ) = default; AssertionResult( AssertionResult && ) = default; AssertionResult& operator = ( AssertionResult const& ) = default; @@ -716,6 +841,323 @@ namespace Catch { } // end namespace Catch +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + namespace Catch { struct TestFailureException{}; @@ -742,11 +1184,12 @@ namespace Catch { ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ); + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); template - ExpressionLhs operator->* ( T const& operand ); - ExpressionLhs operator->* ( bool value ); + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); template ResultBuilder& operator << ( T const& value ) { @@ -771,6 +1214,9 @@ namespace Catch { void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; bool allowThrows() const; @@ -949,13 +1395,51 @@ namespace Internal { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( NULL, rhs ); + return Evaluator::evaluate( nullptr, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, NULL ); + return Evaluator::evaluate( lhs, nullptr ); } #endif // CATCH_CONFIG_CPP11_NULLPTR @@ -969,40 +1453,6 @@ namespace Internal { // #included from: catch_tostring.h #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED -// #included from: catch_sfinae.hpp -#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED - -// Try to detect if the current compiler supports SFINAE - -namespace Catch { - - struct TrueType { - static const bool value = true; - typedef void Enable; - char sizer[1]; - }; - struct FalseType { - static const bool value = false; - typedef void Disable; - char sizer[2]; - }; - -#ifdef CATCH_CONFIG_SFINAE - - template struct NotABooleanExpression; - - template struct If : NotABooleanExpression {}; - template<> struct If : TrueType {}; - template<> struct If : FalseType {}; - - template struct SizedIf; - template<> struct SizedIf : TrueType {}; - template<> struct SizedIf : FalseType {}; - -#endif // CATCH_CONFIG_SFINAE - -} // end namespace Catch - #include #include #include @@ -1055,8 +1505,11 @@ inline id performOptionalSelector( id obj, SEL sel ) { #endif -#ifdef CATCH_CPP11_OR_GREATER +#ifdef CATCH_CONFIG_CPP11_TUPLE #include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM #include #endif @@ -1084,6 +1537,11 @@ std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); #endif @@ -1096,34 +1554,15 @@ std::string toString( std::nullptr_t ); namespace Detail { - extern std::string unprintableString; - -// SFINAE is currently disabled by default for all compilers. -// If the non SFINAE version of IsStreamInsertable is ambiguous for you -// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE -#ifdef CATCH_CONFIG_SFINAE - - template - class IsStreamInsertableHelper { - template struct TrueIfSizeable : TrueType {}; - - template - static TrueIfSizeable dummy(T2*); - static FalseType dummy(...); - - public: - typedef SizedIf type; - }; - - template - struct IsStreamInsertable : IsStreamInsertableHelper::type {}; - -#else + extern const std::string unprintableString; struct BorgType { template BorgType( T const& ); }; + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + TrueType& testStreamable( std::ostream& ); FalseType testStreamable( FalseType ); @@ -1136,9 +1575,7 @@ namespace Detail { enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; }; -#endif - -#if defined(CATCH_CPP11_OR_GREATER) +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) template::value > @@ -1160,7 +1597,7 @@ namespace Detail { #endif template struct StringMakerBase { -#if defined(CATCH_CPP11_OR_GREATER) +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) template static std::string convert( T const& v ) { @@ -1200,7 +1637,7 @@ struct StringMaker { template static std::string convert( U* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -1210,7 +1647,7 @@ template struct StringMaker { static std::string convert( R C::* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -1233,7 +1670,7 @@ std::string toString( std::vector const& v ) { return Detail::rangeToString( v.begin(), v.end() ); } -#ifdef CATCH_CPP11_OR_GREATER +#ifdef CATCH_CONFIG_CPP11_TUPLE // toString for tuples namespace TupleDetail { @@ -1273,7 +1710,7 @@ struct StringMaker> { return os.str(); } }; -#endif +#endif // CATCH_CONFIG_CPP11_TUPLE namespace Detail { template @@ -1318,13 +1755,13 @@ namespace Catch { template class ExpressionLhs { ExpressionLhs& operator = ( ExpressionLhs const& ); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS ExpressionLhs& operator = ( ExpressionLhs && ) = delete; # endif public: ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS ExpressionLhs( ExpressionLhs const& ) = default; ExpressionLhs( ExpressionLhs && ) = default; # endif @@ -1405,11 +1842,11 @@ private: namespace Catch { template - inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { return ExpressionLhs( *this, operand ); } - inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { return ExpressionLhs( *this, value ); } @@ -1482,6 +1919,7 @@ namespace Catch { class AssertionResult; struct AssertionInfo; struct SectionInfo; + struct SectionEndInfo; struct MessageInfo; class ScopedMessageBuilder; struct Counts; @@ -1493,7 +1931,8 @@ namespace Catch { virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; @@ -1581,7 +2020,7 @@ namespace Catch { do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ - ( __catchResult->*expr ).endExpression(); \ + ( __catchResult <= expr ).endExpression(); \ } \ catch( ... ) { \ __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ @@ -1614,16 +2053,16 @@ namespace Catch { } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ try { \ expr; \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + __catchResult.captureExpectedException( matcher ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ @@ -1676,14 +2115,14 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ try { \ - std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + std::string matcherAsString = (matcher).toString(); \ __catchResult \ .setLhs( Catch::toString( arg ) ) \ .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ .setOp( "matches" ) \ - .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + .setResultType( (matcher).match( arg ) ); \ __catchResult.captureExpression(); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ @@ -1697,21 +2136,6 @@ namespace Catch { // #included from: catch_section_info.h #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - -} // end namespace Catch - // #included from: catch_totals.hpp #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED @@ -1782,6 +2206,31 @@ namespace Catch { }; } +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + // #included from: catch_timer.h #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED @@ -2022,6 +2471,8 @@ using namespace Generators; #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include +#include + // #included from: catch_interfaces_registry_hub.h #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED @@ -2046,7 +2497,8 @@ namespace Catch { struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; }; @@ -2058,14 +2510,16 @@ namespace Catch { } - namespace Catch { typedef std::string(*exceptionTranslateFunction)(); + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + struct IExceptionTranslator { virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { @@ -2083,9 +2537,12 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate() const { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { - throw; + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); @@ -2192,231 +2649,6 @@ inline std::string toString( Detail::Approx const& value ) { } // end namespace Catch -// #included from: internal/catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct Equals : MatcherImpl { - Equals( std::string const& str ) : m_str( str ){} - Equals( Equals const& other ) : m_str( other.m_str ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_str == expr; - } - virtual std::string toString() const { - return "equals: \"" + m_str + "\""; - } - - std::string m_str; - }; - - struct Contains : MatcherImpl { - Contains( std::string const& substr ) : m_substr( substr ){} - Contains( Contains const& other ) : m_substr( other.m_substr ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr ) : m_substr( substr ){} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == 0; - } - virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr ) : m_substr( substr ){} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); - } - virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str ) { - return Impl::StdString::Equals( str ); - } - inline Impl::StdString::Equals Equals( const char* str ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); - } - inline Impl::StdString::Contains Contains( std::string const& substr ) { - return Impl::StdString::Contains( substr ); - } - inline Impl::StdString::Contains Contains( const char* substr ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - // #included from: internal/catch_interfaces_tag_alias_registry.h #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED @@ -2450,12 +2682,12 @@ namespace Catch { template class Option { public: - Option() : nullableValue( NULL ) {} + Option() : nullableValue( CATCH_NULL ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) {} ~Option() { @@ -2479,7 +2711,7 @@ namespace Catch { void reset() { if( nullableValue ) nullableValue->~T(); - nullableValue = NULL; + nullableValue = CATCH_NULL; } T& operator*() { return *nullableValue; } @@ -2491,10 +2723,10 @@ namespace Catch { return nullableValue ? *nullableValue : defaultValue; } - bool some() const { return nullableValue != NULL; } - bool none() const { return nullableValue == NULL; } + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } - bool operator !() const { return nullableValue == NULL; } + bool operator !() const { return nullableValue == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } @@ -2552,6 +2784,8 @@ namespace Catch { TestCaseInfo( TestCaseInfo const& other ); + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + bool isHidden() const; bool throws() const; bool okToFail() const; @@ -2664,7 +2898,7 @@ namespace Catch { inline size_t registerTestMethods() { size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); + int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); @@ -2806,7 +3040,7 @@ return @ desc; \ #pragma clang diagnostic ignored "-Wweak-vtables" #endif -// #included from: ../catch_runner.hpp +// #included from: ../catch_session.hpp #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED // #included from: internal/catch_commandline.hpp @@ -2831,6 +3065,67 @@ return @ desc; \ #pragma clang diagnostic ignored "-Wpadded" #endif +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + #include #include @@ -2842,50 +3137,18 @@ namespace Catch { virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { - if( startsWith( m_name, "*" ) ) { - m_name = m_name.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_name, "*" ) ) { - m_name = m_name.substr( 0, m_name.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_name == toLower( testCase.name ); - case WildcardAtStart: - return endsWith( toLower( testCase.name ), m_name ); - case WildcardAtEnd: - return startsWith( toLower( testCase.name ), m_name ); - case WildcardAtBothEnds: - return contains( toLower( testCase.name ), m_name ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif + return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: - std::string m_name; - WildcardPosition m_wildcard; + WildcardPattern m_wildcardPattern; }; + class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} @@ -2896,6 +3159,7 @@ namespace Catch { private: std::string m_tag; }; + class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} @@ -3093,28 +3357,62 @@ namespace Catch { // #included from: catch_stream.h #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED -#include +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif +#include namespace Catch { - class Stream { + class StreamBufBase : public std::streambuf { public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); - - std::streambuf* streamBuf; - - private: - bool isOwned; + virtual ~StreamBufBase() CATCH_NOEXCEPT; }; +} + +#include +#include +#include + +namespace Catch { std::ostream& cout(); std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; } #include @@ -3142,6 +3440,7 @@ namespace Catch { showHelp( false ), showInvisibles( false ), forceColour( false ), + filenamesAsTags( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), @@ -3161,6 +3460,7 @@ namespace Catch { bool showHelp; bool showInvisibles; bool forceColour; + bool filenamesAsTags; int abortAfter; unsigned int rngSeed; @@ -3170,11 +3470,11 @@ namespace Catch { ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; - std::string reporterName; std::string outputFilename; std::string name; std::string processName; + std::vector reporterNames; std::vector testsOrTags; }; @@ -3186,12 +3486,11 @@ namespace Catch { public: Config() - : m_os( Catch::cout().rdbuf() ) {} Config( ConfigData const& data ) : m_data( data ), - m_os( Catch::cout().rdbuf() ) + m_stream( openStream() ) { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); @@ -3202,12 +3501,6 @@ namespace Catch { } virtual ~Config() { - m_os.rdbuf( Catch::cout().rdbuf() ); - m_stream.release(); - } - - void setFilename( std::string const& filename ) { - m_data.outputFilename = filename; } std::string const& getFilename() const { @@ -3223,18 +3516,7 @@ namespace Catch { bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() ); - } - - void useStream( std::string const& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - - std::string getReporterName() const { return m_data.reporterName; } + std::vector getReporterNames() const { return m_data.reporterNames; } int abortAfter() const { return m_data.abortAfter; } @@ -3245,7 +3527,7 @@ namespace Catch { // IConfig interface virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_os; } + virtual std::ostream& stream() const { return m_stream->stream(); } virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } @@ -3255,10 +3537,22 @@ namespace Catch { virtual bool forceColour() const { return m_data.forceColour; } private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } ConfigData m_data; - Stream m_stream; - mutable std::ostream m_os; + std::auto_ptr m_stream; TestSpec m_testSpec; }; @@ -3514,7 +3808,7 @@ namespace Clara { template struct IArgFunction { virtual ~IArgFunction() {} -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS IArgFunction() = default; IArgFunction( IArgFunction const& ) = default; # endif @@ -3527,11 +3821,11 @@ namespace Clara { template class BoundArgFunction { public: - BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction() : functionObj( CATCH_NULL ) {} BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {} BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL; delete functionObj; functionObj = newFunctionObj; return *this; @@ -3547,7 +3841,7 @@ namespace Clara { bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { - return functionObj != NULL; + return functionObj != CATCH_NULL; } private: IArgFunction* functionObj; @@ -3765,12 +4059,7 @@ namespace Clara { } }; - // NOTE: std::auto_ptr is deprecated in c++11/c++0x -#if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr ArgAutoPtr; -#else - typedef std::auto_ptr ArgAutoPtr; -#endif + typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr; friend void addOptName( Arg& arg, std::string const& optName ) { @@ -3846,8 +4135,8 @@ namespace Clara { m_arg->description = description; return *this; } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; + ArgBuilder& detail( std::string const& _detail ) { + m_arg->detail = _detail; return *this; } @@ -3930,14 +4219,14 @@ namespace Clara { maxWidth = (std::max)( maxWidth, it->commands().size() ); for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() + Detail::Text usageText( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); Detail::Text desc( it->description, Detail::TextAttributes() .setWidth( width - maxWidth - 3 ) ); - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; + for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) { + std::string usageCol = i < usageText.size() ? usageText[i] : ""; os << usageCol; if( i < desc.size() && !desc[i].empty() ) @@ -4143,6 +4432,7 @@ namespace Catch { config.abortAfter = x; } inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } inline void addWarning( ConfigData& config, std::string const& _warning ) { if( _warning == "NoAssertions" ) @@ -4236,7 +4526,7 @@ namespace Catch { cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) .describe( "reporter to use (defaults to console)" ) - .bind( &ConfigData::reporterName, "name" ); + .bind( &addReporterName, "name" ); cli["-n"]["--name"] .describe( "suite name" ) @@ -4273,6 +4563,10 @@ namespace Catch { .describe( "load test names to run from a file" ) .bind( &loadTestNamesFromFile, "filename" ); + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) @@ -4530,18 +4824,18 @@ namespace Catch { namespace Catch { struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) + explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } + Ptr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; - Ptr m_fullConfig; + Ptr m_fullConfig; }; struct ReporterPreferences { @@ -4605,7 +4899,7 @@ namespace Catch } virtual ~AssertionStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; @@ -4628,7 +4922,7 @@ namespace Catch missingAssertions( _missingAssertions ) {} virtual ~SectionStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SectionStats( SectionStats const& ) = default; SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; @@ -4655,7 +4949,7 @@ namespace Catch {} virtual ~TestCaseStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; @@ -4683,7 +4977,7 @@ namespace Catch {} virtual ~TestGroupStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; @@ -4705,7 +4999,7 @@ namespace Catch {} virtual ~TestRunStats(); -# ifndef CATCH_CPP11_OR_GREATER +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS TestRunStats( TestRunStats const& _other ) : runInfo( _other.runInfo ), totals( _other.totals ), @@ -4743,6 +5037,7 @@ namespace Catch // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; @@ -4751,20 +5046,24 @@ namespace Catch virtual void skipTest( TestCaseInfo const& testInfo ) = 0; }; - struct IReporterFactory { + struct IReporterFactory : IShared { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; struct IReporterRegistry { - typedef std::map FactoryMap; + typedef std::map > FactoryMap; + typedef std::vector > Listeners; virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; }; + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + } #include @@ -4787,8 +5086,7 @@ namespace Catch { nameAttr.setInitialIndent( 2 ).setIndent( 4 ); tagsAttr.setIndent( 6 ); - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4816,8 +5114,7 @@ namespace Catch { if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4857,8 +5154,7 @@ namespace Catch { std::map tagCounts; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4929,7 +5225,7 @@ namespace Catch { } // end namespace Catch -// #included from: internal/catch_runner_impl.hpp +// #included from: internal/catch_run_context.hpp #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED // #included from: catch_test_case_tracker.hpp @@ -4938,132 +5234,300 @@ namespace Catch { #include #include #include +#include namespace Catch { -namespace SectionTracking { +namespace TestCaseTracking { - class TrackedSection { + struct ITracker : SharedImpl<> { + virtual ~ITracker(); - typedef std::map TrackedSections; + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { - public: enum RunState { NotStarted, Executing, - ExecutingChildren, - Completed + CompletedCycle }; - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) {} - RunState runState() const { return m_runState; } + ITracker& startRun(); - TrackedSection* findChild( std::string const& childName ) { - TrackedSections::iterator it = m_children.find( childName ); - return it != m_children.end() - ? &it->second - : NULL; + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; } - TrackedSection* acquireChild( std::string const& childName ) { - if( TrackedSection* child = findChild( childName ) ) - return child; - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - return findChild( childName ); + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; } - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; + void completeCycle() { + m_runState = CompletedCycle; } - void leave() { - for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if( it->second.runState() != Completed ) { - m_runState = ExecutingChildren; - return; - } - m_runState = Completed; + + bool completedCycle() const { + return m_runState == CompletedCycle; } - TrackedSection* getParent() { - return m_parent; + ITracker& currentTracker() { + return *m_currentTracker; } - bool hasChildren() const { + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { return !m_children.empty(); } - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } }; - class TestCaseTracker { + class SectionTracker : public TrackerBase { public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) {} + virtual ~SectionTracker(); - bool enterSection( std::string const& name ) { - TrackedSection* child = m_currentSection->acquireChild( name ); - if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) - return false; + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; - m_currentSection = child; - m_currentSection->enter(); - return true; - } - void leaveSection() { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); - m_completedASectionThisRun = true; - } - - bool currentSectionHasChildren() const { - return m_currentSection->hasChildren(); - } - bool isCompleted() const { - return m_testCase.runState() == TrackedSection::Completed; - } - - class Guard { - public: - Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { - m_tracker.enterTestCase(); + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); + assert( section ); } - ~Guard() { - m_tracker.leaveTestCase(); + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; + if( !ctx.completedCycle() && !section->isComplete() ) { - private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); + section->open(); + } + return *section; } - void leaveTestCase() { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; }; -} // namespace SectionTracking + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); -using SectionTracking::TestCaseTracker; + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; } // namespace Catch @@ -5179,15 +5643,12 @@ namespace Catch { public: - explicit RunContext( Ptr const& config, Ptr const& reporter ) - : m_runInfo( config->name() ), + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), - m_activeTestCase( NULL ), - m_config( config ), - m_reporter( reporter ), - m_prevRunner( m_context.getRunner() ), - m_prevResultCapture( m_context.getResultCapture() ), - m_prevConfig( m_context.getConfig() ) + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -5197,10 +5658,6 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { @@ -5221,14 +5678,17 @@ namespace Catch { m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; - m_testCaseTracker = TestCaseTracker( testInfo.name ); do { + m_trackerContext.startRun(); do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); runCurrentTest( redirectedCout, redirectedCerr ); } - while( !m_testCaseTracker->isCompleted() && !aborting() ); + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } + // !TBD: deprecated - this will be replaced by indexed trackers while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); @@ -5239,8 +5699,8 @@ namespace Catch { redirectedCerr, aborting() ) ); - m_activeTestCase = NULL; - m_testCaseTracker.reset(); + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; return deltaTotals; } @@ -5275,8 +5735,10 @@ namespace Catch { std::ostringstream oss; oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - if( !m_testCaseTracker->enterSection( oss.str() ) ) + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) return false; + m_activeSections.push_back( §ionTracker ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; @@ -5287,30 +5749,40 @@ namespace Catch { return true; } bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) return false; m_totals.assertions.failed++; assertions.failed++; return true; } - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { - if( std::uncaught_exception() ) { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; - } - - Counts assertions = m_totals.assertions - prevAssertions; + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); - m_testCaseTracker->leaveSection(); + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } @@ -5376,7 +5848,8 @@ namespace Catch { double duration = 0; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); + + seedRng( *m_config ); Timer timer; timer.start(); @@ -5396,6 +5869,7 @@ namespace Catch { catch(...) { makeUnexpectedResultBuilder().useActiveException(); } + m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); @@ -5430,39 +5904,29 @@ namespace Catch { void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it ) - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + sectionEnded( *it ); m_unfinishedSections.clear(); } - struct UnfinishedSections { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) - : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; - }; - TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; - Option m_testCaseTracker; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; AssertionResult m_lastResult; Ptr m_config; Totals m_totals; Ptr m_reporter; std::vector m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; }; IResultCapture& getResultCapture() { @@ -5483,18 +5947,19 @@ namespace Catch { struct Version { Version( unsigned int _majorVersion, unsigned int _minorVersion, - unsigned int _buildNumber, - char const* const _branchName ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - buildNumber( _buildNumber ), - branchName( _branchName ) - {} + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); unsigned int const majorVersion; unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; unsigned int const buildNumber; - char const* const branchName; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); private: void operator=( Version const& ); @@ -5509,89 +5974,87 @@ namespace Catch { namespace Catch { - class Runner { + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } - public: - Runner( Ptr const& config ) - : m_config( config ) - { - openStream(); - makeReporter(); + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); } - Totals runTests() { + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } - RunContext context( m_config.get(), m_reporter ); + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; - Totals totals; + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); - context.testGroupStarting( "all tests", 1, 1 ); // deprecated? + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); - TestSpec testSpec = m_config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); - - int testsRunForGroup = 0; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) { - testsRunForGroup++; - if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); - } - } - std::vector skippedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true ); - - for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); - it != itEnd; - ++it ) - m_reporter->skipTest( *it ); - - context.testGroupEnded( "all tests", totals, 1, 1 ); - return totals; + tags.insert( "#" + filename ); + setTags( test, tags ); } - - private: - void openStream() { - // Open output file, if specified - if( !m_config->getFilename().empty() ) { - m_ofs.open( m_config->getFilename().c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - m_config->setStreamBuf( m_ofs.rdbuf() ); - } - } - void makeReporter() { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if( !m_reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - } - - private: - Ptr m_config; - std::ofstream m_ofs; - Ptr m_reporter; - std::set m_testsAlreadyRun; - }; + } class Session : NonCopyable { static bool alreadyInstantiated; @@ -5614,18 +6077,13 @@ namespace Catch { } void showHelp( std::string const& processName ) { - Catch::cout() << "\nCatch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " build " - << libraryVersion.buildNumber; - if( libraryVersion.branchName != std::string( "master" ) ) - Catch::cout() << " (" << libraryVersion.branchName << " branch)"; - Catch::cout() << "\n"; + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; m_cli.usage( Catch::cout(), processName ); Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + int applyCommandLine( int argc, char const* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); @@ -5636,9 +6094,10 @@ namespace Catch { catch( std::exception& ex ) { { Colour colourGuard( Colour::Red ); - Catch::cerr() << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; } m_cli.usage( Catch::cout(), m_configData.processName ); return (std::numeric_limits::max)(); @@ -5651,7 +6110,7 @@ namespace Catch { m_config.reset(); } - int run( int argc, char* const argv[] ) { + int run( int argc, char const* const argv[] ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) @@ -5667,15 +6126,16 @@ namespace Catch { { config(); // Force config to be constructed - std::srand( m_configData.rngSeed ); + seedRng( *m_config ); - Runner runner( m_config ); + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); - return static_cast( runner.runTests().assertions.failed ); + return static_cast( runTests( m_config ).assertions.failed ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; @@ -5683,7 +6143,7 @@ namespace Catch { } } - Clara::CommandLine const& cli() const { + Clara::CommandLine & cli() { return m_cli; } std::vector const& unusedTokens() const { @@ -5697,7 +6157,6 @@ namespace Catch { m_config = new Config( m_configData ); return *m_config; } - private: Clara::CommandLine m_cli; std::vector m_unusedTokens; @@ -5723,16 +6182,76 @@ namespace Catch { namespace Catch { - class TestRegistry : public ITestCaseRegistry { - struct LexSort { - bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { public: - TestRegistry() : m_unnamedCount( 0 ) {} + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} virtual ~TestRegistry(); virtual void registerTest( TestCase const& testCase ) { @@ -5742,69 +6261,29 @@ namespace Catch { oss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( oss.str() ) ); } - - if( m_functions.find( testCase ) == m_functions.end() ) { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if( !testCase.isHidden() ) - m_nonHiddenFunctions.push_back( testCase ); - } - else { - TestCase const& prev = *m_functions.find( testCase ); - { - Colour colourGuard( Colour::Red ); - Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - } - exit(1); - } + m_functions.push_back( testCase ); } virtual std::vector const& getAllTests() const { - return m_functionsInOrder; + return m_functions; } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); - virtual std::vector const& getAllNonHiddenTests() const { - return m_nonHiddenFunctions; - } - - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const { - - for( std::vector::const_iterator it = m_functionsInOrder.begin(), - itEnd = m_functionsInOrder.end(); - it != itEnd; - ++it ) { - bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ); - if( includeTest != negated ) - matchingTestCases.push_back( *it ); + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); } - sortTests( config, matchingTestCases ); + return m_sortedFunctions; } private: - - static void sortTests( IConfig const& config, std::vector& matchingTestCases ) { - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() ); - break; - case RunTests::InRandomOrder: - { - RandomNumberGenerator rng; - std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - } - std::set m_functions; - std::vector m_functionsInOrder; - std::vector m_nonHiddenFunctions; + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; /////////////////////////////////////////////////////////////////////////// @@ -5837,29 +6316,38 @@ namespace Catch { return className; } - /////////////////////////////////////////////////////////////////////////// + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); } - AutoReg::~AutoReg() {} + /////////////////////////////////////////////////////////////////////////// - void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); } + AutoReg::~AutoReg() {} + } // end namespace Catch // #included from: catch_reporter_registry.hpp @@ -5873,27 +6361,32 @@ namespace Catch { public: - virtual ~ReporterRegistry() { - deleteAllValues( m_factories ); - } + virtual ~ReporterRegistry() CATCH_OVERRIDE {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) - return NULL; + return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } - void registerReporter( std::string const& name, IReporterFactory* factory ) { + void registerReporter( std::string const& name, Ptr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } - FactoryMap const& getFactories() const { + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { return m_factories; } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } private: FactoryMap m_factories; + Listeners m_listeners; }; } @@ -5921,13 +6414,13 @@ namespace Catch { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { - throw; + return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else - throw; + return tryTranslators(); #endif } catch( TestFailureException& ) { @@ -5943,20 +6436,15 @@ namespace Catch { return msg; } catch(...) { - return tryTranslators( m_translators.begin() ); + return "Unknown exception"; } } - std::string tryTranslators( std::vector::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: @@ -5976,24 +6464,27 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const { + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const { + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerTest( TestCase const& testInfo ) { + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) { + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } @@ -6005,7 +6496,7 @@ namespace Catch { // Single, global, instance inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = NULL; + static RegistryHub* theRegistryHub = CATCH_NULL; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; @@ -6020,7 +6511,7 @@ namespace Catch { } void cleanUp() { delete getTheRegistryHub(); - getTheRegistryHub() = NULL; + getTheRegistryHub() = CATCH_NULL; cleanUpContext(); } std::string translateActiveException() { @@ -6056,19 +6547,6 @@ namespace Catch { // #included from: catch_stream.hpp #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - #include #include #include @@ -6113,6 +6591,19 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + struct OutputDebugWriter { void operator()( std::string const&str ) { @@ -6120,23 +6611,26 @@ namespace Catch { } }; - Stream::Stream() - : streamBuf( NULL ), isOwned( false ) + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) {} - Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) - {} - - void Stream::release() { - if( isOwned ) { - delete streamBuf; - streamBuf = NULL; - isOwned = false; - } + std::ostream& DebugOutStream::stream() const { + return m_os; } -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions std::ostream& cout() { return std::cout; } @@ -6150,7 +6644,7 @@ namespace Catch { class Context : public IMutableContext { - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} Context( Context const& ); void operator=( Context const& ); @@ -6196,7 +6690,7 @@ namespace Catch { m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second - : NULL; + : CATCH_NULL; } IGeneratorsForTest& getGeneratorsForCurrentTest() { @@ -6217,7 +6711,7 @@ namespace Catch { }; namespace { - Context* currentContext = NULL; + Context* currentContext = CATCH_NULL; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) @@ -6228,17 +6722,9 @@ namespace Catch { return getCurrentMutableContext(); } - Stream createStream( std::string const& streamName ) { - if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false ); - if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false ); - if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); - - throw std::domain_error( "Unknown stream: " + streamName ); - } - void cleanUpContext() { delete currentContext; - currentContext = NULL; + currentContext = CATCH_NULL; } } @@ -6294,12 +6780,13 @@ namespace { { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Red: return setTextAttribute( FOREGROUND_RED ); case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); @@ -6319,10 +6806,11 @@ namespace { private: void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); } HANDLE stdoutHandle; - WORD originalAttributes; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; }; IColourImpl* platformColourInstance() { @@ -6648,6 +7136,21 @@ namespace Catch { return TestCase( _testCase, info ); } + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, @@ -6656,18 +7159,10 @@ namespace Catch { : name( _name ), className( _className ), description( _description ), - tags( _tags ), lineInfo( _lineInfo ), properties( None ) { - std::ostringstream oss; - for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { - oss << "[" << *it << "]"; - std::string lcaseTag = toLower( *it ); - properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); - lcaseTags.insert( lcaseTag ); - } - tagsAsString = oss.str(); + setTags( *this, _tags ); } TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) @@ -6750,8 +7245,33 @@ namespace Catch { namespace Catch { - // These numbers are maintained by a script - Version libraryVersion( 1, 1, 1, "master" ); + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 3, 2, "", 0 ); + } // #included from: catch_message.hpp @@ -6943,7 +7463,7 @@ namespace Catch { #else uint64_t getCurrentTicks() { timeval t; - gettimeofday(&t,NULL); + gettimeofday(&t,CATCH_NULL); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif @@ -7042,6 +7562,14 @@ namespace Catch { return line < other.line || ( line == other.line && file < other.file ); } + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << "(" << info.line << ")"; @@ -7081,8 +7609,13 @@ namespace Catch { } Section::~Section() { - if( m_sectionIncluded ) - getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } } // This indicates whether the section should be executed or not @@ -7134,7 +7667,7 @@ namespace Catch { // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } @@ -7188,9 +7721,11 @@ namespace Catch { namespace Detail { - std::string unprintableString = "{?}"; + const std::string unprintableString = "{?}"; namespace { + const int hexThreshold = 255; + struct Endianness { enum Arch { Big, Little }; @@ -7271,19 +7806,17 @@ std::string toString( wchar_t* const value ) std::string toString( int value ) { std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; return oss.str(); } std::string toString( unsigned long value ) { std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; return oss.str(); } @@ -7332,6 +7865,23 @@ std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; @@ -7361,11 +7911,17 @@ std::string toString( std::nullptr_t ) { namespace Catch { + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), m_shouldDebugBreak( false ), m_shouldThrow( false ) {} @@ -7406,15 +7962,41 @@ namespace Catch { setResultType( resultType ); captureExpression(); } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } void ResultBuilder::captureExpression() { AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { getResultCapture().assertionEnded( result ); if( !result.isOk() ) { if( getCurrentContext().getConfig()->shouldDebugBreak() ) m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) m_shouldThrow = true; } } @@ -7561,6 +8143,137 @@ namespace Catch { } // end namespace Catch +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + // #included from: ../reporters/catch_reporter_xml.hpp #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED @@ -7576,47 +8289,53 @@ namespace Catch { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } - virtual ~StreamingReporterBase(); + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void noMatchingTestCases( std::string const& ) {} + virtual ~StreamingReporterBase() CATCH_OVERRIDE; - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { currentTestRunInfo = _testRunInfo; } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { currentGroupInfo = _groupInfo; } - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { currentTestCaseInfo = _testInfo; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_sectionStack.push_back( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { currentGroupInfo.reset(); } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } - virtual void skipTest( TestCaseInfo const& ) { + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } - Ptr m_config; + Ptr m_config; std::ostream& stream; LazyStat currentTestRunInfo; @@ -7624,6 +8343,7 @@ namespace Catch { LazyStat currentTestCaseInfo; std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; }; struct CumulativeReporterBase : SharedImpl { @@ -7674,15 +8394,21 @@ namespace Catch { CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } ~CumulativeReporterBase(); - virtual void testRunStarting( TestRunInfo const& ) {} - virtual void testGroupStarting( GroupInfo const& ) {} + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void testCaseStarting( TestCaseInfo const& ) {} + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { @@ -7707,7 +8433,7 @@ namespace Catch { m_deepestSection = node; } - virtual void assertionStarting( AssertionInfo const& ) {} + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& assertionStats ) { assert( !m_sectionStack.empty() ); @@ -7715,13 +8441,13 @@ namespace Catch { sectionNode.assertions.push_back( assertionStats ); return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); @@ -7732,12 +8458,12 @@ namespace Catch { m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); @@ -7745,9 +8471,9 @@ namespace Catch { } virtual void testRunEndedCumulative() = 0; - virtual void skipTest( TestCaseInfo const& ) {} + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - Ptr m_config; + Ptr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; @@ -7759,6 +8485,7 @@ namespace Catch { Ptr m_rootSection; Ptr m_deepestSection; std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; }; @@ -7772,6 +8499,17 @@ namespace Catch { return line; } + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + } // end namespace Catch // #included from: ../internal/catch_reporter_registrars.hpp @@ -7802,7 +8540,7 @@ namespace Catch { template class ReporterRegistrar { - class ReporterFactory : public IReporterFactory { + class ReporterFactory : public SharedImpl { // *** Please Note ***: // - If you end up here looking at a compiler error because it's trying to register @@ -7830,22 +8568,102 @@ namespace Catch { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + // #included from: ../internal/catch_xmlwriter.hpp #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #include #include #include +#include namespace Catch { + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + class XmlWriter { public: @@ -7857,7 +8675,7 @@ namespace Catch { ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ - other.m_writer = NULL; + other.m_writer = CATCH_NULL; } ~ScopedElement() { @@ -7897,27 +8715,6 @@ namespace Catch { endElement(); } -//# ifndef CATCH_CPP11_OR_GREATER -// XmlWriter& operator = ( XmlWriter const& other ) { -// XmlWriter temp( other ); -// swap( temp ); -// return *this; -// } -//# else -// XmlWriter( XmlWriter const& ) = default; -// XmlWriter( XmlWriter && ) = default; -// XmlWriter& operator = ( XmlWriter const& ) = default; -// XmlWriter& operator = ( XmlWriter && ) = default; -//# endif -// -// void swap( XmlWriter& other ) { -// std::swap( m_tagIsOpen, other.m_tagIsOpen ); -// std::swap( m_needsNewline, other.m_needsNewline ); -// std::swap( m_tags, other.m_tags ); -// std::swap( m_indent, other.m_indent ); -// std::swap( m_os, other.m_os ); -// } - XmlWriter& startElement( std::string const& name ) { ensureTagClosed(); newlineIfNecessary(); @@ -7949,11 +8746,8 @@ namespace Catch { } XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; return *this; } @@ -7964,9 +8758,9 @@ namespace Catch { template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - if( !name.empty() ) - stream() << " " << name << "=\"" << attribute << "\""; - return *this; + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { @@ -7975,7 +8769,7 @@ namespace Catch { ensureTagClosed(); if( tagWasOpen && indent ) stream() << m_indent; - writeEncodedText( text ); + stream() << XmlEncode( text ); m_needsNewline = true; } return *this; @@ -8020,30 +8814,6 @@ namespace Catch { } } - void writeEncodedText( std::string const& text ) { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while( pos != std::string::npos ) { - stream() << mtext.substr( 0, pos ); - - switch( mtext[pos] ) { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos+1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - bool m_tagIsOpen; bool m_needsNewline; std::vector m_tags; @@ -8052,32 +8822,44 @@ namespace Catch { }; } +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + namespace Catch { class XmlReporter : public StreamingReporterBase { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_sectionDepth( 0 ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - virtual ~XmlReporter(); + virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as an XML document"; } public: // StreamingReporterBase - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - virtual void noMatchingTestCases( std::string const& s ) { + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { StreamingReporterBase::noMatchingTestCases( s ); } - virtual void testRunStarting( TestRunInfo const& testInfo ) { + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); m_xml.setStream( stream ); m_xml.startElement( "Catch" ); @@ -8085,13 +8867,13 @@ namespace Catch { m_xml.writeAttribute( "name", m_config->name() ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); @@ -8099,7 +8881,7 @@ namespace Catch { m_testCaseTimer.start(); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) @@ -8108,9 +8890,9 @@ namespace Catch { } } - virtual void assertionStarting( AssertionInfo const& ) { } + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { const AssertionResult& assertionResult = assertionStats.assertionResult; // Print any info messages in tags. @@ -8181,7 +8963,7 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); @@ -8196,7 +8978,7 @@ namespace Catch { } } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); @@ -8207,7 +8989,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) @@ -8217,7 +8999,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) @@ -8248,28 +9030,24 @@ namespace Catch { JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - ~JunitReporter(); + virtual ~JunitReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) { + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); @@ -8277,25 +9055,25 @@ namespace Catch { CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } - virtual void testRunEndedCumulative() { + virtual void testRunEndedCumulative() CATCH_OVERRIDE { xml.endElement(); } @@ -8460,24 +9238,19 @@ namespace Catch { m_headerPrinted( false ) {} - virtual ~ConsoleReporter(); + virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - virtual void noMatchingTestCases( std::string const& spec ) { + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << "'" << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) { + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; @@ -8497,11 +9270,11 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) { + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -8523,11 +9296,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -8536,7 +9309,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; @@ -8700,12 +9473,7 @@ namespace Catch { stream << "\n" << getLineOfChars<'~'>() << "\n"; Colour colour( Colour::SecondaryText ); stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " b" - << libraryVersion.buildNumber; - if( libraryVersion.branchName != std::string( "master" ) ) - stream << " (" << libraryVersion.branchName << ")"; - stream << " host application.\n" + << " is a Catch v" << libraryVersion << " host application.\n" << "Run with -? for options\n\n"; if( m_config->rngSeed() != 0 ) @@ -9180,8 +9948,14 @@ namespace Catch { } // end namespace Catch namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} @@ -9215,6 +9989,7 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} @@ -9226,6 +10001,13 @@ namespace Catch { Matchers::Impl::StdString::EndsWith::~EndsWith() {} void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } } #ifdef __clang__ @@ -9241,7 +10023,7 @@ namespace Catch { #ifndef __OBJC__ // Standard C/C++ main entry point -int main (int argc, char * const argv[]) { +int main (int argc, char * argv[]) { return Catch::Session().run( argc, argv ); } @@ -9279,8 +10061,9 @@ int main (int argc, char * const argv[]) { #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) @@ -9291,6 +10074,7 @@ int main (int argc, char * const argv[]) { #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) @@ -9306,6 +10090,7 @@ int main (int argc, char * const argv[]) { #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) @@ -9313,6 +10098,7 @@ int main (int argc, char * const argv[]) { #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) @@ -9332,11 +10118,11 @@ int main (int argc, char * const argv[]) { #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else @@ -9344,8 +10130,9 @@ int main (int argc, char * const argv[]) { #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) @@ -9354,8 +10141,9 @@ int main (int argc, char * const argv[]) { #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) @@ -9371,6 +10159,7 @@ int main (int argc, char * const argv[]) { #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) @@ -9378,6 +10167,7 @@ int main (int argc, char * const argv[]) { #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) @@ -9401,27 +10191,13 @@ int main (int argc, char * const argv[]) { #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define GIVEN( desc ) SECTION( " Given: " desc, "" ) -#define WHEN( desc ) SECTION( " When: " desc, "" ) -#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) -#define THEN( desc ) SECTION( " Then: " desc, "" ) -#define AND_THEN( desc ) SECTION( " And: " desc, "" ) +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; -// #included from: internal/catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/test/catch_ext.hpp b/test/catch_ext.hpp new file mode 100644 index 000000000..3168ecf43 --- /dev/null +++ b/test/catch_ext.hpp @@ -0,0 +1,22 @@ +#ifndef TEST_CATCH_EXT_HPP +#define TEST_CATCH_EXT_HPP + +#include "catch.hpp" + +#define TRY_CHECK( expr ) \ + try { \ + CHECK( expr ); \ + } \ + catch ( Catch::TestFailureException & ) { \ + /* thrown by CHECK after it catches and reports */ \ + /* an exception from expr => swallow this */ \ + } + +#define TRY_CHECK_FALSE( expr ) \ + try { \ + CHECK_FALSE( expr ); \ + } \ + catch ( Catch::TestFailureException & ) { \ + } + +#endif // TEST_CATCH_EXT_HPP diff --git a/test/cleanup.hpp b/test/cleanup.hpp index f175e72b4..c775915b5 100644 --- a/test/cleanup.hpp +++ b/test/cleanup.hpp @@ -1,6 +1,9 @@ #ifndef TEST_MEMORY_CLEANUP #define TEST_MEMORY_CLEANUP +#pragma GCC diagnostic push +#include + #if defined(HAVE_LIBXML2) #include #include @@ -16,6 +19,8 @@ #include #endif +#pragma GCC diagnostic pop + namespace testing { inline void run_cleanup() diff --git a/test/data b/test/data index 9869ca2a0..14eabf8f4 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 9869ca2a0b3d0e31efa6a5ae01af6445916f0c1e +Subproject commit 14eabf8f407294e71636cddfce68297a4f4e0303 diff --git a/test/data-visual b/test/data-visual index 972b039bf..bb0a8927f 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit 972b039bfc5a5e189f68852c22df717a30c1adf7 +Subproject commit bb0a8927f4305df861d1b5c6366216bb4e530975 diff --git a/test/run b/test/run index cd45c681f..014b79861 100755 --- a/test/run +++ b/test/run @@ -1,5 +1,8 @@ #!/usr/bin/env bash +set -o pipefail +set -eu + failures=0 cd "$( dirname "${BASH_SOURCE[0]}" )" @@ -9,30 +12,45 @@ source ./localize.sh function run_step { >&2 echo -e "\033[1m\033[34m* $1\033[0m"; } function run_substep { >&2 echo -e "\033[1m\033[36m* $1\033[0m"; } function run_success { >&2 echo -e "\033[1m\033[32m* $1\033[0m"; } +function run_warn { >&2 echo -e "\033[1m\033[31m* $1\033[0m"; } run_step "Starting Mapnik tests" +ran_a_test=false if [ -d "test/data" ]; then run_substep "Running C++ Unit tests..." - ./test/unit/run - failures=$((failures+$?)) + if [[ -f ./test/unit/run ]]; then + ran_a_test=true + ./test/unit/run || failures=$((failures+$?)) + else + run_warn "Skipping unit tests since they were not built" + fi run_substep "Running standalone C++ tests..." + found_test=false if [ -n "$(find test/standalone/ -maxdepth 1 -name '*-bin' -print -quit)" ]; then for FILE in test/standalone/*-bin; do - ${FILE}; - failures=$((failures+$?)) + found_test=true + ran_a_test=true + ${FILE} || failures=$((failures+$?)) done fi + if [[ $found_test == false ]]; then + run_warn "Skipping standalone tests since they were not built" + fi if [ -d "test/data-visual/styles" ]; then run_substep "Running visual tests..." - if [ -z "$JOBS" ]; then + if [ -z "${JOBS:-}" ]; then JOBS=1 fi - ./test/visual/run -j $JOBS - failures=$((failures+$?)) + if [[ -f ./test/visual/run ]]; then + ran_a_test=true + ./test/visual/run -j $JOBS || failures=$((failures+$?)) + else + run_warn "Skipping visual tests since they were not built" + fi else echo "Notice: Skipping visual tests, the visual tests data are not present under the standard directory \"test/data-visual\"." fi @@ -41,4 +59,8 @@ else echo "Notice: Skipping all tests, the test data are not present under the standard directory \"test/data\"." fi +if [[ $ran_a_test == false ]]; then + run_warn "**** WARNING: no tests were run ****" +fi + exit $failures diff --git a/test/standalone/font_registration_test.cpp b/test/standalone/font_registration_test.cpp index fda605f0c..db56a30a2 100644 --- a/test/standalone/font_registration_test.cpp +++ b/test/standalone/font_registration_test.cpp @@ -46,16 +46,16 @@ SECTION("registration") { REQUIRE( m.load_fonts() ); REQUIRE( m.get_font_memory_cache().size() == 1 ); REQUIRE( m.register_fonts(fontdir , true ) ); - REQUIRE( m.get_font_file_mapping().size() == 22 ); + REQUIRE( m.get_font_file_mapping().size() == 23 ); REQUIRE( m.load_fonts() ); - REQUIRE( m.get_font_memory_cache().size() == 22 ); + REQUIRE( m.get_font_memory_cache().size() == 23 ); // copy discards memory cache but not file mapping mapnik::Map m2(m); REQUIRE( m2.get_font_memory_cache().size() == 0 ); - REQUIRE( m2.get_font_file_mapping().size() == 22 ); + REQUIRE( m2.get_font_file_mapping().size() == 23 ); REQUIRE( m2.load_fonts() ); - REQUIRE( m2.get_font_memory_cache().size() == 22 ); + REQUIRE( m2.get_font_memory_cache().size() == 23 ); // test font-directory from XML mapnik::Map m3(1,1); @@ -132,7 +132,7 @@ SECTION("registration") { // recurse to find all dejavu fonts REQUIRE( mapnik::freetype_engine::register_fonts(fontdir, true) ); face_names = mapnik::freetype_engine::face_names(); - REQUIRE( face_names.size() == 22 ); + REQUIRE( face_names.size() == 23 ); // we should have re-registered 'DejaVu Sans Mono Bold Oblique' again, // but now at a new path @@ -154,7 +154,7 @@ SECTION("registration") { mapnik::Map m4(1,1); REQUIRE( m4.register_fonts(fontdir , true ) ); REQUIRE( m4.get_font_memory_cache().size() == 0 ); - REQUIRE( m4.get_font_file_mapping().size() == 22 ); + REQUIRE( m4.get_font_file_mapping().size() == 23 ); REQUIRE( !m4.load_fonts() ); REQUIRE( m4.get_font_memory_cache().size() == 0 ); REQUIRE( m4.register_fonts(dejavu_bold_oblique, false) ); @@ -166,7 +166,7 @@ SECTION("registration") { // https://github.com/mapnik/mapnik/issues/2274 REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/NotoSans-Regular.ttc") ); face_names = mapnik::freetype_engine::face_names(); - REQUIRE( face_names.size() == 24 ); + REQUIRE( face_names.size() == 25 ); // now blindly register as many system fonts as possible // the goal here to make sure we don't crash @@ -179,7 +179,7 @@ SECTION("registration") { // windows mapnik::freetype_engine::register_fonts("C:\\Windows\\Fonts", true); face_names = mapnik::freetype_engine::face_names(); - REQUIRE( face_names.size() > 22 ); + REQUIRE( face_names.size() > 23 ); } catch (std::exception const & ex) { @@ -188,4 +188,4 @@ SECTION("registration") { } } -} \ No newline at end of file +} diff --git a/test/unit/color/css_color.cpp b/test/unit/color/css_color.cpp index 7ff6e3fa5..f1bc17196 100644 --- a/test/unit/color/css_color.cpp +++ b/test/unit/color/css_color.cpp @@ -1,7 +1,9 @@ + #include "catch.hpp" #include #include #include +#include TEST_CASE("css color") { @@ -164,4 +166,27 @@ TEST_CASE("css color") { CHECK( !boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), color_grammar, space) ); } } + SECTION("operator<< / to_string()") + { + mapnik::color c("salmon"); + std::ostringstream ss; + ss << c ; + CHECK(ss.str() == "rgb(250,128,114)"); + c.set_alpha(127); + ss.seekp(0); + ss << c ; + CHECK(ss.str() == "rgba(250,128,114,0.498)"); + } + SECTION("premultiply/demultiply") + { + mapnik::color c("cornflowerblue"); + c.set_alpha(127); + c.premultiply(); + CHECK(int(c.red()) == 50); + CHECK(int(c.green()) == 74); + CHECK(int(c.blue()) == 118); + CHECK(int(c.alpha()) == 127); + c.demultiply(); + CHECK(c == mapnik::color(100, 148, 236, 127)); + } } diff --git a/test/unit/core/box2d_test.cpp b/test/unit/core/box2d_test.cpp index 87f2e1475..8385bba7c 100644 --- a/test/unit/core/box2d_test.cpp +++ b/test/unit/core/box2d_test.cpp @@ -1,7 +1,9 @@ + #include "catch.hpp" #include #include +#include "agg_trans_affine.h" TEST_CASE("box2d") { SECTION("coord init") { @@ -159,4 +161,62 @@ SECTION("envelope clipping") { REQUIRE(e1 == e2); } +SECTION("mapnik::box2d intersects") +{ + mapnik::box2d b0(0,0,100,100); + // another box2d + mapnik::box2d b1(100,100,200,200); + CHECK(b0.intersects(b1)); + CHECK(b1.intersects(b0)); + mapnik::box2d b2(100.001,100,200,200); + CHECK(!b0.intersects(b2)); + CHECK(!b2.intersects(b0)); + // coord + CHECK(b0.intersects(mapnik::coord(100,100))); + CHECK(!b0.intersects(mapnik::coord(100.001,100))); +} + +SECTION("mapnik::box2d intersect") +{ + mapnik::box2d b0(0,0,100,100); + mapnik::box2d b1(100,100,200,200); + CHECK(b0.intersect(b1) == mapnik::box2d(100,100,100,100)); + CHECK(b1.intersect(b0) == mapnik::box2d(100,100,100,100)); + mapnik::box2d b2(100.001,100,200,200); + CHECK(b0.intersect(b2) == mapnik::box2d()); + CHECK(b2.intersect(b0) == mapnik::box2d()); +} + +SECTION("mapnik::box2d re_center") +{ + mapnik::box2d b(0, 0, 100, 100); + b.re_center(0, 0); + CHECK(b == mapnik::box2d(-50, -50, 50, 50)); + b.re_center(mapnik::coord2d(50,50)); + CHECK(b == mapnik::box2d(0, 0, 100, 100)); +} + +SECTION("mapnik::box2d operator+=") +{ + mapnik::box2d b(0, 0, 50, 50); + b += mapnik::box2d(100, 100, 200, 200); + CHECK(b == mapnik::box2d(0, 0, 200, 200)); + b += 100; + CHECK(b == mapnik::box2d(-100, -100, 300, 300)); +} + +SECTION("mapnik::box2d operator*= operator=/ ") +{ + mapnik::box2d b(0, 0, 100, 100); + b *= 2.0; + CHECK(b == mapnik::box2d(-50, -50, 150, 150)); + b /= 2.0; + CHECK(b == mapnik::box2d(0, 0, 100, 100)); + + agg::trans_affine tr; + tr.translate(-50,-50); + tr.scale(2.0); + b *= tr; + CHECK(b == mapnik::box2d(-100, -100, 100, 100)); +} } // TEST_CASE diff --git a/test/unit/core/comparison_test.cpp b/test/unit/core/comparison_test.cpp index 41b524c7a..7e8e8e414 100644 --- a/test/unit/core/comparison_test.cpp +++ b/test/unit/core/comparison_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/core/conversions_test.cpp b/test/unit/core/conversions_test.cpp index ba0c22371..43592af01 100644 --- a/test/unit/core/conversions_test.cpp +++ b/test/unit/core/conversions_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/core/exceptions_test.cpp b/test/unit/core/exceptions_test.cpp index 46abcce55..16ed51974 100644 --- a/test/unit/core/exceptions_test.cpp +++ b/test/unit/core/exceptions_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/core/expressions_test.cpp b/test/unit/core/expressions_test.cpp new file mode 100644 index 000000000..22ba3c00d --- /dev/null +++ b/test/unit/core/expressions_test.cpp @@ -0,0 +1,206 @@ +#include "catch_ext.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace { + +template +mapnik::feature_ptr make_test_feature(mapnik::value_integer id, std::string const& wkt, Properties const& prop) +{ + auto ctx = std::make_shared(); + mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, id)); + mapnik::geometry::geometry geom; + if (mapnik::from_wkt(wkt, geom)) + { + feature->set_geometry(std::move(geom)); + } + + for (auto const& kv : prop) + { + feature->put_new(kv.first, kv.second); + } + return feature; +} + +template +mapnik::value_type evaluate(Feature const& feature, Expression const& expr) +{ + auto value = mapnik::util::apply_visitor( + mapnik::evaluate( + feature, mapnik::attributes()), expr); + return value; +} + +mapnik::value evaluate_string(mapnik::feature_ptr const& feature, std::string const& str) +{ + auto expr = mapnik::parse_expression(str); + return evaluate(*feature, *expr); +} + +std::string parse_and_dump(std::string const& str) +{ + auto expr = mapnik::parse_expression(str); + return mapnik::to_expression_string(*expr); +} + +} // namespace + +TEST_CASE("expressions") +{ + using namespace std::placeholders; + using properties_type = std::vector > ; + mapnik::transcoder tr("utf8"); + + properties_type prop = {{ "foo" , tr.transcode("bar") }, + { "name" , tr.transcode("Québec")}, + { "grass" , tr.transcode("grow")}, + { "wind" , tr.transcode("blow")}, + { "sky" , tr.transcode("is blue")}, + { "double", mapnik::value_double(1.23456)}, + { "int" , mapnik::value_integer(123)}, + { "bool" , mapnik::value_bool(true)}, + { "null" , mapnik::value_null()}}; + + auto feature = make_test_feature(1, "POINT(100 200)", prop); + auto eval = std::bind(evaluate_string, feature, _1); + auto approx = Approx::custom().epsilon(1e-6); + + TRY_CHECK(eval(" [foo]='bar' ") == true); + + // primary expressions + // null + TRY_CHECK(parse_and_dump("null") == "null"); + // boolean + TRY_CHECK(parse_and_dump("true") == "true"); + TRY_CHECK(parse_and_dump("false") == "false"); + // floating point + TRY_CHECK(parse_and_dump("3.14159") == "3.14159"); + // integer + TRY_CHECK(parse_and_dump("123") == "123"); + // unicode + TRY_CHECK(parse_and_dump("''") == "''"); + TRY_CHECK(parse_and_dump("'single-quoted string'") == "'single-quoted string'"); + TRY_CHECK(parse_and_dump("\"double-quoted string\"") == "'double-quoted string'"); + TRY_CHECK(parse_and_dump("'escaped \\' apostrophe'") == "'escaped \\' apostrophe'"); + TRY_CHECK(parse_and_dump("'escaped \\\\ backslash'") == "'escaped \\\\ backslash'"); + + // floating point constants + TRY_CHECK(parse_and_dump("pi") == "3.14159"); + TRY_CHECK(parse_and_dump("deg_to_rad") == "0.0174533"); + TRY_CHECK(parse_and_dump("rad_to_deg") == "57.2958"); + + // unary functions + // sin / cos + TRY_CHECK(eval(" sin(0.25 * pi) / cos(0.25 * pi) ").to_double() == approx(1.0)); + // tan + TRY_CHECK(eval(" tan(0.25 * pi) ").to_double() == approx(1.0)); + // atan + TRY_CHECK(eval(" rad_to_deg * atan(1.0) ").to_double() == approx(45.0)); + // exp + TRY_CHECK(eval(" exp(0.0) ") == 1.0); + // log + TRY_CHECK(eval(" log(1.0) ") == 0.0); + TRY_CHECK(eval(" log(exp(1.0)) ") == 1.0); + // abs + TRY_CHECK(eval(" abs(cos(-pi)) ") == 1.0); + // length (string) + TRY_CHECK(eval(" length('1234567890') ").to_int() == 10); + + // binary functions + // min + TRY_CHECK(eval(" min(-0.01, 0.001) ") == -0.01); + // max + TRY_CHECK(eval(" max(0.01, -0.1) ") == 0.01); + // pow + TRY_CHECK(eval(" pow(2, 32) ") == 4294967296.0); + + // geometry types + TRY_CHECK(eval(" [mapnik::geometry_type] = point ") == true); + TRY_CHECK(eval(" [mapnik::geometry_type] <> linestring ") == true); + TRY_CHECK(eval(" [mapnik::geometry_type] != polygon ") == true); + TRY_CHECK(eval(" [mapnik::geometry_type] neq collection ") == true); + TRY_CHECK(eval(" [mapnik::geometry_type] eq collection ") == false); + + //unary expression + TRY_CHECK(eval(" -123.456 ") == -123.456); + TRY_CHECK(eval(" +123.456 ") == 123.456); + + // multiplicative/additive + auto expr = mapnik::parse_expression("(2.0 * 2.0 + 3.0 * 3.0)/(2.0 * 2.0 - 3.0 * 3.0)"); + TRY_CHECK(evaluate(*feature, *expr) == -2.6); + auto expr2 = mapnik::parse_expression("(2.0 * 2.0 + 3.0 * 3.0)/((2.0 - 3.0) * (2.0 + 3.0))"); + TRY_CHECK(evaluate(*feature, *expr) == evaluate(*feature, *expr2)); + + // logical + TRY_CHECK(eval(" [int] = 123 and [double] = 1.23456 && [bool] = true and [null] = null && [foo] = 'bar' ") == true); + TRY_CHECK(eval(" [int] = 456 or [foo].match('foo') || length([foo]) = 3 ") == true); + TRY_CHECK(eval(" not true and not true ") == eval(" (not true ) and (not true ) ")); + TRY_CHECK(eval(" not true or not true ") == eval(" (not true ) or (not true ) ")); + TRY_CHECK(eval(" not false and not false ") == eval(" (not false) and (not false) ")); + TRY_CHECK(eval(" not false or not false ") == eval(" (not false) or (not false) ")); + + // test not/and/or precedence using combinations of "not EQ1 OP1 not EQ2 OP2 not EQ3" + TRY_CHECK(eval(" not [grass] = 'grow' and not [wind] = 'blow' and not [sky] = 'is blue' ") == false); + TRY_CHECK(eval(" not [grass] = 'grow' and not [wind] = 'blow' or not [sky] = 'is blue' ") == false); + TRY_CHECK(eval(" not [grass] = 'grow' or not [wind] = 'blow' and not [sky] = 'is blue' ") == false); + TRY_CHECK(eval(" not [grass] = 'grow' or not [wind] = 'blow' or not [sky] = 'is blue' ") == false); + TRY_CHECK(eval(" not [grass] = 'grew' and not [wind] = 'blew' and not [sky] = 'was blue' ") == true); + TRY_CHECK(eval(" not [grass] = 'grew' and not [wind] = 'blew' or not [sky] = 'was blue' ") == true); + TRY_CHECK(eval(" not [grass] = 'grew' or not [wind] = 'blew' and not [sky] = 'was blue' ") == true); + TRY_CHECK(eval(" not [grass] = 'grew' or not [wind] = 'blew' or not [sky] = 'was blue' ") == true); + + // relational + TRY_CHECK(eval(" [int] > 100 and [int] gt 100.0 and [double] < 2 and [double] lt 2.0 ") == true); + TRY_CHECK(eval(" [int] >= 123 and [int] ge 123.0 and [double] <= 1.23456 and [double] le 1.23456 ") == true); + + // empty string/null equality + TRY_CHECK(eval("[null] = null") == true); + TRY_CHECK(eval("[null] != null") == false); + TRY_CHECK(eval("[null] = ''") == false); + ///////////////////// ref: https://github.com/mapnik/mapnik/issues/1859 + TRY_CHECK(eval("[null] != ''") == false); // back compatible - will be changed in 3.1.x + ////////////////////// + TRY_CHECK(eval("'' = [null]") == false); + TRY_CHECK(eval("'' != [null]") == true); + + // regex + // replace + TRY_CHECK(eval(" [foo].replace('(\\B)|( )','$1 ') ") == tr.transcode("b a r")); + + // https://en.wikipedia.org/wiki/Chess_symbols_in_Unicode + //'\u265C\u265E\u265D\u265B\u265A\u265D\u265E\u265C' - black chess figures + // replace black knights with white knights + auto val0 = eval(u8"'\u265C\u265E\u265D\u265B\u265A\u265D\u265E\u265C'.replace('\u265E','\u2658')"); + auto val1 = eval("'♜♞♝♛♚♝♞♜'.replace('♞','♘')"); // ==> expected ♜♘♝♛♚♝♘♜ + TRY_CHECK(val0 == val1); + TRY_CHECK(val0.to_string() == val1.to_string()); // UTF-8 + TRY_CHECK(val0.to_unicode() == val1.to_unicode()); // Unicode (UTF-16) + + // following test will fail if boost_regex is built without ICU support (unpaired surrogates in output) + TRY_CHECK(eval("[name].replace('(\\B)|( )',' ') ") == tr.transcode("Q u é b e c")); + TRY_CHECK(eval("'Москва'.replace('(? diff --git a/test/unit/core/value_test.cpp b/test/unit/core/value_test.cpp new file mode 100644 index 000000000..cdb64dbbe --- /dev/null +++ b/test/unit/core/value_test.cpp @@ -0,0 +1,110 @@ + +#include "catch.hpp" + +#include +#include + +TEST_CASE("mapnik::value") +{ + SECTION("add/sub/mult/div") + { + mapnik::value v0 = 1; // mapnik::value_integer + mapnik::value v1 = 1.001; // mapnik::value_double + mapnik::value v2 = true; // mapnik::value_boolean + + CHECK(v0.is()); + CHECK(v1.is()); + CHECK(v2.is()); + + // add + auto add0 = v0 + v1; // result value_double + auto add1 = v1 + v0; + auto add2 = v1 + v2; // result value_double + auto add3 = v2 + v1; + auto add4 = v0 + v2; // result value_integer + auto add5 = v2 + v0; + auto add6 = v2 + v2; // result_integer + // check type promotion + CHECK(add0.is()); + CHECK(add1.is()); + CHECK(add2.is()); + CHECK(add3.is()); + CHECK(add4.is()); + CHECK(add5.is()); + CHECK(add6.is()); + // + CHECK(add6 == v0 + v0); + // check commutative rules + CHECK(add0 == add1); + CHECK(add2 == add3); + CHECK(add4 == add5); + + // sub + auto sub0 = v0 - v1; // result value_double + auto sub1 = v1 - v0; + auto sub2 = v1 - v2; // result value_double + auto sub3 = v2 - v1; + auto sub4 = v0 - v2; // result value_integer + auto sub5 = v2 - v0; + auto sub6 = v2 - v2; // result value_integer + + CHECK(sub0.is()); + CHECK(sub1.is()); + CHECK(sub2.is()); + CHECK(sub3.is()); + CHECK(sub4.is()); + CHECK(sub5.is()); + CHECK(sub6.is()); + + // check commutative rules + CHECK(sub0 == -sub1); + CHECK(sub2 == -sub3); + CHECK(sub4 == -sub5); + CHECK(sub6 == v0 - v0); + + // multl + auto mult0 = v0 * v1; // result value_double + auto mult1 = v1 * v0; + auto mult2 = v1 * v2; // result value_double + auto mult3 = v2 * v1; + auto mult4 = v0 * v2; // result value_integer + auto mult5 = v2 * v0; + auto mult6 = v2 * v2; // result value_integer + + CHECK(mult0.is()); + CHECK(mult1.is()); + CHECK(mult2.is()); + CHECK(mult3.is()); + CHECK(mult4.is()); + CHECK(mult5.is()); + CHECK(mult6.is()); + // check commutative rules + CHECK(mult0 == mult1); + CHECK(mult2 == mult3); + CHECK(mult4 == mult5); + // + CHECK(mult6 == v0 * v0); + + // div + auto div0 = v0 / v1; // result value_double + auto div1 = v1 / v0; + auto div2 = v1 / v2; // result value_double + auto div3 = v2 / v1; + auto div4 = v0 / v2; // result value_integer + auto div5 = v2 / v0; + auto div6 = v2 / v2; // result value_interger + + CHECK(div0.is()); + CHECK(div1.is()); + CHECK(div2.is()); + CHECK(div3.is()); + CHECK(div4.is()); + CHECK(div5.is()); + CHECK(div6.is()); + + CHECK(div0 == 1.0/div1); + CHECK(div2 == 1.0/div3); + CHECK(div4 == 1.0/div5); + CHECK(div6 == v0/v0); + } +} diff --git a/test/unit/data/well-known-geometries.test b/test/unit/data/well-known-geometries.test new file mode 100644 index 000000000..1c6273b29 --- /dev/null +++ b/test/unit/data/well-known-geometries.test @@ -0,0 +1,13 @@ +POINT (30 10);\x01010000000000000000003e400000000000002440;\x01003c14 +LINESTRING (30 10, 10 30, 40 40);\x0102000000030000000000000000003e40000000000000244000000000000024400000000000003e4000000000000044400000000000004440;\x0200033c1427283c14 +POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10));\x010300000001000000050000000000000000003e4000000000000024400000000000004440000000000000444000000000000034400000000000004440000000000000244000000000000034400000000000003e400000000000002440;\x030001053c14143c270013272813 +POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30));\x0103000000020000000500000000000000008041400000000000002440000000000080464000000000008046400000000000002e40000000000000444000000000000024400000000000003440000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40;\x03000205461414463b0909273213041d281e0a091d1314 +MULTIPOINT ((10 40), (40 30), (20 20), (30 10));\x010400000004000000010100000000000000000024400000000000004440010100000000000000000044400000000000003e4001010000000000000000003440000000000000344001010000000000000000003e400000000000002440;\x04000414503c1327131413 +MULTIPOINT (10 40, 40 30, 20 20, 30 10);\x010400000004000000010100000000000000000024400000000000004440010100000000000000000044400000000000003e4001010000000000000000003440000000000000344001010000000000000000003e400000000000002440;\x04000414503c1327131413 +MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10));\x010500000002000000010200000003000000000000000000244000000000000024400000000000003440000000000000344000000000000024400000000000004440010200000004000000000000000000444000000000000044400000000000003e400000000000003e40000000000000444000000000000034400000000000003e400000000000002440;\x05000203141414141328043c00131314131313 +MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)));\x010600000002000000010300000001000000040000000000000000003e40000000000000344000000000008046400000000000004440000000000000244000000000000044400000000000003e400000000000003440010300000001000000050000000000000000002e4000000000000014400000000000004440000000000000244000000000000024400000000000003440000000000000144000000000000024400000000000002e400000000000001440;\x06000201043c281e284500282701051d1d320a3b1409131409 +MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),(30 20, 20 15, 20 25, 30 20)));\x01060000000200000001030000000100000004000000000000000000444000000000000044400000000000003440000000000080464000000000008046400000000000003e4000000000000044400000000000004440010300000002000000060000000000000000003440000000000080414000000000000024400000000000003e40000000000000244000000000000024400000000000003e4000000000000014400000000000804640000000000000344000000000000034400000000000804140040000000000000000003e40000000000000344000000000000034400000000000002e40000000000000344000000000000039400000000000003e400000000000003440;\x06000201045050270a321d0914020627091309002728091e1e311e04141d130900141409 +GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10));\x010700000002000000010100000000000000000010400000000000001840010200000002000000000000000000104000000000000018400000000000001c400000000000002440;\x0700020100080c020002080c0608 +POINT EMPTY;\x0101000000000000000000f87f000000000000f87f;\x0110 +LINESTRING EMPTY;\x010200000000000000;\x0210 +POLYGON EMPTY;\x010300000000000000;\x0310 diff --git a/test/unit/datasource/csv.cpp b/test/unit/datasource/csv.cpp index 72e87193c..6142185ca 100644 --- a/test/unit/datasource/csv.cpp +++ b/test/unit/datasource/csv.cpp @@ -24,6 +24,7 @@ #include "ds_test_util.hpp" #include +#include #include #include #include @@ -68,6 +69,10 @@ mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = tr mapnik::parameters params; params["type"] = std::string("csv"); params["file"] = file_name; + if (!base.empty()) + { + params["base"] = base; + } params["strict"] = mapnik::value_bool(strict); auto ds = mapnik::datasource_cache::instance().create(params); // require a non-null pointer returned @@ -75,31 +80,11 @@ mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = tr return ds; } -int create_disk_index(std::string const& filename, bool silent = true) -{ - std::string cmd; - if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) - { - cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && "; - } - cmd += "mapnik-index " + filename; - if (silent) - { -#ifndef _WINDOWS - cmd += " 2>/dev/null"; -#else - cmd += " 2> nul"; -#endif - } - return std::system(cmd.c_str()); -} - } // anonymous namespace -static const std::string csv_plugin("./plugins/input/csv.input"); - TEST_CASE("csv") { + std::string csv_plugin("./plugins/input/csv.input"); if (mapnik::util::exists(csv_plugin)) { // make the tests silent since we intentionally test error conditions that are noisy @@ -157,7 +142,7 @@ TEST_CASE("csv") { int ret_posix = (ret >> 8) & 0x000000ff; INFO(ret); INFO(ret_posix); - require_fail = (path == "test/data/csv/warns/feature_id_counting.csv") ? false : true; + require_fail = (boost::iends_with(path,"feature_id_counting.csv")) ? false : true; if (!require_fail) { REQUIRE(mapnik::util::exists(path + ".index")); @@ -204,7 +189,7 @@ TEST_CASE("csv") { int ret_posix = (ret >> 8) & 0x000000ff; INFO(ret); INFO(ret_posix); - if (path != "test/data/csv/more_headers_than_column_values.csv") // mapnik-index won't create *.index for 0 features + if (!boost::iends_with(path,"more_headers_than_column_values.csv")) // mapnik-index won't create *.index for 0 features { CHECK(mapnik::util::exists(path + ".index")); } @@ -288,7 +273,7 @@ TEST_CASE("csv") { INFO(ret_posix); CHECK(mapnik::util::exists(filepath + ".index")); } - auto ds = get_csv_ds(filepath,true,base); + auto ds = get_csv_ds(filename,true,base); CHECK(ds->type() == mapnik::datasource::datasource_t::Vector); auto fields = ds->get_descriptor().get_descriptors(); require_field_names(fields, {"Precinct", "Phone", "Address", "City", "geo_longitude", "geo_latitude", "geo_accuracy"}); @@ -892,7 +877,15 @@ TEST_CASE("csv") { auto feature = all_features(ds)->next(); REQUIRE(bool(feature)); REQUIRE(feature->has_key("Name")); - CHECK(feature->get("Name") == ustring(name.c_str())); + std::string utf8; + mapnik::transcoder tr("utf-8"); + ustring expected_string = tr.transcode(name.c_str()); + mapnik::value val(expected_string); + mapnik::to_utf8(expected_string,utf8); + INFO(feature->get("Name")); + INFO(utf8); + INFO(val); + CHECK(feature->get("Name") == val); } } // END SECTION @@ -983,7 +976,7 @@ TEST_CASE("csv") { using ustring = mapnik::value_unicode_string; using row = std::pair; - for (auto const &r : { + for (auto const& r : { row{"test/data/csv/fails/needs_headers_two_lines.csv", 2}, row{"test/data/csv/fails/needs_headers_one_line.csv", 1}, row{"test/data/csv/fails/needs_headers_one_line_no_newline.csv", 1}}) diff --git a/test/unit/datasource/ds_test_util.hpp b/test/unit/datasource/ds_test_util.hpp index e33431872..46868d4e5 100644 --- a/test/unit/datasource/ds_test_util.hpp +++ b/test/unit/datasource/ds_test_util.hpp @@ -20,6 +20,10 @@ * *****************************************************************************/ + +#ifndef MAPNIK_UNIT_DATSOURCE_UTIL +#define MAPNIK_UNIT_DATSOURCE_UTIL + #include "catch.hpp" #include @@ -36,7 +40,7 @@ std::string vector_to_string(T const& vec) std::stringstream s; for (auto const& item : vec) { - s << item << "\n"; + s << " " << item << "\n"; } return s.str(); } @@ -47,34 +51,41 @@ std::string vector_to_string(std::vector const& ve std::stringstream s; for (auto const& item : vec) { - s << item.get_name() << "\n"; + s << " " << item.get_name() << "\n"; } return s.str(); } +#define REQUIRE_FIELD_NAMES(fields, names) \ + INFO("fields:\n" + vector_to_string(fields) + "names:\n" + vector_to_string(names)); \ + REQUIRE(fields.size() == names.size()); \ + auto itr_a = fields.begin(); \ + auto const end_a = fields.end(); \ + auto itr_b = names.begin(); \ + for (; itr_a != end_a; ++itr_a, ++itr_b) \ + { \ + CHECK(itr_a->get_name() == *itr_b); \ + } \ + inline void require_field_names(std::vector const &fields, std::initializer_list const &names) { - INFO("fields: " + vector_to_string(fields) + " names: " + vector_to_string(names)); - REQUIRE(fields.size() == names.size()); - auto itr_a = fields.begin(); - auto const end_a = fields.end(); - auto itr_b = names.begin(); - for (; itr_a != end_a; ++itr_a, ++itr_b) - { - CHECK(itr_a->get_name() == *itr_b); - } + REQUIRE_FIELD_NAMES(fields,names); } +#define REQUIRE_FIELD_TYPES(fields, types) \ + REQUIRE(fields.size() == types.size()); \ + auto itr_a = fields.begin(); \ + auto const end_a = fields.end(); \ + auto itr_b = types.begin(); \ + for (; itr_a != end_a; ++itr_a, ++itr_b) { \ + CHECK(itr_a->get_type() == *itr_b); \ + } \ + inline void require_field_types(std::vector const &fields, - std::initializer_list const &types) { - REQUIRE(fields.size() == types.size()); - auto itr_a = fields.begin(); - auto const end_a = fields.end(); - auto itr_b = types.begin(); - for (; itr_a != end_a; ++itr_a, ++itr_b) { - CHECK(itr_a->get_type() == *itr_b); - } + std::initializer_list const &types) +{ + REQUIRE_FIELD_TYPES(fields, types); } inline mapnik::featureset_ptr all_features(mapnik::datasource_ptr ds) { @@ -95,13 +106,18 @@ inline std::size_t count_features(mapnik::featureset_ptr features) { } using attr = std::tuple; + +#define REQUIRE_ATTRIBUTES(feature, attrs) \ + REQUIRE(bool(feature)); \ + for (auto const &kv : attrs) { \ + REQUIRE(feature->has_key(std::get<0>(kv))); \ + CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); \ + } \ + + inline void require_attributes(mapnik::feature_ptr feature, std::initializer_list const &attrs) { - REQUIRE(bool(feature)); - for (auto const &kv : attrs) { - REQUIRE(feature->has_key(std::get<0>(kv))); - CHECK(feature->get(std::get<0>(kv)) == std::get<1>(kv)); - } + REQUIRE_ATTRIBUTES(feature, attrs); } namespace detail { @@ -169,4 +185,25 @@ inline void require_geometry(mapnik::feature_ptr feature, CHECK(feature_count(feature->get_geometry()) == num_parts); } +inline int create_disk_index(std::string const& filename, bool silent = true) +{ + std::string cmd; + if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) + { + cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " "; + } + cmd += "mapnik-index " + filename; + if (silent) + { +#ifndef _WINDOWS + cmd += " 2>/dev/null"; +#else + cmd += " 2> nul"; +#endif + } + return std::system(cmd.c_str()); } + +} + +#endif // MAPNIK_UNIT_DATSOURCE_UTIL diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp index d27347c6b..6d953c8bd 100644 --- a/test/unit/datasource/geojson.cpp +++ b/test/unit/datasource/geojson.cpp @@ -21,7 +21,9 @@ *****************************************************************************/ #include "catch.hpp" +#include "ds_test_util.hpp" +#include #include #include #include @@ -61,25 +63,6 @@ std::pair fetch_first_feature(std::s return std::make_pair(ds,feature); } -int create_disk_index(std::string const& filename, bool silent = true) -{ - std::string cmd; - if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) - { - cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && "; - } - cmd += "mapnik-index " + filename; - if (silent) - { -#ifndef _WINDOWS - cmd += " 2>/dev/null"; -#else - cmd += " 2> nul"; -#endif - } - return std::system(cmd.c_str()); -} - } TEST_CASE("geojson") { @@ -113,6 +96,25 @@ TEST_CASE("geojson") { } } + SECTION("GeoJSON an empty FeatureCollection") + { + for (auto cache_features : {true, false}) + { + mapnik::parameters params; + params["type"] = "geojson"; + params["file"] = "./test/data/json/empty_featurecollection.json"; + params["cache_features"] = cache_features; + auto ds = mapnik::datasource_cache::instance().create(params); + CHECK(ds != nullptr); + auto fs = all_features(ds); + REQUIRE(!mapnik::is_valid(fs)); + while (auto f = fs->next()) + { + CHECK(false); // shouldn't get here + } + } + } + SECTION("GeoJSON invalid Point") { for (auto cache_features : {true, false}) @@ -302,8 +304,6 @@ TEST_CASE("geojson") { } auto features = ds->features(query); auto features2 = ds->features_at_point(ds->envelope().center(),0); - REQUIRE(features != nullptr); - REQUIRE(features2 != nullptr); auto feature = features->next(); auto feature2 = features2->next(); REQUIRE(feature != nullptr); @@ -421,7 +421,6 @@ TEST_CASE("geojson") { query.add_property_name(field.get_name()); } auto features = ds->features(query); - REQUIRE(features != nullptr); auto feature = features->next(); REQUIRE(feature != nullptr); REQUIRE(feature->envelope() == mapnik::box2d(123,456,123,456)); @@ -629,5 +628,114 @@ TEST_CASE("geojson") { } } } + + SECTION("GeoJSON descriptor returns all field names") + { + mapnik::parameters params; + params["type"] = "geojson"; + + std::string filename("./test/data/json/featurecollection-multipleprops.geojson"); + params["file"] = filename; + + // cleanup in the case of a failed previous run + if (mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + + for (auto create_index : { true, false }) + { + if (create_index) + { + CHECK(!mapnik::util::exists(filename + ".index")); + int ret = create_disk_index(filename); + int ret_posix = (ret >> 8) & 0x000000ff; + INFO(ret); + INFO(ret_posix); + CHECK(mapnik::util::exists(filename + ".index")); + } + + for (auto cache_features : {true, false}) + { + params["cache_features"] = cache_features; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(bool(ds)); + auto fields = ds->get_descriptor().get_descriptors(); + std::initializer_list names = {"one", "two"}; + REQUIRE_FIELD_NAMES(fields, names); + } + // cleanup + if (create_index && mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + } + } + + SECTION("GeoJSON properties are properly expressed") + { + mapnik::transcoder tr("utf8"); + mapnik::parameters params; + params["type"] = "geojson"; + + std::string filename("./test/data/json/escaped.geojson"); + params["file"] = filename; + + // cleanup in the case of a failed previous run + if (mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + + for (auto create_index : { true, false }) + { + if (create_index) + { + CHECK(!mapnik::util::exists(filename + ".index")); + int ret = create_disk_index(filename); + int ret_posix = (ret >> 8) & 0x000000ff; + INFO(ret); + INFO(ret_posix); + CHECK(mapnik::util::exists(filename + ".index")); + } + + for (auto cache_features : {true, false}) + { + params["cache_features"] = cache_features; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(bool(ds)); + auto fields = ds->get_descriptor().get_descriptors(); + std::initializer_list names = {"NOM_FR","array","boolean","description","double","empty_array", "empty_object","int","name","object","spaces"}; + REQUIRE_FIELD_NAMES(fields, names); + + auto fs = all_features(ds); + std::initializer_list attrs = { + attr{"name", tr.transcode("Test")}, + attr{"NOM_FR", tr.transcode("Québec")}, + attr{"boolean", mapnik::value_bool("true")}, + attr{"description", tr.transcode("Test: \u005C")}, + attr{"double", mapnik::value_double(1.1)}, + attr{"int", mapnik::value_integer(1)}, + attr{"object", tr.transcode("{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\":1,\"double\":1.1,\"boolean\":false" + ",\"NOM_FR\":\"Québec\",\"array\":[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],\"another_object\":{\"name\":\"nested object\"}}")}, + attr{"spaces", tr.transcode("this has spaces")}, + attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{\"name\":\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", tr.transcode("[]")}, + attr{"empty_object", tr.transcode("{}")}, + }; + auto feature = fs->next(); + REQUIRE(bool(feature)); + REQUIRE_ATTRIBUTES(feature, attrs); + } + // cleanup + if (create_index && mapnik::util::exists(filename + ".index")) + { + mapnik::util::remove(filename + ".index"); + } + } + } } } diff --git a/test/unit/datasource/postgis.cpp b/test/unit/datasource/postgis.cpp index 4aaa76fe1..95ee65851 100644 --- a/test/unit/datasource/postgis.cpp +++ b/test/unit/datasource/postgis.cpp @@ -29,24 +29,24 @@ #include /* - -Compile and run just this test: - -clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` && ./test-postgis -d yes - + Compile and run just this test: + clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` && ./test-postgis -d yes */ +#include + namespace { -int run(std::string const& command, bool silent = false) +bool run(std::string const& command, bool okay_to_fail = false) { std::string cmd; if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) { - cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && "; + cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && "; } cmd += command; - if (silent) + // silence output unless MAPNIK_TEST_DEBUG is defined + if (std::getenv("MAPNIK_TEST_DEBUG") == nullptr) { #ifndef _WINDOWS cmd += " 2>/dev/null"; @@ -54,41 +54,287 @@ int run(std::string const& command, bool silent = false) cmd += " 2> nul"; #endif } + else + { + std::clog << "Running " << cmd << "\n"; + } bool worked = (std::system(cmd.c_str()) == 0); - if (silent == true) return true; + if (okay_to_fail == true) return true; return worked; } +std::string const dbname("mapnik-tmp-postgis-test-db"); +bool status = false; + +bool ping_postmaster() +{ + return (run("psql --version") + && run("dropdb --if-exists " + dbname) + && run("createdb -T template_postgis " + dbname)); +} + +} + TEST_CASE("postgis") { - SECTION("Postgis data initialization") + SECTION("Ping Postmaster (check if server is runnging and accessible") { - REQUIRE(run("dropdb mapnik-tmp-postgis-test-db",true)); - REQUIRE(run("createdb -T template_postgis mapnik-tmp-postgis-test-db")); - std::stringstream cmd; - cmd << "psql -q mapnik-tmp-postgis-test-db -f ./test/data/sql/table1.sql"; - REQUIRE(run(cmd.str())); - } - - std::string datasource_plugin("./plugins/input/postgis.input"); - if (mapnik::util::exists(datasource_plugin)) - { - SECTION("Postgis plugin initialization") + if (!ping_postmaster()) { - mapnik::parameters params; - params["type"] = "postgis"; - params["dbname"] = "mapnik-tmp-postgis-test-db"; + WARN("Can't run postgis.input tests - check postmaster is running and accessible"); + return; + } + else + { + status = true; + } + } + if (status) + { + SECTION("Postgis data initialization") + { + //don't add 'true' here, to get error message, when drop fails. If it works nothing is output + REQUIRE(run("dropdb --if-exists " + dbname)); + REQUIRE(run("createdb -T template_postgis " + dbname)); + //REQUIRE(run("createdb " + dbname)); + // Breaks when raster support is missing (unfortunately this is common) + //REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true)); + REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname)); + } + + mapnik::parameters base_params; + base_params["type"] = "postgis"; + base_params["dbname"] = dbname; + + SECTION("Postgis should throw without 'table' parameter") + { + mapnik::parameters params(base_params); + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["max_async_connection"] = "2"; + params["max_size"] = "1"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw with invalid metadata query") + { + mapnik::parameters params(base_params); + params["table"] = "does_not_exist"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw with invalid key field") + { + mapnik::parameters params(base_params); + params["table"] = "test_invalid_id"; + params["key_field"] = "id"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw with multicolumn primary key") + { + mapnik::parameters params(base_params); + params["table"] = "test_invalid_multi_col_pk"; + params["autodetect_key_field"] = "true"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis should throw without geom column") + { + mapnik::parameters params(base_params); + params["table"] = "test_no_geom_col"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + CHECK_THROWS(all_features(ds)); + } + + SECTION("Postgis should throw with invalid credentials") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["user"] = "not_a_valid_user"; + params["password"] = "not_a_valid_pwd"; + CHECK_THROWS(mapnik::datasource_cache::instance().create(params)); + } + + SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit") + { + mapnik::parameters params(base_params); + params["persist_connection"] = "false"; + params["table"] = "public.test"; + params["geometry_field"] = "geom"; + params["autodetect_key_field"] = "true"; + params["extent"] = "-1 -1, -1 2, 4 3, 3 -1, -1 -1"; + params["simplify_geometries"] = "true"; + params["row_limit"] = "1"; + auto ds = mapnik::datasource_cache::instance().create(params); + } + + SECTION("Postgis dataset geometry type") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test WHERE gid=1) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point); + } + + SECTION("Postgis query field names") + { + mapnik::parameters params(base_params); params["table"] = "test"; auto ds = mapnik::datasource_cache::instance().create(params); REQUIRE(ds != nullptr); - CHECK(ds->type() == mapnik::datasource::datasource_t::Vector); + REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector); auto fields = ds->get_descriptor().get_descriptors(); - require_field_names(fields, {"gid"}); - require_field_types(fields, {mapnik::Integer}); + require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" }); + require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String }); } + + SECTION("Postgis iterate features") + { + mapnik::parameters params(base_params); + params["table"] = "test"; + params["key_field"] = "gid"; + params["max_async_connection"] = "2"; + //params["cursor_size"] = "2"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + + auto featureset = ds->features_at_point(mapnik::coord2d(1, 1)); + mapnik::feature_ptr feature; + while ((bool(feature = featureset->next()))) { + REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string()); + REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool()); + REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double()); + REQUIRE(feature->get(5).to_string() == feature->get("colnumeric").to_string()); + } + + featureset = all_features(ds); + feature = featureset->next(); + //deactivate char tests for now: not yet implemented. + //add at postgis_datasource.cpp:423 + //case 18: // char + //REQUIRE("A" == feature->get("col-char").to_string()); + feature = featureset->next(); + //REQUIRE("B" == feature->get("col-char").to_string()); + feature = featureset->next(); + REQUIRE(false == feature->get("col+bool").to_bool()); + } + + SECTION("Postgis cursorresultest") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test) as data"; + params["cursor_size"] = "2"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + auto featureset = all_features(ds); + CHECK(count_features(featureset) == 8); + + featureset = all_features(ds); + mapnik::feature_ptr feature; + while (bool(feature = featureset->next())) { + CHECK(feature->size() == 10); + } + + featureset = all_features(ds); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point); + require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPoint); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::LineString); + require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiLineString); + require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Polygon); + require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPolygon); + require_geometry(featureset->next(), 3, mapnik::geometry::geometry_types::GeometryCollection); + } + + SECTION("Postgis bbox query") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == -2); + REQUIRE(ext.miny() == -2); + REQUIRE(ext.maxx() == 5); + REQUIRE(ext.maxy() == 4); + } + + SECTION("Postgis query extent: full dataset") + { + //include schema to increase coverage + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM public.test) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == -2); + REQUIRE(ext.miny() == -2); + REQUIRE(ext.maxx() == 5); + REQUIRE(ext.maxy() == 4); + } +/* deactivated for merging: still investigating a proper fix + SECTION("Postgis query extent from subquery") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test where gid=4) as data"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == 0); + REQUIRE(ext.miny() == 0); + REQUIRE(ext.maxx() == 1); + REQUIRE(ext.maxy() == 2); + } +*/ + SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'") + { + mapnik::parameters params(base_params); + params["table"] = "(SELECT * FROM test where gid=4) as data"; + params["extent_from_subquery"] = "true"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == 0); + REQUIRE(ext.miny() == 0); + REQUIRE(ext.maxx() == 1); + REQUIRE(ext.maxy() == 2); + } +/* deactivated for merging: still investigating a proper fix + SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'") + { + mapnik::parameters params(base_params); + // !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000' + // https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617 + params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data"; + params["extent_from_subquery"] = "true"; + auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); + mapnik::box2d ext = ds->envelope(); + CAPTURE(ext); + INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy()); + REQUIRE(ext.minx() == 0); + REQUIRE(ext.miny() == 0); + REQUIRE(ext.maxx() == 1); + REQUIRE(ext.maxy() == 2); + } +*/ + } } - - -} \ No newline at end of file diff --git a/test/unit/datasource/shapeindex.cpp b/test/unit/datasource/shapeindex.cpp index e16967812..51f47ac7c 100644 --- a/test/unit/datasource/shapeindex.cpp +++ b/test/unit/datasource/shapeindex.cpp @@ -24,8 +24,10 @@ #include #include +#include #include #include +#include #pragma GCC diagnostic push #include #include @@ -35,10 +37,14 @@ namespace { std::size_t count_shapefile_features(std::string const& filename) { +#if defined(MAPNIK_MEMORY_MAPPED_FILE) + mapnik::mapped_memory_cache::instance().clear(); +#endif mapnik::parameters params; params["type"] = "shape"; params["file"] = filename; auto ds = mapnik::datasource_cache::instance().create(params); + REQUIRE(ds != nullptr); CHECK(ds->type() == mapnik::datasource::datasource_t::Vector); auto fields = ds->get_descriptor().get_descriptors(); mapnik::query query(ds->envelope()); @@ -47,6 +53,7 @@ std::size_t count_shapefile_features(std::string const& filename) query.add_property_name(field.get_name()); } auto features = ds->features(query); + REQUIRE(features != nullptr); std::size_t feature_count = 0; auto feature = features->next(); @@ -55,17 +62,21 @@ std::size_t count_shapefile_features(std::string const& filename) ++feature_count; feature = features->next(); } + return feature_count; } -int create_shapefile_index(std::string const& filename, bool silent = true) +int create_shapefile_index(std::string const& filename, bool index_parts, bool silent = true) { std::string cmd; if (std::getenv("DYLD_LIBRARY_PATH") != nullptr) { - cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && "; + cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " "; } - cmd += "shapeindex " + filename; + + cmd += "shapeindex "; + if (index_parts) cmd+= "--index-parts "; + cmd += filename; if (silent) { #ifndef _WINDOWS @@ -79,39 +90,92 @@ int create_shapefile_index(std::string const& filename, bool silent = true) } +TEST_CASE("invalid shapeindex") +{ + std::string shape_plugin("./plugins/input/shape.input"); + if (mapnik::util::exists(shape_plugin)) + { + SECTION("Invalid index") + { + for (auto val : {std::make_tuple(true, std::string("mapnik-invalid-index.................")), // invalid header + std::make_tuple(false, std::string("mapnik-index................."))}) // valid header + invalid index + { + std::string path = "test/data/shp/boundaries.shp"; + std::string index_path = path.substr(0, path.rfind(".")) + ".index"; + // remove *.index if present + if (mapnik::util::exists(index_path)) + { + mapnik::util::remove(index_path); + } + // count features + + std::size_t feature_count = count_shapefile_features(path); + + // create index + std::ofstream index(index_path.c_str(), std::ios::binary); + index.write(std::get<1>(val).c_str(), std::get<1>(val).size()); + index.close(); + + // count features + std::size_t feature_count_indexed = count_shapefile_features(path); + if (std::get<0>(val)) // fallback to un-indexed access + { + // ensure number of features are the same + CHECK(feature_count == feature_count_indexed); + } + else // the header is valid but index file itself is not - expect datasource to fail and return 0 features. + { + CHECK(feature_count_indexed == 0); + } + // remove *.index if present + if (mapnik::util::exists(index_path)) + { + mapnik::util::remove(index_path); + } + } + } + } +} + TEST_CASE("shapeindex") { std::string shape_plugin("./plugins/input/shape.input"); if (mapnik::util::exists(shape_plugin)) { - SECTION("Shapefile index") + SECTION("Index") { for (auto const& path : mapnik::util::list_directory("test/data/shp/")) { if (boost::iends_with(path,".shp")) { - std::string index_path = path.substr(0, path.rfind(".")) + ".index"; - // remove *.index if present - if (mapnik::util::exists(index_path)) + for (bool index_parts : {false, true} ) { - mapnik::util::remove(index_path); - } - // count features - std::size_t feature_count = count_shapefile_features(path); - // create *.index - create_shapefile_index(path); - if (feature_count == 0) - { - REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features - } - // count features - std::size_t feature_count_indexed = count_shapefile_features(path); - // ensure number of features are the same - REQUIRE(feature_count == feature_count_indexed); - // remove *.index if present - if (mapnik::util::exists(index_path)) - { - mapnik::util::remove(index_path); + CAPTURE(path); + CAPTURE(index_parts); + + std::string index_path = path.substr(0, path.rfind(".")) + ".index"; + // remove *.index if present + if (mapnik::util::exists(index_path)) + { + mapnik::util::remove(index_path); + } + // count features + std::size_t feature_count = count_shapefile_features(path); + // create *.index + REQUIRE(create_shapefile_index(path, index_parts) == 0); + if (feature_count == 0) + { + REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features + } + // count features + std::size_t feature_count_indexed = count_shapefile_features(path); + // ensure number of features are the same + REQUIRE(feature_count == feature_count_indexed); + // remove *.index if present + if (mapnik::util::exists(index_path)) + { + mapnik::util::remove(index_path); + } } } } diff --git a/test/unit/datasource/topojson.cpp b/test/unit/datasource/topojson.cpp new file mode 100644 index 000000000..41d9b1908 --- /dev/null +++ b/test/unit/datasource/topojson.cpp @@ -0,0 +1,113 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include "catch.hpp" +#include "ds_test_util.hpp" + +#include +#include +#include +#include +#include + +namespace { + +using iterator_type = std::string::const_iterator; +const mapnik::topojson::topojson_grammar grammar; + +bool parse_topology(std::string const& filename, mapnik::topojson::topology & topo) +{ + mapnik::util::file file(filename); + std::string buffer; + buffer.resize(file.size()); + std::fread(&buffer[0], buffer.size(), 1, file.get()); + if (!file) return false; + boost::spirit::standard::space_type space; + iterator_type itr = buffer.begin(); + iterator_type end = buffer.end(); + bool result = boost::spirit::qi::phrase_parse(itr, end, grammar, space, topo); + return (result && (itr == end)); +} + +} + +TEST_CASE("topojson") +{ + SECTION("geometry parsing") + { + mapnik::value_integer feature_id = 0; + mapnik::context_ptr ctx = std::make_shared(); + mapnik::transcoder tr("utf8"); + for (auto const& path : mapnik::util::list_directory("test/data/topojson/")) + { + mapnik::topojson::topology topo; + REQUIRE(parse_topology(path, topo)); + for (auto const& geom : topo.geometries) + { + mapnik::box2d bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom); + CHECK(bbox.valid()); + mapnik::topojson::feature_generator visitor(ctx, tr, topo, feature_id++); + mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom); + CHECK(feature); + CHECK(feature->envelope() == bbox); + } + } + } + + SECTION("TopoJSON properties are properly expressed") + { + std::string filename("./test/data/topojson/escaped.topojson"); + mapnik::context_ptr ctx = std::make_shared(); + mapnik::transcoder tr("utf8"); + mapnik::topojson::topology topo; + REQUIRE(parse_topology(filename, topo)); + mapnik::value_integer feature_id = 0; + for (auto const& geom : topo.geometries) + { + mapnik::box2d bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom); + CHECK(bbox.valid()); + mapnik::topojson::feature_generator visitor(ctx, tr, topo, feature_id); + mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom); + CHECK(feature); + CHECK(feature->envelope() == bbox); + std::initializer_list attrs = { + attr{"name", tr.transcode("Test")}, + attr{"NOM_FR", tr.transcode("Québec")}, + attr{"boolean", mapnik::value_bool("true")}, + attr{"description", tr.transcode("Test: \u005C")}, + attr{"double", mapnik::value_double(1.1)}, + attr{"int", mapnik::value_integer(1)}, + attr{"object", tr.transcode("{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\":1,\"double\":1.1,\"boolean\":false" + ",\"NOM_FR\":\"Québec\",\"array\":[\"string\",\"value with spaces\",3,1.1,null,true" + ",\"Québec\"],\"another_object\":{\"name\":\"nested object\"}}")}, + attr{"spaces", tr.transcode("this has spaces")}, + attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true," + "\"Québec\",{\"name\":\"object within an array\"}," + "[\"array\",\"within\",\"an\",\"array\"]]")}, + attr{"empty_array", tr.transcode("[]")}, + attr{"empty_object", tr.transcode("{}")}, + }; + REQUIRE_ATTRIBUTES(feature, attrs); + } + } + +} diff --git a/test/unit/font/fontset_runtime_test.cpp b/test/unit/font/fontset_runtime_test.cpp index e5a621190..bfbae2786 100644 --- a/test/unit/font/fontset_runtime_test.cpp +++ b/test/unit/font/fontset_runtime_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/geometry/centroid.cpp b/test/unit/geometry/centroid.cpp index 1e58aad4e..cdfbd6e4b 100644 --- a/test/unit/geometry/centroid.cpp +++ b/test/unit/geometry/centroid.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/geometry/geometry.cpp b/test/unit/geometry/geometry.cpp index d42f0abb9..53c1e2e57 100644 --- a/test/unit/geometry/geometry.cpp +++ b/test/unit/geometry/geometry.cpp @@ -9,7 +9,7 @@ TEST_CASE("geometry") { SECTION("json point") { mapnik::util::file input("./test/data/json/point1.json"); - REQUIRE( input.open() ); + REQUIRE( input ); mapnik::geometry::geometry geom; REQUIRE( input.data() ); std::string json_string(input.data().get(), input.size()); @@ -24,7 +24,20 @@ SECTION("json point") { SECTION("json point reversed") { mapnik::util::file input("./test/data/json/point2.json"); - REQUIRE( input.open() ); + REQUIRE( input ); + mapnik::geometry::geometry geom; + REQUIRE( input.data() ); + std::string json_string(input.data().get(), input.size()); + REQUIRE( mapnik::json::from_geojson(json_string,geom) ); + REQUIRE( geom.is >() ); + auto const& point = mapnik::util::get >(geom); + REQUIRE( point.x == 30 ); + REQUIRE( point.y == 10 ); +} + +SECTION("json point reversed + extra attributes") { + mapnik::util::file input("./test/data/json/point3.json"); + REQUIRE( input ); mapnik::geometry::geometry geom; REQUIRE( input.data() ); std::string json_string(input.data().get(), input.size()); diff --git a/test/unit/geometry/geometry_envelope_test.cpp b/test/unit/geometry/geometry_envelope_test.cpp index d23c9760c..75049820a 100644 --- a/test/unit/geometry/geometry_envelope_test.cpp +++ b/test/unit/geometry/geometry_envelope_test.cpp @@ -2,15 +2,18 @@ #include #include -#include -TEST_CASE("geometry ops - envelope") { +namespace { -SECTION("envelope_test - double") { +template +void envelope_test() +{ using namespace mapnik::geometry; + using coord_type = T; + { - geometry geom(point(1,2)); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(point(1,2)); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == 1 ); REQUIRE( bbox.miny() == 2 ); REQUIRE( bbox.maxx() == 1 ); @@ -18,80 +21,67 @@ SECTION("envelope_test - double") { } { // Test empty geom - geometry geom = mapnik::geometry::geometry_empty(); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom = mapnik::geometry::geometry_empty(); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE_FALSE( bbox.valid() ); } { - line_string line; + line_string line; line.add_coord(0,0); line.add_coord(1,1); line.add_coord(2,2); - geometry geom(line); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(line); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == 0 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 2 ); REQUIRE( bbox.maxy() == 2 ); } { - line_string line; + line_string line; line.add_coord(0,0); line.add_coord(1,1); line.add_coord(2,2); - line_string line2; + line_string line2; line2.add_coord(0,0); line2.add_coord(-1,-1); line2.add_coord(-2,-2); - multi_line_string multi_line; + multi_line_string multi_line; multi_line.emplace_back(std::move(line)); multi_line.emplace_back(std::move(line2)); - geometry geom(multi_line); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(multi_line); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == -2 ); REQUIRE( bbox.miny() == -2 ); REQUIRE( bbox.maxx() == 2 ); REQUIRE( bbox.maxy() == 2 ); } { - polygon poly; - linear_ring ring; + polygon poly; + linear_ring ring; ring.add_coord(0,0); ring.add_coord(-10,0); ring.add_coord(-10,10); ring.add_coord(0,10); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); - geometry geom(poly); - mapnik::box2d bbox = mapnik::geometry::envelope(geom); + geometry geom(poly); + mapnik::box2d bbox = mapnik::geometry::envelope(geom); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - multi_polygon mp; + multi_polygon mp; mp.push_back(poly); - geometry geom_mp(mp); + geometry geom_mp(mp); bbox = mapnik::geometry::envelope(geom_mp); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - correct(geom); - bbox = mapnik::geometry::envelope(geom); - REQUIRE( bbox.minx() == -10 ); - REQUIRE( bbox.miny() == 0 ); - REQUIRE( bbox.maxx() == 0 ); - REQUIRE( bbox.maxy() == 10 ); - correct(geom_mp); - bbox = mapnik::geometry::envelope(geom_mp); - REQUIRE( bbox.minx() == -10 ); - REQUIRE( bbox.miny() == 0 ); - REQUIRE( bbox.maxx() == 0 ); - REQUIRE( bbox.maxy() == 10 ); - - geometry_collection gc; + geometry_collection gc; bbox = mapnik::geometry::envelope(gc); REQUIRE_FALSE( bbox.valid() ); gc.push_back(geom_mp); @@ -100,7 +90,7 @@ SECTION("envelope_test - double") { REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); - gc.emplace_back(point(-50,-50)); + gc.emplace_back(point(-50,-50)); bbox = mapnik::geometry::envelope(gc); REQUIRE( bbox.minx() == -50 ); REQUIRE( bbox.miny() == -50 ); @@ -110,30 +100,30 @@ SECTION("envelope_test - double") { { // polygon with hole - polygon poly; - linear_ring ring; + polygon poly; + linear_ring ring; ring.add_coord(0,0); ring.add_coord(-10,0); ring.add_coord(-10,10); ring.add_coord(0,10); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); - linear_ring hole; + linear_ring hole; hole.add_coord(-7,7); hole.add_coord(-7,3); hole.add_coord(-3,3); hole.add_coord(-3,7); hole.add_coord(-7,7); poly.add_hole(std::move(hole)); - geometry geom(poly); - mapnik::box2d bbox = mapnik::geometry::envelope(poly); + geometry geom(poly); + mapnik::box2d bbox = mapnik::geometry::envelope(poly); REQUIRE( bbox.minx() == -10 ); REQUIRE( bbox.miny() == 0 ); REQUIRE( bbox.maxx() == 0 ); REQUIRE( bbox.maxy() == 10 ); // add another hole inside the first hole // which should be considered a hit - linear_ring fill; + linear_ring fill; fill.add_coord(-6,4); fill.add_coord(-6,6); fill.add_coord(-4,6); @@ -149,3 +139,14 @@ SECTION("envelope_test - double") { } } + +TEST_CASE("geometry ops - envelope") { + +SECTION("envelope_test") +{ + envelope_test(); + envelope_test(); + envelope_test(); +} + +} diff --git a/test/unit/geometry/geometry_equal.hpp b/test/unit/geometry/geometry_equal.hpp index cb4a30ddf..4ff80abab 100644 --- a/test/unit/geometry/geometry_equal.hpp +++ b/test/unit/geometry/geometry_equal.hpp @@ -1,3 +1,6 @@ +#ifndef MAPNIK_UNIT_GEOMETRY_EQUAL +#define MAPNIK_UNIT_GEOMETRY_EQUAL + #include "catch.hpp" // boost @@ -81,7 +84,15 @@ auto zip_crange(Conts&... conts) #include #include -using namespace mapnik::geometry; +using mapnik::geometry::geometry; +using mapnik::geometry::geometry_empty; +using mapnik::geometry::point; +using mapnik::geometry::line_string; +using mapnik::geometry::polygon; +using mapnik::geometry::multi_point; +using mapnik::geometry::multi_line_string; +using mapnik::geometry::multi_polygon; +using mapnik::geometry::geometry_collection; template void assert_g_equal(geometry const& g1, geometry const& g2); @@ -89,26 +100,26 @@ void assert_g_equal(geometry const& g1, geometry const& g2); struct geometry_equal_visitor { template - void operator() (T1 const&, T2 const&) + void operator() (T1 const&, T2 const&) const { // comparing two different types! REQUIRE(false); } - void operator() (geometry_empty const&, geometry_empty const&) + void operator() (geometry_empty const&, geometry_empty const&) const { REQUIRE(true); } template - void operator() (point const& p1, point const& p2) + void operator() (point const& p1, point const& p2) const { REQUIRE(p1.x == Approx(p2.x)); REQUIRE(p1.y == Approx(p2.y)); } template - void operator() (line_string const& ls1, line_string const& ls2) + void operator() (line_string const& ls1, line_string const& ls2) const { if (ls1.size() != ls2.size()) { @@ -123,7 +134,7 @@ struct geometry_equal_visitor } template - void operator() (polygon const& p1, polygon const& p2) + void operator() (polygon const& p1, polygon const& p2) const { (*this)(static_cast const&>(p1.exterior_ring), static_cast const&>(p2.exterior_ring)); @@ -139,13 +150,13 @@ struct geometry_equal_visitor } template - void operator() (multi_point const& mp1, multi_point const& mp2) + void operator() (multi_point const& mp1, multi_point const& mp2) const { (*this)(static_cast const&>(mp1), static_cast const&>(mp2)); } template - void operator() (multi_line_string const& mls1, multi_line_string const& mls2) + void operator() (multi_line_string const& mls1, multi_line_string const& mls2) const { if (mls1.size() != mls2.size()) { @@ -159,7 +170,7 @@ struct geometry_equal_visitor } template - void operator() (multi_polygon const& mpoly1, multi_polygon const& mpoly2) + void operator() (multi_polygon const& mpoly1, multi_polygon const& mpoly2) const { if (mpoly1.size() != mpoly2.size()) { @@ -173,7 +184,7 @@ struct geometry_equal_visitor } template - void operator() (mapnik::util::recursive_wrapper > const& c1_, mapnik::util::recursive_wrapper > const& c2_) + void operator() (mapnik::util::recursive_wrapper > const& c1_, mapnik::util::recursive_wrapper > const& c2_) const { geometry_collection const& c1 = static_cast const&>(c1_); geometry_collection const& c2 = static_cast const&>(c2_); @@ -189,7 +200,7 @@ struct geometry_equal_visitor } template - void operator() (geometry_collection const& c1, geometry_collection const& c2) + void operator() (geometry_collection const& c1, geometry_collection const& c2) const { if (c1.size() != c2.size()) { @@ -214,3 +225,5 @@ void assert_g_equal(T const& g1, T const& g2) { return geometry_equal_visitor()(g1,g2); } + +#endif // MAPNIK_UNIT_GEOMETRY_EQUAL diff --git a/test/unit/geometry/geometry_hit_test.cpp b/test/unit/geometry/geometry_hit_test.cpp index 7552d0143..3b21407f6 100644 --- a/test/unit/geometry/geometry_hit_test.cpp +++ b/test/unit/geometry/geometry_hit_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/geometry/geometry_is_simple.cpp b/test/unit/geometry/geometry_is_simple.cpp index dbed04a1e..55480585c 100644 --- a/test/unit/geometry/geometry_is_simple.cpp +++ b/test/unit/geometry/geometry_is_simple.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include @@ -163,6 +164,36 @@ SECTION("polygon 3 repeated points") { CHECK( !mapnik::geometry::is_simple(poly) ); } +#if BOOST_VERSION >= 106000 + +SECTION("polygon that is empty") { + mapnik::geometry::polygon poly; + CHECK( !mapnik::geometry::is_simple(poly) ); +} + +SECTION("polygon that has empty exterior ring") { + mapnik::geometry::polygon poly; + mapnik::geometry::linear_ring ring; + poly.set_exterior_ring(std::move(ring)); + CHECK( !mapnik::geometry::is_simple(poly) ); +} + +SECTION("polygon that has empty interior ring") { + mapnik::geometry::polygon poly; + mapnik::geometry::linear_ring ring; + ring.add_coord(0,0); + ring.add_coord(1,0); + ring.add_coord(1,1); + ring.add_coord(0,1); + ring.add_coord(0,0); + poly.set_exterior_ring(std::move(ring)); + mapnik::geometry::linear_ring ring2; + poly.add_hole(std::move(ring2)); + CHECK( !mapnik::geometry::is_simple(poly) ); +} + +#else // BOOST_VERSION >= 1.60 + SECTION("polygon that is empty") { mapnik::geometry::polygon poly; CHECK( mapnik::geometry::is_simple(poly) ); @@ -189,6 +220,8 @@ SECTION("polygon that has empty interior ring") { CHECK( mapnik::geometry::is_simple(poly) ); } +#endif // BOOST_VERSION >= 1.60 + // A polygon with a spike can still be simple SECTION("polygon with spike") { mapnik::geometry::polygon poly; diff --git a/test/unit/geometry/geometry_is_valid.cpp b/test/unit/geometry/geometry_is_valid.cpp index 6d8b922dd..de1ee4c04 100644 --- a/test/unit/geometry/geometry_is_valid.cpp +++ b/test/unit/geometry/geometry_is_valid.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include @@ -43,6 +44,8 @@ SECTION("point -- geometry object") { CHECK( failure == boost::geometry::no_failure ); } +#if BOOST_VERSION < 106000 + SECTION("point unitialized") { mapnik::geometry::point pt2; CHECK( mapnik::geometry::is_valid(pt2) ); @@ -53,6 +56,37 @@ SECTION("point unitialized") { CHECK( mapnik::geometry::is_valid(pt2, failure2) ); CHECK( failure2 == boost::geometry::no_failure ); } +#endif + +#if BOOST_VERSION >= 106000 + +SECTION("point NaN") { + mapnik::geometry::point pt(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); + CHECK( std::isnan(pt.x) ); + CHECK( std::isnan(pt.y) ); + CHECK( !mapnik::geometry::is_valid(pt) ); + std::string message; + CHECK( !mapnik::geometry::is_valid(pt, message) ); + CHECK( message == "Geometry has point(s) with invalid coordinate(s)"); + boost::geometry::validity_failure_type failure; + CHECK( !mapnik::geometry::is_valid(pt, failure) ); + CHECK( failure == boost::geometry::failure_invalid_coordinate ); +} + +SECTION("point Infinity") { + mapnik::geometry::point pt(std::numeric_limits::infinity(),std::numeric_limits::infinity()); + CHECK( std::isinf(pt.x) ); + CHECK( std::isinf(pt.y) ); + CHECK( !mapnik::geometry::is_valid(pt) ); + std::string message; + CHECK( !mapnik::geometry::is_valid(pt, message) ); + CHECK( message == "Geometry has point(s) with invalid coordinate(s)"); + boost::geometry::validity_failure_type failure; + CHECK( !mapnik::geometry::is_valid(pt, failure) ); + CHECK( failure == boost::geometry::failure_invalid_coordinate ); +} + +#else // BOOST_VERSION >= 1.60 // This is funky that boost geometry is_valid does not check for NAN when dealing with a point // this test is here in case the logic ever changes @@ -86,9 +120,11 @@ SECTION("point Infinity") { CHECK( failure == boost::geometry::no_failure ); } +#endif // BOOST_VERSION >= 1.60 + SECTION("multi point") { mapnik::geometry::multi_point mpt; - mpt.add_coord(0,0); + mpt.add_coord(0,0); mpt.add_coord(1,1); CHECK( mapnik::geometry::is_valid(mpt) ); std::string message; @@ -113,7 +149,7 @@ SECTION("multi point empty") { SECTION("line_string") { mapnik::geometry::line_string line; - line.add_coord(0,0); + line.add_coord(0,0); line.add_coord(1,1); CHECK( mapnik::geometry::is_valid(line) ); std::string message; @@ -127,7 +163,7 @@ SECTION("line_string") { // This shouldn't fail -- test added in case logic ever changes SECTION("line_string repeated points") { mapnik::geometry::line_string line; - line.add_coord(0,0); + line.add_coord(0,0); line.add_coord(1,1); line.add_coord(1,1); line.add_coord(2,2); @@ -153,10 +189,10 @@ SECTION("line_string empty") { SECTION("multi_line_string") { mapnik::geometry::line_string line1; - line1.add_coord(0,0); + line1.add_coord(0,0); line1.add_coord(1,1); mapnik::geometry::line_string line2; - line2.add_coord(0,1); + line2.add_coord(0,1); line2.add_coord(1,2); mapnik::geometry::multi_line_string lines; lines.emplace_back(line1); @@ -184,7 +220,7 @@ SECTION("multi_line_string empty") { SECTION("polygon") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(1,0); ring.add_coord(1,1); ring.add_coord(0,1); @@ -202,7 +238,7 @@ SECTION("polygon") { SECTION("polygon invalid winding order") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(0,1); ring.add_coord(1,1); ring.add_coord(1,0); @@ -221,7 +257,7 @@ SECTION("polygon invalid winding order") { SECTION("polygon 2 repeated points") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(1,0); ring.add_coord(1,1); ring.add_coord(1,1); @@ -240,7 +276,7 @@ SECTION("polygon 2 repeated points") { SECTION("polygon 3 repeated points") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(1,0); ring.add_coord(1,1); ring.add_coord(1,1); @@ -271,7 +307,7 @@ SECTION("polygon that is empty") { SECTION("polygon with spike") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(1,0); ring.add_coord(1,1); ring.add_coord(2,2); @@ -291,14 +327,14 @@ SECTION("polygon with spike") { SECTION("polygon with hole") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(3,0); ring.add_coord(3,3); ring.add_coord(0,3); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); mapnik::geometry::linear_ring hole; - hole.add_coord(1,1); + hole.add_coord(1,1); hole.add_coord(1,2); hole.add_coord(2,2); hole.add_coord(2,1); @@ -316,7 +352,7 @@ SECTION("polygon with hole") { SECTION("polygon with empty hole") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(3,0); ring.add_coord(3,3); ring.add_coord(0,3); @@ -337,14 +373,14 @@ SECTION("polygon with empty hole") { SECTION("polygon with hole with invalid winding order") { mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(3,0); ring.add_coord(3,3); ring.add_coord(0,3); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); mapnik::geometry::linear_ring hole; - hole.add_coord(1,1); + hole.add_coord(1,1); hole.add_coord(2,1); hole.add_coord(2,2); hole.add_coord(1,2); @@ -363,7 +399,7 @@ SECTION("multi polygon") { mapnik::geometry::multi_polygon mp; mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(1,0); ring.add_coord(1,1); ring.add_coord(0,1); @@ -371,7 +407,7 @@ SECTION("multi polygon") { poly.set_exterior_ring(std::move(ring)); mapnik::geometry::polygon poly2; mapnik::geometry::linear_ring ring2; - ring2.add_coord(0,0); + ring2.add_coord(0,0); ring2.add_coord(-1,0); ring2.add_coord(-1,-1); ring2.add_coord(0,-1); @@ -392,14 +428,14 @@ SECTION("multi polygon with hole") { mapnik::geometry::multi_polygon mp; mapnik::geometry::polygon poly; mapnik::geometry::linear_ring ring; - ring.add_coord(0,0); + ring.add_coord(0,0); ring.add_coord(3,0); ring.add_coord(3,3); ring.add_coord(0,3); ring.add_coord(0,0); poly.set_exterior_ring(std::move(ring)); mapnik::geometry::linear_ring hole; - hole.add_coord(1,1); + hole.add_coord(1,1); hole.add_coord(1,2); hole.add_coord(2,2); hole.add_coord(2,1); @@ -407,14 +443,14 @@ SECTION("multi polygon with hole") { poly.add_hole(std::move(hole)); mapnik::geometry::polygon poly2; mapnik::geometry::linear_ring ring2; - ring2.add_coord(0,0); + ring2.add_coord(0,0); ring2.add_coord(-3,0); ring2.add_coord(-3,-3); ring2.add_coord(0,-3); ring2.add_coord(0,0); poly2.set_exterior_ring(std::move(ring2)); mapnik::geometry::linear_ring hole2; - hole2.add_coord(-1,-1); + hole2.add_coord(-1,-1); hole2.add_coord(-1,-2); hole2.add_coord(-2,-2); hole2.add_coord(-2,-1); diff --git a/test/unit/geometry/geometry_reprojection.cpp b/test/unit/geometry/geometry_reprojection.cpp index dad9e294e..c8ec36243 100644 --- a/test/unit/geometry/geometry_reprojection.cpp +++ b/test/unit/geometry/geometry_reprojection.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include "geometry_equal.hpp" diff --git a/test/unit/geometry/geometry_strategy_test.cpp b/test/unit/geometry/geometry_strategy_test.cpp index 50acb721d..c08e828cb 100644 --- a/test/unit/geometry/geometry_strategy_test.cpp +++ b/test/unit/geometry/geometry_strategy_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include "geometry_equal.hpp" diff --git a/test/unit/geometry/geometry_test_helper.cpp b/test/unit/geometry/geometry_test_helper.cpp new file mode 100644 index 000000000..44bcce596 --- /dev/null +++ b/test/unit/geometry/geometry_test_helper.cpp @@ -0,0 +1,15 @@ +#include +#include +#include + + +namespace mapnik { namespace geometry { +// instantiate types required by geometry_envelope_test +template mapnik::box2d envelope(geometry const& geom); +template mapnik::box2d envelope(geometry const& geom); +template mapnik::box2d envelope(polygon const& geom); +template mapnik::box2d envelope(polygon const& geom); +template mapnik::box2d envelope(geometry_collection const& geom); +template mapnik::box2d envelope(geometry_collection const& geom); + +}} diff --git a/test/unit/geometry/has_empty.cpp b/test/unit/geometry/has_empty.cpp index a240c6f9b..b7fcab14e 100644 --- a/test/unit/geometry/has_empty.cpp +++ b/test/unit/geometry/has_empty.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/geometry/is_clockwise.cpp b/test/unit/geometry/is_clockwise.cpp new file mode 100644 index 000000000..42aebf6cf --- /dev/null +++ b/test/unit/geometry/is_clockwise.cpp @@ -0,0 +1,27 @@ +#include "catch.hpp" + +#include +#include + +TEST_CASE("Ring is_clockwise") { + + // Input is rather thin triangle to test precision issues aren't getting in the way. + SECTION("Clockwise") + { + mapnik::geometry::linear_ring ring; + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + ring.emplace_back(-13499697.1113113686, 4698431.85179749783); + ring.emplace_back(-13499697.0366658326, 4698431.92644303292); + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + REQUIRE(mapnik::util::is_clockwise(ring) == true); + } + SECTION("Anti-Clockwise") + { + mapnik::geometry::linear_ring ring; + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + ring.emplace_back(-13499697.0366658326, 4698431.92644303292); + ring.emplace_back(-13499697.1113113686, 4698431.85179749783); + ring.emplace_back(-13499697.0366658326, 4698431.85179749783); + REQUIRE(mapnik::util::is_clockwise(ring) == false); + } +} diff --git a/test/unit/geometry/is_empty.cpp b/test/unit/geometry/is_empty.cpp index bb6a6349b..949b2b285 100644 --- a/test/unit/geometry/is_empty.cpp +++ b/test/unit/geometry/is_empty.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/geometry/remove_empty.cpp b/test/unit/geometry/remove_empty.cpp index 15237542f..93881c854 100644 --- a/test/unit/geometry/remove_empty.cpp +++ b/test/unit/geometry/remove_empty.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/imaging/image.cpp b/test/unit/imaging/image.cpp index 9800860b9..2024953eb 100644 --- a/test/unit/imaging/image.cpp +++ b/test/unit/imaging/image.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/imaging/image_apply_opacity.cpp b/test/unit/imaging/image_apply_opacity.cpp index 09f8dd1c3..512097c0d 100644 --- a/test/unit/imaging/image_apply_opacity.cpp +++ b/test/unit/imaging/image_apply_opacity.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/imaging/image_filter.cpp b/test/unit/imaging/image_filter.cpp index 8d41ccbe2..5329ea4bb 100644 --- a/test/unit/imaging/image_filter.cpp +++ b/test/unit/imaging/image_filter.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik @@ -6,29 +7,30 @@ #include #include #include -#include -#include -#include +#include +// stl +#include +#include TEST_CASE("image filter") { SECTION("test bad filter input") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("red")); - + REQUIRE_THROWS( mapnik::filter::filter_image(im, "foo,asdfasdf()"); ); REQUIRE_THROWS( mapnik::filter::filter_image(im, "colorize-alpha("); ); REQUIRE_THROWS( mapnik::filter::filter_image(im, "color-to-alpha(blue"); ); REQUIRE_THROWS( mapnik::filter::filter_image(im, "color-to-alpha(,blue)"); ); REQUIRE_THROWS( mapnik::filter::filter_image(im, "colorize-alpha()"); ); - REQUIRE_THROWS( + REQUIRE_THROWS( mapnik::image_rgba8 const& im2 = im; mapnik::image_rgba8 new_im = mapnik::filter::filter_image(im2, "foo"); ); - + CHECK(im(0,0) == 0xffff0000); CHECK(im(0,1) == 0xffff0000); CHECK(im(0,2) == 0xffff0000); @@ -38,11 +40,11 @@ SECTION("test bad filter input") { CHECK(im(2,0) == 0xffff0000); CHECK(im(2,1) == 0xffff0000); CHECK(im(2,2) == 0xffff0000); - + } // END SECTION SECTION("test blur") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("red")); @@ -58,11 +60,11 @@ SECTION("test blur") { CHECK(im(2,0) == 0xffc60038); CHECK(im(2,1) == 0xffe2001c); CHECK(im(2,2) == 0xffc60038); - + } // END SECTION SECTION("test blur constant") { - + mapnik::image_rgba8 im_orig(3,3); mapnik::fill(im_orig,mapnik::color("blue")); mapnik::set_pixel(im_orig, 1, 1, mapnik::color("red")); @@ -79,11 +81,11 @@ SECTION("test blur constant") { CHECK(im(2,0) == 0xffc60038); CHECK(im(2,1) == 0xffe2001c); CHECK(im(2,2) == 0xffc60038); - + } // END SECTION SECTION("test gray") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("red")); @@ -99,11 +101,11 @@ SECTION("test gray") { CHECK(im(2,0) == 0xff1c1c1c); CHECK(im(2,1) == 0xff1c1c1c); CHECK(im(2,2) == 0xff1c1c1c); - + } // END SECTION SECTION("test agg stack blur") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("red")); @@ -123,7 +125,7 @@ SECTION("test agg stack blur") { } // END SECTION SECTION("test scale-hsla 1") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("red")); @@ -139,7 +141,7 @@ SECTION("test scale-hsla 1") { CHECK(im(2,0) == 0x80004000); CHECK(im(2,1) == 0x80004000); CHECK(im(2,2) == 0x80004000); - + } // END SECTION SECTION("test scale-hsla 2") { @@ -172,7 +174,7 @@ SECTION("test scale-hsla 2") { } // END SECTION SECTION("test emboss") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("white")); mapnik::set_pixel(im, 1, 1, mapnik::color("orange")); @@ -188,11 +190,11 @@ SECTION("test emboss") { CHECK(im(2,0) == 0xffffffff); CHECK(im(2,1) == 0xffffffff); CHECK(im(2,2) == 0xffffffff); - + } // END SECTION SECTION("test sharpen") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -208,11 +210,11 @@ SECTION("test sharpen") { CHECK(im(2,0) == 0xffff0000); CHECK(im(2,1) == 0xffff0000); CHECK(im(2,2) == 0xffff0000); - + } // END SECTION SECTION("test edge detect") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -228,11 +230,11 @@ SECTION("test edge detect") { CHECK(im(2,0) == 0xff000000); CHECK(im(2,1) == 0xff008080); CHECK(im(2,2) == 0xff000000); - + } // END SECTION SECTION("test sobel") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -248,11 +250,11 @@ SECTION("test sobel") { CHECK(im(2,0) == 0xfffeffff); CHECK(im(2,1) == 0xfffeffff); CHECK(im(2,2) == 0xfffeffff); - + } // END SECTION SECTION("test x-gradient") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -268,11 +270,11 @@ SECTION("test x-gradient") { CHECK(im(2,0) == 0xff808080); CHECK(im(2,1) == 0xff41c0c0); CHECK(im(2,2) == 0xff808080); - + } // END SECTION SECTION("test y-gradient") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -288,11 +290,11 @@ SECTION("test y-gradient") { CHECK(im(2,0) == 0xff808080); CHECK(im(2,1) == 0xff808080); CHECK(im(2,2) == 0xff808080); - + } // END SECTION SECTION("test invert") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -308,11 +310,11 @@ SECTION("test invert") { CHECK(im(2,0) == 0xff00ffff); CHECK(im(2,1) == 0xff00ffff); CHECK(im(2,2) == 0xff00ffff); - + } // END SECTION SECTION("test colorize-alpha - one color") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -328,11 +330,11 @@ SECTION("test colorize-alpha - one color") { CHECK(im(2,0) == 0xffff0000); CHECK(im(2,1) == 0xffff0000); CHECK(im(2,2) == 0xffff0000); - + } // END SECTION SECTION("test colorize-alpha - two color") { - + mapnik::image_rgba8 im(3,3); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 1, 1, mapnik::color("gray")); @@ -348,7 +350,7 @@ SECTION("test colorize-alpha - two color") { CHECK(im(2,0) == 0xfffd0000); CHECK(im(2,1) == 0xfffd0000); CHECK(im(2,2) == 0xfffd0000); - + } // END SECTION SECTION("test colorize-alpha - one color with transparency") { @@ -391,15 +393,53 @@ SECTION("test colorize-alpha - two color with transparency") { } // END SECTION +SECTION("test parsing image-filters") { + + std::string str = ""; // empty string + std::vector filters; + CHECK(parse_image_filters(str, filters)); + CHECK(filters.size() == 0); + + std::array expected = {{ "emboss", + "emboss", + "blur", + "gray", + "edge-detect", + "sobel", + "sharpen", + "x-gradient", + "y-gradient", + "invert", + "color-blind-protanope", + "color-blind-deuteranope", + "color-blind-tritanope", + "agg-stack-blur(1,1)", + "agg-stack-blur(1,1)", + "agg-stack-blur(2,2)", + "agg-stack-blur(2,3)"}}; + + str += "emboss emboss() blur,gray ,edge-detect, sobel , , sharpen,,,x-gradient y-gradientinvert"; + str += "color-blind-protanope color-blind-deuteranope color-blind-tritanope agg-stack-blur,agg-stack-blur(),agg-stack-blur(2),agg-stack-blur(2,3)" ; + CHECK(parse_image_filters(str, filters)); + CHECK(filters.size() == expected.size()); + std::size_t count = 0; + for (auto const& filter : filters) + { + std::stringstream ss; + ss << filter; + CHECK (expected[count++] == ss.str()); + } +} + SECTION("test colorize-alpha - parsing correct input") { - mapnik::image_filter_grammar> filter_grammar; - boost::spirit::qi::ascii::space_type space; - std::vector f; std::string s("colorize-alpha(#0000ff 0%, #00ff00 100%)"); - CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), filter_grammar, space, f) ); + std::vector f; + REQUIRE(parse_image_filters(s, f)); mapnik::filter::colorize_alpha const & ca = mapnik::util::get(f.front()); + CHECK(ca.size() == 2); + CHECKED_IF(ca.size() > 0) { mapnik::filter::color_stop const & s2 = ca[0]; CHECK( s2.color.alpha() == 0xff ); @@ -409,6 +449,7 @@ SECTION("test colorize-alpha - parsing correct input") { CHECK( s2.offset == 0.0 ); } + CHECKED_IF(ca.size() > 1) { mapnik::filter::color_stop const & s2 = ca[1]; CHECK( s2.color.alpha() == 0xff ); @@ -422,20 +463,15 @@ SECTION("test colorize-alpha - parsing correct input") { SECTION("test colorize-alpha - parsing incorrect input") { - mapnik::image_filter_grammar> filter_grammar; - boost::spirit::qi::ascii::space_type space; std::string s("colorize-alpha(#0000ff 0%, #00ff00 00 100%)"); - std::string::const_iterator itr = s.cbegin(); - std::string::const_iterator end = s.cend(); std::vector f; - CHECK( boost::spirit::qi::phrase_parse(s.cbegin(), s.cend(), filter_grammar, space, f) ); + CHECK(!parse_image_filters(s, f)); CHECK( f.empty() ); - CHECK( itr != end ); } // END SECTION SECTION("test color-blind-protanope") { - + mapnik::image_rgba8 im(2,2); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 0, 1, mapnik::color("green")); @@ -448,11 +484,11 @@ SECTION("test color-blind-protanope") { CHECK(im(0,1) == 0xff006e7c); CHECK(im(1,0) == 0xffd9f6ff); CHECK(im(1,1) == 0xff1d7e8e); - + } // END SECTION SECTION("test color-blind-deuteranope") { - + mapnik::image_rgba8 im(2,2); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 0, 1, mapnik::color("green")); @@ -465,11 +501,11 @@ SECTION("test color-blind-deuteranope") { CHECK(im(0,1) == 0xff1c688b); CHECK(im(1,0) == 0xffe9f5ff); CHECK(im(1,1) == 0xff0077a0); - + } // END SECTION SECTION("test color-blind-tritanope") { - + mapnik::image_rgba8 im(2,2); mapnik::fill(im,mapnik::color("blue")); mapnik::set_pixel(im, 0, 1, mapnik::color("green")); @@ -482,8 +518,7 @@ SECTION("test color-blind-tritanope") { CHECK(im(0,1) == 0xff80763a); CHECK(im(1,0) == 0xfff8f3ff); CHECK(im(1,1) == 0xff0017fd); - + } // END SECTION } // END TEST CASE - diff --git a/test/unit/imaging/image_io_test.cpp b/test/unit/imaging/image_io_test.cpp index 37f8fee89..18c01da18 100644 --- a/test/unit/imaging/image_io_test.cpp +++ b/test/unit/imaging/image_io_test.cpp @@ -1,6 +1,7 @@ #include "catch.hpp" -#include +#include +#include #include #include #include @@ -11,6 +12,41 @@ #include #endif +#pragma GCC diagnostic push +#include +#include +#include +#pragma GCC diagnostic pop + +inline void make_directory(std::string const& dir) { + boost::filesystem::create_directories(dir); +} + +namespace { +template +void check_tiny_png_image_quantising(T const& im) +{ + std::ostringstream ss(std::ios::binary); + mapnik::save_to_stream(im, ss, "png8"); + ss.flush(); + std::string str = ss.str(); + std::unique_ptr reader(mapnik::get_image_reader(str.data(), str.size())); + auto w = reader->width(); + auto h = reader->height(); + CHECK(w > 0); + CHECK(h > 0); + auto im2 = mapnik::util::get(reader->read(0, 0, w, h)); + for (std::size_t i = 0; i < w; ++i) + { + for (std::size_t j = 0; j < h; ++j) + { + REQUIRE(im2(i,j) == im(i,j)); + } + } +} + +} + TEST_CASE("image io") { SECTION("readers") { @@ -110,7 +146,91 @@ SECTION("writers options") int q1 = mapnik::detail::parse_jpeg_quality("jpeg:quality=50"); REQUIRE(q0 == q1); #endif +} // END SECTION + +SECTION("image_util : save_to_file/save_to_stream/save_to_string") +{ + mapnik::image_rgba8 im(256,256); + std::string named_color = "lightblue"; + mapnik::fill(im, mapnik::color(named_color).rgba()); + //////////////////////////////////////////////////// + std::vector > supported_types; +#if defined(HAVE_PNG) + supported_types.push_back(std::make_tuple("png","png")); + supported_types.push_back(std::make_tuple("png","png24")); + supported_types.push_back(std::make_tuple("png","png32")); + supported_types.push_back(std::make_tuple("png","png8")); + supported_types.push_back(std::make_tuple("png","png256")); +#endif +#if defined(HAVE_JPEG) + supported_types.push_back(std::make_tuple("jpeg","jpeg")); + supported_types.push_back(std::make_tuple("jpeg","jpeg80")); + supported_types.push_back(std::make_tuple("jpeg","jpeg90")); +#endif +#if defined(HAVE_TIFF) + supported_types.push_back(std::make_tuple("tiff","tiff")); +#endif +#if defined(HAVE_WEBP) + supported_types.push_back(std::make_tuple("webp","webp")); +#endif + + std::string directory_name("/tmp/mapnik-tests/"); + make_directory(directory_name); + REQUIRE(mapnik::util::exists(directory_name)); + + for (auto const& info : supported_types) + { + std::string extension; + std::string format; + std::tie(extension, format) = info; + std::string filename = (boost::format(directory_name + "mapnik-%1%.%2%") % named_color % extension).str(); + mapnik::save_to_file(im, filename); + std::string str = mapnik::save_to_string(im, format); + std::ostringstream ss; + mapnik::save_to_stream(im, ss, format); + CHECK(str.length() == ss.str().length()); + // wrap reader in scope to ensure the file handle is + // released before we try to remove the file + { + std::unique_ptr reader(mapnik::get_image_reader(filename, extension)); + unsigned w = reader->width(); + unsigned h = reader->height(); + auto im2 = reader->read(0, 0, w, h); + CHECK(im2.size() == im.size()); + if (extension == "png" || extension == "tiff") + { + CHECK(0 == std::memcmp(im2.bytes(), im.bytes(), im.width() * im.height())); + } + } + if (mapnik::util::exists(filename)) + { + mapnik::util::remove(filename); + } + } +} + +SECTION("Quantising small (less than 3 pixel images preserve original colours") +{ +#if defined(HAVE_PNG) + { // 1x1 + mapnik::image_rgba8 im(1,1); // 1 pixel + im(0,0) = mapnik::color("green").rgba(); + check_tiny_png_image_quantising(im); + } + { // 1x2 + mapnik::image_rgba8 im(1,2); // 2 pixels + mapnik::fill(im, mapnik::color("red").rgba()); + im(0,0) = mapnik::color("green").rgba(); + check_tiny_png_image_quantising(im); + } + { // 2x1 + mapnik::image_rgba8 im(2,1); // 2 pixels + mapnik::fill(im, mapnik::color("red").rgba()); + im(0,0) = mapnik::color("green").rgba(); + check_tiny_png_image_quantising(im); + } +#endif } // END SECTION } // END TEST_CASE diff --git a/test/unit/imaging/image_is_solid.cpp b/test/unit/imaging/image_is_solid.cpp index 5bc8217ba..ffc527e1a 100644 --- a/test/unit/imaging/image_is_solid.cpp +++ b/test/unit/imaging/image_is_solid.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/imaging/image_painted_test.cpp b/test/unit/imaging/image_painted_test.cpp index 5d0b403f7..3705f2e40 100644 --- a/test/unit/imaging/image_painted_test.cpp +++ b/test/unit/imaging/image_painted_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/imaging/image_premultiply.cpp b/test/unit/imaging/image_premultiply.cpp index 3a5e2a1c0..813d21c28 100644 --- a/test/unit/imaging/image_premultiply.cpp +++ b/test/unit/imaging/image_premultiply.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/imaging/image_set_pixel.cpp b/test/unit/imaging/image_set_pixel.cpp index 3488e0005..d23476535 100644 --- a/test/unit/imaging/image_set_pixel.cpp +++ b/test/unit/imaging/image_set_pixel.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/imaging/image_view.cpp b/test/unit/imaging/image_view.cpp index 25dbacfd9..db129d75c 100644 --- a/test/unit/imaging/image_view.cpp +++ b/test/unit/imaging/image_view.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/imaging/tiff_io.cpp b/test/unit/imaging/tiff_io.cpp index 1ace38fa1..14f9e5f29 100644 --- a/test/unit/imaging/tiff_io.cpp +++ b/test/unit/imaging/tiff_io.cpp @@ -1,4 +1,3 @@ - // disabled on windows due to https://github.com/mapnik/mapnik/issues/2838 // TODO - get to the bottom of why including `tiff_reader.cpp` breaks windows // or re-write image_readers to allow `#include tiff_reader.hpp` @@ -12,7 +11,7 @@ #include "../../../src/tiff_reader.cpp" #define TIFF_ASSERT(filename) \ - mapnik::tiff_reader tiff_reader(filename); \ + mapnik::tiff_reader tiff_reader(filename); \ REQUIRE( tiff_reader.width() == 256 ); \ REQUIRE( tiff_reader.height() == 256 ); \ REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \ @@ -20,7 +19,7 @@ REQUIRE( reader->width() == 256 ); \ REQUIRE( reader->height() == 256 ); \ mapnik::util::file file(filename); \ - mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); \ + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); \ REQUIRE( tiff_reader2.width() == 256 ); \ REQUIRE( tiff_reader2.height() == 256 ); \ std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); \ @@ -57,11 +56,13 @@ REQUIRE( subimage.width() == 1 ); \ REQUIRE( subimage.height() == 1 ); \ -TEST_CASE("tiff io") { +TEST_CASE("tiff io") +{ -SECTION("scan rgb8 striped") { +SECTION("scan rgb8 striped") +{ std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif"); - mapnik::tiff_reader tiff_reader(filename); + mapnik::tiff_reader tiff_reader(filename); REQUIRE( tiff_reader.width() == 512 ); REQUIRE( tiff_reader.height() == 512 ); REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); @@ -76,7 +77,7 @@ SECTION("scan rgb8 striped") { REQUIRE( reader->width() == 512 ); REQUIRE( reader->height() == 512 ); mapnik::util::file file(filename); - mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); REQUIRE( tiff_reader2.width() == 512 ); REQUIRE( tiff_reader2.height() == 512 ); std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); @@ -91,7 +92,7 @@ SECTION("scan rgb8 striped") { SECTION("scan rgb8 tiled") { std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif"); - mapnik::tiff_reader tiff_reader(filename); + mapnik::tiff_reader tiff_reader(filename); REQUIRE( tiff_reader.width() == 512 ); REQUIRE( tiff_reader.height() == 512 ); REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); @@ -106,7 +107,7 @@ SECTION("scan rgb8 tiled") { REQUIRE( reader->width() == 512 ); REQUIRE( reader->height() == 512 ); mapnik::util::file file(filename); - mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); REQUIRE( tiff_reader2.width() == 512 ); REQUIRE( tiff_reader2.height() == 512 ); std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); diff --git a/test/unit/numerics/enumeration.cpp b/test/unit/numerics/enumeration.cpp new file mode 100644 index 000000000..64a6afcc3 --- /dev/null +++ b/test/unit/numerics/enumeration.cpp @@ -0,0 +1,17 @@ + +#include "catch.hpp" +#include +#include +#include + +TEST_CASE("enumeration") { + + mapnik::line_cap_e e(mapnik::ROUND_CAP); + CHECK( e.as_string() == "round" ); + // note: test the << operator, which calls `as_string` internally + // is not used in mapnik, but kept for back compat + std::stringstream s; + s << e; + CHECK( s.str() == "round" ); + +} \ No newline at end of file diff --git a/test/unit/numerics/safe_cast.cpp b/test/unit/numerics/safe_cast.cpp index b6cba62c1..cb743dffd 100644 --- a/test/unit/numerics/safe_cast.cpp +++ b/test/unit/numerics/safe_cast.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/pixel/agg_blend_src_over_test.cpp b/test/unit/pixel/agg_blend_src_over_test.cpp index 60846f7a2..f457703d7 100644 --- a/test/unit/pixel/agg_blend_src_over_test.cpp +++ b/test/unit/pixel/agg_blend_src_over_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/pixel/palette.cpp b/test/unit/pixel/palette.cpp index c45d06815..a1e74d236 100644 --- a/test/unit/pixel/palette.cpp +++ b/test/unit/pixel/palette.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/projection/proj_transform.cpp b/test/unit/projection/proj_transform.cpp index d2a37893a..95c959587 100644 --- a/test/unit/projection/proj_transform.cpp +++ b/test/unit/projection/proj_transform.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/run.cpp b/test/unit/run.cpp index 8ae4ddc73..caaab46dc 100644 --- a/test/unit/run.cpp +++ b/test/unit/run.cpp @@ -1,17 +1,73 @@ #define CATCH_CONFIG_RUNNER #include "catch.hpp" +#include +#include #include +#include #include "cleanup.hpp" // run_cleanup() +std::string plugin_path; + +inline void set_plugin_path(Catch::ConfigData&, std::string const& _plugin_path ) { + plugin_path = _plugin_path; +} + +std::string working_dir; + +inline void set_working_dir(Catch::ConfigData&, std::string const& _working_dir ) { + working_dir = _working_dir; +} + + int main (int argc, char* const argv[]) { - mapnik::datasource_cache::instance().register_datasources("plugins/input/"); + Catch::Session session; - int result = Catch::Session().run( argc, argv ); + auto & cli = session.cli(); + + cli["-p"]["--plugins"] + .describe("path to mapnik plugins") + .bind(&set_plugin_path, "plugins"); + + cli["-C"]["--working-directory"] + .describe("change working directory") + .bind(&set_working_dir, "working directory"); + + int result = session.applyCommandLine(argc, argv); + + if (!plugin_path.empty()) + { + if (!mapnik::util::exists(plugin_path)) + { + std::clog << "Could not find " << plugin_path << "\n"; + return -1; + } + mapnik::datasource_cache::instance().register_datasources(plugin_path); + } + else + { + mapnik::datasource_cache::instance().register_datasources("plugins/input/"); + } + + if (!working_dir.empty()) + { + if (!mapnik::util::exists(working_dir)) + { + std::clog << "Could not find " << working_dir << "\n"; + return -1; + } + boost::filesystem::current_path(working_dir); + } + + if (result == 0) + { + result = session.run(); + } testing::run_cleanup(); return result; + } diff --git a/test/unit/serialization/parse_hex.hpp b/test/unit/serialization/parse_hex.hpp new file mode 100644 index 000000000..48c70a5d4 --- /dev/null +++ b/test/unit/serialization/parse_hex.hpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2016 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_PARSE_HEX_HPP +#define MAPNIK_PARSE_HEX_HPP + +#include +#include + +namespace mapnik { namespace util { + +template +bool parse_hex(std::string const& input, Out & output) +{ + boost::spirit::qi::lit_type lit; + auto itr = input.begin(); + auto end = input.end(); + using hex2 = boost::spirit::qi::uint_parser< unsigned, 16, 2, 2 >; + return boost::spirit::qi::parse(itr, end, -(lit("\\x") | lit("0x")) > *hex2(), output); +} + +}} + + +#endif // MAPNIK_PARSE_HEX_HPP diff --git a/test/unit/serialization/wkb_formats_test.cpp b/test/unit/serialization/wkb_formats_test.cpp index 1f3a82e2f..bc0c17198 100644 --- a/test/unit/serialization/wkb_formats_test.cpp +++ b/test/unit/serialization/wkb_formats_test.cpp @@ -2,11 +2,9 @@ #include #include -#include #include #include #include -#include #include TEST_CASE("geometry formats") { @@ -55,9 +53,6 @@ SECTION("wkb") { unsigned char sq_invalid_blob[] = { 0x23, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x23 }; - mapnik::context_ptr ctx(new mapnik::context_type); - mapnik::feature_ptr feature = mapnik::feature_factory::create(ctx, 1); - // test of parsing wkb geometries try { diff --git a/test/unit/serialization/wkb_test.cpp b/test/unit/serialization/wkb_test.cpp new file mode 100644 index 000000000..8a617df26 --- /dev/null +++ b/test/unit/serialization/wkb_test.cpp @@ -0,0 +1,117 @@ +#include "catch.hpp" +// mapnik +#include +#include +#include +#include +#include +// bool +#include +#include +#include +// stl +#include "parse_hex.hpp" +#include +#include +#include +#include + +#if BOOST_VERSION >= 105800 +namespace { + +struct spatially_equal_visitor +{ + using result_type = bool; + + result_type operator() (mapnik::geometry::geometry_empty, mapnik::geometry::geometry_empty) const + { + return true; + } + + result_type operator() (mapnik::geometry::geometry_collection const& lhs, mapnik::geometry::geometry_collection const& rhs) const + { + std::size_t size0 = lhs.size(); + std::size_t size1 = rhs.size(); + if (size0 != size1) return false; + for (std::size_t index = 0; index < size0 ; ++index) + { + if (!mapnik::util::apply_visitor(*this, lhs[index], rhs[index])) + return false; + } + return true; + } + + result_type operator() (mapnik::geometry::multi_point const& lhs, mapnik::geometry::multi_point const& rhs) const + { + std::size_t size0 = lhs.size(); + std::size_t size1 = rhs.size(); + if (size0 != size1) return false; + auto tmp0 = lhs; + auto tmp1 = rhs; + std::sort(tmp0.begin(), tmp0.end(), boost::geometry::less>()); + std::sort(tmp1.begin(), tmp1.end(), boost::geometry::less>()); + for (std::size_t index = 0; index < size0 ; ++index) + { + if (!boost::geometry::equals(tmp0[index], tmp1[index])) return false; + } + return true; + } + + template + result_type operator() (T const& lhs, T const& rhs) const + { + if (mapnik::geometry::is_empty(lhs) && mapnik::geometry::is_empty(rhs)) + return true; //Empty geometries of the same type are considered to be spatially equal + return boost::geometry::equals(lhs, rhs); + } + + template + result_type operator() (T0 const& lhs, T1 const& rhs) const + { + return false; + } + +}; + +template +bool spatially_equal(mapnik::geometry::geometry const& g0, mapnik::geometry::geometry const& g1) +{ + return mapnik::util::apply_visitor(spatially_equal_visitor(), g0, g1); +} + +} +#endif + +TEST_CASE("Well-known-geometries") +{ + SECTION("wkb") + { + std::string filename("test/unit/data/well-known-geometries.test"); + std::ifstream is(filename.c_str(),std::ios_base::in | std::ios_base::binary); + if (!is) throw std::runtime_error("could not open: '" + filename + "'"); + + for (std::string line; std::getline(is, line,'\n');) + { + std::vector columns; + boost::split(columns, line, boost::is_any_of(";")); + REQUIRE(columns.size() == 3); + std::vector wkb, twkb; + REQUIRE(mapnik::util::parse_hex(columns[1], wkb)); + REQUIRE(mapnik::util::parse_hex(columns[2], twkb)); + mapnik::geometry::geometry geom_0 = mapnik::geometry_utils::from_wkb(wkb.data(), wkb.size(), mapnik::wkbAuto); + mapnik::geometry::geometry geom_1 = mapnik::geometry_utils::from_twkb(twkb.data(), twkb.size()); + // compare WKTs + std::string wkt0, wkt1; + REQUIRE(mapnik::util::to_wkt(wkt0, geom_0)); + REQUIRE(mapnik::util::to_wkt(wkt1, geom_1)); + if (!mapnik::geometry::is_empty(geom_0) && !mapnik::geometry::is_empty(geom_1)) + { + REQUIRE(wkt0 == wkt1); + // compare spatially (NOTE: GeometryCollection comparison also enforces strict order) +#if BOOST_VERSION >= 105800 + REQUIRE(spatially_equal(geom_0, geom_1)); +#endif + } + } + } +} diff --git a/test/unit/serialization/xml_parser_trim.cpp b/test/unit/serialization/xml_parser_trim.cpp index afd282416..0a556e9ef 100644 --- a/test/unit/serialization/xml_parser_trim.cpp +++ b/test/unit/serialization/xml_parser_trim.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/svg/svg_parser_test.cpp b/test/unit/svg/svg_parser_test.cpp index c92b79756..0e383045e 100644 --- a/test/unit/svg/svg_parser_test.cpp +++ b/test/unit/svg/svg_parser_test.cpp @@ -30,25 +30,44 @@ #include #include #include - -#include +#include "util.hpp" #include #include -namespace detail { - -template -struct vertex_equal +namespace // internal { - template - bool operator() (T const& lhs, T const& rhs) const + struct test_parser { - static const double eps = 1.0 / std::pow(10,N); - return (std::fabs(std::get<0>(lhs) - std::get<0>(rhs)) < eps) - && (std::fabs(std::get<1>(lhs) - std::get<1>(rhs)) < eps) - && std::get<2>(lhs) == std::get<2>(rhs); + mapnik::svg_storage_type path; + mapnik::svg::vertex_stl_adapter stl_storage; + mapnik::svg::svg_path_adapter svg_path; + mapnik::svg::svg_converter_type svg; + mapnik::svg::svg_parser p; + + test_parser() + : stl_storage(path.source()) + , svg_path(stl_storage) + , svg(svg_path, path.attributes()) + , p(svg) + {} + + mapnik::svg::svg_parser* operator->() + { + return &p; + } + }; + + template + std::string join(C const& container) + { + std::string result; + for (auto const& str : container) + { + if (!result.empty()) result += "\n "; + result += str; + } + return result; } -}; } TEST_CASE("SVG parser") { @@ -66,142 +85,112 @@ TEST_CASE("SVG parser") { SECTION("SVG::parse i/o") { std::string svg_name("FAIL"); - - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - - if (!p.parse(svg_name)) + char const* expected_errors[] = { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 1); - REQUIRE(errors[0] == "Unable to open 'FAIL'"); - } + "Unable to open 'FAIL'" + }; + + test_parser p; + REQUIRE(!p->parse(svg_name)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG::parse_from_string syntax error") { std::string svg_name("./test/data/svg/invalid.svg"); + char const* expected_errors[] = + { + "Unable to parse '\n\n'" + }; + std::ifstream in(svg_name.c_str()); std::string svg_str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - - if (!p.parse_from_string(svg_str)) - { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 1); - REQUIRE(errors[0] == "Unable to parse '\n\n'"); - } + test_parser p; + REQUIRE(!p->parse_from_string(svg_str)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG::parse_from_string syntax error") { std::string svg_name("./test/data/svg/invalid.svg"); - - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - - if (!p.parse(svg_name)) + char const* expected_errors[] = { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 1); - REQUIRE(errors[0] == "svg_parser::parse - Unable to parse './test/data/svg/invalid.svg'"); - } + "svg_parser::parse - Unable to parse './test/data/svg/invalid.svg'" + }; + + test_parser p; + REQUIRE(!p->parse(svg_name)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG parser color ") { std::string svg_name("./test/data/svg/color_fail.svg"); + char const* expected_errors[] = + { + "Failed to parse color: \"fail\"", + "Failed to parse SVG value: 'fail'", + "Failed to parse color: \"fail\"", + }; + std::ifstream in(svg_name.c_str()); std::string svg_str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - - if (!p.parse_from_string(svg_str)) - { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 3); - REQUIRE(errors[0] == "Failed to parse color: \"fail\""); - REQUIRE(errors[1] == "Failed to parse double: \"fail\""); - REQUIRE(errors[2] == "Failed to parse color: \"fail\""); - } + test_parser p; + REQUIRE(!p->parse_from_string(svg_str)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG - cope with erroneous geometries") { std::string svg_name("./test/data/svg/errors.svg"); + char const* expected_errors[] = + { + "parse_rect: Invalid width", + "Failed to parse SVG value: 'FAIL'", + "parse_rect: Invalid height", + "parse_rect: Invalid rx", + "parse_rect: Invalid ry", + "Failed to parse SVG value: '100invalidunit', trailing garbage: 'validunit'", + "unable to parse invalid svg ", + "unable to parse invalid svg with id 'fail-path'", + "unable to parse invalid svg with id 'fail-path'", + "parse_circle: Invalid radius", + "Failed to parse 'points'", + "Failed to parse 'points'", + "parse_ellipse: Invalid rx", + "parse_ellipse: Invalid ry", + }; + std::ifstream in(svg_name.c_str()); std::string svg_str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - if (!p.parse_from_string(svg_str)) - { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 13); - REQUIRE(errors[0] == "parse_rect: Invalid width"); - REQUIRE(errors[1] == "Failed to parse double: \"FAIL\""); - REQUIRE(errors[2] == "parse_rect: Invalid height"); - REQUIRE(errors[3] == "parse_rect: Invalid rx"); - REQUIRE(errors[4] == "parse_rect: Invalid ry"); - REQUIRE(errors[5] == "unable to parse invalid svg "); - REQUIRE(errors[6] == "unable to parse invalid svg with id 'fail-path'"); - REQUIRE(errors[7] == "unable to parse invalid svg with id 'fail-path'"); - REQUIRE(errors[8] == "parse_circle: Invalid radius"); - REQUIRE(errors[9] == "Failed to parse 'points'"); - REQUIRE(errors[10] == "Failed to parse 'points'"); - REQUIRE(errors[11] == "parse_ellipse: Invalid rx"); - REQUIRE(errors[12] == "parse_ellipse: Invalid ry"); - } + test_parser p; + REQUIRE(!p->parse_from_string(svg_str)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG parser double % ") { std::string svg_name("./test/data/svg/gradient-radial-error.svg"); + char const* expected_errors[] = + { + "Failed to parse SVG value: 'FAIL'" + }; + std::ifstream in(svg_name.c_str()); std::string svg_str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - - if (!p.parse_from_string(svg_str)) - { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 1); - REQUIRE(errors[0] == "Failed to parse double (optional %) from FAIL"); - } + test_parser p; + REQUIRE(!p->parse_from_string(svg_str)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG parser display=none") @@ -328,7 +317,7 @@ TEST_CASE("SVG parser") { std::make_tuple(0, 10,2), std::make_tuple(0, 10,95)}; - REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),detail::vertex_equal<3>())); + REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),vertex_equal<3>())); } SECTION("SVG viewbox fallback") @@ -337,16 +326,10 @@ TEST_CASE("SVG parser") { std::ifstream in(svg_name.c_str()); std::string svg_str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - p.parse_from_string(svg_str); - auto width = svg.width(); - auto height = svg.height(); + test_parser p; + REQUIRE(p->parse_from_string(svg_str)); + auto width = p.svg.width(); + auto height = p.svg.height(); REQUIRE(width == 100); REQUIRE(height == 100); } @@ -394,7 +377,7 @@ TEST_CASE("SVG parser") { std::make_tuple(0, 10,2), std::make_tuple(0, 10,95)}; - REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),detail::vertex_equal<3>())); + REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),vertex_equal<3>())); } SECTION("SVG beveled ") @@ -621,41 +604,33 @@ TEST_CASE("SVG parser") { SECTION("SVG missing def") { std::string svg_name("./test/data/svg/gradient-nodef.svg"); - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - REQUIRE(!p.parse(svg_name)); - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 2); - REQUIRE(errors[0] == "Failed to find gradient fill: MyGradient"); - REQUIRE(errors[1] == "Failed to find gradient stroke: MyGradient"); + char const* expected_errors[] = + { + "Failed to find gradient fill: MyGradient", + "Failed to find gradient stroke: MyGradient", + }; + + test_parser p; + REQUIRE(!p->parse(svg_name)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG missing id") { - std::string svg_name("./test/data/svg/gradient-no-id.svg"); + char const* expected_errors[] = + { + "Failed to find gradient fill: MyGradient", + "Failed to find gradient stroke: MyGradient", + }; + std::ifstream in(svg_name.c_str()); std::string svg_str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - using namespace mapnik::svg; - mapnik::svg_storage_type path; - vertex_stl_adapter stl_storage(path.source()); - svg_path_adapter svg_path(stl_storage); - svg_converter_type svg(svg_path, path.attributes()); - svg_parser p(svg); - - if (!p.parse_from_string(svg_str)) - { - auto const& errors = p.error_messages(); - REQUIRE(errors.size() == 2); - REQUIRE(errors[0] == "Failed to find gradient fill: MyGradient"); - REQUIRE(errors[1] == "Failed to find gradient stroke: MyGradient"); - } + test_parser p; + REQUIRE(!p->parse_from_string(svg_str)); + REQUIRE(join(p->error_messages()) == join(expected_errors)); } SECTION("SVG missing inheritance") diff --git a/test/unit/svg/svg_path_parser_test.cpp b/test/unit/svg/svg_path_parser_test.cpp new file mode 100644 index 000000000..21a094cd7 --- /dev/null +++ b/test/unit/svg/svg_path_parser_test.cpp @@ -0,0 +1,164 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include "catch.hpp" + +#include +#include +#include +#include +#include +#include "util.hpp" + +namespace { + +template +void test_path_parser(std::string const& str, Expected const& expected) +{ + using namespace mapnik::svg; + mapnik::svg_path_ptr marker_path(std::make_shared()); + vertex_stl_adapter stl_storage(marker_path->source()); + svg_path_adapter svg_path(stl_storage); + svg_converter_type svg(svg_path, marker_path->attributes()); + + CHECK(mapnik::svg::parse_path(str.c_str(), svg)); + double x,y; + unsigned cmd; + auto & p = svg.storage(); + std::vector> vec; + while ((cmd = p.vertex(&x,&y)) != mapnik::SEG_END) + { + vec.emplace_back(x, y, cmd); + //std::cerr << "std::make_tuple(" << x << ", " << y << ", " << cmd << ")," << std::endl; + } + REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(), vertex_equal<3>())); +} +} // anonymous ns + +TEST_CASE("SVG path parser") { + + SECTION("MoveTo/LineTo") + { + std::string str = "M 100 100 L 300 100 L 200 300 z"; + std::string str2 = "M100,100L300,100L200,300z"; + std::string str3 = "M100,100l200 0L200,300z"; + std::vector> expected = { + std::make_tuple(100, 100, 1), + std::make_tuple(300, 100, 2), + std::make_tuple(200, 300, 2), + std::make_tuple(100, 100, 79) }; + test_path_parser(str, expected); + test_path_parser(str2, expected); + test_path_parser(str3, expected); + } + + SECTION("MoveTo/HLine/VLine") + { + std::string str = "M100 100H300V200z"; + std::string str2 = "M100,100h200v100z"; + std::vector> expected = { + std::make_tuple(100, 100, 1), + std::make_tuple(300, 100, 2), + std::make_tuple(300, 200, 2), + std::make_tuple(100, 100, 79) + }; + test_path_parser(str, expected); + test_path_parser(str2, expected); + } + + SECTION("Arcs") + { + std::string str = "M300,200 h-150 a150,150 0 1,0 150,-150 z"; + + std::vector> expected = { + std::make_tuple(300, 200, 1), + std::make_tuple(150, 200, 2), + std::make_tuple(150, 282.843, 4), + std::make_tuple(217.157, 350, 4), + std::make_tuple(300, 350, 4), + std::make_tuple(382.843, 350, 4), + std::make_tuple(450, 282.843, 4), + std::make_tuple(450, 200, 4), + std::make_tuple(450, 117.157, 4), + std::make_tuple(382.843, 50, 4), + std::make_tuple(300, 50, 4), + std::make_tuple(300, 200, 79)}; + test_path_parser(str, expected); + } + + + SECTION("Arcs 2") + { + std::string str = "M275,175 v-150 a150,150 0 0,0 -150,150 z"; + + std::vector> expected = { + std::make_tuple(275, 175, 1), + std::make_tuple(275, 25, 2), + std::make_tuple(192.157, 25, 4), + std::make_tuple(125, 92.1573, 4), + std::make_tuple(125, 175, 4), + std::make_tuple(275, 175, 79)}; + test_path_parser(str, expected); + } + + SECTION("Arcs 3") + { + std::string str = "M600,350 l 50,-25" + "a25,25 -30 0,1 50,-25 l 50,-25" + "a25,50 -30 0,1 50,-25 l 50,-25" + "a25,75 -30 0,1 50,-25 l 50,-25" + "a25,100 -30 0,1 50,-25 l 50,-25"; + + std::vector> expected = { + std::make_tuple(600, 350, 1), + std::make_tuple(650, 325, 2), + std::make_tuple(643.096, 311.193, 4), + std::make_tuple(648.693, 294.404, 4), + std::make_tuple(662.5, 287.5, 4), + std::make_tuple(676.307, 280.596, 4), + std::make_tuple(693.096, 286.193, 4), + std::make_tuple(700, 300, 4), + std::make_tuple(750, 275, 2), + std::make_tuple(734.991, 248.079, 4), + std::make_tuple(734.017, 220.66, 4), + std::make_tuple(747.825, 213.756, 4), + std::make_tuple(761.632, 206.852, 4), + std::make_tuple(784.991, 223.079, 4), + std::make_tuple(800, 250, 4), + std::make_tuple(850, 225, 2), + std::make_tuple(827.153, 184.812, 4), + std::make_tuple(819.825, 146.636, 4), + std::make_tuple(833.632, 139.733, 4), + std::make_tuple(847.44, 132.829, 4), + std::make_tuple(877.153, 159.812, 4), + std::make_tuple(900, 200, 4), + std::make_tuple(950, 175, 2), + std::make_tuple(919.382, 121.506, 4), + std::make_tuple(905.754, 72.5436, 4), + std::make_tuple(919.561, 65.64, 4), + std::make_tuple(933.368, 58.7365, 4), + std::make_tuple(969.382, 96.5057, 4), + std::make_tuple(1000, 150, 4), + std::make_tuple(1050, 125, 2)}; + test_path_parser(str, expected); + } +} diff --git a/test/unit/svg/util.hpp b/test/unit/svg/util.hpp new file mode 100644 index 000000000..bbfcc1112 --- /dev/null +++ b/test/unit/svg/util.hpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef TEST_UNIT_SVG_UTIL_HPP +#define TEST_UNIT_SVG_UTIL_HPP + +#include + +namespace { + +template +struct vertex_equal +{ + template + bool operator() (T const& lhs, T const& rhs) const + { + static const double eps = 1.0 / std::pow(10,N); + return (std::fabs(std::get<0>(lhs) - std::get<0>(rhs)) < eps) + && (std::fabs(std::get<1>(lhs) - std::get<1>(rhs)) < eps) + && std::get<2>(lhs) == std::get<2>(rhs); + } +}; +} + +#endif // TEST_UNIT_SVG_UTIL_HPP diff --git a/test/unit/symbolizer/symbolizer_test.cpp b/test/unit/symbolizer/symbolizer_test.cpp index 3af053251..1b7c26934 100644 --- a/test/unit/symbolizer/symbolizer_test.cpp +++ b/test/unit/symbolizer/symbolizer_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/unit/text/shaping.cpp b/test/unit/text/shaping.cpp index 2e2701b8f..d9da17efb 100644 --- a/test/unit/text/shaping.cpp +++ b/test/unit/text/shaping.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include #include diff --git a/test/unit/vertex_adapter/clipping_test.cpp b/test/unit/vertex_adapter/clipping_test.cpp index 29a3e425a..2239e264c 100644 --- a/test/unit/vertex_adapter/clipping_test.cpp +++ b/test/unit/vertex_adapter/clipping_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/vertex_adapter/line_offset_test.cpp b/test/unit/vertex_adapter/line_offset_test.cpp index eba472faa..dcb8dc68b 100644 --- a/test/unit/vertex_adapter/line_offset_test.cpp +++ b/test/unit/vertex_adapter/line_offset_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/vertex_adapter/offset_converter.cpp b/test/unit/vertex_adapter/offset_converter.cpp index 8c2780d5b..9255f7d97 100644 --- a/test/unit/vertex_adapter/offset_converter.cpp +++ b/test/unit/vertex_adapter/offset_converter.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" // mapnik diff --git a/test/unit/vertex_adapter/simplify_converters_test.cpp b/test/unit/vertex_adapter/simplify_converters_test.cpp index a86f8d5e3..b43bb9355 100644 --- a/test/unit/vertex_adapter/simplify_converters_test.cpp +++ b/test/unit/vertex_adapter/simplify_converters_test.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" //#include diff --git a/test/unit/vertex_adapter/vertex_adapter.cpp b/test/unit/vertex_adapter/vertex_adapter.cpp index 4505faa56..da3e815fa 100644 --- a/test/unit/vertex_adapter/vertex_adapter.cpp +++ b/test/unit/vertex_adapter/vertex_adapter.cpp @@ -1,3 +1,4 @@ + #include "catch.hpp" #include diff --git a/test/visual/renderer.hpp b/test/visual/renderer.hpp index 6b033f99c..7ea9198df 100644 --- a/test/visual/renderer.hpp +++ b/test/visual/renderer.hpp @@ -38,10 +38,21 @@ #if defined(GRID_RENDERER) #include #endif + #if defined(HAVE_CAIRO) #include #include +#ifdef CAIRO_HAS_SVG_SURFACE +#include #endif +#ifdef CAIRO_HAS_PS_SURFACE +#include +#endif +#ifdef CAIRO_HAS_PDF_SURFACE +#include +#endif +#endif + #if defined(SVG_RENDERER) #include #endif @@ -53,7 +64,7 @@ namespace visual_tests { template -struct renderer_base +struct raster_renderer_base { using image_type = ImageType; @@ -80,7 +91,35 @@ struct renderer_base } }; -struct agg_renderer : renderer_base +struct vector_renderer_base +{ + using image_type = std::string; + + static constexpr const bool support_tiles = false; + + unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const + { + std::ifstream stream(reference.string().c_str(), std::ios_base::in | std::ios_base::binary); + if (!stream) + { + throw std::runtime_error("Could not open: " + reference.string()); + } + std::string expected(std::istreambuf_iterator(stream.rdbuf()), std::istreambuf_iterator()); + return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); + } + + void save(image_type const & image, boost::filesystem::path const& path) const + { + std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); + if (!file) + { + throw std::runtime_error("Cannot open file for writing: " + path.string()); + } + file << image; + } +}; + +struct agg_renderer : raster_renderer_base { static constexpr const char * name = "agg"; @@ -94,7 +133,7 @@ struct agg_renderer : renderer_base }; #if defined(HAVE_CAIRO) -struct cairo_renderer : renderer_base +struct cairo_renderer : raster_renderer_base { static constexpr const char * name = "cairo"; @@ -111,14 +150,65 @@ struct cairo_renderer : renderer_base return image; } }; + +using surface_create_type = cairo_surface_t *(&)(cairo_write_func_t, void *, double, double); + +template +struct cairo_vector_renderer : vector_renderer_base +{ + static cairo_status_t write(void *closure, + const unsigned char *data, + unsigned int length) + { + std::ostringstream & ss = *reinterpret_cast(closure); + ss.write(reinterpret_cast(data), length); + return ss ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR; + } + + image_type render(mapnik::Map const & map, double scale_factor) const + { + std::ostringstream ss(std::stringstream::binary); + mapnik::cairo_surface_ptr image_surface( + SurfaceCreateFunction(write, &ss, map.width(), map.height()), + mapnik::cairo_surface_closer()); + mapnik::cairo_ptr image_context(mapnik::create_context(image_surface)); + mapnik::cairo_renderer ren(map, image_context, scale_factor); + ren.apply(); + cairo_surface_finish(&*image_surface); + return ss.str(); + } +}; + +#ifdef CAIRO_HAS_SVG_SURFACE +struct cairo_svg_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-svg"; + static constexpr const char * ext = ".svg"; +}; +#endif + +#ifdef CAIRO_HAS_PS_SURFACE +struct cairo_ps_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-ps"; + static constexpr const char * ext = ".ps"; +}; +#endif + +#ifdef CAIRO_HAS_PDF_SURFACE +struct cairo_pdf_renderer : cairo_vector_renderer +{ + static constexpr const char * name = "cairo-pdf"; + static constexpr const char * ext = ".pdf"; +}; +#endif #endif #if defined(SVG_RENDERER) -struct svg_renderer : renderer_base +struct svg_renderer : vector_renderer_base { static constexpr const char * name = "svg"; static constexpr const char * ext = ".svg"; - static constexpr const bool support_tiles = false; image_type render(mapnik::Map const & map, double scale_factor) const { @@ -128,35 +218,11 @@ struct svg_renderer : renderer_base ren.apply(); return ss.str(); } - - unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const - { - std::ifstream stream(reference.string().c_str(),std::ios_base::in|std::ios_base::binary); - if (!stream.is_open()) - { - throw std::runtime_error("could not open: '" + reference.string() + "'"); - } - std::string expected(std::istreambuf_iterator(stream.rdbuf()),(std::istreambuf_iterator())); - stream.close(); - return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); - } - - void save(image_type const & image, boost::filesystem::path const& path) const - { - std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); - if (!file) { - throw std::runtime_error((std::string("cannot open file for writing file ") + path.string()).c_str()); - } else { - file << image; - file.close(); - } - } - }; #endif #if defined(GRID_RENDERER) -struct grid_renderer : renderer_base +struct grid_renderer : raster_renderer_base { static constexpr const char * name = "grid"; @@ -335,6 +401,15 @@ private: using renderer_type = mapnik::util::variant #if defined(HAVE_CAIRO) ,renderer +#ifdef CAIRO_HAS_SVG_SURFACE + ,renderer +#endif +#ifdef CAIRO_HAS_PS_SURFACE + ,renderer +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + ,renderer +#endif #endif #if defined(SVG_RENDERER) ,renderer diff --git a/test/visual/run.cpp b/test/visual/run.cpp index 70284bc3e..587727906 100644 --- a/test/visual/run.cpp +++ b/test/visual/run.cpp @@ -48,30 +48,48 @@ namespace po = boost::program_options; runner::renderer_container create_renderers(po::variables_map const & args, boost::filesystem::path const & output_dir, - bool append_all = false) + bool force_append = false) { boost::filesystem::path reference_dir(args["images-dir"].as()); bool overwrite = args.count("overwrite"); runner::renderer_container renderers; - if (append_all || args.count(agg_renderer::name)) + if (force_append || args.count(agg_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } #if defined(HAVE_CAIRO) - if (append_all || args.count(cairo_renderer::name)) + if (force_append || args.count(cairo_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } +#ifdef CAIRO_HAS_SVG_SURFACE + if (args.count(cairo_svg_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif +#ifdef CAIRO_HAS_PS_SURFACE + if (args.count(cairo_ps_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + if (args.count(cairo_pdf_renderer::name)) + { + renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); + } +#endif #endif #if defined(SVG_RENDERER) - if (append_all || args.count(svg_renderer::name)) + if (force_append || args.count(svg_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } #endif #if defined(GRID_RENDERER) - if (append_all || args.count(grid_renderer::name)) + if (force_append || args.count(grid_renderer::name)) { renderers.emplace_back(renderer(output_dir, reference_dir, overwrite)); } @@ -112,6 +130,15 @@ int main(int argc, char** argv) (agg_renderer::name, "render with AGG renderer") #if defined(HAVE_CAIRO) (cairo_renderer::name, "render with Cairo renderer") +#ifdef CAIRO_HAS_SVG_SURFACE + (cairo_svg_renderer::name, "render with Cairo SVG renderer") +#endif +#ifdef CAIRO_HAS_PS_SURFACE + (cairo_ps_renderer::name, "render with Cairo PS renderer") +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + (cairo_pdf_renderer::name, "render with Cairo PDF renderer") +#endif #endif #if defined(SVG_RENDERER) (svg_renderer::name, "render with SVG renderer") @@ -183,7 +210,7 @@ int main(int argc, char** argv) } catch (std::exception & e) { - std::cerr << "Error runnig tests: " << e.what() << std::endl; + std::cerr << "Error running tests: " << e.what() << std::endl; return 1; } diff --git a/test/visual/runner.cpp b/test/visual/runner.cpp index 06ade7779..d0c7222fb 100644 --- a/test/visual/runner.cpp +++ b/test/visual/runner.cpp @@ -57,13 +57,13 @@ public: } template ::type* = nullptr> - void operator()(T const & renderer) + void operator()(T const& renderer) const { test(renderer); } template ::type* = nullptr> - void operator()(T const & renderer) + void operator()(T const & renderer) const { if (tiles_.width == 1 && tiles_.height == 1) { @@ -73,7 +73,7 @@ public: private: template - void test(T const & renderer) + void test(T const & renderer) const { map_size size { map_.width(), map_.height() }; std::chrono::high_resolution_clock::time_point start(std::chrono::high_resolution_clock::now()); @@ -96,7 +96,7 @@ private: } template ::type* = nullptr> - typename T::image_type render(T const & renderer) + typename T::image_type render(T const& renderer) const { if (tiles_.width == 1 && tiles_.height == 1) { @@ -109,7 +109,7 @@ private: } template ::type* = nullptr> - typename T::image_type render(T const & renderer) + typename T::image_type render(T const & renderer) const { return renderer.render(map_, scale_factor_); } @@ -150,7 +150,8 @@ result_list runner::test_all(report_type & report) const result_list runner::test(std::vector const & style_names, report_type & report) const { - std::vector files(style_names.size()); + std::vector files; + files.reserve(style_names.size()); std::transform(style_names.begin(), style_names.end(), std::back_inserter(files), [&](runner::path_type const & name) { @@ -363,4 +364,3 @@ void runner::parse_map_sizes(std::string const & str, std::vector & si } } - diff --git a/utils/mapnik-config/build.py b/utils/mapnik-config/build.py index e74684e62..e4178ba41 100644 --- a/utils/mapnik-config/build.py +++ b/utils/mapnik-config/build.py @@ -63,7 +63,7 @@ CONFIG_MAPNIK_LIBNAME='%(mapnik_libname)s' CONFIG_MAPNIK_LIBPATH="%(mapnik_libpath)s" CONFIG_DEP_LIBS='%(dep_libs)s' CONFIG_MAPNIK_LDFLAGS="%(ldflags)s" -CONFIG_MAPNIK_INCLUDE="${CONFIG_PREFIX}/include -I${CONFIG_PREFIX}/include/mapnik/agg" +CONFIG_MAPNIK_INCLUDE="${CONFIG_PREFIX}/include -I${CONFIG_PREFIX}/include/mapnik/agg -I${CONFIG_PREFIX}/include/mapnik" CONFIG_DEP_INCLUDES="%(dep_includes)s" CONFIG_CXXFLAGS="%(cxxflags)s" CONFIG_CXX='%(cxx)s' @@ -131,11 +131,6 @@ mapnik_bundled_gdal_data = '' mapnik_bundled_proj_data = '' mapnik_bundled_icu_data = '' -if config_env.get('MAPNIK_BUNDLED_SHARE_DIRECTORY'): - mapnik_bundled_gdal_data = 'lib/mapnik/share/gdal' - mapnik_bundled_proj_data = 'lib/mapnik/share/proj' - mapnik_bundled_icu_data = 'lib/mapnik/share/icu' - configuration = { "git_revision": git_revision, "git_describe": git_describe, diff --git a/utils/mapnik-index/build.py b/utils/mapnik-index/build.py index 5bb177046..358ce5f88 100644 --- a/utils/mapnik-index/build.py +++ b/utils/mapnik-index/build.py @@ -24,18 +24,19 @@ import glob from copy import copy Import ('env') +Import ('plugin_base') -program_env = env.Clone() +program_env = plugin_base.Clone() source = Split( """ mapnik-index.cpp process_csv_file.cpp process_geojson_file.cpp + ../../plugins/input/csv/csv_utils.cpp """ ) -#headers = ['#plugins/input/shape'] + env['CPPPATH'] headers = env['CPPPATH'] boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND'] diff --git a/utils/mapnik-index/mapnik-index.cpp b/utils/mapnik-index/mapnik-index.cpp index 7361c05de..9b1859bf2 100644 --- a/utils/mapnik-index/mapnik-index.cpp +++ b/utils/mapnik-index/mapnik-index.cpp @@ -163,7 +163,7 @@ int main (int argc, char** argv) std::clog << "max tree depth:" << depth << std::endl; std::clog << "split ratio:" << ratio << std::endl; - using box_type = mapnik::box2d; + using box_type = mapnik::box2d; using item_type = std::pair>; for (auto const& filename : files_to_process) @@ -175,22 +175,26 @@ int main (int argc, char** argv) } std::vector boxes; - mapnik::box2d extent; + box_type extent; if (mapnik::detail::is_csv(filename)) { std::clog << "processing '" << filename << "' as CSV\n"; auto result = mapnik::detail::process_csv_file(boxes, filename, manual_headers, separator, quote); - if (!result.first) continue; + if (!result.first) + { + std::clog << "Error: failed to process " << filename << std::endl; + return EXIT_FAILURE; + } extent = result.second; } else if (mapnik::detail::is_geojson(filename)) { std::clog << "processing '" << filename << "' as GeoJSON\n"; - auto result = mapnik::detail::process_geojson_file(boxes, filename, validate_features); + auto result = mapnik::detail::process_geojson_file(boxes, filename, validate_features, verbose); if (!result.first) { std::clog << "Error: failed to process " << filename << std::endl; - continue; + return EXIT_FAILURE; } extent = result.second; } @@ -198,10 +202,12 @@ int main (int argc, char** argv) if (extent.valid()) { std::clog << extent << std::endl; - mapnik::quad_tree> tree(extent, depth, ratio); + mapnik::box2d extent_d(extent.minx(), extent.miny(), extent.maxx(), extent.maxy()); + mapnik::quad_tree> tree(extent_d, depth, ratio); for (auto const& item : boxes) { - tree.insert(std::get<1>(item), std::get<0>(item)); + auto ext_f = std::get<0>(item); + tree.insert(std::get<1>(item), mapnik::box2d(ext_f.minx(), ext_f.miny(), ext_f.maxx(), ext_f.maxy())); } std::fstream file((filename + ".index").c_str(), @@ -222,6 +228,11 @@ int main (int argc, char** argv) file.close(); } } + else + { + std::clog << "Invalid extent " << extent << std::endl; + return EXIT_FAILURE; + } } std::clog << "done!" << std::endl; return EXIT_SUCCESS; diff --git a/utils/mapnik-index/process_csv_file.cpp b/utils/mapnik-index/process_csv_file.cpp index 908ec9a79..a0342cff5 100644 --- a/utils/mapnik-index/process_csv_file.cpp +++ b/utils/mapnik-index/process_csv_file.cpp @@ -21,13 +21,16 @@ *****************************************************************************/ #include "process_csv_file.hpp" +#include "../../plugins/input/csv/csv_getline.hpp" #include "../../plugins/input/csv/csv_utils.hpp" +#include #include #include #if defined(MAPNIK_MEMORY_MAPPED_FILE) #pragma GCC diagnostic push #include +#include #include #include #pragma GCC diagnostic pop @@ -35,13 +38,20 @@ #endif #include +#include +#include namespace mapnik { namespace detail { template -std::pair> process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote) +std::pair process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote) { - mapnik::box2d extent; + using box_type = typename T::value_type::first_type; + csv_utils::csv_file_parser p; + p.manual_headers_ = manual_headers; + p.separator_ = separator; + p.quote_ = quote; + #if defined(MAPNIK_MEMORY_MAPPED_FILE) using file_source_type = boost::interprocess::ibufferstream; file_source_type csv_file; @@ -56,7 +66,7 @@ std::pair> process_csv_file(T & boxes, std::string const& fil else { std::clog << "Error : cannot mmap " << filename << std::endl; - return std::make_pair(false, extent); + return std::make_pair(false, box_type(p.extent_)); } #else #if defined(_WINDOWS) @@ -67,173 +77,24 @@ std::pair> process_csv_file(T & boxes, std::string const& fil if (!csv_file.is_open()) { std::clog << "Error : cannot open " << filename << std::endl; - return std::make_pair(false, extent); + return std::make_pair(false, box_type(p.extent_)); } #endif - auto file_length = ::detail::file_length(csv_file); - // set back to start - csv_file.seekg(0, std::ios::beg); - char newline; - bool has_newline; - char detected_quote; - std::tie(newline, has_newline, detected_quote) = ::detail::autodect_newline_and_quote(csv_file, file_length); - if (quote == 0) quote = detected_quote; - // set back to start - csv_file.seekg(0, std::ios::beg); - // get first line - std::string csv_line; - csv_utils::getline_csv(csv_file, csv_line, newline, quote); - if (separator == 0) separator = ::detail::detect_separator(csv_line); - csv_file.seekg(0, std::ios::beg); - int line_number = 0; - ::detail::geometry_column_locator locator; - std::vector headers; - std::clog << "Parsing CSV using SEPARATOR=" << separator << " QUOTE=" << quote << std::endl; - if (!manual_headers.empty()) + try { - std::size_t index = 0; - headers = csv_utils::parse_line(manual_headers, separator, quote); - for (auto const& header : headers) - { - ::detail::locate_geometry_column(header, index++, locator); - headers.push_back(header); - } + p.parse_csv_and_boxes(csv_file, boxes); + return std::make_pair(true, box_type(p.extent_)); } - else // parse first line as headers + catch (std::exception const& ex) { - while (csv_utils::getline_csv(csv_file,csv_line,newline, quote)) - { - try - { - headers = csv_utils::parse_line(csv_line, separator, quote); - // skip blank lines - if (headers.size() > 0 && headers[0].empty()) ++line_number; - else - { - std::size_t index = 0; - for (auto & header : headers) - { - mapnik::util::trim(header); - if (header.empty()) - { - // create a placeholder for the empty header - std::ostringstream s; - s << "_" << index; - header = s.str(); - } - else - { - ::detail::locate_geometry_column(header, index, locator); - } - ++index; - } - ++line_number; - break; - } - } - catch (std::exception const& ex) - { - std::string s("CSV index: error parsing headers: "); - s += ex.what(); - std::clog << s << std::endl; - return std::make_pair(false, extent); - } - } + std::clog << ex.what() << std::endl; + return std::make_pair(false, box_type(p.extent_)); } - - std::size_t num_headers = headers.size(); - if (!::detail::valid(locator, num_headers)) - { - std::clog << "CSV index: could not detect column(s) with the name(s) of wkt, geojson, x/y, or " - << "latitude/longitude in:\n" - << csv_line - << "\n - this is required for reading geometry data" - << std::endl; - return std::make_pair(false, extent); - } - - auto pos = csv_file.tellg(); - - // handle rare case of a single line of data and user-provided headers - // where a lack of a newline will mean that csv_utils::getline_csv returns false - bool is_first_row = false; - if (!has_newline) - { - csv_file.setstate(std::ios::failbit); - pos = 0; - if (!csv_line.empty()) - { - is_first_row = true; - } - } - while (is_first_row || csv_utils::getline_csv(csv_file, csv_line, newline, quote)) - { - ++line_number; - auto record_offset = pos; - auto record_size = csv_line.length(); - pos = csv_file.tellg(); - is_first_row = false; - // skip blank lines - if (record_size <= 10) - { - std::string trimmed = csv_line; - boost::trim_if(trimmed, boost::algorithm::is_any_of("\",'\r\n ")); - if (trimmed.empty()) - { - std::clog << "CSV index: empty row encountered at line: " << line_number << std::endl; - continue; - } - } - try - { - auto values = csv_utils::parse_line(csv_line, separator, quote); - unsigned num_fields = values.size(); - if (num_fields > num_headers || num_fields < num_headers) - { - // skip this row - std::ostringstream s; - s << "CSV Index: # of columns(" - << num_fields << ") > # of headers(" - << num_headers << ") parsed for row " << line_number; - throw mapnik::datasource_exception(s.str()); - } - - auto geom = ::detail::extract_geometry(values, locator); - if (!geom.is()) - { - auto box = mapnik::geometry::envelope(geom); - if (!extent.valid()) extent = box; - else extent.expand_to_include(box); - boxes.emplace_back(std::move(box), make_pair(record_offset, record_size)); - } - else - { - std::ostringstream s; - s << "CSV Index: expected geometry column: could not parse row " - << line_number << " " - << values[locator.index] << "'"; - throw mapnik::datasource_exception(s.str()); - } - } - catch (mapnik::datasource_exception const& ex ) - { - std::clog << ex.what() << " at line: " << line_number << std::endl; - } - catch (std::exception const& ex) - { - std::ostringstream s; - s << "CSV Index: unexpected error parsing line: " << line_number - << " - found " << headers.size() << " with values like: " << csv_line << "\n" - << " and got error like: " << ex.what(); - std::clog << s.str() << std::endl; - } - } - return std::make_pair(true, extent);; } -using box_type = mapnik::box2d; +using box_type = mapnik::box2d; using item_type = std::pair>; using boxes_type = std::vector; -template std::pair> process_csv_file(boxes_type&, std::string const&, std::string const&, char, char); +template std::pair process_csv_file(boxes_type&, std::string const&, std::string const&, char, char); }} diff --git a/utils/mapnik-index/process_csv_file.hpp b/utils/mapnik-index/process_csv_file.hpp index f84393d7c..395bf55c7 100644 --- a/utils/mapnik-index/process_csv_file.hpp +++ b/utils/mapnik-index/process_csv_file.hpp @@ -29,7 +29,7 @@ namespace mapnik { namespace detail { template -std::pair> process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote); +std::pair process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote); }} diff --git a/utils/mapnik-index/process_geojson_file.cpp b/utils/mapnik-index/process_geojson_file.cpp index af9656bee..44553185f 100644 --- a/utils/mapnik-index/process_geojson_file.cpp +++ b/utils/mapnik-index/process_geojson_file.cpp @@ -21,11 +21,6 @@ *****************************************************************************/ #include "process_geojson_file.hpp" -#include -#include -#include -#include -#include #if defined(MAPNIK_MEMORY_MAPPED_FILE) #pragma GCC diagnostic push @@ -35,40 +30,46 @@ #include #pragma GCC diagnostic pop #include +#else +#include #endif -#include #include #include namespace { + +template struct feature_validate_callback { - feature_validate_callback(mapnik::box2d const& box) + feature_validate_callback(mapnik::box2d const& box) : box_(box) {} void operator() (mapnik::feature_ptr const& f) const { - if (box_ != f->envelope()) + if (box_ != box_) { throw std::runtime_error("Bounding boxes mismatch validation feature"); } } - mapnik::box2d const& box_; + mapnik::box2d const& box_; }; +using box_type = mapnik::box2d; +using boxes_type = std::vector>>; using base_iterator_type = char const*; -const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; +const mapnik::json::extract_bounding_box_grammar geojson_datasource_static_bbox_grammar; const mapnik::transcoder tr("utf8"); -const mapnik::json::feature_grammar_callback fc_grammar(tr); +const mapnik::json::feature_grammar_callback> fc_grammar(tr); } namespace mapnik { namespace detail { template -std::pair> process_geojson_file(T & boxes, std::string const& filename, bool validate_features) +std::pair process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose) { - mapnik::box2d extent; + using box_type = typename T::value_type::first_type; + box_type extent; #if defined(MAPNIK_MEMORY_MAPPED_FILE) mapnik::mapped_region_ptr mapped_region; boost::optional memory = @@ -86,7 +87,7 @@ std::pair> process_geojson_file(T & boxes, std::string const& char const* end = start + mapped_region->get_size(); #else mapnik::util::file file(filename); - if (!file.open()) + if (!file) { std::clog << "Error : cannot open " << filename << std::endl; return std::make_pair(false, extent); @@ -125,12 +126,13 @@ std::pair> process_geojson_file(T & boxes, std::string const& { base_iterator_type feat_itr = start + item.second.first; base_iterator_type feat_end = feat_itr + item.second.second; - feature_validate_callback callback(item.first); + feature_validate_callback callback(item.first); bool result = boost::spirit::qi::phrase_parse(feat_itr, feat_end, (fc_grammar) (boost::phoenix::ref(ctx), boost::phoenix::ref(start_id), boost::phoenix::ref(callback)), space); if (!result || feat_itr != feat_end) { + if (verbose) std::clog << std::string(start + item.second.first, feat_end ) << std::endl; return std::make_pair(false, extent); } } @@ -139,9 +141,6 @@ std::pair> process_geojson_file(T & boxes, std::string const& return std::make_pair(true, extent); } -using box_type = mapnik::box2d; -using item_type = std::pair>; -using boxes_type = std::vector; -template std::pair> process_geojson_file(boxes_type&, std::string const&, bool); +template std::pair process_geojson_file(boxes_type&, std::string const&, bool, bool); }} diff --git a/utils/mapnik-index/process_geojson_file.hpp b/utils/mapnik-index/process_geojson_file.hpp index a4d468ad2..a377d23e3 100644 --- a/utils/mapnik-index/process_geojson_file.hpp +++ b/utils/mapnik-index/process_geojson_file.hpp @@ -29,7 +29,7 @@ namespace mapnik { namespace detail { template -std::pair> process_geojson_file(T & boxes, std::string const& filename, bool validate_features); +std::pair process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose); }} diff --git a/utils/mapnik-render/mapnik-render.cpp b/utils/mapnik-render/mapnik-render.cpp index 0ed950cca..c172995c7 100644 --- a/utils/mapnik-render/mapnik-render.cpp +++ b/utils/mapnik-render/mapnik-render.cpp @@ -21,7 +21,7 @@ int main (int argc,char** argv) namespace po = boost::program_options; bool verbose = false; - bool auto_open = true; + bool auto_open = false; int return_value = 0; std::string xml_file; std::string img_file; @@ -32,12 +32,12 @@ int main (int argc,char** argv) try { - po::options_description desc("nik2img utility"); + po::options_description desc("mapnik-render utility"); desc.add_options() ("help,h", "produce usage message") ("version,V","print version string") ("verbose,v","verbose output") - ("open","automatically open the file after rendering (os x only)") + ("open","automatically open the file after rendering") ("xml",po::value(),"xml map to read") ("img",po::value(),"image to render") ("scale-factor",po::value(),"scale factor for rendering") diff --git a/utils/pgsql2sqlite/main.cpp b/utils/pgsql2sqlite/main.cpp index 39ced62be..81eff635e 100644 --- a/utils/pgsql2sqlite/main.cpp +++ b/utils/pgsql2sqlite/main.cpp @@ -26,10 +26,13 @@ #include #include "connection_manager.hpp" -// boost +#pragma GCC diagnostic push +#include #include -#include #include +#pragma GCC diagnostic pop + +#include //stl #include diff --git a/utils/pgsql2sqlite/pgsql2sqlite.hpp b/utils/pgsql2sqlite/pgsql2sqlite.hpp index e339a8f58..9de886732 100644 --- a/utils/pgsql2sqlite/pgsql2sqlite.hpp +++ b/utils/pgsql2sqlite/pgsql2sqlite.hpp @@ -352,23 +352,23 @@ void pgsql2sqlite(Connection conn, break; } case 23: - output_rec.push_back(sqlite::value_type(int4net(buf))); + output_rec.emplace_back(int4net(buf)); break; case 21: - output_rec.push_back(sqlite::value_type(int2net(buf))); + output_rec.emplace_back(int(int2net(buf))); break; case 700: { float val; float4net(val,buf); - output_rec.push_back(sqlite::value_type(val)); + output_rec.emplace_back(double(val)); break; } case 701: { double val; float8net(val,buf); - output_rec.push_back(sqlite::value_type(val)); + output_rec.emplace_back(val); break; } case 1700: @@ -377,7 +377,7 @@ void pgsql2sqlite(Connection conn, double val; if (mapnik::util::string2double(str,val)) { - output_rec.push_back(sqlite::value_type(val)); + output_rec.emplace_back(val); } break; } diff --git a/utils/pgsql2sqlite/sqlite.hpp b/utils/pgsql2sqlite/sqlite.hpp index 07d2128a3..be4e4a384 100644 --- a/utils/pgsql2sqlite/sqlite.hpp +++ b/utils/pgsql2sqlite/sqlite.hpp @@ -24,8 +24,11 @@ #include // boost #include -//sqlite3 + +#pragma GCC diagnostic push +#include #include +#pragma GCC diagnostic pop //stl #ifdef MAPNIK_DEBUG diff --git a/utils/shapeindex/build.py b/utils/shapeindex/build.py index 9f7de7445..2a4c2ab07 100644 --- a/utils/shapeindex/build.py +++ b/utils/shapeindex/build.py @@ -25,7 +25,9 @@ from copy import copy Import ('env') -program_env = env.Clone() +Import ('plugin_base') + +program_env = plugin_base.Clone() source = Split( """ diff --git a/utils/shapeindex/shapeindex.cpp b/utils/shapeindex/shapeindex.cpp index a9c524249..9dcff1189 100644 --- a/utils/shapeindex/shapeindex.cpp +++ b/utils/shapeindex/shapeindex.cpp @@ -26,9 +26,10 @@ #include #include #include +#include #include "shapefile.hpp" #include "shape_io.hpp" - +#include "shape_index_featureset.hpp" #pragma GCC diagnostic push #include #include @@ -44,8 +45,9 @@ int main (int argc,char** argv) namespace po = boost::program_options; bool verbose=false; - unsigned int depth=DEFAULT_DEPTH; - double ratio=DEFAULT_RATIO; + bool index_parts = false; + unsigned int depth = DEFAULT_DEPTH; + double ratio = DEFAULT_RATIO; std::vector shape_files; try @@ -54,6 +56,7 @@ int main (int argc,char** argv) desc.add_options() ("help,h", "produce usage message") ("version,V","print version string") + ("index-parts","index individual shape parts (default: no)") ("verbose,v","verbose output") ("depth,d", po::value(), "max tree depth\n(default 8)") ("ratio,r",po::value(),"split ratio (default 0.55)") @@ -69,18 +72,22 @@ int main (int argc,char** argv) if (vm.count("version")) { std::clog << "version 0.3.0" <(); @@ -98,7 +105,7 @@ int main (int argc,char** argv) catch (std::exception const& ex) { std::clog << "Error: " << ex.what() << std::endl; - return -1; + return EXIT_FAILURE; } std::clog << "max tree depth:" << depth << std::endl; @@ -107,7 +114,7 @@ int main (int argc,char** argv) if (shape_files.size() == 0) { std::clog << "no shape files to index" << std::endl; - return 0; + return EXIT_FAILURE; } for (auto const& filename : shape_files) { @@ -157,54 +164,103 @@ int main (int argc,char** argv) std::clog << "type=" << shape_type << std::endl; std::clog << "extent:" << extent << std::endl; + if (!extent.valid() || std::isnan(extent.width()) || std::isnan(extent.height())) + { + std::clog << "Invalid extent aborting..." << std::endl; + return EXIT_FAILURE; + } int pos = 50; shx.seek(pos * 2); - mapnik::quad_tree tree(extent, depth, ratio); + mapnik::quad_tree tree(extent, depth, ratio); int count = 0; - while (shx.is_good() && pos <= file_length - 4) + if (shape_type != shape_io::shape_null) { - int offset = shx.read_xdr_integer(); - int content_length = shx.read_xdr_integer(); - pos += 4; - box2d item_ext; - shp.seek(offset * 2); - int record_number = shp.read_xdr_integer(); - if (content_length != shp.read_xdr_integer()) + while (shx.is_good() && pos <= file_length - 4) { - std::clog << "Content length mismatch for record number " << record_number << std::endl; - continue; - } - shape_type = shp.read_ndr_integer(); + int offset = shx.read_xdr_integer(); + int shx_content_length = shx.read_xdr_integer(); + pos += 4; + box2d item_ext; + shp.seek(offset * 2); + int record_number = shp.read_xdr_integer(); + int shp_content_length = shp.read_xdr_integer(); + if (shx_content_length != shp_content_length) + { + std::clog << "Content length mismatch for record number " << record_number << std::endl; + continue; + } + shape_type = shp.read_ndr_integer(); - if (shape_type==shape_io::shape_point - || shape_type==shape_io::shape_pointm - || shape_type == shape_io::shape_pointz) - { - double x=shp.read_double(); - double y=shp.read_double(); - item_ext=box2d(x,y,x,y); - } - else - { - shp.read_envelope(item_ext); - } - if (verbose) - { - std::clog << "record number " << record_number << " box=" << item_ext << std::endl; - } - if (item_ext.valid()) - { - tree.insert(offset * 2,item_ext); - ++count; + if (shape_type == shape_io::shape_null) continue; + + if (shape_type==shape_io::shape_point + || shape_type==shape_io::shape_pointm + || shape_type == shape_io::shape_pointz) + { + double x=shp.read_double(); + double y=shp.read_double(); + item_ext=box2d(x,y,x,y); + } + else if (index_parts && + (shape_type == shape_io::shape_polygon || shape_type == shape_io::shape_polygonm || shape_type == shape_io::shape_polygonz + || shape_type == shape_io::shape_polyline || shape_type == shape_io::shape_polylinem || shape_type == shape_io::shape_polylinez)) + { + shp.read_envelope(item_ext); + int num_parts = shp.read_ndr_integer(); + int num_points = shp.read_ndr_integer(); + std::vector parts; + parts.resize(num_parts); + std::for_each(parts.begin(), parts.end(), [&](int & part) { part = shp.read_ndr_integer();}); + for (int k = 0; k < num_parts; ++k) + { + int start = parts[k]; + int end; + if (k == num_parts - 1) end = num_points; + else end = parts[k + 1]; + + mapnik::geometry::linear_ring ring; + ring.reserve(end - start); + for (int j = start; j < end; ++j) + { + double x = shp.read_double(); + double y = shp.read_double(); + ring.emplace_back(x, y); + } + item_ext = mapnik::geometry::envelope(ring); + if (item_ext.valid()) + { + if (verbose) + { + std::clog << "record number " << record_number << " box=" << item_ext << std::endl; + } + tree.insert(mapnik::detail::node(offset * 2, start, end),item_ext); + ++count; + } + } + item_ext = mapnik::box2d(); //invalid + } + else + { + shp.read_envelope(item_ext); + } + + if (item_ext.valid()) + { + if (verbose) + { + std::clog << "record number " << record_number << " box=" << item_ext << std::endl; + } + tree.insert(mapnik::detail::node(offset * 2,-1,0),item_ext); + ++count; + } } } if (count > 0) { std::clog << " number shapes=" << count << std::endl; - std::fstream file((shapename+".index").c_str(), - std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary); + std::ofstream file((shapename+".index").c_str(), std::ios::trunc | std::ios::binary); if (!file) { std::clog << "cannot open index file for writing file \"" @@ -227,5 +283,5 @@ int main (int argc,char** argv) } std::clog << "done!" << std::endl; - return 0; + return EXIT_SUCCESS; } diff --git a/utils/svg2png/svg2png.cpp b/utils/svg2png/svg2png.cpp index 8e855fd91..b78f53b16 100644 --- a/utils/svg2png/svg2png.cpp +++ b/utils/svg2png/svg2png.cpp @@ -40,12 +40,16 @@ #include #pragma GCC diagnostic pop +#pragma GCC diagnostic push +#include #include "agg_rasterizer_scanline_aa.h" #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_renderer_base.h" #include "agg_pixfmt_rgba.h" #include "agg_scanline_u.h" +#pragma GCC diagnostic pop + struct main_marker_visitor { @@ -56,7 +60,7 @@ struct main_marker_visitor verbose_(verbose), auto_open_(auto_open) {} - int operator() (mapnik::marker_svg const& marker) + int operator() (mapnik::marker_svg const& marker) const { using pixfmt = agg::pixfmt_rgba32_pre; using renderer_base = agg::renderer_base; @@ -67,6 +71,11 @@ struct main_marker_visitor double opacity = 1; int w = marker.width(); int h = marker.height(); + if (w == 0 || h == 0) + { + // fallback to svg width/height or viewBox + std::tie(w, h) = marker.dimensions(); + } if (verbose_) { std::clog << "found width of '" << w << "' and height of '" << h << "'\n"; @@ -117,14 +126,14 @@ struct main_marker_visitor // default template - int operator() (T const&) + int operator() (T const&) const { std::clog << "svg2png error: '" << svg_name_ << "' is not a valid vector!\n"; return -1; } private: - std::string const& svg_name_; + std::string svg_name_; bool verbose_; bool auto_open_; };