diff --git a/.circleci/config.yml b/.circleci/config.yml index 9eeb1549e..e81f187f7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ jobs: distcheck: docker: - - image: ubuntu:17.10 + - image: ubuntu:19.04 steps: - checkout - run: apt update && apt install -y ninja-build binutils libtool autoconf automake make cmake gcc g++ pkg-config ragel gtk-doc-tools libfontconfig1-dev libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip @@ -192,18 +192,27 @@ jobs: - run: make -j32 - run: make check || .ci/fail.sh | asan_symbolize | c++filt - fedora-O0-debug-outoftreebuild: + fedora-O0-debug-outoftreebuild-mingw: docker: - image: fedora steps: - checkout - - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python || true + - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python wine mingw32-gcc-c++ mingw64-gcc-c++ mingw32-glib2 mingw32-cairo mingw32-freetype mingw64-glib2 mingw64-cairo mingw64-freetype glibc-devel.i686 || true - run: CFLAGS="-O0" CXXFLAGS="-O0" CPPFLAGS="-DHB_DEBUG" NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 - - run: mkdir build && cd build && ../configure && make && (make check || ../.ci/fail.sh) + - run: mkdir build && cd build && ../configure && make -j32 && (make check || ../.ci/fail.sh) + - run: pip install pefile + - run: mkdir winbuild32 && cd winbuild32 && ../mingw32.sh && make -j32 && make dist-win && cp harfbuzz-*-win32.zip harfbuzz-win32.zip + - run: mkdir winbuild64 && cd winbuild64 && ../mingw64.sh && make -j32 && make dist-win && cp harfbuzz-*-win64.zip harfbuzz-win64.zip + - store_artifacts: + path: winbuild32/harfbuzz-win32.zip + destination: harfbuzz-win32.zip + - store_artifacts: + path: winbuild64/harfbuzz-win64.zip + destination: harfbuzz-win64.zip cmake-gcc: docker: - - image: ubuntu:17.10 + - image: ubuntu:19.04 steps: - checkout - run: apt update && apt install -y ninja-build binutils cmake gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip @@ -213,17 +222,17 @@ jobs: - run: CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test - run: ninja -Cbuild install - cmake-oracledeveloperstudio: - docker: - - image: fedora - steps: - - checkout - - run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python libnsl || true - - run: wget http://$ODSUSER:$ODSPASS@behdad.org/harfbuzz-private/OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 && tar xf OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 --owner root --group root --no-same-owner - - run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_BUILTIN_UCDN=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H. - - run: make -Cbuild -j32 - - run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test - - run: make -Cbuild install + #cmake-oracledeveloperstudio: + # docker: + # - image: fedora + # steps: + # - checkout + # - run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python libnsl || true + # - run: wget http://$ODSUSER:$ODSPASS@behdad.org/harfbuzz-private/OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 && tar xf OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 --owner root --group root --no-same-owner + # - run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H. + # - run: make -Cbuild -j32 + # - run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test + # - run: make -Cbuild install crosscompile-notest-djgpp: docker: @@ -253,12 +262,12 @@ jobs: - run: cmake -Bbuild -H. -GNinja - run: ninja -Cbuild - crosscompile-cmake-notest-browser-asmjs: + crosscompile-cmake-notest-browser-asmjs-hb_tiny: docker: - image: dockcross/browser-asmjs steps: - checkout - - run: cmake -Bbuild -H. -GNinja + - run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY" - run: ninja -Cbuild crosscompile-cmake-notest-linux-arm64: @@ -308,7 +317,7 @@ workflows: - clang-msan - clang-tsan - clang-ubsan - - fedora-O0-debug-outoftreebuild + - fedora-O0-debug-outoftreebuild-mingw # cmake based builds - cmake-gcc @@ -322,7 +331,7 @@ workflows: ## cmake - crosscompile-cmake-notest-android-arm - - crosscompile-cmake-notest-browser-asmjs + - crosscompile-cmake-notest-browser-asmjs-hb_tiny - crosscompile-cmake-notest-linux-arm64 - crosscompile-cmake-notest-linux-mips #- crosscompile-cmake-notest-windows-x64 diff --git a/.travis.yml b/.travis.yml index 703fac25c..d788263ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ # Build Configuration for Travis -dist: trusty +dist: xenial language: cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a8d12c163..4ffabad10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,6 @@ endif () ## HarfBuzz build configurations option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF) option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF) -option(HB_BUILTIN_UCDN "Use HarfBuzz provided UCDN" ON) option(HB_HAVE_GLIB "Enable glib unicode functions" OFF) option(HB_HAVE_ICU "Enable icu unicode functions" OFF) if (APPLE) @@ -70,7 +69,6 @@ option(HB_CHECK OFF "Do a configuration suitable for testing (shared library and if (HB_CHECK) set (BUILD_SHARED_LIBS ON) set (HB_BUILD_UTILS ON) - set (HB_BUILTIN_UCDN ON) set (HB_HAVE_ICU) set (HB_HAVE_GLIB ON) #set (HB_HAVE_GOBJECT ON) @@ -160,7 +158,6 @@ endfunction () file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES) file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES) -file(READ ${PROJECT_SOURCE_DIR}/src/hb-ucdn/Makefile.sources UCDNSOURCES) extract_make_variable(HB_BASE_sources ${SRCSOURCES}) add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/") @@ -191,9 +188,6 @@ add_prefix_to_list(HB_SUBSET_CLI_sources "${PROJECT_SOURCE_DIR}/util/") extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES}) add_prefix_to_list(HB_OT_SHAPE_CLOSURE_sources "${PROJECT_SOURCE_DIR}/util/") -extract_make_variable(LIBHB_UCDN_sources ${UCDNSOURCES}) -add_prefix_to_list(LIBHB_UCDN_sources "${PROJECT_SOURCE_DIR}/src/hb-ucdn/") - file(READ configure.ac CONFIGUREAC) string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC}) @@ -295,14 +289,6 @@ if (HB_HAVE_GRAPHITE2) mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY) endif () -if (HB_BUILTIN_UCDN) - include_directories(src/hb-ucdn) - add_definitions(-DHAVE_UCDN) - - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ucdn.cc) - list(APPEND project_extra_sources ${LIBHB_UCDN_sources}) -endif () - if (HB_HAVE_GLIB) add_definitions(-DHAVE_GLIB) diff --git a/Makefile.am b/Makefile.am index f9f6e3630..26ebdc6e7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,12 +9,18 @@ SUBDIRS = src util test docs EXTRA_DIST = \ autogen.sh \ harfbuzz.doap \ + README.md \ + README.mingw.md \ README.python.md \ - README.wine.md \ BUILD.md \ RELEASING.md \ + TESTING.md \ CMakeLists.txt \ replace-enum-strings.cmake \ + mingw-configure.sh \ + mingw-ldd.py \ + mingw32.sh \ + mingw64.sh \ $(NULL) MAINTAINERCLEANFILES = \ @@ -60,8 +66,6 @@ DISTCHECK_CONFIGURE_FLAGS = \ --enable-introspection \ $(NULL) -# TODO: Copy infrastructure from cairo - # TAR_OPTIONS is not set as env var for 'make dist'. How to fix that? TAR_OPTIONS = --owner=0 --group=0 @@ -70,8 +74,7 @@ dist-hook: dist-clear-sticky-bits dist-clear-sticky-bits: chmod -R a-s $(distdir) - -tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.bz2 +tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.xz sha256_file = $(tar_file).sha256 gpg_file = $(sha256_file).asc $(sha256_file): $(tar_file) @@ -82,5 +85,18 @@ $(gpg_file): $(sha256_file) release-files: $(tar_file) $(sha256_file) $(gpg_file) +dist-win: + @case $(host_triplet) in *-w64-mingw32) ;; *) echo "Error: Requires mingw build. See README.mingw.md.">&2; exit 1 ;; esac + @DIR=$(PACKAGE_TARNAME)-$(VERSION)-win`case $(host_triplet) in i686-*) echo 32 ;; x86_64-*) echo 64 ;; esac`; \ + $(RM) -r $$DIR; $(MKDIR_P) $$DIR || exit 1; \ + cp util/.libs/hb-{shape,view,subset}.exe $$DIR && \ + $(top_srcdir)/mingw-ldd.py $$DIR/hb-view.exe | grep -v 'not found' | cut -d '>' -f 2 | xargs cp -t $$DIR && \ + cp src/.libs/libharfbuzz{,-subset}-0.dll $$DIR && \ + chmod a+x $$DIR/*.{exe,dll} && \ + $(STRIP) $$DIR/*.{exe,dll} && \ + zip -r $$DIR.zip $$DIR && \ + $(RM) -r $$DIR && \ + echo "$$DIR.zip is ready." + -include $(top_srcdir)/git.mk diff --git a/NEWS b/NEWS index f3e424fbc..51929738a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,28 @@ +Overview of changes leading to 2.5.1 +Friday, May 31, 2019 +==================================== +- Fix build with various versions of Visual Studio. +- Improved documentation, thanks to Nathan Willis. +- Bugfix in subsetting glyf table. +- Improved scripts for cross-compiling for Windows using mingw. +- Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER. + A deprecated macro is added for backwards-compatibility. + + +Overview of changes leading to 2.5.0 +Friday, May 24, 2019 +==================================== +- This release does not include much functional changes, but includes major internal + code-base changes. We now require C++11. Support for gcc 4.8 and earlier has been + dropped. +- New hb-config.hh facility for compiling smaller library for embedded and web usecases. +- New Unicode Character Databse implementation that is half the size of previously-used + UCDN. +- Subsetter improvements. +- Improved documentation, thanks to Nathan Willis. +- Misc shaping fixes. + + Overview of changes leading to 2.4.0 Monday, March 25, 2019 ==================================== diff --git a/README.md b/README.md index fd93be84f..ce0a04d1f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ For bug reports, mailing list, and other information please visit: http://harfbuzz.org/ -For license information, see the file COPYING. +For license information, see [COPYING](COPYING). + +For build information, see [BUILD.md](BUILD.md). + +For test execution, see [TESTING.md](TESTING.md). Documentation: https://harfbuzz.github.io diff --git a/README.mingw.md b/README.mingw.md new file mode 100644 index 000000000..76d1a8754 --- /dev/null +++ b/README.mingw.md @@ -0,0 +1,48 @@ +For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe, +as a widely used and tested shaper is used as more-or-less OpenType reference +implementation and that specially is important where OpenType specification +is or wasn't that clear. For having access to Uniscribe on Linux/macOS these +steps are recommended: + +1. Install Wine from your favorite package manager. On Fedora that's `dnf install wine`. + +2. And `mingw-w64` compiler. + With `brew` on macOS, you can have it like `brew install mingw-w64`. + On Fedora, with `dnf install mingw32-gcc-c++`, or `dnf install mingw64-gcc-c++` for the + 64-bit Windows. + +3. Install cross-compiled dependency packages. Alternatively see [^1] below. + On Fedora that would be `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype` + for 32-bit, or `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype` for 64-bit. + +5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild` + +6. Run `../mingw32.sh` for 32-bit build, or `../mingw64.sh` for 64-bit. This configures + HarfBuzz for cross-compiling. It enables Uniscribe backend as well. + +7. `make` + +Now you can use hb-shape using `wine util/hb-shape.exe` but if you like to shape with +the Microsoft Uniscribe, + +8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your + Windows installation (assuming you have a 64-bit installation, otherwise + `C:\Windows\System32\usp10.dll`) that it is not a DirectWrite proxy + ([for more info](https://en.wikipedia.org/wiki/Uniscribe)). + Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise + it is designed to work with DirectWrite which Wine can't work with its original one. + You want a Uniscribe from Windows 7 or older. + + Put the DLL in the folder you are going to run the next command, + +9. `WINEDLLOVERRIDES="usp10=n" wine util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe` + +(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need) + + +[^1] Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) + in your `~/.local/i686-w64-mingw32`. Then replace all the instances of + `/home/behdad/.local/i586-mingw32msvc` and `/home/behdad/.local/i686-w64-mingw32` + with `<$HOME>/.local/i686-w64-mingw32` on that folder. + (`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS) + You shouldn't replace the instances of those inside binary files. diff --git a/README.wine.md b/README.wine.md deleted file mode 100644 index 799eb631f..000000000 --- a/README.wine.md +++ /dev/null @@ -1,40 +0,0 @@ -For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe, -as a widely used and tested shaper is used as more-or-less OpenType reference -implementation and that specially is important where OpenType specification -is or wasn't that clear. For having access to Uniscribe on Linux/macOS these -steps are recommended: - -1. Install Wine from your favorite package manager. - -2. And `mingw-w64` compiler. - With `brew` on macOS, you can have it like `brew install mingw-w64` - -3. Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) - on your `~/.local/i686-w64-mingw32`. - -4. Replace all the instances of `/home/behdad/.local/i586-mingw32msvc` - and `/home/behdad/.local/i686-w64-mingw32` with `<$HOME>/.local/i686-w64-mingw32` - on that folder. (`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS) - - Probably you shouldn't replace the ones are inside binaries. - -5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild` - -6. `../mingw32.sh --with-uniscribe && cd ..` - -7. `make -Cwinbuild` - -Now you can use hb-shape using `wine winbuild/util/hb-shape.exe` but if you like to -to use the original Uniscribe, - -8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your - Windows installation (assuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`) - that it is not a DirectWrite proxy ([for more info](https://en.wikipedia.org/wiki/Uniscribe)). - Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise - it is designed to work with DirectWrite which Wine can't work with its original one. - - Put the dll on the folder you are going to run the next command, - -9. `WINEDLLOVERRIDES="usp10=n" wine winbuild/util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe` - -(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need) diff --git a/RELEASING.md b/RELEASING.md index 5dcce5884..360aea764 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -46,27 +46,21 @@ HarfBuzz release walk-through checklist: 10. Build win32 bundle. - a. Put contents of [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) on your `~/.local/i686-w64-mingw32`, + a. Build Win32 binaries. See [README.mingw.md](README.mingw.md). - b. Run `../mingw32.sh --with-uniscribe` script to configure harfbuzz with mingw - in a subdirector (eg. winbuild/), - - c. make - - d. Back in the parent directory, run `./UPDATE.sh`(available below) to build win32 - bundle. + b. Run "make dist-win" to build Win32 bundle. 11. Copy all artefacts to users.freedesktop.org and move them into `/srv/www.freedesktop.org/www/software/harfbuzz/release` There should be four files. Eg.: ``` --rw-r--r-- 1 behdad eng 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.bz2 --rw-r--r-- 1 behdad eng 89 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256 --rw-r--r-- 1 behdad eng 339 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256.asc +-rw-r--r-- 1 behdad eng 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.xz +-rw-r--r-- 1 behdad eng 89 Jul 18 11:34 harfbuzz-1.4.7.tar.xz.sha256 +-rw-r--r-- 1 behdad eng 339 Jul 18 11:34 harfbuzz-1.4.7.tar.xz.sha256.asc -rw-r--r-- 1 behdad eng 2895619 Jul 18 11:34 harfbuzz-1.4.7-win32.zip ``` -12. While doing that, quickly double-check the size of the .tar.bz2 and .zip +12. While doing that, quickly double-check the size of the .tar.xz and .zip files against their previous releases to make sure nothing bad happened. They should be in the ballpark, perhaps slightly larger. Sometimes they do shrink, that's not by itself a stopper. @@ -76,39 +70,3 @@ HarfBuzz release walk-through checklist: 14. Go to GitHub release page [here](https://github.com/harfbuzz/harfbuzz/releases), edit the tag, upload artefacts and NEWS entry and save. - - -## UPDATE.sh -```bash -#!/bin/bash - -v=$1 - -if test "x$v" = x; then - echo "usage: UPDATE.sh micro-version" - exit 1 -fi - -dir_prefix=harfbuzz-1.4. -dir_suffix=-win32 -dir=$dir_prefix$v$dir_suffix -dir_old=$dir_prefix$((v-1))$dir_suffix -if test -d "$dir"; then - echo "New dir $dir exists; not overwriting" - exit 1 -fi -if ! test -d "$dir_old"; then - echo "Old dir $dir_old does NOT exist; aborting" - exit 1 -fi -set -ex -cp -a "$dir_old" "$dir.tmp" -rm -f "$dir.tmp"/GDX32.dll -rm -f "$dir.tmp"/usp10.dll -cp ../winbuild/src/.libs/libharfbuzz-0.dll{,.def} $dir.tmp/ -cp ../winbuild/util/.libs/hb-{shape,view}.exe $dir.tmp/ -i686-w64-mingw32-strip $dir.tmp/{hb-shape.exe,hb-view.exe,libharfbuzz-0.dll} -mv $dir.tmp $dir -zip -r $dir.zip $dir -echo Bundle $dir.zip ready -``` diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 000000000..4efc64ca5 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,75 @@ +## Build & Run + +Depending on what area you are working in change or add `HB_DEBUG_`. +Values defined in `hb-debug.hh`. + +```shell +# quick sanity check +time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \ + && (make -j4 -C test/api check || cat test/api/test-suite.log)) + +# slower sanity check +time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \ + && make -j4 -C src check \ + && make -j4 -C test/api check \ + && make -j4 -C test/subset check) + +# confirm you didn't break anything else +time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \ + && make -j4 check) + +# often catches files you didn't add, e.g. test fonts to EXTRA_DIST +make distcheck +``` + +### Run tests with asan + +**NOTE**: this sometimes yields harder to read results than the full fuzzer + +```shell +# For nice symbols tell asan how to symoblize. Note that it doesn't like versioned copies like llvm-symbolizer-3.8 +# export ASAN_SYMBOLIZER_PATH=path to version-less llvm-symbolizer +# ex +export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.8/bin/llvm-symbolizer + +./configure CC=clang CXX=clang++ CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address +# make/run tests as usual +``` + +### Debug with GDB + +``` +cd ./util +../libtool --mode=execute gdb --args ./hb-subset ... +``` + +### Enable Debug Logging + +```shell +# make clean if you previously build w/o debug logging +make CPPFLAGS=-DHB_DEBUG_SUBSET=100 +``` + +## Build and Test via CMake + +Note: You'll need to first install ninja-build via apt-get. + +```shell +cd harfbuzz +mkdir buid +cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild && CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test +``` +## Test with the Fuzzer + +```shell +# push your changs to a branch on googlefonts/harfbuzz +# In a local copy of oss-fuzz, edit projects/harfbuzz/Dockerfile +# Change the git clone to pull your branch + +# Do this periodically +sudo python infra/helper.py build_image harfbuzz + +# Do these to update/run +sudo python infra/helper.py build_fuzzers --sanitizer address harfbuzz +sudo python infra/helper.py run_fuzzer harfbuzz hb-subset-fuzzer +``` diff --git a/appveyor.yml b/appveyor.yml index 21d4ea798..236bb1b12 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,11 +2,13 @@ platform: x64 environment: matrix: + - compiler: msvc generator: Visual Studio 14 platform: Win32 configuration: Debug triplet: x86-windows + - compiler: msvc generator: Visual Studio 14 Win64 platform: x64 @@ -19,10 +21,35 @@ environment: configuration: Debug + # Build only + + #- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + # compiler: msvc2 + # generator: Visual Studio 12 + # platform: Win32 + # configuration: Release + # triplet: x86-windows + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + compiler: msvc2 + generator: Visual Studio 15 + platform: Win32 + configuration: Release + triplet: x86-windows + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + compiler: msvc2 + generator: Visual Studio 16 + platform: Win32 + configuration: Release + triplet: x86-windows + + - compiler: msys2 MINGW_PREFIX: /mingw64 MINGW_CHOST: x86_64-w64-mingw32 MSYS2_ARCH: x86_64 + - compiler: msys2 MINGW_PREFIX: /mingw32 MINGW_CHOST: i686-w64-mingw32 @@ -30,30 +57,26 @@ environment: install: -# - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -Sy && pacman --noconfirm --force -S pacman-mirrors && pacman --force -Syu --noconfirm"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"' - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" - - set PATH=%PATH%;C:\msys64\mingw64\bin # msys2 is added just for having "ragel" on PATH - - 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\setup-%CYGWIN_ARCH%.exe -g -q -P cygwin-devel,libfreetype-devel,libcairo-devel,libicu-devel,gcc,gcc-g++,gobject-introspection,libglib2.0-devel,libgraphite2-devel,pkg-config,python2' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2,ragel}"' - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" vcpkg install glib:%triplet% freetype:%triplet% cairo:%triplet%' build_script: - - 'if "%compiler%"=="msvc" md build' - - 'if "%compiler%"=="msvc" cd build' + - 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%"' + - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake' + - 'if "%compiler%"=="msvc" set PATH=%PATH%;C:\Program Files (x86)\MSBuild\14.0\Bin' - - - 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%" ../' - - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake ../' - + - 'if "%compiler%"=="msvc" cd build' - 'if "%compiler%"=="msvc" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%' - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%' + - 'if "%compiler%"=="msvc2" cmake -G "%generator%" -Bbuild -H.' + - 'if "%compiler%"=="msvc2" cmake --build build --config %configuration%' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"' cache: - c:\tools\vcpkg\installed\ - - '%CYGWIN_PREFIX%\var\cache\setup' notifications: - provider: Email diff --git a/configure.ac b/configure.ac index 98e9c32d8..6a68df79e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [2.4.0], + [2.5.1], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) @@ -9,7 +9,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/harfbuzz.pc.in]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability]) +AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-xz no-dist-gzip -Wall no-define color-tests -Wno-portability]) AM_SILENT_RULES([yes]) AX_CODE_COVERAGE @@ -134,9 +134,7 @@ AC_MSG_RESULT([$hb_os_win32]) AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes") have_pthread=false -if test "$hb_os_win32" = no; then - AX_PTHREAD([have_pthread=true]) -fi +AX_PTHREAD([have_pthread=true]) if $have_pthread; then AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads]) fi @@ -300,21 +298,6 @@ AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin") dnl =========================================================================== -AC_ARG_WITH(ucdn, - [AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@], - [Use builtin UCDN library @<:@default=yes@:>@])],, - [with_ucdn=yes]) -have_ucdn=false -if test "x$with_ucdn" = "xyes"; then - have_ucdn=true -fi -if $have_ucdn; then - AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions]) -fi -AM_CONDITIONAL(HAVE_UCDN, $have_ucdn) - -dnl ========================================================================== - AC_ARG_WITH(graphite2, [AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@], [Use the graphite2 library @<:@default=no@:>@])],, @@ -497,7 +480,6 @@ AC_CONFIG_FILES([ Makefile src/Makefile src/harfbuzz-config.cmake -src/hb-ucdn/Makefile util/Makefile test/Makefile test/api/Makefile @@ -525,7 +507,7 @@ AC_MSG_NOTICE([ Build configuration: Unicode callbacks (you want at least one): - Builtin (UCDN): ${have_ucdn} + Builtin true Glib: ${have_glib} ICU: ${have_icu} diff --git a/docs/Makefile.am b/docs/Makefile.am index 9b54b40e1..f4bf2fdbc 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -33,7 +33,7 @@ SCAN_OPTIONS=--rebuild-types --deprecated-guards="HB_DISABLE_DEPRECATED" \ # Header files or dirs to ignore when scanning. Use base file/dir names # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code -IGNORE_HFILES=`cd $(top_srcdir)/src; find . -path './hb-*/*.h' | sed 's@^.*/@@'` +IGNORE_HFILES=`cd $(top_srcdir)/src; find . -path './*/*.h' | sed 's@^.*/@@'` if HAVE_GOBJECT else IGNORE_HFILES+=hb-gobject.h hb-gobject-enums.h hb-gobject-structs.h @@ -75,12 +75,14 @@ content_files= \ usermanual-what-is-harfbuzz.xml \ usermanual-install-harfbuzz.xml \ usermanual-getting-started.xml \ + usermanual-glyph-information.xml \ usermanual-shaping-concepts.xml \ + usermanual-object-model.xml \ usermanual-buffers-language-script-and-direction.xml \ usermanual-fonts-and-faces.xml \ - usermanual-clusters.xml \ usermanual-opentype-features.xml \ - usermanual-glyph-information.xml \ + usermanual-clusters.xml \ + usermanual-utilities.xml \ version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml index e48d17593..2e4b35cbb 100644 --- a/docs/harfbuzz-docs.xml +++ b/docs/harfbuzz-docs.xml @@ -33,11 +33,12 @@ + - - + + diff --git a/docs/usermanual-buffers-language-script-and-direction.xml b/docs/usermanual-buffers-language-script-and-direction.xml index 1c6b5dab1..2865426f2 100644 --- a/docs/usermanual-buffers-language-script-and-direction.xml +++ b/docs/usermanual-buffers-language-script-and-direction.xml @@ -7,30 +7,38 @@ Buffers, language, script and direction - The input to HarfBuzz is a series of Unicode characters, stored in a + The input to the HarfBuzz shaper is a series of Unicode characters, stored in a buffer. In this chapter, we'll look at how to set up a buffer with - the text that we want and then customize the properties of the - buffer. + the text that we want and how to customize the properties of the + buffer. We'll also look at a piece of lower-level machinery that + you will need to understand before proceeding: the functions that + HarfBuzz uses to retrieve Unicode information. + + + After shaping is complete, HarfBuzz puts its output back + into the buffer. But getting that output requires setting up a + face and a font first, so we will look at that in the next chapter + instead of here.
Creating and destroying buffers As we saw in our Getting Started example, a buffer is created and - initialized with hb_buffer_create(). This + initialized with hb_buffer_create(). This produces a new, empty buffer object, instantiated with some default values and ready to accept your Unicode strings. HarfBuzz manages the memory of objects (such as buffers) that it creates, so you don't have to. When you have finished working on - a buffer, you can call hb_buffer_destroy(): + a buffer, you can call hb_buffer_destroy(): - hb_buffer_t *buffer = hb_buffer_create(); - ... - hb_buffer_destroy(buffer); - + hb_buffer_t *buf = hb_buffer_create(); + ... + hb_buffer_destroy(buf); + This will destroy the object and free its associated memory - unless some other part of the program holds a reference to this @@ -39,46 +47,364 @@ else destroying it, you should increase its reference count: -void somefunc(hb_buffer_t *buffer) { - buffer = hb_buffer_reference(buffer); - ... - + void somefunc(hb_buffer_t *buf) { + buf = hb_buffer_reference(buf); + ... + And then decrease it once you're done with it: - hb_buffer_destroy(buffer); -} - + hb_buffer_destroy(buf); + } + + + While we are on the subject of reference-counting buffers, it is + worth noting that an individual buffer can only meaningfully be + used by one thread at a time. + To throw away all the data in your buffer and start from scratch, - call hb_buffer_reset(buffer). If you want to + call hb_buffer_reset(buf). If you want to throw away the string in the buffer but keep the options, you can - instead call hb_buffer_clear_contents(buffer). + instead call hb_buffer_clear_contents(buf).
+
Adding text to the buffer Now we have a brand new HarfBuzz buffer. Let's start filling it with text! From HarfBuzz's perspective, a buffer is just a stream - of Unicode codepoints, but your input string is probably in one of - the standard Unicode character encodings (UTF-8, UTF-16, UTF-32) + of Unicode code points, but your input string is probably in one of + the standard Unicode character encodings (UTF-8, UTF-16, or + UTF-32). HarfBuzz provides convenience functions that accept + each of these encodings: + hb_buffer_add_utf8(), + hb_buffer_add_utf16(), and + hb_buffer_add_utf32(). Other than the + character encoding they accept, they function identically. + + You can add UTF-8 text to a buffer by passing in the text array, + the array's length, an offset into the array for the first + character to add, and the length of the segment to add: + + + hb_buffer_add_utf8 (hb_buffer_t *buf, + const char *text, + int text_length, + unsigned int item_offset, + int item_length) + + + So, in practice, you can say: + + + hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text)); + + + This will append your new characters to + buf, not replace its existing + contents. Also, note that you can use -1 in + place of the first instance of strlen(text) + if your text array is NULL-terminated. Similarly, you can also use + -1 as the final argument want to add its full + contents. + + + Whatever start item_offset and + item_length you provide, HarfBuzz will also + attempt to grab the five characters before + the offset point and the five characters + after the designated end. These are the + before and after "context" segments, which are used internally + for HarfBuzz to make shaping decisions. They will not be part of + the final output, but they ensure that HarfBuzz's + script-specific shaping operations are correct. If there are + fewer than five characters available for the before or after + contexts, HarfBuzz will just grab what is there. + + + For longer text runs, such as full paragraphs, it might be + tempting to only add smaller sub-segments to a buffer and + shape them in piecemeal fashion. Generally, this is not a good + idea, however, because a lot of shaping decisions are + dependent on this context information. For example, in Arabic + and other connected scripts, HarfBuzz needs to know the code + points before and after each character in order to correctly + determine which glyph to return. + + + The safest approach is to add all of the text available, then + use item_offset and + item_length to indicate which characters you + want shaped, so that HarfBuzz has access to any context. + + + You can also add Unicode code points directly with + hb_buffer_add_codepoints(). The arguments + to this function are the same as those for the UTF + encodings. But it is particularly important to note that + HarfBuzz does not do validity checking on the text that is added + to a buffer. Invalid code points will be replaced, but it is up + to you to do any deep-sanity checking necessary. + +
+
Setting buffer properties + Buffers containing input characters still need several + properties set before HarfBuzz can shape their text correctly. -
-
- What about the other scripts? + Initially, all buffers are set to the + HB_BUFFER_CONTENT_TYPE_INVALID content + type. After adding text, the buffer should be set to + HB_BUFFER_CONTENT_TYPE_UNICODE instead, which + indicates that it contains un-shaped input + characters. After shaping, the buffer will have the + HB_BUFFER_CONTENT_TYPE_GLYPHS content type. + + + hb_buffer_add_utf8() and the + other UTF functions set the content type of their buffer + automatically. But if you are reusing a buffer you may want to + check its state with + hb_buffer_get_content_type(buffer). If + necessary you can set the content type with + + + hb_buffer_set_content_type(buf, HB_BUFFER_CONTENT_TYPE_UNICODE); + + + to prepare for shaping. + + + Buffers also need to carry information about the script, + language, and text direction of their contents. You can set + these properties individually: + + + hb_buffer_set_direction(buf, HB_DIRECTION_LTR); + hb_buffer_set_script(buf, HB_SCRIPT_LATIN); + hb_buffer_set_language(buf, hb_language_from_string("en", -1)); + + + However, since these properties are often the repeated for + multiple text runs, you can also save them in a + hb_segment_properties_t for reuse: + + + hb_segment_properties_t *savedprops; + hb_buffer_get_segment_properties (buf, savedprops); + ... + hb_buffer_set_segment_properties (buf2, savedprops); + + + HarfBuzz also provides getter functions to retrieve a buffer's + direction, script, and language properties individually. + + + HarfBuzz recognizes four text directions in + hb_direction_t: left-to-right + (HB_DIRECTION_LTR), right-to-left (HB_DIRECTION_RTL), + top-to-bottom (HB_DIRECTION_TTB), and + bottom-to-top (HB_DIRECTION_BTT). For the + script property, HarfBuzz uses identifiers based on the + ISO 15924 + standard. For languages, HarfBuzz uses tags based on the + IETF BCP 47 standard. + + + Helper functions are provided to convert character strings into + the necessary script and language tag types. + + + Two additional buffer properties to be aware of are the + "invisible glyph" and the replacement code point. The + replacement code point is inserted into buffer output in place of + any invalid code points encountered in the input. By default, it + is the Unicode REPLACEMENT CHARACTER code + point, U+FFFD "�". You can change this with + + + hb_buffer_set_replacement_codepoint(buf, replacement); + + + passing in the replacement Unicode code point as the + replacement parameter. + + + The invisible glyph is used to replace all output glyphs that + are invisible. By default, the standard space character + U+0020 is used; you can replace this (for + example, when using a font that provides script-specific + spaces) with + + + hb_buffer_set_invisible_glyph(buf, replacement_glyph); + + + Do note that in the replacement_glyph + parameter, you must provide the glyph ID of the replacement you + wish to use, not the Unicode code point. + + + HarfBuzz supports a few additional flags you might want to set + on your buffer under certain circumstances. The + HB_BUFFER_FLAG_BOT and + HB_BUFFER_FLAG_EOT flags tell HarfBuzz + that the buffer represents the beginning or end (respectively) + of a text element (such as a paragraph or other block). Knowing + this allows HarfBuzz to apply certain contextual font features + when shaping, such as initial or final variants in connected + scripts. + + + HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES + tells HarfBuzz not to hide glyphs with the + Default_Ignorable property in Unicode. This + property designates control characters and other non-printing + code points, such as joiners and variation selectors. Normally + HarfBuzz replaces them in the output buffer with zero-width + space glyphs (using the "invisible glyph" property discussed + above); setting this flag causes them to be printed, which can + be helpful for troubleshooting. + + + Conversely, setting the + HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES flag + tells HarfBuzz to remove Default_Ignorable + glyphs from the output buffer entirely. Finally, setting the + HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE + flag tells HarfBuzz not to insert the dotted-circle glyph + (U+25CC, "◌"), which is normally + inserted into buffer output when broken character sequences are + encountered (such as combining marks that are not attached to a + base character).
+
Customizing Unicode functions + HarfBuzz requires some simple functions for accessing + information from the Unicode Character Database (such as the + General_Category (gc) and + Script (sc) properties) that is useful + for shaping, as well as some useful operations like composing and + decomposing code points. + + + HarfBuzz includes its own internal, lightweight set of Unicode + functions. At build time, it is also possible to compile support + for some other options, such as the Unicode functions provided + by GLib or the International Components for Unicode (ICU) + library. Generally, this option is only of interest for client + programs that have specific integration requirements or that do + a significant amount of customization. + + + If your program has access to other Unicode functions, however, + such as through a system library or application framework, you + might prefer to use those instead of the built-in + options. HarfBuzz supports this by implementing its Unicode + functions as a set of virtual methods that you can replace — + without otherwise affecting HarfBuzz's functionality. + + + The Unicode functions are specified in a structure called + unicode_funcs which is attached to each + buffer. But even though unicode_funcs is + associated with a hb_buffer_t, the functions + themselves are called by other HarfBuzz APIs that access + buffers, so it would be unwise for you to hook different + functions into different buffers. + + + In addition, you can mark your unicode_funcs + as immutable by calling + hb_unicode_funcs_make_immutable (ufuncs). + This is especially useful if your code is a + library or framework that will have its own client programs. By + marking your Unicode function choices as immutable, you prevent + your own client programs from changing the + unicode_funcs configuration and introducing + inconsistencies and errors downstream. + + + You can retrieve the Unicode-functions configuration for + your buffer by calling hb_buffer_get_unicode_funcs(): + + + hb_unicode_funcs_t *ufunctions; + ufunctions = hb_buffer_get_unicode_funcs(buf); + + + The current version of unicode_funcs uses six functions: + + + + + hb_unicode_combining_class_func_t: + returns the Canonical Combining Class of a code point. + + + + + hb_unicode_general_category_func_t: + returns the General Category (gc) of a code point. + + + + + hb_unicode_mirroring_func_t: returns + the Mirroring Glyph code point (for bi-directional + replacement) of a code point. + + + + + hb_unicode_script_func_t: returns the + Script (sc) property of a code point. + + + + + hb_unicode_compose_func_t: returns the + canonical composition of a sequence of two code points. + + + + + hb_unicode_decompose_func_t: returns + the canonical decomposition of a code point. + + + + + Note, however, that future HarfBuzz releases may alter this set. + + + Each Unicode function has a corresponding setter, with which you + can assign a callback to your replacement function. For example, + to replace + hb_unicode_general_category_func_t, you can call + + + hb_unicode_funcs_set_general_category_func (*ufuncs, func, *user_data, destroy) + + + Virtualizing this set of Unicode functions is primarily intended + to improve portability. There is no need for every client + program to make the effort to replace the default options, so if + you are unsure, do not feel any pressure to customize + unicode_funcs.
+
diff --git a/docs/usermanual-clusters.xml b/docs/usermanual-clusters.xml index b8d919133..a7b16580a 100644 --- a/docs/usermanual-clusters.xml +++ b/docs/usermanual-clusters.xml @@ -158,7 +158,7 @@ For left-to-right scripts (LTR) and top-to-bottom scripts (TTB), HarfBuzz will preserve the monotonic property: client programs - are guaranteed that monotonically increasing initial clulster + are guaranteed that monotonically increasing initial cluster values will be returned as monotonically increasing final cluster values. @@ -167,7 +167,7 @@ the directionality of the buffer itself is reversed for final output as a matter of design. Therefore, HarfBuzz inverts the monotonic property: client programs are guaranteed that - monotonically increasing initial clulster values will be + monotonically increasing initial cluster values will be returned as monotonically decreasing final cluster values. diff --git a/docs/usermanual-fonts-and-faces.xml b/docs/usermanual-fonts-and-faces.xml index 553600439..b87f0e5e8 100644 --- a/docs/usermanual-fonts-and-faces.xml +++ b/docs/usermanual-fonts-and-faces.xml @@ -5,20 +5,449 @@ ]> - Fonts and faces -
+ Fonts, faces, and output + + In the previous chapter, we saw how to set up a buffer and fill + it with text as Unicode code points. In order to shape this + buffer text with HarfBuzz, you will need also need a font + object. + + + HarfBuzz provides abstractions to help you cache and reuse the + heavier parts of working with binary fonts, so we will look at + how to do that. We will also look at how to work with the + FreeType font-rendering library and at how you can customize + HarfBuzz to work with other libraries. + + + Finally, we will look at how to work with OpenType variable + fonts, the latest update to the OpenType font format, and at + some other recent additions to OpenType. + + +
+ Font and face objects + + The outcome of shaping a run of text depends on the contents of + a specific font file (such as the substitutions and positioning + moves in the 'GSUB' and 'GPOS' tables), so HarfBuzz makes + accessing those internals fast. + + + An hb_face_t represents a face + in HarfBuzz. This data type is a wrapper around an + hb_blob_t blob that holds the contents of a binary + font file. Since HarfBuzz supports TrueType Collections and + OpenType Collections (each of which can include multiple + typefaces), a HarfBuzz face also requires an index number + specifying which typeface in the file you want to use. Most of + the font files you will encounter in the wild include just a + single face, however, so most of the time you would pass in + 0 as the index when you create a face: + + + hb_blob_t* blob = hb_blob_create_from_file(file); + ... + hb_face_t* face = hb_face_create(blob, 0); + + + On its own, a face object is not quite ready to use for + shaping. The typeface must be set to a specific point size in + order for some details (such as hinting) to work. In addition, + if the font file in question is an OpenType Variable Font, then + you may need to specify one or variation-axis settings (or a + named instance) in order to get the output you need. + + + In HarfBuzz, you do this by creating a font + object from your face. + + + Font objects also have the advantage of being considerably + lighter-weight than face objects (remember that a face contains + the contents of a binary font file mapped into memory). As a + result, you can cache and reuse a font object, but you could + also create a new one for each additional size you needed. + Creating new fonts incurs some additional overhead, of course, + but whether or not it is excessive is your call in the end. In + contrast, face objects are substantially larger, and you really + should cache them and reuse them whenever possible. + + + You can create a font object from a face object: + + + hb_font_t* hb_font = hb_font_create(hb_face); + + + After creating a font, there are a few properties you should + set. Many fonts enable and disable hints based on the size it + is used at, so setting this is important for font + objects. hb_font_set_ppem(font, x_ppem, + y_ppem) sets the pixels-per-EM value of the font. You + can also set the point size of the font with + hb_font_set_ppem(font, ptem). HarfBuzz uses the + industry standard 72 points per inch. + + + HarfBuzz lets you specify the degree subpixel precision you want + through a scaling factor. You can set horizontal and + vertical scaling factors on the + font by calling hb_font_set_scale(font, x_scale, + y_scale). + + + There may be times when you are handed a font object and need to + access the face object that it comes from. For that, you can call + + + hb_face = hb_font_get_face(hb_font); + + + You can also create a font object from an existing font object + using the hb_font_create_sub_font() + function. This creates a child font object that is initiated + with the same attributes as its parent; it can be used to + quickly set up a new font for the purpose of overriding a specific + font-functions method. + + + All face objects and font objects are lifecycle-managed by + HarfBuzz. After creating a face, you increase its reference + count with hb_face_reference(face) and + decrease it with + hb_face_destroy(face). Likewise, you + increase the reference count on a font with + hb_font_reference(font) and decrease it + with hb_font_destroy(font). + + + You can also attach user data to face objects and font objects. + +
+ +
+ Customizing font functions + + During shaping, HarfBuzz frequently needs to query font objects + to get at the contents and parameters of the glyphs in a font + file. It includes a built-in set of functions that is tailored + to working with OpenType fonts. However, as was the case with + Unicode functions in the buffers chapter, HarfBuzz also wants to + make it easy for you to assign a substitute set of font + functions if you are developing a program to work with a library + or platform that provides its own font functions. + + + Therefore, the HarfBuzz API defines a set of virtual + methods for accessing font-object properties, and you can + replace the defaults with your own selections without + interfering with the shaping process. Each font object in + HarfBuzz includes a structure called + font_funcs that serves as a vtable for the + font object. The virtual methods in + font_funcs are: + + + + + hb_font_get_font_h_extents_func_t: returns + the extents of the font for horizontal text. + + + + + hb_font_get_font_v_extents_func_t: returns + the extents of the font for vertical text. + + + + + hb_font_get_nominal_glyph_func_t: returns + the font's nominal glyph for a given code point. + + + + + hb_font_get_variation_glyph_func_t: returns + the font's glyph for a given code point when it is followed by a + given Variation Selector. + + + + + hb_font_get_nominal_glyphs_func_t: returns + the font's nominal glyphs for a series of code points. + + + + + hb_font_get_glyph_advance_func_t: returns + the advance for a glyph. + + + + + hb_font_get_glyph_h_advance_func_t: returns + the advance for a glyph for horizontal text. + + + + + hb_font_get_glyph_v_advance_func_t:returns + the advance for a glyph for vertical text. + + + + + hb_font_get_glyph_advances_func_t: returns + the advances for a series of glyphs. + + + + + hb_font_get_glyph_h_advances_func_t: returns + the advances for a series of glyphs for horizontal text . + + + + + hb_font_get_glyph_v_advances_func_t: returns + the advances for a series of glyphs for vertical text. + + + + + hb_font_get_glyph_origin_func_t: returns + the origin coordinates of a glyph. + + + + + hb_font_get_glyph_h_origin_func_t: returns + the origin coordinates of a glyph for horizontal text. + + + + + hb_font_get_glyph_v_origin_func_t: returns + the origin coordinates of a glyph for vertical text. + + + + + hb_font_get_glyph_extents_func_t: returns + the extents for a glyph. + + + + + hb_font_get_glyph_contour_point_func_t: + returns the coordinates of a specific contour point from a glyph. + + + + + hb_font_get_glyph_name_func_t: returns the + name of a glyph (from its glyph index). + + + + + hb_font_get_glyph_from_name_func_t: returns + the glyph index that corresponds to a given glyph name. + + + + + You can fetch the font-functions configuration for a font object + by calling hb_font_get_font_funcs(): + + + hb_font_funcs_t *ffunctions; + ffunctions = hb_font_get_font_funcs (font); + + + The individual methods can each be replaced with their own setter + function, such as + hb_font_funcs_set_nominal_glyph_func(*ffunctions, + func, *user_data, destroy). + + + Font-functions structures can be reused for multiple font + objects, and can be reference counted with + hb_font_funcs_reference() and + hb_font_funcs_destroy(). Just like other + objects in HarfBuzz, you can set user-data for each + font-functions structure and assign a destroy callback for + it. + + + You can also mark a font-functions structure as immutable, + with hb_font_funcs_make_immutable(). This + is especially useful if your code is a library or framework that + will have its own client programs. By marking your + font-functions structures as immutable, you prevent your client + programs from changing the configuration and introducing + inconsistencies and errors downstream. + +
+ +
+ Font objects and HarfBuzz's native OpenType implementation + + By default, whenever HarfBuzz creates a font object, it will + configure the font to use a built-in set of font functions that + supports contemporary OpenType font internals. If you want to + work with OpenType or TrueType fonts, you should be able to use + these functions without difficulty. + + + Many of the methods in the font-functions structure deal with + the fundamental properties of glyphs that are required for + shaping text: extents (the maximums and minimums on each axis), + origins (the (0,0) coordinate point which + glyphs are drawn in reference to), and advances (the amount that + the cursor needs to be moved after drawing each glyph, including + any empty space for the glyph's side bearings). + + + As you can see in the list of functions, there are separate "horizontal" + and "vertical" variants depending on whether the text is set in + the horizontal or vertical direction. For some scripts, fonts + that are designed to support text set horizontally or vertically (for + example, in Japanese) may include metrics for both text + directions. When fonts don't include this information, HarfBuzz + does its best to transform what the font provides. + + + In addition to the direction-specific functions, HarfBuzz + provides some higher-level functions for fetching information + like extents and advances for a glyph. If you call + + + hb_font_get_glyph_advance_for_direction(font, direction, extents); + + + then you can provide any hb_direction_t as the + direction parameter, and HarfBuzz will + use the correct function variant for the text direction. There + are similar higher-level versions of the functions for fetching + extents, origin coordinates, and contour-point + coordinates. There are also addition and subtraction functions + for moving points with respect to the origin. + + + There are also methods for fetching the glyph ID that + corresponds to a Unicode code point (possibly when followed by a + variation-selector code point), fetching the glyph name from the + font, and fetching the glyph ID that corresponds to a glyph name + you already have. + + + HarfBuzz also provides functions for converting between glyph + names and string + variables. hb_font_glyph_to_string(font, glyph, s, + size) retrieves the name for the glyph ID + glyph from the font object. It generates a + generic name of the form gidDDD (where DDD is + the glyph index) if there is no name for the glyph in the + font. The hb_font_glyph_from_string(font, s, len, + glyph) takes an input string s + and looks for a glyph with that name in the font, returning its + glyph ID in the glyph + output parameter. It automatically parses + gidDDD and uniUUUU strings. + +
+ + + + + + +
+ Working with OpenType Variable Fonts + If you are working with OpenType Variable Fonts, there are a few + additional functions you should use to specify the + variation-axis settings of your font object. Without doing so, + your variable font's font object can still be used, but only at + the default setting for every axis (which, of course, is + sometimes what you want, but does not cover general usage). + + + HarfBuzz manages variation settings in the + hb_variation_t data type, which holds a tag for the + variation-axis identifier tag and a value for its + setting. You can retrieve the list of variation axes in a font + binary from the face object (not from a font object, notably) by + calling hb_ot_var_get_axis_count(face) to + find the number of axes, then using + hb_ot_var_get_axis_infos() to collect the + axis structures: + + + axes = hb_ot_var_get_axis_count(face); + ... + hb_ot_var_get_axis_infos(face, 0, axes, axes_array); + + + For each axis returned in the array, you can can access the + identifier in its tag. HarfBuzz also has + tag definitions predefined for the five standard axes specified + in OpenType (ital for italic, + opsz for optical size, + slnt for slant, wdth for + width, and wght for weight). Each axis also + has a min_value, a + default_value, and a max_value. + + + To set your font object's variation settings, you call the + hb_font_set_variations() function with an + array of hb_variation_t variation settings. Let's + say our font has weight and width axes. We need to specify each + of the axes by tag and assign a value on the axis: + + + unsigned int variation_count = 2; + hb_variation_t variation_data[variation_count]; + variation_data[0].tag = HB_OT_TAG_VAR_AXIS_WIDTH; + variation_data[1].tag = HB_OT_TAG_VAR_AXIS_WEIGHT; + variation_data[0].value = 80; + variation_data[1].value = 750; + ... + hb_font_set_variations(font, variation_data, variation_count); + + + That should give us a slightly condensed font ("normal" on the + wdth axis is 100) at a noticeably bolder + weight ("regular" is 400 on the wght axis). + + + In practice, though, you should always check that the value you + want to set on the axis is within the + [min_value,max_value] + range actually implemented in the font's variation axis. After + all, a font might only provide lighter-than-regular weights, and + setting a heavier value on the wght axis will + not change that. + + + Once your variation settings are specified on your font object, + however, shaping with a variable font is just like shaping a + static font.
- + + diff --git a/docs/usermanual-install-harfbuzz.xml b/docs/usermanual-install-harfbuzz.xml index a1e7ab012..2b61ce81d 100644 --- a/docs/usermanual-install-harfbuzz.xml +++ b/docs/usermanual-install-harfbuzz.xml @@ -246,7 +246,7 @@ Use GLib. (Default = auto) - + This option enables or disables usage of the GLib library. The default setting is to check for the @@ -297,7 +297,7 @@ Use Fontconfig. (Default = auto) - + This option enables or disables usage of the Fontconfig library, which provides font-matching functions and @@ -317,7 +317,7 @@ Use the ICU library. (Default = auto) - + This option enables or disables usage of the International Components for @@ -330,30 +330,12 @@ - - --with-ucdn - - - Use HarfBuzz's built-in UCDN library. (Default = auto) - - - The HarfBuzz source tree includes a Unicode - Database and Normalization (UCDN) library - that provides access to basic character properties in - the Unicode Character Database (UCD) as well as low-level - normalization functions. HarfBuzz can be built without - this UCDN support if the usage of a different UCDN - library is desired. - - - - --with-graphite2 Use the Graphite2 library. (Default = no) - + This option enables or disables usage of the Graphite2 library, which provides support for the Graphite shaping @@ -367,7 +349,7 @@ Use the FreeType library. (Default = auto) - + This option enables or disables usage of the FreeType font-rendering library. The default setting is to check for the @@ -384,7 +366,7 @@ Use the Uniscribe library (experimental). (Default = no) - + This option enables or disables usage of the Uniscribe font-rendering library. Uniscribe is available on @@ -400,7 +382,7 @@ Use the DirectWrite library (experimental). (Default = no) - + This option enables or disables usage of the DirectWrite font-rendering library. DirectWrite is available on @@ -416,7 +398,7 @@ Use the CoreText library. (Default = no) - + This option enables or disables usage of the CoreText library. CoreText is available on macOS and iOS systems. diff --git a/docs/usermanual-object-model.xml b/docs/usermanual-object-model.xml new file mode 100644 index 000000000..f571c477f --- /dev/null +++ b/docs/usermanual-object-model.xml @@ -0,0 +1,258 @@ + + + +]> + + The HarfBuzz object model +
+ An overview of data types in HarfBuzz + + HarfBuzz features two kinds of data types: non-opaque, + pass-by-value types and opaque, heap-allocated types. This kind + of separation is common in C libraries that have to provide + API/ABI compatibility (almost) indefinitely. + + + Value types: The non-opaque, pass-by-value + types include integer types, enums, and small structs. Exposing + a struct in the public API makes it impossible to expand the + struct in the future. As such, exposing structs is reserved for + cases where it’s extremely inefficient to do otherwise. + + + In HarfBuzz, several structs, like hb_glyph_info_t and + hb_glyph_position_t, fall into that efficiency-sensitive + category and are non-opaque. + + + For all non-opaque structs where future extensibility may be + necessary, reserved members are included to hold space for + possible future members. As such, it’s important to provide + equal(), and hash() + methods for such structs, allowing users of the API do + effectively deal with the type without having to + adapt their code to future changes. + + + Important value types provided by HarfBuzz include the structs + for working with Unicode code points, glyphs, and tags for font + tables and features, as well as the enums for many Unicode and + OpenType properties. + +
+ +
+ Objects in HarfBuzz + + Object types: Opaque struct types are used + for what HarfBuzz loosely calls "objects." This doesn’t have + much to do with the terminology from object-oriented programming + (OOP), although some of the concepts are similar. + + + In HarfBuzz, all object types provide certain + lifecycle-management APIs. Objects are reference-counted, and + constructed with various create() methods, referenced via + reference() and dereferenced using + destroy(). + + + For example, + the hb_buffer_t object has + hb_buffer_create() as its constructor, + hb_buffer_reference() to reference, and + hb_buffer_destroy() to dereference. + + + After construction, each object's properties are accessible only + through the setter and getter functions described in the API + Reference manual. + + + Key object types provided by HarfBuzz include: + + + + + blobs, which act as low-level wrappers around binary + data. Blobs are typically used to hold the contents of a + binary font file. + + + + + faces, which represent typefaces from a + font file, but without specific parameters (such as size) set. + + + + + fonts, which represent instances of a + face with all of their parameters specified. + + + + + buffers, which hold Unicode code points + for characters (before shaping) and the shaped glyph output + (after shaping). + + + + + shape plans, which store the settings + that HarfBuzz will use when shaping a particular text + segment. Shape plans are not generally used by client + programs directly, but as we will see in a later chapter, + they are still valuable to understand. + + + + +
+ + + +
+ Object lifecycle management + + Each object type in HarfBuzz provides a + create() method. Some object types provide + additional variants of create() to handle + special cases or to speed up common tasks; those variants are + documented in the API reference. For example, + hb_blob_create_from_file() constructs a new + blob directly from the contents of a file. + + + All objects are created with an initial reference count of + 1. Client programs can increase the reference + count on an object by calling its + reference() method. Whenever a client + program is finished with an object, it should call its + corresponding destroy() method. The destroy + method will decrease the reference count on the object and, + whenever the reference count reaches zero, it will also destroy + the object and free all of the associated memory. + + + All of HarfBuzz's object-lifecycle-management APIs are + thread-safe (unless you compiled HarfBuzz from source with the + HB_NO_MT configuration flag), even when the + object as a whole is not thread-safe. + It is also permissible to reference() or to + destroy() the NULL + value. + + + Some objects are thread-safe after they have been constructed + and set up. The general pattern is to + create() the object, make a few + set_*() calls to set up the + object, and then use it without further modification. + + + To ensure that such an object is not modified, client programs + can explicitly mark an object as immutable. HarfBuzz provides + make_immutable() methods to mark an object + as immutable and is_immutable() methods to + test whether or not an object is immutable. Attempts to use + setter functions on immutable objects will fail silently; see the API + Reference manual for specifics. + + + Note also that there are no "make mutable" methods. If client + programs need to alter an object previously marked as immutable, + they will need to make a duplicate of the original. + + + Finally, object constructors (and, indeed, as much of the + shaping API as possible) will never return + NULL. Instead, if there is an allocation + error, each constructor will return an “empty” object + singleton. + + + These empty-object singletons are inert and safe (although + typically useless) to pass around. This design choice avoids + having to check for NULL pointers all + throughout the code. + + + In addition, this “empty” object singleton can also be accessed + using the get_empty() method of the object + type in question. + +
+ + +
+ User data + + To better integrate with client programs, HarfBuzz's objects + offer a "user data" mechanism that can be used to attach + arbitrary data to the object. User-data attachment can be + useful for tying the lifecycles of various pieces of data + together, or for creating language bindings. + + + Each object type has a set_user_data() + method and a get_user_data() method. The + set_user_data() methods take a client-provided + key and a pointer, + user_data, pointing to the data itself. Once + the key-data pair has been attached to the object, the + get_user_data() method can be called with + the key, returning the user_data pointer. + + + The set_user_data() methods also support an + optional destroy callback. Client programs + can set the destroy callback and receive + notification from HarfBuzz whenever the object is destructed. + + + Finally, each set_user_data() method allows + the client program to set a replace Boolean + indicating whether or not the function call should replace any + existing user_data + associated with the specified key. + +
+ + + +
+ Blobs + + While most of HarfBuzz's object types are specific to the + shaping process, blobs are somewhat + different. + + + Blobs are an abstraction desgined to negotiate lifecycle and + permissions for raw pieces of data. For example, when you load + the raw font data into memory and want to pass it to HarfBuzz, + you do so in a hb_blob_t wrapper. + + + This allows you to take advantage of HarffBuzz's + reference-counting and destroy + callbacks. If you allocated the memory for the data using + malloc(), you would create the blob using + + + hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, NULL, free) + + + That way, HarfBuzz will call free() on the + allocated memory whenever the blob drops its last reference and + is deconstructed. Consequently, the user code can stop worrying + about freeing memory and let the reference-counting machinery + take care of that. + +
+ +
diff --git a/docs/usermanual-opentype-features.xml b/docs/usermanual-opentype-features.xml index 51ff55a77..3eedab3d4 100644 --- a/docs/usermanual-opentype-features.xml +++ b/docs/usermanual-opentype-features.xml @@ -6,14 +6,299 @@ ]> Shaping and shape plans -
+ + Once you have your face and font objects configured as desired and + your input buffer is filled with the characters you need to shape, + all you need to do is call hb_shape(). + + + HarfBuzz will return the shaped version of the text in the same + buffer that you provided, but it will be in output mode. At that + point, you can iterate through the glyphs in the buffer, drawing + each one at the specified position or handing them off to the + appropriate graphics library. + + + For the most part, HarfBuzz's shaping step is straightforward from + the outside. But that doesn't mean there will never be cases where + you want to look under the hood and see what is happening on the + inside. HarfBuzz provides facilities for doing that, too. + + +
+ Shaping and buffer output + + The hb_shape() function call takes four arguments: the font + object to use, the buffer of characters to shape, an array of + user-specified features to apply, and the length of that feature + array. The feature array can be NULL, so for the sake of + simplicity we will start with that case. + + + Internally, HarfBuzz looks at the tables of the font file to + determine where glyph classes, substitutions, and positioning + are defined, using that information to decide which + shaper to use (ot for + OpenType fonts, aat for Apple Advanced + Typography fonts, and so on). It also looks at the direction, + script, and language properties of the segment to figure out + which script-specific shaping model is needed (at least, in + shapers that support multiple options). + + + If a font has a GDEF table, then that is used for + glyph classes; if not, HarfBuzz will fall back to Unicode + categorization by code point. If a font has an AAT "morx" table, + then it is used for substitutions; if not, but there is a GSUB + table, then the GSUB table is used. If the font has an AAT + "kerx" table, then it is used for positioning; if not, but + there is a GPOS table, then the GPOS table is used. If neither + table is found, but there is a "kern" table, then HarfBuzz will + use the "kern" table. If there is no "kerx", no GPOS, and no + "kern", HarfBuzz will fall back to positioning marks itself. + + + With a well-behaved OpenType font, you expect GDEF, GSUB, and + GPOS tables to all be applied. HarfBuzz implements the + script-specific shaping models in internal functions, rather + than in the public API. + + + The algorithms + used for complex scripts can be quite involved; HarfBuzz tries + to be compatible with the OpenType Layout specification + and, wherever there is any ambiguity, HarfBuzz attempts to replicate the + output of Microsoft's Uniscribe engine. See the Microsoft + Typography pages for more detail. + + + In general, though, all that you need to know is that + hb_shape() returns the results of shaping + in the same buffer that you provided. The buffer's content type + will now be set to + HB_BUFFER_CONTENT_TYPE_GLYPHS, indicating + that it contains shaped output, rather than input text. You can + now extract the glyph information and positioning arrays: + + + hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count); + hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); + + + The glyph information array holds a hb_glyph_info_t + for each output glyph, which has two fields: + codepoint and + cluster. Whereas, in the input buffer, + the codepoint field contained the Unicode + code point, it now contains the glyph ID of the corresponding + glyph in the font. The cluster field is + an integer that you can use to help identify when shaping has + reordered, split, or combined code points; we will say more + about that in the next chapter. + + + The glyph positions array holds a corresponding + hb_glyph_position_t for each output glyph, + containing four fields: x_advance, + y_advance, + x_offset, and + y_offset. The advances tell you how far + you need to move the drawing point after drawing this glyph, + depending on whether you are setting horizontal text (in which + case you will have x advances) or vertical text (for which you + will have y advances). The x and y offsets tell you where to + move to start drawing the glyph; usually you will have both and + x and a y offset, regardless of the text direction. + + + Most of the time, you will rely on a font-rendering library or + other graphics library to do the actual drawing of glyphs, so + you will need to iterate through the glyphs in the buffer and + pass the corresponding values off. + +
+ +
OpenType features + OpenType features enable fonts to include smart behavior, + implemented as "lookup" rules stored in the GSUB and GPOS + tables. The OpenType specification defines a long list of + standard features that fonts can use for these behaviors; each + feature has a four-character reserved name and a well-defined + semantic meaning. + + + Some OpenType features are defined for the purpose of supporting + complex-script shaping, and are automatically activated, but + only when a buffer's script property is set to a script that the + feature supports. + + + Other features are more generic and can apply to several (or + any) script, and shaping engines are expected to implement + them. By default, HarfBuzz activates several of these features + on every text run. They include ccmp, + locl, mark, + mkmk, and rlig. + + + In addition, if the text direction is horizontal, HarfBuzz + also applies the calt, + clig, curs, + kern, liga, + rclt, and frac features. + + + If the text direction is vertical, HarfBuzz applies + the vert feature by default. + + + Still other features are designed to be purely optional and left + up to the application or the end user to enable or disable as desired. + + + You can adjust the set of features that HarfBuzz applies to a + buffer by supplying an array of hb_feature_t + features as the third argument to + hb_shape(). For a simple case, let's just + enable the dlig feature, which turns on any + "discretionary" ligatures in the font: + + + hb_feature_t userfeatures[1]; + userfeatures[0].tag = HB_TAG('d','l','i','g'); + userfeatures[0].value = 1; + userfeatures[0].start = HB_FEATURE_GLOBAL_START; + userfeatures[0].end = HB_FEATURE_GLOBAL_END; + + + HB_FEATURE_GLOBAL_END and + HB_FEATURE_GLOBAL_END are macros we can use + to indicate that the features will be applied to the entire + buffer. We could also have used a literal 0 + for the start and a -1 to indicate the end of + the buffer (or have selected other start and end positions, if needed). + + + When we pass the userfeatures array to + hb_shape(), any discretionary ligature + substitutions from our font that match the text in our buffer + will get performed: + + + hb_shape(font, buf, userfeatures, num_features); + + + Just like we enabled the dlig feature by + setting its value to + 1, you would disable a feature by setting its + value to 0. Some + features can take other value settings; + be sure you read the full specification of each feature tag to + understand what it does and how to control it.
-
+ +
+ Shaper selection + + The basic version of hb_shape() determines + its shaping strategy based on examining the capabilities of the + font file. OpenType font tables cause HarfBuzz to try the + ot shaper, while AAT font tables cause HarfBuzz to try the + aat shaper. + + + In the real world, however, a font might include some unusual + mix of tables, or one of the tables might simply be broken for + the script you need to shape. So, sometimes, you might not + want to rely on HarfBuzz's process for deciding what to do, and + just tell hb_shape() what you want it to try. + + + hb_shape_full() is an alternate shaping + function that lets you supply a list of shapers for HarfBuzz to + try, in order, when shaping your buffer. For example, if you + have determined that HarfBuzz's attempts to work around broken + tables gives you better results than the AAT shaper itself does, + you might move the AAT shaper to the end of your list of + preferences and call hb_shape_full() + + + char *shaperprefs[3] = {"ot", "default", "aat"}; + ... + hb_shape_full(font, buf, userfeatures, num_features, shaperprefs); + + + to get results you are happier with. + + + You may also want to call + hb_shape_list_shapers() to get a list of + the shapers that were built at compile time in your copy of HarfBuzz. + +
+ +
Plans and caching + Internally, HarfBuzz uses a structure called a shape plan to + track its decisions about how to shape the contents of a + buffer. The hb_shape() function builds up the shape plan by + examining segment properties and by inspecting the contents of + the font. + + + This process can involve some decision-making and + trade-offs — for example, HarfBuzz inspects the GSUB and GPOS + lookups for the script and language tags set on the segment + properties, but it falls back on the lookups under the + DFLT tag (and sometimes other common tags) + if there are actually no lookups for the tag requested. + + + HarfBuzz also includes some work-arounds for + handling well-known older font conventions that do not follow + OpenType or Unicode specifications, for buggy system fonts, and for + peculiarities of Microsoft Uniscribe. All of that means that a + shape plan, while not something that you should edit directly in + client code, still might be an object that you want to + inspect. Furthermore, if resources are tight, you might want to + cache the shape plan that HarfBuzz builds for your buffer and + font, so that you do not have to rebuild it for every shaping call. + + + You can create a cacheable shape plan with + hb_shape_plan_create_cached(face, props, + user_features, num_user_features, shaper_list), where + face is a face object (not a font object, + notably), props is an + hb_segment_properties_t, + user_features is an array of + hb_feature_ts (with length + num_user_features), and + shaper_list is a list of shapers to try. + + + Shape plans are objects in HarfBuzz, so there are + reference-counting functions and user-data attachment functions + you can + use. hb_shape_plan_reference(shape_plan) + increases the reference count on a shape plan, while + hb_shape_plan_destroy(shape_plan) decreases + the reference count, destroying the shape plan when the last + reference is dropped. + + + You can attach user data to a shaper (with a key) using the + hb_shape_plan_set_user_data(shape_plan,key,data,destroy,replace) + function, optionally supplying a destroy + callback to use. You can then fetch the user data attached to a + shape plan with + hb_shape_plan_get_user_data(shape_plan, key).
+ diff --git a/docs/usermanual-utilities.xml b/docs/usermanual-utilities.xml new file mode 100644 index 000000000..1c5370c11 --- /dev/null +++ b/docs/usermanual-utilities.xml @@ -0,0 +1,244 @@ + + + +]> + + Utilities + + HarfBuzz includes several auxiliary components in addition to the + main APIs. These include a set of command-line tools, a set of + lower-level APIs for common data types that may be of interest to + client programs, and an embedded library for working with + Unicode Character Database (UCD) data. + + +
+ Command-line tools + + HarfBuzz include three command-line tools: + hb-shape, hb-view, and + hb-subset. They can be used to examine + HarfBuzz's functionality, debug font binaries, or explore the + various shaping models and features from a terminal. + + +
+ hb-shape + + hb-shape allows you to run HarfBuzz's + hb_shape() function on an input string and + to examine the outcome, in human-readable form, as terminal + output. hb-shape does + not render the results of the shaping call + into rendered text (you can use hb-view, below, for + that). Instead, it prints out the final glyph indices and + positions, taking all shaping operations into account, as if the + input string were a HarfBuzz input buffer. + + + You can specify the font to be used for shaping and, with + command-line options, you can add various aspects of the + internal state to the output that is sent to the terminal. The + general format is + + + hb-shape [OPTIONS] + path/to/font/file.ttf + yourinputtext + + + The default output format is plain text (although JSON output + can be selected instead by specifying the option + --output-format=json). The default output + syntax reports each glyph name (or glyph index if there is no + name) followed by its cluster value, its horizontal and vertical + position displacement, and its horizontal and vertical advances. + + + Output options exist to skip any of these elements in the + output, and to include additional data, such as Unicode + code-point values, glyph extents, glyph flags, or interim + shaping results. + + + Output can also be redirected to a file, or input read from a + file. Additional options enable you to enable or disable + specific font features, to set variation-font axis values, to + alter the language, script, direction, and clustering settings + used, to enable sanity checks, or to change which shaping engine is used. + + + For a complete explanation of the options available, run + + + hb-shape --help + +
+ +
+ hb-view + + hb-view allows you to + see the shaped output of an input string in rendered + form. Like hb-shape, + hb-view takes a font file and a text string + as its arguments: + + + hb-view [OPTIONS] + path/to/font/file.ttf + yourinputtext + + + By default, hb-view renders the shaped + text in ASCII block-character images as terminal output. By + appending the + --output-file=filename + switch, you can write the output to a PNG, SVG, or PDF file + (among other formats). + + + As with hb-shape, a lengthy set of options + is available, with which you can enable or disable + specific font features, set variation-font axis values, + alter the language, script, direction, and clustering settings + used, enable sanity checks, or change which shaping engine is + used. + + + You can also set the foreground and background colors used for + the output, independently control the width of all four + margins, alter the line spacing, and annotate the output image + with + + + In general, hb-view is a quick way to + verify that the output of HarfBuzz's shaping operation looks + correct for a given text-and-font combination, but you may + want to use hb-shape to figure out exactly + why something does not appear as expected. + +
+ +
+ hb-subset + + hb-subset allows you + to generate a subset of a given font, with a limited set of + supported characters, features, and variation settings. + + + By default, you provide an input font and an input text string + as the arguments to hb-subset, and it will + generate a font that covers the input text exactly like the + input font does, but includes no other characters or features. + + + hb-subset [OPTIONS] + path/to/font/file.ttf + yourinputtext + + + For example, to create a subset of Noto Serif that just includes the + numerals and the lowercase Latin alphabet, you could run + + + hb-subset [OPTIONS] + NotoSerif-Regular.ttf + 0123456789abcdefghijklmnopqrstuvwxyz + + + There are options available to remove hinting from the + subsetted font and to specify a list of variation-axis settings. + +
+ +
+ +
+ Common data types and APIs + + HarfBuzz includes several APIs for working with general-purpose + data that you may find convenient to leverage in your own + software. They include set operations and integer-to-integer + mapping operations. + + + HarfBuzz uses set operations for internal bookkeeping, such as + when it collects all of the glyph IDs covered by a particular + font feature. You can also use the set API to build sets, add + and remove elements, test whether or not sets contain particular + elements, or compute the unions, intersections, or differences + between sets. + + + All set elements are integers (specifically, + hb_codepoint_t 32-bit unsigned ints), and there are + functions for fetching the minimum and maximum element from a + set. The set API also includes some functions that might not + be part of a generic set facility, such as the ability to add a + contiguous range of integer elements to a set in bulk, and the + ability to fetch the next-smallest or next-largest element. + + + The HarfBuzz set API includes some conveniences as well. All + sets are lifecycle-managed, just like other HarfBuzz + objects. You increase the reference count on a set with + hb_set_reference() and decrease it with + hb_set_destroy(). You can also attach + user data to a set, just like you can to blobs, buffers, faces, + fonts, and other objects, and set destroy callbacks. + + + HarfBuzz also provides an API for keeping track of + integer-to-integer mappings. As with the set API, each integer is + stored as an unsigned 32-bit hb_codepoint_t + element. Maps, like other objects, are reference counted with + reference and destroy functions, and you can attach user data to + them. The mapping operations include adding and deleting + integer-to-integer key:value pairs to the map, testing for the + presence of a key, fetching the population of the map, and so on. + + + There are several other internal HarfBuzz facilities that are + exposed publicly and which you may want to take advantage of + while processing text. HarfBuzz uses a common + hb_tag_t for a variety of OpenType tag identifiers (for + scripts, languages, font features, table names, variation-axis + names, and more), and provides functions for converting strings + to tags and vice-versa. + + + Finally, HarfBuzz also includes data type for Booleans, bit + masks, and other simple types. + +
+ +
+ UCDN + + HarfBuzz includes a copy of the UCDN (Unicode + Database and Normalization) library, which provides functions + for accessing basic Unicode character properties, performing + canonical composition, and performing both canonical and + compatibility decomposition. + + + Currently, UCDN supports direct queries for several more character + properties than HarfBuzz's built-in set of Unicode functions + does, such as the BiDirectional Class, East Asian Width, Paired + Bracket and Resolved Linebreak properties. If you need to access + more properties than HarfBuzz's internal implementation + provides, using the built-in UCDN functions may be a useful solution. + + + The built-in UCDN functions are compiled by default when + building HarfBuzz from source, but this can be disabled with a + compile-time switch. + +
+ +
diff --git a/mingw-configure.sh b/mingw-configure.sh new file mode 100755 index 000000000..3281ce382 --- /dev/null +++ b/mingw-configure.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +case $1 in + i686 | x86_64) ;; + *) echo "Usage: $0 i686|x86_64" >&2; exit 1 ;; +esac + +target=$1-w64-mingw32 +shift + +exec "$(dirname "$0")"/configure \ + --build=`../config.guess` \ + --host=$target \ + --prefix=$HOME/.local/$target \ + CC= \ + CXX= \ + CPP= \ + LD= \ + CFLAGS="-static-libgcc" \ + CXXFLAGS="-static-libgcc -static-libstdc++" \ + CPPFLAGS="-I$HOME/.local/$target/include" \ + LDFLAGS=-L$HOME/.local/$target/lib \ + PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig:/usr/$target/sys-root/mingw/lib/pkgconfig/ \ + PKG_CONFIG_PATH=$HOME/.local/$target/share/pkgconfig:/usr/$target/sys-root/mingw/share/pkgconfig/ \ + PATH=$HOME/.local/$target/bin:/usr/$target/sys-root/mingw/bin:/usr/$target/bin:$PATH \ + --without-icu \ + --with-uniscribe \ + "$@" diff --git a/mingw-ldd.py b/mingw-ldd.py new file mode 100755 index 000000000..1d659efa4 --- /dev/null +++ b/mingw-ldd.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +# Copied from https://github.com/xantares/mingw-ldd/blob/master/mingw-ldd.py +# Modified to point to right prefix location on Fedora. + +# WTFPL - Do What the Fuck You Want to Public License +from __future__ import print_function +import pefile +import os +import sys + + +def get_dependency(filename): + deps = [] + pe = pefile.PE(filename) + for imp in pe.DIRECTORY_ENTRY_IMPORT: + deps.append(imp.dll.decode()) + return deps + + +def dep_tree(root, prefix=None): + if not prefix: + arch = get_arch(root) + #print('Arch =', arch) + prefix = '/usr/'+arch+'-w64-mingw32/sys-root/mingw/bin' + #print('Using default prefix', prefix) + dep_dlls = dict() + + def dep_tree_impl(root, prefix): + for dll in get_dependency(root): + if dll in dep_dlls: + continue + full_path = os.path.join(prefix, dll) + if os.path.exists(full_path): + dep_dlls[dll] = full_path + dep_tree_impl(full_path, prefix=prefix) + else: + dep_dlls[dll] = 'not found' + + dep_tree_impl(root, prefix) + return (dep_dlls) + + +def get_arch(filename): + type2arch= {pefile.OPTIONAL_HEADER_MAGIC_PE: 'i686', + pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: 'x86_64'} + pe = pefile.PE(filename) + try: + return type2arch[pe.PE_TYPE] + except KeyError: + sys.stderr.write('Error: unknown architecture') + sys.exit(1) + +if __name__ == '__main__': + filename = sys.argv[1] + for dll, full_path in dep_tree(filename).items(): + print(' ' * 7, dll, '=>', full_path) + diff --git a/mingw32.sh b/mingw32.sh index 67744051c..77edffa98 100755 --- a/mingw32.sh +++ b/mingw32.sh @@ -1,22 +1,2 @@ -#!/bin/bash - -target=i686-w64-mingw32 - -unset CC -unset CXX -unset CPP -unset LD -unset LDFLAGS -unset CFLAGS -unset CXXFLAGS -unset PKG_CONFIG_PATH - -# Removed -static from the following -export CFLAGS="-static-libgcc" -export CXXFLAGS="-static-libgcc -static-libstdc++" -export CPPFLAGS="-I$HOME/.local/$target/include -O2" -export LDFLAGS=-L$HOME/.local/$target/lib -export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig -export PATH=$HOME/.local/$target/bin:$PATH - -../configure --build=`../config.guess` --host=$target --prefix=$HOME/.local/$target "$@" +#!/bin/sh +exec "$(dirname "$0")"/mingw-configure.sh i686 "$@" diff --git a/mingw64.sh b/mingw64.sh index 49a143179..28724a48e 100755 --- a/mingw64.sh +++ b/mingw64.sh @@ -1,22 +1,2 @@ -#!/bin/bash - -target=x86_64-w64-mingw32 - -unset CC -unset CXX -unset CPP -unset LD -unset LDFLAGS -unset CFLAGS -unset CXXFLAGS -unset PKG_CONFIG_PATH - -# Removed -static from the following -export CFLAGS="-static-libgcc" -export CXXFLAGS="-static-libgcc -static-libstdc++" -export CPPFLAGS="-I$HOME/.local/$target/include -O2" -export LDFLAGS=-L$HOME/.local/$target/lib -export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig -export PATH=$HOME/.local/$target/bin:$PATH - -../configure --build=`../config.guess` --host=$target --prefix=$HOME/.local/$target "$@" +#!/bin/sh +exec "$(dirname "$0")"/mingw-configure.sh x86_64 "$@" diff --git a/src/Makefile.am b/src/Makefile.am index 9b5512f20..d126c4017 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,17 +87,6 @@ HBSOURCES += $(HB_CORETEXT_sources) HBHEADERS += $(HB_CORETEXT_headers) endif -if HAVE_UCDN -SUBDIRS += hb-ucdn -HBCFLAGS += -I$(srcdir)/hb-ucdn -HBLIBS += hb-ucdn/libhb-ucdn.la -HBSOURCES += $(HB_UCDN_sources) -hb-ucdn/libhb-ucdn.la: ucdn -ucdn: - @$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn -endif -DIST_SUBDIRS += hb-ucdn - BUILT_SOURCES += \ hb-version.h @@ -258,6 +247,7 @@ GENERATORS = \ gen-indic-table.py \ gen-os2-unicode-ranges.py \ gen-tag-table.py \ + gen-ucd-table.py \ gen-use-table.py \ gen-vowel-constraints.py \ $(NULL) @@ -384,7 +374,7 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc dump_use_data_CPPFLAGS = $(HBCFLAGS) dump_use_data_LDADD = libharfbuzz.la $(HBLIBS) -COMPILED_TESTS = test-algs test-iter test-ot-tag test-unicode-ranges +COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS) check_PROGRAMS += $(COMPILED_TESTS) @@ -398,6 +388,10 @@ test_iter_SOURCES = test-iter.cc hb-static.cc test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_iter_LDADD = $(COMPILED_TESTS_LDADD) +test_meta_SOURCES = test-meta.cc hb-static.cc +test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) +test_meta_LDADD = $(COMPILED_TESTS_LDADD) + test_ot_tag_SOURCES = hb-ot-tag.cc test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD) diff --git a/src/Makefile.sources b/src/Makefile.sources index 289e12601..477bf5ab2 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -31,6 +31,7 @@ HB_BASE_sources = \ hb-cff1-interp-cs.hh \ hb-cff2-interp-cs.hh \ hb-common.cc \ + hb-config.hh \ hb-debug.hh \ hb-dispatch.hh \ hb-face.cc \ @@ -147,6 +148,8 @@ HB_BASE_sources = \ hb-shaper.hh \ hb-static.cc \ hb-string-array.hh \ + hb-ucd-table.hh \ + hb-ucd.cc \ hb-unicode-emoji-table.hh \ hb-unicode.cc \ hb-unicode.hh \ @@ -226,9 +229,6 @@ HB_DIRECTWRITE_headers = hb-directwrite.h HB_UNISCRIBE_sources = hb-uniscribe.cc HB_UNISCRIBE_headers = hb-uniscribe.h -# Additional supplemental sources -HB_UCDN_sources = hb-ucdn.cc - # Sources for libharfbuzz-gobject and libharfbuzz-icu HB_ICU_sources = hb-icu.cc HB_ICU_headers = hb-icu.h @@ -244,9 +244,6 @@ HB_SUBSET_sources = \ hb-subset-cff1.hh \ hb-subset-cff2.cc \ hb-subset-cff2.hh \ - hb-subset-glyf.cc \ - hb-subset-glyf.hh \ - hb-subset-glyf.hh \ hb-subset-input.cc \ hb-subset-input.hh \ hb-subset-plan.cc \ diff --git a/src/check-symbols.sh b/src/check-symbols.sh index 423d18613..f181b6312 100755 --- a/src/check-symbols.sh +++ b/src/check-symbols.sh @@ -7,7 +7,7 @@ test -z "$srcdir" && srcdir=. test -z "$libs" && libs=.libs stat=0 -IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_flush\|llvm_.*' +IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*' if which nm 2>/dev/null >/dev/null; then : diff --git a/src/gen-os2-unicode-ranges.py b/src/gen-os2-unicode-ranges.py old mode 100644 new mode 100755 index 8cf598588..515f4ca14 --- a/src/gen-os2-unicode-ranges.py +++ b/src/gen-os2-unicode-ranges.py @@ -1,8 +1,10 @@ +#!/usr/bin/python + # -*- coding: utf-8 -*- # Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh # Input is a tab seperated list of unicode ranges from the otspec -# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1). +# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur). from __future__ import print_function, division, absolute_import diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py new file mode 100755 index 000000000..3f821802d --- /dev/null +++ b/src/gen-ucd-table.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +from __future__ import print_function, division, absolute_import + +import io, os.path, sys, re + +if len (sys.argv) != 2: + print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr) + sys.exit(1) + + +# https://github.com/harfbuzz/packtab +import packTab +import packTab.ucdxml + +ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1]) +ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml) + + +gc = [u['gc'] for u in ucd] +ccc = [int(u['ccc']) for u in ucd] +bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)] +#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass) +#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr) + +sc = [u['sc'] for u in ucd] + +dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd) + if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)} +ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'} + +assert not any(v for v in dm.values() if len(v) not in (1,2)) +dm1 = sorted(set(v for v in dm.values() if len(v) == 1)) +dm1_array = ['0x%04Xu' % v for v in dm1] +dm1_order = {v:i+1 for i,v in enumerate(dm1)} +dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2) +dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % + (v+(i if i not in ce and not ccc[i] else 0,)), v) + for v,i in dm2] +dm2_array = [s for s,v in dm2] +l = 1 + len(dm1_array) +dm2_order = {v[1]:i+l for i,v in enumerate(dm2)} +dm_order = {None: 0} +dm_order.update(dm1_order) +dm_order.update(dm2_order) + +gc_order = packTab.AutoMapping() +for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', + 'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', + 'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',): + gc_order[_] + +sc_order = packTab.AutoMapping() +sc_array = [] +sc_re = re.compile(" (HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]") +for line in open('hb-common.h'): + m = sc_re.search (line) + if not m: continue + name = m.group(1) + tag = ''.join(m.group(i) for i in range(2, 6)) + i = sc_order[tag] + assert i == len(sc_array) + sc_array.append(name) + +# TODO Currently if gc_order or sc_order do not capture all values, we get in +# trouble because they silently add new values. We should be able to "freeze" +# them, or just do the mapping ourselves. + +DEFAULT = 1 +COMPACT = 3 + + +print("/* == Start of generated table == */") +print("/*") +print(" * The following table is generated by running:") +print(" *") +print(" * ./gen-ucd-table.py ucd.nonunihan.grouped.xml") +print(" *") +print(" * on file with this description:", ucdxml.description) +print(" */") +print() +print("#ifndef HB_UCD_TABLE_HH") +print("#define HB_UCD_TABLE_HH") +print() + +print() +print('#include "hb.hh"') +print() + +code = packTab.Code('_hb_ucd') +sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array) +dm1_array, _ = code.addArray('hb_codepoint_t', 'dm1_map', dm1_array) +dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array) +code.print_c(linkage='static inline') + +for compression in (DEFAULT, COMPACT): + print() + if compression == DEFAULT: + print('#ifndef HB_OPTIMIZE_SIZE') + else: + print('#else') + print() + + code = packTab.Code('_hb_ucd') + + packTab.pack_table(gc, 'Cn', mapping=gc_order, compression=compression).genCode(code, 'gc') + packTab.pack_table(ccc, 0, compression=compression).genCode(code, 'ccc') + packTab.pack_table(bmg, 0, compression=compression).genCode(code, 'bmg') + packTab.pack_table(sc, 'Zzzz', mapping=sc_order, compression=compression).genCode(code, 'sc') + packTab.pack_table(dm, None, mapping=dm_order, compression=compression).genCode(code, 'dm') + + code.print_c(linkage='static inline') + + + if compression != DEFAULT: + print() + print('#endif') + print() + +print() +print("#endif /* HB_UCD_TABLE_HH */") +print() +print("/* == End of generated table == */") diff --git a/src/gen-use-table.py b/src/gen-use-table.py index 1a33b8af5..820838cf8 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -47,6 +47,14 @@ defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block') # TODO Characters that are not in Unicode Indic files, but used in USE data[0][0x034F] = defaults[0] +data[0][0x1B61] = defaults[0] +data[0][0x1B63] = defaults[0] +data[0][0x1B64] = defaults[0] +data[0][0x1B65] = defaults[0] +data[0][0x1B66] = defaults[0] +data[0][0x1B67] = defaults[0] +data[0][0x1B69] = defaults[0] +data[0][0x1B6A] = defaults[0] data[0][0x2060] = defaults[0] # TODO https://github.com/harfbuzz/harfbuzz/pull/1685 data[0][0x1B5B] = 'Consonant_Placeholder' @@ -54,7 +62,7 @@ data[0][0x1B5C] = 'Consonant_Placeholder' data[0][0x1B5F] = 'Consonant_Placeholder' data[0][0x1B62] = 'Consonant_Placeholder' data[0][0x1B68] = 'Consonant_Placeholder' -# TODO https://github.com/roozbehp/unicode-data/issues/9 +# TODO https://github.com/harfbuzz/harfbuzz/issues/1035 data[0][0x11C44] = 'Consonant_Placeholder' data[0][0x11C45] = 'Consonant_Placeholder' # TODO https://github.com/harfbuzz/harfbuzz/pull/1399 @@ -189,15 +197,15 @@ def is_BASE_OTHER(U, UISC, UGC): def is_CGJ(U, UISC, UGC): return U == 0x034F def is_CONS_FINAL(U, UISC, UGC): - # Consonant_Initial_Postfixed is new in Unicode 11; not in the spec. return ((UISC == Consonant_Final and UGC != Lo) or - UISC == Consonant_Initial_Postfixed or UISC == Consonant_Succeeding_Repha) def is_CONS_FINAL_MOD(U, UISC, UGC): #SPEC-DRAFT return UISC in [Consonant_Final_Modifier, Syllable_Modifier] return UISC == Syllable_Modifier def is_CONS_MED(U, UISC, UGC): - return UISC == Consonant_Medial and UGC != Lo + # Consonant_Initial_Postfixed is new in Unicode 11; not in the spec. + return (UISC == Consonant_Medial and UGC != Lo or + UISC == Consonant_Initial_Postfixed) def is_CONS_MOD(U, UISC, UGC): return UISC in [Nukta, Gemination_Mark, Consonant_Killer] def is_CONS_SUB(U, UISC, UGC): @@ -206,7 +214,9 @@ def is_CONS_SUB(U, UISC, UGC): def is_CONS_WITH_STACKER(U, UISC, UGC): return UISC == Consonant_With_Stacker def is_HALANT(U, UISC, UGC): - return UISC in [Virama, Invisible_Stacker] and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC) + return (UISC in [Virama, Invisible_Stacker] + and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC) + and not is_SAKOT(U, UISC, UGC)) def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC): # https://github.com/harfbuzz/harfbuzz/issues/1102 # https://github.com/harfbuzz/harfbuzz/issues/1379 @@ -222,6 +232,7 @@ def is_Word_Joiner(U, UISC, UGC): def is_OTHER(U, UISC, UGC): #SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters return (UISC == Other + and not is_SYM(U, UISC, UGC) and not is_SYM_MOD(U, UISC, UGC) and not is_CGJ(U, UISC, UGC) and not is_Word_Joiner(U, UISC, UGC) @@ -231,6 +242,8 @@ def is_Reserved(U, UISC, UGC): return UGC == 'Cn' def is_REPHA(U, UISC, UGC): return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed] +def is_SAKOT(U, UISC, UGC): + return U == 0x1A60 def is_SYM(U, UISC, UGC): if U == 0x25CC: return False #SPEC-DRAFT #SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter @@ -240,11 +253,11 @@ def is_SYM_MOD(U, UISC, UGC): def is_VARIATION_SELECTOR(U, UISC, UGC): return 0xFE00 <= U <= 0xFE0F def is_VOWEL(U, UISC, UGC): - # https://github.com/roozbehp/unicode-data/issues/6 + # https://github.com/harfbuzz/harfbuzz/issues/376 return (UISC == Pure_Killer or (UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29])) def is_VOWEL_MOD(U, UISC, UGC): - # https://github.com/roozbehp/unicode-data/issues/6 + # https://github.com/harfbuzz/harfbuzz/issues/376 return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or (UGC != Lo and (UISC == Bindu or U in [0xAA29]))) @@ -270,6 +283,7 @@ use_mapping = { 'Rsv': is_Reserved, 'R': is_REPHA, 'S': is_SYM, + 'Sk': is_SAKOT, 'SM': is_SYM_MOD, 'VS': is_VARIATION_SELECTOR, 'V': is_VOWEL, @@ -311,7 +325,11 @@ use_positions = { 'H': None, 'HVM': None, 'B': None, - 'FM': None, + 'FM': { + 'Abv': [Top], + 'Blw': [Bottom], + 'Pst': [Not_Applicable], + }, 'SUB': None, } @@ -350,15 +368,9 @@ def map_to_use(data): # the nasalization marks, maybe only for U+1CE9..U+1CF1. if U == 0x1CED: UISC = Tone_Mark - # TODO: https://github.com/harfbuzz/harfbuzz/issues/525 - if U == 0x1A7F: UISC = Consonant_Final - # TODO: https://github.com/harfbuzz/harfbuzz/issues/1105 if U == 0x11134: UISC = Gemination_Mark - # TODO: https://github.com/harfbuzz/harfbuzz/pull/1399 - if U == 0x111C9: UISC = Consonant_Final - values = [k for k,v in items if v(U,UISC,UGC)] assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values) USE = values[0] diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py index afb21d928..1340d97dc 100755 --- a/src/gen-vowel-constraints.py +++ b/src/gen-vowel-constraints.py @@ -180,6 +180,9 @@ print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB print ('\t\t\t\t hb_buffer_t *buffer,') print ('\t\t\t\t hb_font_t *font HB_UNUSED)') print ('{') +print ('#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)') +print (' return;') +print ('#endif') print (' if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)') print (' return;') print () diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh index 4087b8c1f..ef988841a 100644 --- a/src/hb-aat-layout-ankr-table.hh +++ b/src/hb-aat-layout-ankr-table.hh @@ -83,7 +83,7 @@ struct ankr protected: HBUINT16 version; /* Version number (set to zero) */ HBUINT16 flags; /* Flags (currently unused; set to zero) */ - LOffsetTo > > + LOffsetTo>> lookupTable; /* Offset to the table's lookup table */ LNNOffsetTo anchorData; /* Offset to the glyph data table */ diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 7c74d7938..a8c4b7637 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -125,7 +125,7 @@ struct LookupFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - VarSizedBinSearchArrayOf > + VarSizedBinSearchArrayOf> segments; /* The actual segments. These must already be sorted, * according to the first word in each one (the last * glyph in each segment). */ @@ -154,7 +154,7 @@ struct LookupSegmentArray valuesZ.sanitize (c, base, last - first + 1)); } template - bool sanitize (hb_sanitize_context_t *c, const void *base, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && @@ -164,7 +164,7 @@ struct LookupSegmentArray GlyphID last; /* Last GlyphID in this segment */ GlyphID first; /* First GlyphID in this segment */ - NNOffsetTo > + NNOffsetTo> valuesZ; /* A 16-bit offset from the start of * the table to the data. */ public: @@ -196,7 +196,7 @@ struct LookupFormat4 protected: HBUINT16 format; /* Format identifier--format = 4 */ - VarSizedBinSearchArrayOf > + VarSizedBinSearchArrayOf> segments; /* The actual segments. These must already be sorted, * according to the first word in each one (the last * glyph in each segment). */ @@ -253,7 +253,7 @@ struct LookupFormat6 protected: HBUINT16 format; /* Format identifier--format = 6 */ - VarSizedBinSearchArrayOf > + VarSizedBinSearchArrayOf> entries; /* The actual entries, sorted by glyph index. */ public: DEFINE_SIZE_ARRAY (8, entries); @@ -419,7 +419,7 @@ struct Lookup /* Ugly hand-coded null objects for template Lookup<> :(. */ extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2]; template -struct Null > { +struct Null> { static AAT::Lookup const & get_null () { return *reinterpret_cast *> (_hb_Null_AAT_Lookup); } }; @@ -510,7 +510,7 @@ struct StateTable const Entry &get_entry (int state, unsigned int klass) const { if (unlikely (klass >= nClasses)) - klass = StateTable >::CLASS_OUT_OF_BOUNDS; + klass = StateTable>::CLASS_OUT_OF_BOUNDS; const HBUSHORT *states = (this+stateArrayTable).arrayZ; const Entry *entries = (this+entryTable).arrayZ; @@ -576,7 +576,7 @@ struct StateTable if (unlikely (stop > states)) return_trace (false); for (const HBUSHORT *p = states; stop < p; p--) - num_entries = MAX (num_entries, *(p - 1) + 1); + num_entries = hb_max (num_entries, *(p - 1) + 1); state_neg = min_state; } } @@ -597,7 +597,7 @@ struct StateTable if (unlikely (stop < states)) return_trace (false); for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++) - num_entries = MAX (num_entries, *p + 1); + num_entries = hb_max (num_entries, *p + 1); state_pos = max_state + 1; } } @@ -611,8 +611,8 @@ struct StateTable for (const Entry *p = &entries[entry]; p < stop; p++) { int newState = new_state (p->newState); - min_state = MIN (min_state, newState); - max_state = MAX (max_state, newState); + min_state = hb_min (min_state, newState); + max_state = hb_max (max_state, newState); } entry = num_entries; } @@ -631,7 +631,7 @@ struct StateTable classTable; /* Offset to the class table. */ NNOffsetTo, HBUINT> stateArrayTable;/* Offset to the state array. */ - NNOffsetTo >, HBUINT> + NNOffsetTo>, HBUINT> entryTable; /* Offset to the entry array. */ public: diff --git a/src/hb-aat-layout-feat-table.hh b/src/hb-aat-layout-feat-table.hh index ab23ee056..a20ef8640 100644 --- a/src/hb-aat-layout-feat-table.hh +++ b/src/hb-aat-layout-feat-table.hh @@ -165,7 +165,7 @@ struct feat unsigned int feature_count = featureNameCount; if (count && *count) { - unsigned int len = MIN (feature_count - start_offset, *count); + unsigned int len = hb_min (feature_count - start_offset, *count); for (unsigned int i = 0; i < len; i++) features[i] = namesZ[i + start_offset].get_feature_type (); *count = len; diff --git a/src/hb-aat-layout-just-table.hh b/src/hb-aat-layout-just-table.hh index d53f8f19e..e15c946a2 100644 --- a/src/hb-aat-layout-just-table.hh +++ b/src/hb-aat-layout-just-table.hh @@ -309,7 +309,7 @@ struct WidthDeltaPair public: DEFINE_SIZE_STATIC (24); }; - + typedef OT::LArrayOf WidthDeltaCluster; struct JustificationCategory @@ -371,7 +371,7 @@ struct JustificationHeader * of postcompensation subtable (set to zero if none). * * The postcompensation subtable, if present in the font. */ - Lookup > + Lookup> lookupTable; /* Lookup table associating glyphs with width delta * clusters. See the description of Width Delta Clusters * table for details on how to interpret the lookup values. */ diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index a64c80738..cec63ac6d 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -251,7 +251,7 @@ struct KerxSubTableFormat1 if (Format1EntryT::performAction (entry) && depth) { - unsigned int tuple_count = MAX (1u, table->header.tuple_count ()); + unsigned int tuple_count = hb_max (1u, table->header.tuple_count ()); unsigned int kern_idx = Format1EntryT::kernActionIndex (entry); kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ); @@ -712,18 +712,18 @@ struct KerxSubTableFormat6 { struct Long { - LNNOffsetTo > rowIndexTable; - LNNOffsetTo > columnIndexTable; - LNNOffsetTo > array; + LNNOffsetTo> rowIndexTable; + LNNOffsetTo> columnIndexTable; + LNNOffsetTo> array; } l; struct Short { - LNNOffsetTo > rowIndexTable; - LNNOffsetTo > columnIndexTable; - LNNOffsetTo > array; + LNNOffsetTo> rowIndexTable; + LNNOffsetTo> columnIndexTable; + LNNOffsetTo> array; } s; } u; - LNNOffsetTo > vector; + LNNOffsetTo> vector; public: DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24); }; @@ -771,17 +771,17 @@ struct KerxSubTable unsigned int get_size () const { return u.header.length; } unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case 0: return_trace (c->dispatch (u.format0)); - case 1: return_trace (c->dispatch (u.format1)); - case 2: return_trace (c->dispatch (u.format2)); - case 4: return_trace (c->dispatch (u.format4)); - case 6: return_trace (c->dispatch (u.format6)); + case 0: return_trace (c->dispatch (u.format0, hb_forward (ds)...)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); + case 4: return_trace (c->dispatch (u.format4, hb_forward (ds)...)); + case 6: return_trace (c->dispatch (u.format6, hb_forward (ds)...)); default: return_trace (c->default_return_value ()); } } diff --git a/src/hb-aat-layout-lcar-table.hh b/src/hb-aat-layout-lcar-table.hh index 4be799fbc..cd96d034d 100644 --- a/src/hb-aat-layout-lcar-table.hh +++ b/src/hb-aat-layout-lcar-table.hh @@ -81,7 +81,7 @@ struct lcar protected: FixedVersion<>version; /* Version number of the ligature caret table */ HBUINT16 format; /* Format of the ligature caret table. */ - Lookup > + Lookup> lookup; /* data Lookup table associating glyphs */ public: diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 4a1d959ef..81d78972a 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -88,7 +88,7 @@ struct RearrangementSubtable start = buffer->idx; if (flags & MarkLast) - end = MIN (buffer->idx + 1, buffer->len); + end = hb_min (buffer->idx + 1, buffer->len); if ((flags & Verb) && start < end) { @@ -117,14 +117,14 @@ struct RearrangementSubtable }; unsigned int m = map[flags & Verb]; - unsigned int l = MIN (2, m >> 4); - unsigned int r = MIN (2, m & 0x0F); + unsigned int l = hb_min (2u, m >> 4); + unsigned int r = hb_min (2u, m & 0x0F); bool reverse_l = 3 == (m >> 4); bool reverse_r = 3 == (m & 0x0F); if (end - start >= l + r) { - buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len)); + buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len)); buffer->merge_clusters (start, end); hb_glyph_info_t *info = buffer->info; @@ -261,13 +261,13 @@ struct ContextualSubtable } if (replacement) { - buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len)); + buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); buffer->info[mark].codepoint = *replacement; ret = true; } replacement = nullptr; - unsigned int idx = MIN (buffer->idx, buffer->len - 1); + unsigned int idx = hb_min (buffer->idx, buffer->len - 1); if (Types::extended) { if (entry.data.currentIndex != 0xFFFF) @@ -337,9 +337,9 @@ struct ContextualSubtable const EntryData &data = entries[i].data; if (data.markIndex != 0xFFFF) - num_lookups = MAX (num_lookups, 1 + data.markIndex); + num_lookups = hb_max (num_lookups, 1 + data.markIndex); if (data.currentIndex != 0xFFFF) - num_lookups = MAX (num_lookups, 1 + data.currentIndex); + num_lookups = hb_max (num_lookups, 1 + data.currentIndex); } return_trace (substitutionTables.sanitize (c, this, num_lookups)); @@ -744,7 +744,7 @@ struct InsertionSubtable buffer->move_to (end + count); - buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len)); + buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len)); } if (flags & SetMark) @@ -883,17 +883,17 @@ struct ChainSubtable Insertion = 5 }; - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case Rearrangement: return_trace (c->dispatch (u.rearrangement)); - case Contextual: return_trace (c->dispatch (u.contextual)); - case Ligature: return_trace (c->dispatch (u.ligature)); - case Noncontextual: return_trace (c->dispatch (u.noncontextual)); - case Insertion: return_trace (c->dispatch (u.insertion)); + case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward (ds)...)); + case Contextual: return_trace (c->dispatch (u.contextual, hb_forward (ds)...)); + case Ligature: return_trace (c->dispatch (u.ligature, hb_forward (ds)...)); + case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward (ds)...)); + case Insertion: return_trace (c->dispatch (u.insertion, hb_forward (ds)...)); default: return_trace (c->default_return_value ()); } } @@ -969,7 +969,7 @@ struct Chain void apply (hb_aat_apply_context_t *c, hb_mask_t flags) const { - const ChainSubtable *subtable = &StructAfter > (featureZ.as_array (featureCount)); + const ChainSubtable *subtable = &StructAfter> (featureZ.as_array (featureCount)); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { @@ -1031,7 +1031,7 @@ struct Chain if (unlikely (!c->buffer->successful)) return; skip: - subtable = &StructAfter > (*subtable); + subtable = &StructAfter> (*subtable); c->set_lookup_index (c->lookup_index + 1); } } @@ -1049,13 +1049,13 @@ struct Chain if (!c->check_array (featureZ.arrayZ, featureCount)) return_trace (false); - const ChainSubtable *subtable = &StructAfter > (featureZ.as_array (featureCount)); + const ChainSubtable *subtable = &StructAfter> (featureZ.as_array (featureCount)); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { if (!subtable->sanitize (c)) return_trace (false); - subtable = &StructAfter > (*subtable); + subtable = &StructAfter> (*subtable); } return_trace (true); @@ -1095,7 +1095,7 @@ struct mortmorx for (unsigned int i = 0; i < count; i++) { map->chain_flags.push (chain->compile_flags (mapper)); - chain = &StructAfter > (*chain); + chain = &StructAfter> (*chain); } } @@ -1109,7 +1109,7 @@ struct mortmorx { chain->apply (c, c->plan->aat_map.chain_flags[i]); if (unlikely (!c->buffer->successful)) return; - chain = &StructAfter > (*chain); + chain = &StructAfter> (*chain); } } @@ -1125,7 +1125,7 @@ struct mortmorx { if (!chain->sanitize (c, version)) return_trace (false); - chain = &StructAfter > (*chain); + chain = &StructAfter> (*chain); } return_trace (true); diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 0c8e4558f..2eace2aa0 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -66,7 +66,7 @@ struct TrackTableEntry NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ - NNOffsetTo > + NNOffsetTo> valuesZ; /* Offset from start of tracking table to * per-size tracking values for this track. */ @@ -133,8 +133,8 @@ struct TrackData if (size_table[size_index].to_float () >= csspx) break; - return round (interpolate_at (size_index ? size_index - 1 : 0, csspx, - *trackTableEntry, base)); + return roundf (interpolate_at (size_index ? size_index - 1 : 0, csspx, + *trackTableEntry, base)); } bool sanitize (hb_sanitize_context_t *c, const void *base) const diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 1966ded32..35ba611a9 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -135,11 +135,15 @@ static const hb_aat_feature_mapping_t feature_mappings[] = const hb_aat_feature_mapping_t * hb_aat_layout_find_feature_mapping (hb_tag_t tag) { - return (const hb_aat_feature_mapping_t *) bsearch (&tag, - feature_mappings, - ARRAY_LENGTH (feature_mappings), - sizeof (feature_mappings[0]), - hb_aat_feature_mapping_t::cmp); +#ifdef HB_NO_SHAPE_AAT + return nullptr; +#endif + + return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag, + feature_mappings, + ARRAY_LENGTH (feature_mappings), + sizeof (feature_mappings[0]), + hb_aat_feature_mapping_t::cmp); } @@ -147,6 +151,8 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag) * hb_aat_apply_context_t */ +/* Note: This context is used for kerning, even without AAT. */ + AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_, hb_font_t *font_, hb_buffer_t *buffer_, @@ -183,6 +189,10 @@ void hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, hb_aat_map_t *map) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + const AAT::morx& morx = *mapper->face->table.morx; if (morx.has_data ()) { @@ -209,6 +219,10 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face) { +#ifdef HB_NO_SHAPE_AAT + return false; +#endif + return face->table.morx->has_data () || face->table.mort->has_data (); } @@ -218,6 +232,10 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + hb_blob_t *morx_blob = font->face->table.morx.get_blob (); const AAT::morx& morx = *morx_blob->as (); if (morx.has_data ()) @@ -240,6 +258,10 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, void hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pos = buffer->pos; @@ -257,6 +279,10 @@ is_deleted_glyph (const hb_glyph_info_t *info) void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph); } @@ -270,6 +296,10 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) hb_bool_t hb_aat_layout_has_positioning (hb_face_t *face) { +#ifdef HB_NO_SHAPE_AAT + return false; +#endif + return face->table.kerx->has_data (); } @@ -278,6 +308,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + hb_blob_t *kerx_blob = font->face->table.kerx.get_blob (); const AAT::kerx& kerx = *kerx_blob->as (); @@ -297,6 +331,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, hb_bool_t hb_aat_layout_has_tracking (hb_face_t *face) { +#ifdef HB_NO_SHAPE_AAT + return false; +#endif + return face->table.trak->has_data (); } @@ -305,6 +343,10 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + const AAT::trak& trak = *font->face->table.trak; AAT::hb_aat_apply_context_t c (plan, font, buffer); @@ -328,6 +370,12 @@ hb_aat_layout_get_feature_types (hb_face_t *face, unsigned int *feature_count, /* IN/OUT. May be NULL. */ hb_aat_layout_feature_type_t *features /* OUT. May be NULL. */) { +#ifdef HB_NO_SHAPE_AAT + if (feature_count) + *feature_count = 0; + return 0; +#endif + return face->table.feat->get_feature_types (start_offset, feature_count, features); } @@ -344,6 +392,10 @@ hb_ot_name_id_t hb_aat_layout_feature_type_get_name_id (hb_face_t *face, hb_aat_layout_feature_type_t feature_type) { +#ifdef HB_NO_SHAPE_AAT + return HB_OT_NAME_ID_INVALID; +#endif + return face->table.feat->get_feature_name_id (feature_type); } @@ -372,5 +424,11 @@ hb_aat_layout_feature_type_get_selector_infos (hb_face_t hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */ unsigned int *default_index /* OUT. May be NULL. */) { +#ifdef HB_NO_SHAPE_AAT + if (selector_count) + *selector_count = 0; + return 0; +#endif + return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index); } diff --git a/src/hb-aat-ltag-table.hh b/src/hb-aat-ltag-table.hh index 6f34a0095..711f9aa6c 100644 --- a/src/hb-aat-ltag-table.hh +++ b/src/hb-aat-ltag-table.hh @@ -50,7 +50,7 @@ struct FTStringRange } protected: - NNOffsetTo > + NNOffsetTo> tag; /* Offset from the start of the table to * the beginning of the string */ HBUINT16 length; /* String length (in bytes) */ diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc index 98c5d7fe4..d57ee849d 100644 --- a/src/hb-aat-map.cc +++ b/src/hb-aat-map.cc @@ -34,6 +34,10 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned int value) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + if (tag == HB_TAG ('a','a','l','t')) { feature_info_t *info = features.push(); @@ -53,6 +57,10 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, void hb_aat_map_builder_t::compile (hb_aat_map_t &m) { +#ifdef HB_NO_SHAPE_AAT + return; +#endif + /* Sort features and merge duplicates */ if (features.length) { diff --git a/src/hb-algs.hh b/src/hb-algs.hh index c3467800b..0b34f7106 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -34,26 +34,54 @@ #include "hb-null.hh" +/* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits, + * values will be truncated / overlap, and might not decode exactly. */ +#define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z)) +#define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42)) +#define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu) +#define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu) + + struct { - template T - operator () (const T& v) const { return v; } -} HB_FUNCOBJ (hb_identity); + /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */ + template auto + operator () (T&& v) const HB_AUTO_RETURN ( hb_forward (v) ) +} +HB_FUNCOBJ (hb_identity); +struct +{ + /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */ + template T& + operator () (T& v) const { return v; } + + template hb_remove_reference + operator () (T&& v) const { return v; } +} +HB_FUNCOBJ (hb_lidentity); +struct +{ + /* Like identity(), but always returns rvalue. */ + template hb_remove_reference + operator () (T&& v) const { return v; } +} +HB_FUNCOBJ (hb_ridentity); struct { template bool - operator () (const T& v) const { return bool (v); } -} HB_FUNCOBJ (hb_bool); + operator () (T&& v) const { return bool (hb_forward (v)); } +} +HB_FUNCOBJ (hb_bool); struct { private: template auto - impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref_pointer (v).hash ()) + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) template auto + hb_enable_if (hb_is_integral (T))> auto impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN ( /* Knuth's multiplicative method: */ @@ -64,40 +92,97 @@ struct template auto operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize)) -} HB_FUNCOBJ (hb_hash); +} +HB_FUNCOBJ (hb_hash); + struct { private: /* Pointer-to-member-function. */ - template auto - impl (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN - ((hb_deref_pointer (hb_forward (v1)).*hb_forward (a)) (hb_forward (vs)...)) + template auto + impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN + ((hb_deref (hb_forward (v)).*hb_forward (a)) (hb_forward (ds)...)) /* Pointer-to-member. */ - template auto - impl (Appl&& a, hb_priority<1>, Val &&v) const HB_AUTO_RETURN - ((hb_deref_pointer (hb_forward (v))).*hb_forward (a)) + template auto + impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN + ((hb_deref (hb_forward (v))).*hb_forward (a)) /* Operator(). */ - template auto - impl (Appl&& a, hb_priority<0>, Vals &&...vs) const HB_AUTO_RETURN - (hb_deref_pointer (hb_forward (a)) (hb_forward (vs)...)) + template auto + impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN + (hb_deref (hb_forward (a)) (hb_forward (ds)...)) public: - template auto - impl2 (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN - (hb_deref_pointer (hb_forward (v1)).*hb_forward (a) (hb_forward (vs)...)) - template auto - operator () (Appl&& a, Vals &&...vs) const HB_AUTO_RETURN + template auto + operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN ( impl (hb_forward (a), hb_prioritize, - hb_forward (vs)...) + hb_forward (ds)...) ) -} HB_FUNCOBJ (hb_invoke); +} +HB_FUNCOBJ (hb_invoke); + +template +struct hb_partial_t +{ + hb_partial_t (Appl a, V v) : a (a), v (v) {} + + static_assert (Pos > 0, ""); + + template auto + operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl), + hb_declval (V), + hb_declval (Ts)...)) + { + return hb_invoke (hb_forward (a), + hb_forward (v), + hb_forward (ds)...); + } + template auto + operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl), + hb_declval (T0), + hb_declval (V), + hb_declval (Ts)...)) + { + return hb_invoke (hb_forward (a), + hb_forward (d0), + hb_forward (v), + hb_forward (ds)...); + } + + private: + hb_reference_wrapper a; + V v; +}; +template +auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN +(( hb_partial_t (a, v) )) + +/* The following hacky replacement version is to make Visual Stuiod build:. */ \ +/* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \ +#ifdef _MSC_VER +#define HB_PARTIALIZE(Pos) \ + template \ + decltype(auto) operator () (_T&& _v) const \ + { return hb_partial (this, hb_forward<_T> (_v)); } \ + static_assert (true, "") +#else +#define HB_PARTIALIZE(Pos) \ + template \ + auto operator () (_T&& _v) const HB_AUTO_RETURN \ + (hb_partial (this, hb_forward<_T> (_v))) \ + static_assert (true, "") +#endif + struct { @@ -105,7 +190,7 @@ struct template auto impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN - (hb_deref_pointer (hb_forward (p)).has (v)) + (hb_deref (hb_forward (p)).has (hb_forward (v))) template auto impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN @@ -122,21 +207,56 @@ struct hb_forward (v), hb_prioritize) ) -} HB_FUNCOBJ (hb_has); +} +HB_FUNCOBJ (hb_has); + +struct +{ + private: + + template auto + impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN + ( + hb_has (hb_forward (p), + hb_forward (v)) + ) + + template auto + impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN + ( + hb_forward (p) == hb_forward (v) + ) + + public: + + template auto + operator () (Pred&& p, Val &&v) const HB_RETURN (bool, + impl (hb_forward (p), + hb_forward (v), + hb_prioritize) + ) +} +HB_FUNCOBJ (hb_match); struct { private: + template auto + impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN + (hb_deref (hb_forward (f)).get (hb_forward (v))) + template auto impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN - (hb_deref_pointer (hb_forward (f)).get (hb_forward (v))) + ( + hb_invoke (hb_forward (f), + hb_forward (v)) + ) template auto impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_invoke (hb_forward (f), - hb_forward (v)) + hb_forward (f)[hb_forward (v)] ) public: @@ -148,7 +268,8 @@ struct hb_forward (v), hb_prioritize) ) -} HB_FUNCOBJ (hb_get); +} +HB_FUNCOBJ (hb_get); template @@ -159,38 +280,61 @@ struct hb_pair_t typedef hb_pair_t pair_t; hb_pair_t (T1 a, T2 b) : first (a), second (b) {} - hb_pair_t (const pair_t& o) : first (o.first), second (o.second) {} + + template + operator hb_pair_t () { return hb_pair_t (first, second); } + + hb_pair_t reverse () const + { return hb_pair_t (second, first); } bool operator == (const pair_t& o) const { return first == o.first && second == o.second; } + bool operator != (const pair_t& o) const { return !(*this == o); } + bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); } + bool operator >= (const pair_t& o) const { return !(*this < o); } + bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); } + bool operator <= (const pair_t& o) const { return !(*this > o); } T1 first; T2 second; }; +#define hb_pair_t(T1,T2) hb_pair_t template static inline hb_pair_t hb_pair (T1&& a, T2&& b) { return hb_pair_t (a, b); } struct { - template auto - operator () (const Pair& pair) const HB_AUTO_RETURN (pair.first) -} HB_FUNCOBJ (hb_first); + template typename Pair::first_t + operator () (const Pair& pair) const { return pair.first; } +} +HB_FUNCOBJ (hb_first); struct { - template auto - operator () (const Pair& pair) const HB_AUTO_RETURN (pair.second) -} HB_FUNCOBJ (hb_second); + template typename Pair::second_t + operator () (const Pair& pair) const { return pair.second; } +} +HB_FUNCOBJ (hb_second); +/* Note. In min/max impl, we can use hb_type_identity for second argument. + * However, that would silently convert between different-signedness integers. + * Instead we accept two different types, such that compiler can err if + * comparing integers of different signedness. */ struct { template auto - operator () (const T& a, const T2& b) const HB_AUTO_RETURN (a <= b ? a : b) -} HB_FUNCOBJ (hb_min); + operator () (T&& a, T2&& b) const HB_AUTO_RETURN + (hb_forward (a) <= hb_forward (b) ? hb_forward (a) : hb_forward (b)) +} +HB_FUNCOBJ (hb_min); struct { template auto - operator () (const T& a, const T2& b) const HB_AUTO_RETURN (a >= b ? a : b) -} HB_FUNCOBJ (hb_max); + operator () (T&& a, T2&& b) const HB_AUTO_RETURN + (hb_forward (a) >= hb_forward (b) ? hb_forward (a) : hb_forward (b)) +} +HB_FUNCOBJ (hb_max); /* @@ -402,14 +546,6 @@ static inline unsigned char TOUPPER (unsigned char c) static inline unsigned char TOLOWER (unsigned char c) { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } -#undef MIN -template -static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } - -#undef MAX -template -static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; } - static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b) { return (a + (b - 1)) / b; } @@ -467,40 +603,19 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) /* * Sort and search. */ - +template static inline void * hb_bsearch (const void *key, const void *base, size_t nmemb, size_t size, - int (*compar)(const void *_key, const void *_item)) -{ - int min = 0, max = (int) nmemb - 1; - while (min <= max) - { - int mid = (min + max) / 2; - const void *p = (const void *) (((const char *) base) + (mid * size)); - int c = compar (key, p); - if (c < 0) - max = mid - 1; - else if (c > 0) - min = mid + 1; - else - return (void *) p; - } - return nullptr; -} - -static inline void * -hb_bsearch_r (const void *key, const void *base, - size_t nmemb, size_t size, - int (*compar)(const void *_key, const void *_item, void *_arg), - void *arg) + int (*compar)(const void *_key, const void *_item, Ts... _ds), + Ts... ds) { int min = 0, max = (int) nmemb - 1; while (min <= max) { int mid = ((unsigned int) min + (unsigned int) max) / 2; const void *p = (const void *) (((const char *) base) + (mid * size)); - int c = compar (key, p, arg); + int c = compar (key, p, ds...); if (c < 0) max = mid - 1; else if (c > 0) @@ -661,7 +776,7 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o { /* Pain because we don't know whether s is nul-terminated. */ char buf[64]; - len = MIN (ARRAY_LENGTH (buf) - 1, len); + len = hb_min (ARRAY_LENGTH (buf) - 1, len); strncpy (buf, s, len); buf[len] = '\0'; @@ -675,30 +790,83 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } -struct HbOpOr -{ - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = true; - template static void process (T &o, const T &a, const T &b) { o = a | b; } -}; -struct HbOpAnd -{ +/* Operators. */ + +struct hb_bitwise_and +{ HB_PARTIALIZE(2); static constexpr bool passthru_left = false; static constexpr bool passthru_right = false; - template static void process (T &o, const T &a, const T &b) { o = a & b; } -}; -struct HbOpMinus -{ - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = false; - template static void process (T &o, const T &a, const T &b) { o = a & ~b; } -}; -struct HbOpXor -{ + template auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) +} +HB_FUNCOBJ (hb_bitwise_and); +struct hb_bitwise_or +{ HB_PARTIALIZE(2); static constexpr bool passthru_left = true; static constexpr bool passthru_right = true; - template static void process (T &o, const T &a, const T &b) { o = a ^ b; } -}; + template auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) +} +HB_FUNCOBJ (hb_bitwise_or); +struct hb_bitwise_xor +{ HB_PARTIALIZE(2); + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = true; + template auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) +} +HB_FUNCOBJ (hb_bitwise_xor); +struct hb_bitwise_sub +{ HB_PARTIALIZE(2); + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = false; + template auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) +} +HB_FUNCOBJ (hb_bitwise_sub); + +struct +{ HB_PARTIALIZE(2); + template auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b) +} +HB_FUNCOBJ (hb_add); +struct +{ HB_PARTIALIZE(2); + template auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b) +} +HB_FUNCOBJ (hb_sub); +struct +{ HB_PARTIALIZE(2); + template auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b) +} +HB_FUNCOBJ (hb_mul); +struct +{ HB_PARTIALIZE(2); + template auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b) +} +HB_FUNCOBJ (hb_div); +struct +{ HB_PARTIALIZE(2); + template auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b) +} +HB_FUNCOBJ (hb_mod); +struct +{ + template auto + operator () (const T &a) const HB_AUTO_RETURN (+a) +} +HB_FUNCOBJ (hb_pos); +struct +{ + template auto + operator () (const T &a) const HB_AUTO_RETURN (-a) +} +HB_FUNCOBJ (hb_neg); /* Compiler-assisted vectorization. */ @@ -714,26 +882,26 @@ struct hb_vector_size_t void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); } - template - hb_vector_size_t process (const hb_vector_size_t &o) const + template + hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const { hb_vector_size_t r; #if HB_VECTOR_SIZE if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) - Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]); + r.u.vec[i] = op (u.vec[i], o.u.vec[i]); else #endif for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) - Op::process (r.u.v[i], u.v[i], o.u.v[i]); + r.u.v[i] = op (u.v[i], o.u.v[i]); return r; } hb_vector_size_t operator | (const hb_vector_size_t &o) const - { return process (o); } + { return process (hb_bitwise_or, o); } hb_vector_size_t operator & (const hb_vector_size_t &o) const - { return process (o); } + { return process (hb_bitwise_and, o); } hb_vector_size_t operator ^ (const hb_vector_size_t &o) const - { return process (o); } + { return process (hb_bitwise_xor, o); } hb_vector_size_t operator ~ () const { hb_vector_size_t r; diff --git a/src/hb-array.hh b/src/hb-array.hh index b4619ee9a..587000cd4 100644 --- a/src/hb-array.hh +++ b/src/hb-array.hh @@ -42,19 +42,20 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> /* * Constructors. */ - hb_array_t () : arrayZ (nullptr), length (0) {} - hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {} - template hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {} + hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {} + hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {} + template + hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {} template + hb_enable_if (hb_is_cr_convertible(U, Type))> hb_array_t (const hb_array_t &o) : hb_iter_with_fallback_t, Type&> (), - arrayZ (o.arrayZ), length (o.length) {} + arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {} template + hb_enable_if (hb_is_cr_convertible(U, Type))> hb_array_t& operator = (const hb_array_t &o) - { arrayZ = o.arrayZ; length = o.length; return *this; } + { arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; } /* * Iterator implementation. @@ -71,15 +72,25 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> if (unlikely (n > length)) n = length; length -= n; + backwards_length += n; arrayZ += n; } void __rewind__ (unsigned n) { - if (unlikely (n > length)) - n = length; - length -= n; + if (unlikely (n > backwards_length)) + n = backwards_length; + length += n; + backwards_length -= n; + arrayZ -= n; } unsigned __len__ () const { return length; } + /* Ouch. The operator== compares the contents of the array. For range-based for loops, + * it's best if we can just compare arrayZ, though comparing contents is still fast, + * but also would require that Type has operator==. As such, we optimize this operator + * for range-based for loop and just compare arrayZ. No need to compare length, as we + * assume we're only compared to .end(). */ + bool operator != (const hb_array_t& o) const + { return arrayZ != o.arrayZ; } /* Extra operators. */ @@ -141,7 +152,7 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> } void qsort (unsigned int start, unsigned int end) { - end = MIN (end, length); + end = hb_min (end, length); assert (start <= end); if (likely (start < end)) ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp); @@ -164,7 +175,7 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> else count -= start_offset; if (seg_count) - count = *seg_count = MIN (count, *seg_count); + count = *seg_count = hb_min (count, *seg_count); return hb_array_t (arrayZ + start_offset, count); } hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const @@ -174,6 +185,17 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> void free () { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; } + template + hb_array_t copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto* out = c->start_embed (arrayZ); + if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ()); + for (unsigned i = 0; i < length; i++) + out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */ + return_trace (hb_array_t (out, length)); + } + template bool sanitize (hb_sanitize_context_t *c) const { return c->check_array (arrayZ, length); } @@ -185,6 +207,7 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> public: Type *arrayZ; unsigned int length; + unsigned int backwards_length; }; template inline hb_array_t hb_array (T *array, unsigned int length) @@ -212,18 +235,23 @@ struct hb_sorted_array_t : hb_sorted_array_t () : hb_array_t () {} hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {} - template hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {} + template + hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {} template + hb_enable_if (hb_is_cr_convertible(U, Type))> hb_sorted_array_t (const hb_array_t &o) : hb_iter_t, Type&> (), hb_array_t (o) {} template + hb_enable_if (hb_is_cr_convertible(U, Type))> hb_sorted_array_t& operator = (const hb_array_t &o) { hb_array_t (*this) = o; return *this; } + /* Iterator implementation. */ + bool operator != (const hb_sorted_array_t& o) const + { return this->arrayZ != o.arrayZ || this->length != o.length; } + hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const { return hb_sorted_array_t (((const hb_array_t *) (this))->sub_array (start_offset, seg_count)); } hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const @@ -296,7 +324,7 @@ bool hb_array_t::operator == (const hb_array_t &o) const { return length == o.length && + hb_zip (*this, o) - | hb_map ([] (hb_pair_t &&_) -> bool { return _.first == _.second; }) + | hb_map ([] (hb_pair_t &&_) { return _.first == _.second; }) | hb_all ; } @@ -306,7 +334,7 @@ uint32_t hb_array_t::hash () const return + hb_iter (*this) | hb_map (hb_hash) - | hb_reduce ([] (uint32_t a, uint32_t b) -> uint32_t { return a * 31 + b; }, 0) + | hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0) ; } diff --git a/src/hb-atomic.hh b/src/hb-atomic.hh index 8307a549d..45413d5e7 100644 --- a/src/hb-atomic.hh +++ b/src/hb-atomic.hh @@ -107,7 +107,7 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) static inline void _hb_memory_barrier () { -#if !defined(MemoryBarrier) +#ifndef MemoryBarrier /* MinGW has a convoluted history of supporting MemoryBarrier. */ LONG dummy = 0; InterlockedExchange (&dummy, 1); @@ -216,7 +216,7 @@ static_assert ((sizeof (long) == sizeof (void *)), ""); #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ -#define _hb_memory_barrier() +#define _hb_memory_barrier() do {} while (0) #define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) @@ -227,7 +227,7 @@ static_assert ((sizeof (long) == sizeof (void *)), ""); #define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) -#define _hb_memory_barrier() +#define _hb_memory_barrier() do {} while (0) #define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 54637c727..5783fb294 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -30,7 +30,7 @@ * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */ -#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) +#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-macros" #define _POSIX_C_SOURCE 200809L @@ -155,7 +155,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent, hb_blob_make_immutable (parent); blob = hb_blob_create (parent->data + offset, - MIN (length, parent->length - offset), + hb_min (length, parent->length - offset), HB_MEMORY_MODE_READONLY, hb_blob_reference (parent), _hb_blob_destroy); diff --git a/src/hb-blob.h b/src/hb-blob.h index d1d9134ac..f80e9af2d 100644 --- a/src/hb-blob.h +++ b/src/hb-blob.h @@ -71,6 +71,9 @@ hb_blob_create (const char *data, void *user_data, hb_destroy_func_t destroy); +HB_EXTERN hb_blob_t * +hb_blob_create_from_file (const char *file_name); + /* Always creates with MEMORY_MODE_READONLY. * Even if the parent blob is writable, we don't * want the user of the sub-blob to be able to @@ -123,9 +126,6 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length); HB_EXTERN char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length); -HB_EXTERN hb_blob_t * -hb_blob_create_from_file (const char *file_name); - HB_END_DECLS #endif /* HB_BLOB_H */ diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc index 6e265e84c..d3732fd02 100644 --- a/src/hb-buffer-serialize.cc +++ b/src/hb-buffer-serialize.cc @@ -28,8 +28,10 @@ static const char *serialize_formats[] = { +#ifndef HB_NO_BUFFER_SERIALIZE "text", "json", +#endif nullptr }; @@ -85,10 +87,12 @@ hb_buffer_serialize_format_from_string (const char *str, int len) const char * hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) { - switch (format) + switch ((unsigned) format) { +#ifndef HB_NO_BUFFER_SERIALIZE case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; +#endif default: case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr; } @@ -138,34 +142,34 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, *p++ = '"'; } else - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster)); } if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) { - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", x+pos[i].x_offset, y+pos[i].y_offset)); if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES)) - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", pos[i].x_advance, pos[i].y_advance)); } if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) { if (info[i].mask & HB_GLYPH_FLAG_DEFINED) - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED)); } if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; hb_font_get_glyph_extents(font, info[i].codepoint, &extents); - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", extents.x_bearing, extents.y_bearing)); - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", extents.width, extents.height)); } @@ -224,37 +228,37 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, p += strlen (p); } else - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster)); } if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) { if (x+pos[i].x_offset || y+pos[i].y_offset) - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset)); if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES)) { *p++ = '+'; - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); if (pos[i].y_advance) - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } } if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) { if (info[i].mask & HB_GLYPH_FLAG_DEFINED) - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED)); } if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; hb_font_get_glyph_extents(font, info[i].codepoint, &extents); - p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); } unsigned int l = p - b; @@ -344,6 +348,10 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, if (buf_size) *buf = '\0'; +#ifdef HB_NO_BUFFER_SERIALIZE + return 0; +#endif + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); @@ -380,7 +388,7 @@ static hb_bool_t parse_uint (const char *pp, const char *end, uint32_t *pv) { char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); + unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); strncpy (buf, pp, len); buf[len] = '\0'; @@ -401,7 +409,7 @@ static hb_bool_t parse_int (const char *pp, const char *end, int32_t *pv) { char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); + unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); strncpy (buf, pp, len); buf[len] = '\0'; @@ -449,6 +457,10 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, end_ptr = &end; *end_ptr = buf; +#ifdef HB_NO_BUFFER_SERIALIZE + return false; +#endif + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 2dc02e9d6..bbbbd227c 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -524,7 +524,7 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int cluster = info[start].cluster; for (unsigned int i = start + 1; i < end; i++) - cluster = MIN (cluster, info[i].cluster); + cluster = hb_min (cluster, info[i].cluster); /* Extend end */ while (end < len && info[end - 1].cluster == info[end].cluster) @@ -555,7 +555,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start, unsigned int cluster = out_info[start].cluster; for (unsigned int i = start + 1; i < end; i++) - cluster = MIN (cluster, out_info[i].cluster); + cluster = hb_min (cluster, out_info[i].cluster); /* Extend start */ while (start && out_info[start - 1].cluster == out_info[start].cluster) @@ -2026,7 +2026,10 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, bool hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) { +#ifdef HB_NO_BUFFER_MESSAGE + return false; +#endif char buf[100]; - vsnprintf (buf, sizeof (buf), fmt, ap); + vsnprintf (buf, sizeof (buf), fmt, ap); return (bool) this->message_func (this, font, buf, this->message_data); } diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 330f88bac..b2b190ace 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -379,7 +379,7 @@ struct hb_buffer_t unsigned int cluster) const { for (unsigned int i = start; i < end; i++) - cluster = MIN (cluster, infos[i].cluster); + cluster = hb_min (cluster, infos[i].cluster); return cluster; } void diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh index 283bdf14a..61bdba5f5 100644 --- a/src/hb-cff-interp-cs-common.hh +++ b/src/hb-cff-interp-cs-common.hh @@ -147,8 +147,9 @@ struct cs_interp_env_t : interp_env_t return callStack.in_error () || SUPER::in_error (); } - bool popSubrNum (const biased_subrs_t& biasedSubrs, unsigned int &subr_num) + bool pop_subr_num (const biased_subrs_t& biasedSubrs, unsigned int &subr_num) { + subr_num = 0; int n = SUPER::argStack.pop_int (); n += biasedSubrs.get_bias (); if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ()))) @@ -158,11 +159,11 @@ struct cs_interp_env_t : interp_env_t return true; } - void callSubr (const biased_subrs_t& biasedSubrs, cs_type_t type) + void call_subr (const biased_subrs_t& biasedSubrs, cs_type_t type) { - unsigned int subr_num; + unsigned int subr_num = 0; - if (unlikely (!popSubrNum (biasedSubrs, subr_num) + if (unlikely (!pop_subr_num (biasedSubrs, subr_num) || callStack.get_count () >= kMaxCallLimit)) { SUPER::set_error (); @@ -175,7 +176,7 @@ struct cs_interp_env_t : interp_env_t SUPER::str_ref = context.str_ref; } - void returnFromSubr () + void return_from_subr () { if (unlikely (SUPER::str_ref.in_error ())) SUPER::set_error (); @@ -246,7 +247,7 @@ struct path_procs_null_t static void flex1 (ENV &env, PARAM& param) {} }; -template > +template > struct cs_opset_t : opset_t { static void process_op (op_code_t op, ENV &env, PARAM& param) @@ -254,7 +255,7 @@ struct cs_opset_t : opset_t switch (op) { case OpCode_return: - env.returnFromSubr (); + env.return_from_subr (); break; case OpCode_endchar: OPSET::check_width (op, env, param); @@ -267,11 +268,11 @@ struct cs_opset_t : opset_t break; case OpCode_callsubr: - env.callSubr (env.localSubrs, CSType_LocalSubr); + env.call_subr (env.localSubrs, CSType_LocalSubr); break; case OpCode_callgsubr: - env.callSubr (env.globalSubrs, CSType_GlobalSubr); + env.call_subr (env.globalSubrs, CSType_GlobalSubr); break; case OpCode_hstem: diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh index c7209ed80..cc528564c 100644 --- a/src/hb-cff1-interp-cs.hh +++ b/src/hb-cff1-interp-cs.hh @@ -81,7 +81,7 @@ struct cff1_cs_interp_env_t : cs_interp_env_t typedef cs_interp_env_t SUPER; }; -template > +template > struct cff1_cs_opset_t : cs_opset_t { /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */ diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh index 49e5ee739..1faf20831 100644 --- a/src/hb-cff2-interp-cs.hh +++ b/src/hb-cff2-interp-cs.hh @@ -193,7 +193,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t typedef cs_interp_env_t SUPER; }; -template > +template > struct cff2_cs_opset_t : cs_opset_t { static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param) diff --git a/src/hb-common.cc b/src/hb-common.cc index c453443e7..71791dba1 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -67,7 +67,7 @@ _hb_options_init () p = c + strlen (c); #define OPTION(name, symbol) \ - if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true; + if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) do { u.opts.symbol = true; } while (0) OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible); OPTION ("aat", aat); @@ -356,7 +356,7 @@ hb_language_from_string (const char *str, int len) { /* NUL-terminate it. */ char strbuf[64]; - len = MIN (len, (int) sizeof (strbuf) - 1); + len = hb_min (len, (int) sizeof (strbuf) - 1); memcpy (strbuf, str, len); strbuf[len] = '\0'; item = lang_find_or_insert (strbuf); @@ -720,7 +720,7 @@ static bool parse_uint (const char **pp, const char *end, unsigned int *pv) { char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); strncpy (buf, *pp, len); buf[len] = '\0'; @@ -744,7 +744,7 @@ static bool parse_uint32 (const char **pp, const char *end, uint32_t *pv) { char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); strncpy (buf, *pp, len); buf[len] = '\0'; @@ -825,7 +825,7 @@ static bool parse_float (const char **pp, const char *end, float *pv) { char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); strncpy (buf, *pp, len); buf[len] = '\0'; @@ -1071,21 +1071,21 @@ hb_feature_to_string (hb_feature_t *feature, { s[len++] = '['; if (feature->start) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); + len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); if (feature->end != feature->start + 1) { s[len++] = ':'; if (feature->end != (unsigned int) -1) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); + len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); } s[len++] = ']'; } if (feature->value > 1) { s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); + len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); } assert (len < ARRAY_LENGTH (s)); - len = MIN (len, size - 1); + len = hb_min (len, size - 1); memcpy (buf, s, len); buf[len] = '\0'; } @@ -1152,20 +1152,21 @@ hb_variation_to_string (hb_variation_t *variation, while (len && s[len - 1] == ' ') len--; s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value)); + len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value)); assert (len < ARRAY_LENGTH (s)); - len = MIN (len, size - 1); + len = hb_min (len, size - 1); memcpy (buf, s, len); buf[len] = '\0'; } /** * hb_color_get_alpha: + * color: a #hb_color_t we are interested in its channels. * + * Return value: Alpha channel value of the given color * - * - * Since: REPLACEME + * Since: 2.1.0 */ uint8_t (hb_color_get_alpha) (hb_color_t color) @@ -1175,10 +1176,11 @@ uint8_t /** * hb_color_get_red: + * color: a #hb_color_t we are interested in its channels. * + * Return value: Red channel value of the given color * - * - * Since: REPLACEME + * Since: 2.1.0 */ uint8_t (hb_color_get_red) (hb_color_t color) @@ -1188,10 +1190,11 @@ uint8_t /** * hb_color_get_green: + * color: a #hb_color_t we are interested in its channels. * + * Return value: Green channel value of the given color * - * - * Since: REPLACEME + * Since: 2.1.0 */ uint8_t (hb_color_get_green) (hb_color_t color) @@ -1201,10 +1204,11 @@ uint8_t /** * hb_color_get_blue: + * color: a #hb_color_t we are interested in its channels. * + * Return value: Blue channel value of the given color * - * - * Since: REPLACEME + * Since: 2.1.0 */ uint8_t (hb_color_get_blue) (hb_color_t color) diff --git a/src/hb-config.hh b/src/hb-config.hh new file mode 100644 index 000000000..8bdce3598 --- /dev/null +++ b/src/hb-config.hh @@ -0,0 +1,131 @@ +/* + * Copyright © 2019 Facebook, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Facebook Author(s): Behdad Esfahbod + */ + +#ifndef HB_CONFIG_HH +#define HB_CONFIG_HH + +#if 0 /* Make test happy. */ +#include "hb.hh" +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#ifdef HB_TINY +#define HB_LEAN +#define HB_MINI +#define HB_NO_MT +#ifndef NDEBUG +#define NDEBUG +#endif +#ifndef __OPTIMIZE_SIZE__ +#define __OPTIMIZE_SIZE__ +#endif +#endif + +#ifdef HB_LEAN +#define HB_DISABLE_DEPRECATED +#define HB_NDEBUG +#define HB_NO_ATEXIT +#define HB_NO_BUFFER_MESSAGE +#define HB_NO_BUFFER_SERIALIZE +#define HB_NO_BITMAP +#define HB_NO_CFF +#define HB_NO_COLOR +#define HB_NO_GETENV +#define HB_NO_LAYOUT_UNUSED +#define HB_NO_MATH +#define HB_NO_NAME +#define HB_NO_SUBSET_LAYOUT +#endif + +#ifdef HB_MINI +#define HB_NO_AAT +#define HB_NO_LEGACY +#endif + +/* Closure. */ + +#ifdef HB_DISABLE_DEPRECATED +#define HB_IF_NOT_DEPRECATED(x) +#else +#define HB_IF_NOT_DEPRECATED(x) x +#endif + +#ifdef HB_NO_AAT +#define HB_NO_OT_NAME_LANGUAGE_AAT +#define HB_NO_SHAPE_AAT +#endif + +#ifdef HB_NO_BITMAP +#define HB_NO_OT_FONT_BITMAP +#endif + +#ifdef HB_NO_CFF +#define HB_NO_OT_FONT_CFF +#define HB_NO_SUBSET_CFF +#endif + +#ifdef HB_NO_GETENV +#define HB_NO_UNISCRIBE_BUG_COMPATIBLE +#endif + +#ifdef HB_NO_LEGACY +#define HB_NO_OT_LAYOUT_BLACKLIST +#define HB_NO_OT_SHAPE_FALLBACK +#endif + +#ifdef HB_NO_NAME +#define HB_NO_OT_NAME_LANGUAGE +#endif + +#ifdef HB_NO_OT_SHAPE_FALLBACK +#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK +#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK +#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK +#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS +#endif + +#ifdef NDEBUG +#ifndef HB_NDEBUG +#define HB_NDEBUG +#endif +#endif + +#ifdef __OPTIMIZE_SIZE__ +#ifndef HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE +#endif +#endif + +#ifdef HAVE_CONFIG_OVERRIDE_H +#include "config-override.h" +#endif + + +#endif /* HB_CONFIG_HH */ diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 66f0fce1a..85993d196 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -55,13 +55,13 @@ coretext_font_size_from_ptem (float ptem) * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html */ ptem *= 96.f / 72.f; - return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem; + return (CGFloat) (ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem); } static float coretext_font_size_to_ptem (CGFloat size) { - size *= 72.f / 96.f; - return size <= 0.f ? 0 : size; + size *= 72. / 96.; + return size <= 0 ? 0 : size; } static void @@ -598,7 +598,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } else { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ ()); + active_features.remove (feature - active_features.arrayZ); } } } @@ -608,7 +608,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, #define ALLOCATE_ARRAY(Type, name, len, on_no_room) \ Type *name = (Type *) scratch; \ - { \ + do { \ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ if (unlikely (_consumed > scratch_size)) \ { \ @@ -617,7 +617,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } \ scratch += _consumed; \ scratch_size -= _consumed; \ - } + } while (0) ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/); unsigned int chars_len = 0; @@ -771,7 +771,7 @@ resize_and_retry: feature.start < chars_len && feature.start < feature.end) { CFRange feature_range = CFRangeMake (feature.start, - MIN (feature.end, chars_len) - feature.start); + hb_min (feature.end, chars_len) - feature.start); if (feature.value) CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName); else @@ -1116,7 +1116,7 @@ resize_and_retry: unsigned int cluster = info[count - 1].cluster; for (unsigned int i = count - 1; i > 0; i--) { - cluster = MIN (cluster, info[i - 1].cluster); + cluster = hb_min (cluster, info[i - 1].cluster); info[i - 1].cluster = cluster; } } @@ -1125,7 +1125,7 @@ resize_and_retry: unsigned int cluster = info[0].cluster; for (unsigned int i = 1; i < count; i++) { - cluster = MIN (cluster, info[i].cluster); + cluster = hb_min (cluster, info[i].cluster); info[i].cluster = cluster; } } diff --git a/src/hb-debug.hh b/src/hb-debug.hh index 52d5942c6..e6d06e310 100644 --- a/src/hb-debug.hh +++ b/src/hb-debug.hh @@ -63,7 +63,7 @@ extern HB_INTERNAL hb_atomic_int_t _hb_options; static inline hb_options_t hb_options () { -#if defined(HB_NO_OPTIONS) +#ifdef HB_NO_GETENV return hb_options_t (); #endif /* Make a local copy, so we can access bitfield threadsafely. */ @@ -161,7 +161,7 @@ _hb_debug_msg_va (const char *what, VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; fprintf (stderr, "%2u %s" VRBAR "%s", level, - bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level), + bars + sizeof (bars) - 1 - hb_min ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level), level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); } else fprintf (stderr, " " VRBAR LBAR); @@ -249,8 +249,8 @@ struct hb_printer_t { }; template <> -struct hb_printer_t { - const char *print (hb_void_t) { return ""; } +struct hb_printer_t { + const char *print (hb_empty_t) { return ""; } }; @@ -266,7 +266,7 @@ static inline void _hb_warn_no_return (bool returned) } } template <> -/*static*/ inline void _hb_warn_no_return (bool returned HB_UNUSED) +/*static*/ inline void _hb_warn_no_return (bool returned HB_UNUSED) {} template @@ -330,18 +330,20 @@ struct hb_auto_trace_t<0, ret_t> const char *message, ...) HB_PRINTF_FUNC(6, 7) {} - ret_t ret (ret_t v, - const char *func HB_UNUSED = nullptr, - unsigned int line HB_UNUSED = 0) { return v; } + template + T ret (T&& v, + const char *func HB_UNUSED = nullptr, + unsigned int line HB_UNUSED = 0) { return hb_forward (v); } }; /* For disabled tracing; optimize out everything. * https://github.com/harfbuzz/harfbuzz/pull/605 */ template struct hb_no_trace_t { - ret_t ret (ret_t v, - const char *func HB_UNUSED = "", - unsigned int line HB_UNUSED = 0) { return v; } + template + T ret (T&& v, + const char *func HB_UNUSED = nullptr, + unsigned int line HB_UNUSED = 0) { return hb_forward (v); } }; #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__) diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h index 4a5e702ff..026a62c74 100644 --- a/src/hb-deprecated.h +++ b/src/hb-deprecated.h @@ -63,7 +63,7 @@ typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t *glyph, void *user_data); -HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void +HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func and hb_font_funcs_set_variation_glyph_func) void hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index d8076c922..b135c49e9 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -530,12 +530,12 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); #define ALLOCATE_ARRAY(Type, name, len) \ Type *name = (Type *) scratch; \ - { \ + do { \ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ assert (_consumed <= scratch_size); \ scratch += _consumed; \ scratch_size -= _consumed; \ - } + } while (0) #define utf16_index() var1.u32 @@ -778,7 +778,7 @@ retry_getglyphs: { uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index ()]]; - *p = MIN (*p, buffer->info[i].cluster); + *p = hb_min (*p, buffer->info[i].cluster); } for (unsigned int i = 1; i < glyphCount; i++) if (vis_clusters[i] == (uint32_t) -1) @@ -930,7 +930,9 @@ _hb_directwrite_font_release (void *data) /** * hb_directwrite_face_create: - * @font_face: + * @font_face: a DirectWrite IDWriteFontFace object. + * + * Return value: #hb_face_t object corresponding to the given input * * Since: 2.4.0 **/ @@ -945,9 +947,11 @@ hb_directwrite_face_create (IDWriteFontFace *font_face) /** * hb_directwrite_face_get_font_face: -* @face: +* @face: a #hb_face_t object * -* Since: REPLACEME +* Return value: DirectWrite IDWriteFontFace object corresponding to the given input +* +* Since: 2.5.0 **/ IDWriteFontFace * hb_directwrite_face_get_font_face (hb_face_t *face) diff --git a/src/hb-dispatch.hh b/src/hb-dispatch.hh index c4347a6ca..be4a90f4f 100644 --- a/src/hb-dispatch.hh +++ b/src/hb-dispatch.hh @@ -38,10 +38,18 @@ template struct hb_dispatch_context_t { + private: + /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ + const Context* thiz () const { return static_cast (this); } + Context* thiz () { return static_cast< Context *> (this); } + public: static constexpr unsigned max_debug_depth = MaxDebugDepth; typedef Return return_t; template bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; } + template + return_t dispatch (const T &obj, Ts&&... ds) + { return obj.dispatch (thiz (), hb_forward (ds)...); } static return_t no_dispatch_return_value () { return Context::default_return_value (); } static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; } }; diff --git a/src/hb-font.cc b/src/hb-font.cc index 20daefd27..19ee353eb 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -336,6 +336,7 @@ hb_font_get_glyph_v_origin_default (hb_font_t *font, return ret; } +#ifndef HB_DISABLE_DEPRECATED static hb_position_t hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, @@ -373,6 +374,7 @@ hb_font_get_glyph_v_kerning_default (hb_font_t *font, { return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); } +#endif static hb_bool_t hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, @@ -925,6 +927,7 @@ hb_font_get_glyph_v_origin (hb_font_t *font, return font->get_glyph_v_origin (glyph, x, y); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_h_kerning: * @font: a font. @@ -964,6 +967,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font, { return font->get_glyph_v_kerning (top_glyph, bottom_glyph); } +#endif /** * hb_font_get_glyph_extents: @@ -1173,6 +1177,7 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, return font->subtract_glyph_origin_for_direction (glyph, direction, x, y); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_kerning_for_direction: * @font: a font. @@ -1195,6 +1200,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font, { return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y); } +#endif /** * hb_font_get_glyph_extents_for_origin: @@ -1347,7 +1353,7 @@ hb_font_create (hb_face_t *face) { hb_font_t *font = _hb_font_create (face); -#if !defined(HB_NO_OT_FONT) +#ifndef HB_NO_OT_FONT /* Install our in-house, very lightweight, funcs. */ hb_ot_font_set_funcs (font); #endif @@ -1916,6 +1922,7 @@ hb_font_get_var_coords_normalized (hb_font_t *font, } +#ifndef HB_DISABLE_DEPRECATED /* * Deprecated get_glyph_func(): */ @@ -2038,3 +2045,4 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, trampoline, trampoline_destroy); } +#endif diff --git a/src/hb-font.hh b/src/hb-font.hh index aaa0fd91c..95551bfd2 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -51,8 +51,8 @@ HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ - HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ - HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ + HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning)) \ + HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \ HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ HB_FONT_FUNC_IMPLEMENT (glyph_name) \ @@ -304,17 +304,25 @@ struct hb_font_t hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) { +#ifdef HB_DISABLE_DEPRECATED + return 0; +#else return klass->get.f.glyph_h_kerning (this, user_data, left_glyph, right_glyph, klass->user_data.glyph_h_kerning); +#endif } hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) { +#ifdef HB_DISABLE_DEPRECATED + return 0; +#else return klass->get.f.glyph_v_kerning (this, user_data, top_glyph, bottom_glyph, klass->user_data.glyph_v_kerning); +#endif } hb_bool_t get_glyph_extents (hb_codepoint_t glyph, @@ -607,7 +615,7 @@ struct hb_font_t return (hb_position_t) (scaled / upem); } hb_position_t em_scalef (float v, int scale) - { return (hb_position_t) round (v * scale / face->get_upem ()); } + { return (hb_position_t) roundf (v * scale / face->get_upem ()); } float em_fscale (int16_t v, int scale) { return (float) v * scale / face->get_upem (); } }; diff --git a/src/hb-ft.cc b/src/hb-ft.cc index f8dab8bc1..d70c38a7a 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -439,7 +439,7 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, else { /* Make a nul-terminated version. */ char buf[128]; - len = MIN (len, (int) sizeof (buf) - 1); + len = hb_min (len, (int) sizeof (buf) - 1); strncpy (buf, name, len); buf[len] = '\0'; *glyph = FT_Get_Name_Index (ft_face, buf); diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index fdb545342..f799f8b22 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -202,6 +202,7 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED { } +#ifndef HB_DISABLE_DEPRECATED /** * hb_graphite2_font_get_gr_font: * @@ -213,6 +214,7 @@ hb_graphite2_font_get_gr_font (hb_font_t *font HB_UNUSED) { return nullptr; } +#endif /* @@ -308,12 +310,12 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, #define ALLOCATE_ARRAY(Type, name, len) \ Type *name = (Type *) scratch; \ - { \ + do { \ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ assert (_consumed <= scratch_size); \ scratch += _consumed; \ scratch_size -= _consumed; \ - } + } while (0) ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len); ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count); diff --git a/src/hb-icu.cc b/src/hb-icu.cc index c26c91d48..399829a81 100644 --- a/src/hb-icu.cc +++ b/src/hb-icu.cc @@ -49,6 +49,9 @@ * Functions for using HarfBuzz with the ICU library to provide Unicode data. **/ +/* ICU doesn't do-while(0) around their statements. Ugh! + * https://unicode-org.atlassian.net/browse/CLDR-13027 */ +#define HB_ICU_STMT(S) do { S } while (0) hb_script_t hb_icu_script_to_script (UScriptCode script) @@ -183,9 +186,9 @@ hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, len = 0; err = false; - U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err); + HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err)); if (err) return false; - U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err); + HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err)); if (err) return false; icu_err = U_ZERO_ERROR; @@ -193,7 +196,7 @@ hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, if (U_FAILURE (icu_err)) return false; if (u_countChar32 (normalized, len) == 1) { - U16_GET_UNSAFE (normalized, 0, *ab); + HB_ICU_STMT (U16_GET_UNSAFE (normalized, 0, *ab)); ret = true; } else { ret = false; @@ -221,13 +224,13 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, len = u_countChar32 (decomposed, len); if (len == 1) { - U16_GET_UNSAFE (decomposed, 0, *a); + HB_ICU_STMT (U16_GET_UNSAFE (decomposed, 0, *a)); *b = 0; return *a != ab; } else if (len == 2) { len =0; - U16_NEXT_UNSAFE (decomposed, len, *a); - U16_NEXT_UNSAFE (decomposed, len, *b); + HB_ICU_STMT (U16_NEXT_UNSAFE (decomposed, len, *a)); + HB_ICU_STMT (U16_NEXT_UNSAFE (decomposed, len, *b)); } return true; } @@ -236,7 +239,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, /* We don't ifdef-out the fallback code such that compiler always * sees it and makes sure it's compilable. */ - UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1]; + UChar utf16[2], normalized[2 * 19/*HB_UNICODE_MAX_DECOMPOSITION_LEN*/ + 1]; unsigned int len; hb_bool_t ret, err; UErrorCode icu_err; @@ -247,7 +250,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, len = 0; err = false; - U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err); + HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err)); if (err) return false; icu_err = U_ZERO_ERROR; @@ -258,13 +261,13 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, len = u_countChar32 (normalized, len); if (len == 1) { - U16_GET_UNSAFE (normalized, 0, *a); + HB_ICU_STMT (U16_GET_UNSAFE (normalized, 0, *a)); *b = 0; ret = *a != ab; } else if (len == 2) { len =0; - U16_NEXT_UNSAFE (normalized, len, *a); - U16_NEXT_UNSAFE (normalized, len, *b); + HB_ICU_STMT (U16_NEXT_UNSAFE (normalized, len, *a)); + HB_ICU_STMT (U16_NEXT_UNSAFE (normalized, len, *b)); /* Here's the ugly part: if ab decomposes to a single character and * that character decomposes again, we have to detect that and undo @@ -275,7 +278,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, if (U_FAILURE (icu_err)) return false; hb_codepoint_t c; - U16_GET_UNSAFE (recomposed, 0, c); + HB_ICU_STMT (U16_GET_UNSAFE (recomposed, 0, c)); if (c != *a && c != ab) { *a = c; *b = 0; @@ -284,7 +287,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, } else { /* If decomposed to more than two characters, take the last one, * and recompose the rest to get the first component. */ - U16_PREV_UNSAFE (normalized, len, *b); /* Changes len in-place. */ + HB_ICU_STMT (U16_PREV_UNSAFE (normalized, len, *b)); /* Changes len in-place. */ UChar recomposed[18 * 2]; icu_err = U_ZERO_ERROR; len = unorm2_normalize (unorm2_getNFCInstance (&icu_err), normalized, len, recomposed, ARRAY_LENGTH (recomposed), &icu_err); @@ -293,7 +296,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, /* We expect that recomposed has exactly one character now. */ if (unlikely (u_countChar32 (recomposed, len) != 1)) return false; - U16_GET_UNSAFE (recomposed, 0, *a); + HB_ICU_STMT (U16_GET_UNSAFE (recomposed, 0, *a)); ret = true; } diff --git a/src/hb-iter.hh b/src/hb-iter.hh index f0947282d..5df433375 100644 --- a/src/hb-iter.hh +++ b/src/hb-iter.hh @@ -42,9 +42,19 @@ * copied by value. If the collection / object being iterated on * is writable, then the iterator returns lvalues, otherwise it * returns rvalues. + * + * TODO Document more. + * + * If iterator implementation implements operator!=, then can be + * used in range-based for loop. That comes free if the iterator + * is random-access. Otherwise, the range-based for loop incurs + * one traversal to find end(), which can be avoided if written + * as a while-style for loop, or if iterator implements a faster + * __end__() method. + * TODO When opting in for C++17, address this by changing return + * type of .end()? */ - /* * Base classes for iterators. */ @@ -72,10 +82,13 @@ struct hb_iter_t /* Operators. */ iter_t iter () const { return *thiz(); } iter_t operator + () const { return *thiz(); } + iter_t begin () const { return *thiz(); } + iter_t end () const { return thiz()->__end__ (); } explicit operator bool () const { return thiz()->__more__ (); } unsigned len () const { return thiz()->__len__ (); } /* The following can only be enabled if item_t is reference type. Otherwise - * it will be returning pointer to temporary rvalue. */ + * it will be returning pointer to temporary rvalue. + * TODO Use a wrapper return type to fix for non-reference type. */ template hb_remove_reference* operator -> () const { return hb_addressof (**thiz()); } @@ -83,30 +96,40 @@ struct hb_iter_t item_t operator * () { return thiz()->__item__ (); } item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); } item_t operator [] (unsigned i) { return thiz()->__item_at__ (i); } - iter_t& operator += (unsigned count) { thiz()->__forward__ (count); return *thiz(); } - iter_t& operator ++ () { thiz()->__next__ (); return *thiz(); } - iter_t& operator -= (unsigned count) { thiz()->__rewind__ (count); return *thiz(); } - iter_t& operator -- () { thiz()->__prev__ (); return *thiz(); } + iter_t& operator += (unsigned count) & { thiz()->__forward__ (count); return *thiz(); } + iter_t operator += (unsigned count) && { thiz()->__forward__ (count); return *thiz(); } + iter_t& operator ++ () & { thiz()->__next__ (); return *thiz(); } + iter_t operator ++ () && { thiz()->__next__ (); return *thiz(); } + iter_t& operator -= (unsigned count) & { thiz()->__rewind__ (count); return *thiz(); } + iter_t operator -= (unsigned count) && { thiz()->__rewind__ (count); return *thiz(); } + iter_t& operator -- () & { thiz()->__prev__ (); return *thiz(); } + iter_t operator -- () && { thiz()->__prev__ (); return *thiz(); } iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; } friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; } iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; } iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; } iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; } template - iter_t& operator >> (T &v) { v = **thiz(); ++*thiz(); return *thiz(); } + iter_t& operator >> (T &v) & { v = **thiz(); ++*thiz(); return *thiz(); } template - iter_t& operator >> (T &v) const { v = **thiz(); ++*thiz(); return *thiz(); } + iter_t operator >> (T &v) && { v = **thiz(); ++*thiz(); return *thiz(); } template - iter_t& operator << (const T v) { **thiz() = v; ++*thiz(); return *thiz(); } + iter_t& operator << (const T v) & { **thiz() = v; ++*thiz(); return *thiz(); } + template + iter_t operator << (const T v) && { **thiz() = v; ++*thiz(); return *thiz(); } protected: - hb_iter_t () {} - hb_iter_t (const hb_iter_t &o HB_UNUSED) {} - void operator = (const hb_iter_t &o HB_UNUSED) {} + hb_iter_t () = default; + hb_iter_t (const hb_iter_t &o HB_UNUSED) = default; + hb_iter_t (hb_iter_t &&o HB_UNUSED) = default; + hb_iter_t& operator = (const hb_iter_t &o HB_UNUSED) = default; + hb_iter_t& operator = (hb_iter_t &&o HB_UNUSED) = default; }; #define HB_ITER_USING(Name) \ using item_t = typename Name::item_t; \ + using Name::begin; \ + using Name::end; \ using Name::item_size; \ using Name::is_iterator; \ using Name::iter; \ @@ -125,18 +148,20 @@ struct hb_iter_t using Name::operator <<; \ static_assert (true, "") -/* Returns iterator type of a type. */ -#define hb_iter_t(Iterable) decltype (hb_declval (Iterable).iter ()) +/* Returns iterator / item type of a type. */ +template +using hb_iter_type = decltype (hb_deref (hb_declval (Iterable)).iter ()); +template +using hb_item_type = decltype (*hb_deref (hb_declval (Iterable)).iter ()); template struct hb_array_t; struct { - template - hb_iter_t (T) + template hb_iter_type operator () (T&& c) const - { return c.iter (); } + { return hb_deref (hb_forward (c)).iter (); } /* Specialization for C arrays. */ @@ -148,8 +173,8 @@ struct operator () (Type (&array)[length]) const { return hb_array_t (array, length); } -} HB_FUNCOBJ (hb_iter); - +} +HB_FUNCOBJ (hb_iter); /* Mixin to fill in what the subclass doesn't provide. */ template @@ -166,22 +191,36 @@ struct hb_iter_fallback_mixin_t item_t __item_at__ (unsigned i) const { return *(*thiz() + i); } /* Termination: Implement __more__(), or __len__() if random-access. */ - bool __more__ () const { return thiz()->len (); } + bool __more__ () const { return bool (thiz()->len ()); } unsigned __len__ () const - { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; } + { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; } return l; } /* Advancing: Implement __next__(), or __forward__() if random-access. */ void __next__ () { *thiz() += 1; } - void __forward__ (unsigned n) { while (n--) ++*thiz(); } + void __forward__ (unsigned n) { while (*thiz() && n--) ++*thiz(); } /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */ void __prev__ () { *thiz() -= 1; } - void __rewind__ (unsigned n) { while (n--) --*thiz(); } + void __rewind__ (unsigned n) { while (*thiz() && n--) --*thiz(); } + + /* Range-based for: Implement __end__() if can be done faster, + * and operator!=. */ + iter_t __end__ () const + { + if (thiz()->is_random_access_iterator) + return *thiz() + thiz()->len (); + /* Above expression loops twice. Following loops once. */ + auto it = *thiz(); + while (it) ++it; + return it; + } protected: - hb_iter_fallback_mixin_t () {} - hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) {} - void operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) {} + hb_iter_fallback_mixin_t () = default; + hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default; + hb_iter_fallback_mixin_t (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default; + hb_iter_fallback_mixin_t& operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default; + hb_iter_fallback_mixin_t& operator = (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default; }; template @@ -190,17 +229,32 @@ struct hb_iter_with_fallback_t : hb_iter_fallback_mixin_t { protected: - hb_iter_with_fallback_t () {} - hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) : - hb_iter_t (o), - hb_iter_fallback_mixin_t (o) {} - void operator = (const hb_iter_with_fallback_t &o HB_UNUSED) {} + hb_iter_with_fallback_t () = default; + hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) = default; + hb_iter_with_fallback_t (hb_iter_with_fallback_t &&o HB_UNUSED) = default; + hb_iter_with_fallback_t& operator = (const hb_iter_with_fallback_t &o HB_UNUSED) = default; + hb_iter_with_fallback_t& operator = (hb_iter_with_fallback_t &&o HB_UNUSED) = default; }; /* * Meta-programming predicates. */ +/* hb_is_iterator() / hb_is_iterator_of() */ + +template +struct hb_is_iterator_of +{ + template + static hb_true_type impl (hb_priority<2>, hb_iter_t> *); + static hb_false_type impl (hb_priority<0>, const void *); + + public: + static constexpr bool value = decltype (impl (hb_prioritize, hb_declval (Iter*)))::value; +}; +#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of::value +#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t) + /* hb_is_iterable() */ template @@ -209,45 +263,78 @@ struct hb_is_iterable private: template - static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_t ()); + static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_type ()); template - static hb_false_t impl (hb_priority<0>); + static hb_false_type impl (hb_priority<0>); public: - - enum { value = decltype (impl (hb_prioritize))::value }; + static constexpr bool value = decltype (impl (hb_prioritize))::value; }; #define hb_is_iterable(Iterable) hb_is_iterable::value -/* TODO Add hb_is_iterable_of(). - * TODO Add random_access / sorted variants. */ - -/* hb_is_iterator() / hb_is_random_access_iterator() / hb_is_sorted_iterator() */ - -template -static inline char _hb_is_iterator_of (hb_priority<0>, const void *) { return 0; } -template -static inline int _hb_is_iterator_of (hb_priority<2>, hb_iter_t *) { return 0; } +/* hb_is_source_of() / hb_is_sink_of() */ template -struct hb_is_iterator_of { enum { - value = sizeof (int) == sizeof (_hb_is_iterator_of (hb_prioritize, hb_declval (Iter*))) }; }; -#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of::value -#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t) +struct hb_is_source_of +{ + private: + template >))> + static hb_true_type impl (hb_priority<2>); + template + static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ()); + static hb_false_type impl (hb_priority<0>); -#define hb_is_random_access_iterator_of(Iter, Item) \ - hb_is_iterator_of (Iter, Item) && Iter::is_random_access_iterator -#define hb_is_random_access_iterator(Iter) \ - hb_is_random_access_iterator_of (Iter, typename Iter::item_t) + public: + static constexpr bool value = decltype (impl (hb_prioritize))::value; +}; +#define hb_is_source_of(Iter, Item) hb_is_source_of::value -#define hb_is_sorted_iterator_of(Iter, Item) \ - hb_is_iterator_of (Iter, Item) && Iter::is_sorted_iterator -#define hb_is_sorted_iterator(Iter) \ - hb_is_sorted_iterator_of (Iter, typename Iter::item_t) +template +struct hb_is_sink_of +{ + private: + template ))> + static hb_true_type impl (hb_priority<2>); + template + static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) << hb_declval (Item), hb_true_type ()); + static hb_false_type impl (hb_priority<0>); + + public: + static constexpr bool value = decltype (impl (hb_prioritize))::value; +}; +#define hb_is_sink_of(Iter, Item) hb_is_sink_of::value + +/* This is commonly used, so define: */ +#define hb_is_sorted_source_of(Iter, Item) \ + (hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator) + + +/* Range-based 'for' for iterables. */ + +template +static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ()) + +template +static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ()) + +/* begin()/end() are NOT looked up non-ADL. So each namespace must declare them. + * Do it for namespace OT. */ +namespace OT { + +template +static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ()) + +template +static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ()) + +} /* @@ -255,46 +342,59 @@ struct hb_is_iterator_of { enum { */ template + hb_requires (hb_is_iterator (Lhs))> static inline auto -operator | (Lhs lhs, const Rhs &rhs) HB_AUTO_RETURN (rhs (lhs)) +operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward (rhs) (hb_forward (lhs))) /* hb_map(), hb_filter(), hb_reduce() */ -template -struct hb_map_iter_t : - hb_iter_t, - decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t)))> -{ - hb_map_iter_t (const Iter& it, Proj f) : it (it), f (f) {} +enum class hb_function_sortedness_t { + NOT_SORTED, + RETAINS_SORTING, + SORTED, +}; - typedef decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t))) __item_t__; +template +struct hb_map_iter_t : + hb_iter_t, + decltype (hb_get (hb_declval (Proj), *hb_declval (Iter)))> +{ + hb_map_iter_t (const Iter& it, Proj f_) : it (it), f (f_) {} + + typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__; static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; - __item_t__ __item__ () const { return hb_get (f, *it); } - __item_t__ __item_at__ (unsigned i) const { return hb_get (f, it[i]); } + static constexpr bool is_sorted_iterator = + Sorted == hb_function_sortedness_t::SORTED ? true : + Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator : + false; + __item_t__ __item__ () const { return hb_get (f.get (), *it); } + __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); } bool __more__ () const { return bool (it); } unsigned __len__ () const { return it.len (); } void __next__ () { ++it; } void __forward__ (unsigned n) { it += n; } void __prev__ () { --it; } void __rewind__ (unsigned n) { it -= n; } + hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); } + bool operator != (const hb_map_iter_t& o) const + { return it != o.it; } private: Iter it; - Proj f; + hb_reference_wrapper f; }; -template +template struct hb_map_iter_factory_t { hb_map_iter_factory_t (Proj f) : f (f) {} template - hb_map_iter_t - operator () (Iter it) const - { return hb_map_iter_t (it, f); } + hb_requires (hb_is_iterator (Iter))> + hb_map_iter_t + operator () (Iter it) + { return hb_map_iter_t (it, f); } private: Proj f; @@ -302,31 +402,51 @@ struct hb_map_iter_factory_t struct { template - hb_map_iter_factory_t + hb_map_iter_factory_t operator () (Proj&& f) const - { return hb_map_iter_factory_t (f); } -} HB_FUNCOBJ (hb_map); + { return hb_map_iter_factory_t (f); } +} +HB_FUNCOBJ (hb_map); +struct +{ + template + hb_map_iter_factory_t + operator () (Proj&& f) const + { return hb_map_iter_factory_t (f); } +} +HB_FUNCOBJ (hb_map_retains_sorting); +struct +{ + template + hb_map_iter_factory_t + operator () (Proj&& f) const + { return hb_map_iter_factory_t (f); } +} +HB_FUNCOBJ (hb_map_sorted); template + hb_requires (hb_is_iterator (Iter))> struct hb_filter_iter_t : hb_iter_with_fallback_t, typename Iter::item_t> { - hb_filter_iter_t (const Iter& it_, Pred p, Proj f) : it (it_), p (p), f (f) - { while (it && !hb_has (p, hb_get (f, *it))) ++it; } + hb_filter_iter_t (const Iter& it_, Pred p_, Proj f_) : it (it_), p (p_), f (f_) + { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; } typedef typename Iter::item_t __item_t__; static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; __item_t__ __item__ () const { return *it; } bool __more__ () const { return bool (it); } - void __next__ () { do ++it; while (it && !p (f (*it))); } - void __prev__ () { --it; } + void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } + void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } + hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); } + bool operator != (const hb_filter_iter_t& o) const + { return it != o.it; } private: Iter it; - Pred p; - Proj f; + hb_reference_wrapper p; + hb_reference_wrapper f; }; template struct hb_filter_iter_factory_t @@ -334,9 +454,9 @@ struct hb_filter_iter_factory_t hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {} template + hb_requires (hb_is_iterator (Iter))> hb_filter_iter_t - operator () (Iter it) const + operator () (Iter it) { return hb_filter_iter_t (it, p, f); } private: @@ -345,12 +465,13 @@ struct hb_filter_iter_factory_t }; struct { - template hb_filter_iter_factory_t - operator () (Pred&& p = hb_bool, Proj&& f = hb_identity) const + operator () (Pred&& p = hb_identity, Proj&& f = hb_identity) const { return hb_filter_iter_factory_t (p, f); } -} HB_FUNCOBJ (hb_filter); +} +HB_FUNCOBJ (hb_filter); template struct hb_reduce_t @@ -358,10 +479,10 @@ struct hb_reduce_t hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {} template AccuT - operator () (Iter it) const + operator () (Iter it) { AccuT value = init_value; for (; it; ++it) @@ -379,7 +500,8 @@ struct hb_reduce_t operator () (Redu&& r, InitT init_value) const { return hb_reduce_t (r, init_value); } -} HB_FUNCOBJ (hb_reduce); +} +HB_FUNCOBJ (hb_reduce); /* hb_zip() */ @@ -387,7 +509,7 @@ struct template struct hb_zip_iter_t : hb_iter_t, - hb_pair_t > + hb_pair_t> { hb_zip_iter_t () {} hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {} @@ -396,17 +518,45 @@ struct hb_zip_iter_t : static constexpr bool is_random_access_iterator = A::is_random_access_iterator && B::is_random_access_iterator; - static constexpr bool is_sorted_iterator = - A::is_sorted_iterator && - B::is_sorted_iterator; + /* Note. The following categorization is only valid if A is strictly sorted, + * ie. does NOT have duplicates. Previously I tried to categorize sortedness + * more granularly, see commits: + * + * 513762849a683914fc266a17ddf38f133cccf072 + * 4d3cf2adb669c345cc43832d11689271995e160a + * + * However, that was not enough, since hb_sorted_array_t, hb_sorted_vector_t, + * SortedArrayOf, etc all needed to be updated to add more variants. At that + * point I saw it not worth the effort, and instead we now deem all sorted + * collections as essentially strictly-sorted for the purposes of zip. + * + * The above assumption is not as bad as it sounds. Our "sorted" comes with + * no guarantees. It's just a contract, put in place to help you remember, + * and think about, whether an iterator you receive is expected to be + * sorted or not. As such, it's not perfect by definition, and should not + * be treated so. The inaccuracy here just errs in the direction of being + * more permissive, so your code compiles instead of erring on the side of + * marking your zipped iterator unsorted in which case your code won't + * compile. + * + * This semantical limitation does NOT affect logic in any other place I + * know of as of this writing. + */ + static constexpr bool is_sorted_iterator = A::is_sorted_iterator; + __item_t__ __item__ () const { return __item_t__ (*a, *b); } __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); } - bool __more__ () const { return a && b; } - unsigned __len__ () const { return MIN (a.len (), b.len ()); } + bool __more__ () const { return bool (a) && bool (b); } + unsigned __len__ () const { return hb_min (a.len (), b.len ()); } void __next__ () { ++a; ++b; } void __forward__ (unsigned n) { a += n; b += n; } void __prev__ () { --a; --b; } void __rewind__ (unsigned n) { a -= n; b -= n; } + hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); } + /* Note, we should stop if ANY of the iters reaches end. As such two compare + * unequal if both items are unequal, NOT if either is unequal. */ + bool operator != (const hb_zip_iter_t& o) const + { return a != o.a && b != o.b; } private: A a; @@ -415,46 +565,12 @@ struct hb_zip_iter_t : struct { template - hb_zip_iter_t - operator () (A& a, B &b) const - { return hb_zip_iter_t (hb_iter (a), hb_iter (b)); } -} HB_FUNCOBJ (hb_zip); - -/* hb_enumerate */ - -template -struct hb_enumerate_iter_t : - hb_iter_t, - hb_pair_t > -{ - hb_enumerate_iter_t (const Iter& it) : i (0), it (it) {} - - typedef hb_pair_t __item_t__; - static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; - static constexpr bool is_sorted_iterator = true; - __item_t__ __item__ () const { return __item_t__ (+i, *it); } - __item_t__ __item_at__ (unsigned j) const { return __item_t__ (i + j, it[j]); } - bool __more__ () const { return bool (it); } - unsigned __len__ () const { return it.len (); } - void __next__ () { ++i; ++it; } - void __forward__ (unsigned n) { i += n; it += n; } - void __prev__ () { --i; --it; } - void __rewind__ (unsigned n) { i -= n; it -= n; } - - private: - unsigned i; - Iter it; -}; -struct -{ - template - hb_enumerate_iter_t - operator () (Iterable& it) const - { return hb_enumerate_iter_t (hb_iter (it)); } -} HB_FUNCOBJ (hb_enumerate); + hb_requires (hb_is_iterable (A) && hb_is_iterable (B))> + hb_zip_iter_t, hb_iter_type> + operator () (A&& a, B&& b) const + { return hb_zip_iter_t, hb_iter_type> (hb_iter (a), hb_iter (b)); } +} +HB_FUNCOBJ (hb_zip); /* hb_apply() */ @@ -464,9 +580,8 @@ struct hb_apply_t hb_apply_t (Appl a) : a (a) {} template - void - operator () (Iter it) const + hb_requires (hb_is_iterator (Iter))> + void operator () (Iter it) { for (; it; ++it) (void) hb_invoke (a, *it); @@ -484,19 +599,91 @@ struct template hb_apply_t operator () (Appl *a) const { return hb_apply_t (*a); } -} HB_FUNCOBJ (hb_apply); +} +HB_FUNCOBJ (hb_apply); + +/* hb_iota()/hb_range() */ + +template +struct hb_counter_iter_t : + hb_iter_t, T> +{ + hb_counter_iter_t (T start, T end_, S step) : v (start), end_ (end_for (start, end_, step)), step (step) {} + + typedef T __item_t__; + static constexpr bool is_random_access_iterator = true; + static constexpr bool is_sorted_iterator = true; + __item_t__ __item__ () const { return +v; } + __item_t__ __item_at__ (unsigned j) const { return v + j * step; } + bool __more__ () const { return v != end_; } + unsigned __len__ () const { return !step ? UINT_MAX : (end_ - v) / step; } + void __next__ () { v += step; } + void __forward__ (unsigned n) { v += n * step; } + void __prev__ () { v -= step; } + void __rewind__ (unsigned n) { v -= n * step; } + hb_counter_iter_t __end__ () const { return hb_counter_iter_t (end_, end_, step); } + bool operator != (const hb_counter_iter_t& o) const + { return v != o.v; } + + private: + static inline T end_for (T start, T end_, S step) + { + if (!step) + return end_; + auto res = (end_ - start) % step; + if (!res) + return end_; + end_ += step - res; + return end_; + } + + private: + T v; + T end_; + S step; +}; +struct +{ + template hb_counter_iter_t + operator () (T start = 0u, S&& step = 1u) const + { return hb_counter_iter_t (start, step >= 0 ? hb_int_max (T) : hb_int_min (T), step); } +} +HB_FUNCOBJ (hb_iota); +struct +{ + template hb_counter_iter_t + operator () (T end = (unsigned) -1) const + { return hb_counter_iter_t (0, end, 1u); } + + template hb_counter_iter_t + operator () (T start, T end, S&& step = 1u) const + { return hb_counter_iter_t (start, end, step); } +} +HB_FUNCOBJ (hb_range); + +/* hb_enumerate */ + +struct +{ + template + auto operator () (Iterable&& it, Index start = 0u) const HB_AUTO_RETURN + ( hb_zip (hb_iota (start), it) ) +} +HB_FUNCOBJ (hb_enumerate); + /* hb_sink() */ template struct hb_sink_t { - hb_sink_t (Sink&& s) : s (s) {} + hb_sink_t (Sink s) : s (s) {} template - void - operator () (Iter it) const + hb_requires (hb_is_iterator (Iter))> + void operator () (Iter it) { for (; it; ++it) s << *it; @@ -514,33 +701,33 @@ struct template hb_sink_t operator () (Sink *s) const { return hb_sink_t (*s); } -} HB_FUNCOBJ (hb_sink); +} +HB_FUNCOBJ (hb_sink); /* hb-drain: hb_sink to void / blackhole / /dev/null. */ struct { template - void - operator () (Iter it) const + hb_requires (hb_is_iterator (Iter))> + void operator () (Iter it) const { for (; it; ++it) (void) *it; } -} HB_FUNCOBJ (hb_drain); +} +HB_FUNCOBJ (hb_drain); /* hb_unzip(): unzip and sink to two sinks. */ template struct hb_unzip_t { - hb_unzip_t (Sink1&& s1, Sink2&& s2) : s1 (s1), s2 (s2) {} + hb_unzip_t (Sink1 s1, Sink2 s2) : s1 (s1), s2 (s2) {} template - void - operator () (Iter it) const + hb_requires (hb_is_iterator (Iter))> + void operator () (Iter it) { for (; it; ++it) { @@ -563,7 +750,8 @@ struct template hb_unzip_t operator () (Sink1 *s1, Sink2 *s2) const { return hb_unzip_t (*s1, *s2); } -} HB_FUNCOBJ (hb_unzip); +} +HB_FUNCOBJ (hb_unzip); /* hb-all, hb-any, hb-none. */ @@ -571,49 +759,61 @@ struct struct { template - bool - operator () (Iterable&& c) const + typename Pred = decltype ((hb_identity)), + typename Proj = decltype ((hb_identity)), + hb_requires (hb_is_iterable (Iterable))> + bool operator () (Iterable&& c, + Pred&& p = hb_identity, + Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (!*it) + if (!hb_match (hb_forward (p), hb_get (hb_forward (f), *it))) return false; return true; } -} HB_FUNCOBJ (hb_all); +} +HB_FUNCOBJ (hb_all); struct { template - bool - operator () (Iterable&& c) const + typename Pred = decltype ((hb_identity)), + typename Proj = decltype ((hb_identity)), + hb_requires (hb_is_iterable (Iterable))> + bool operator () (Iterable&& c, + Pred&& p = hb_identity, + Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (*it) + if (hb_match (hb_forward (p), hb_get (hb_forward (f), *it))) return true; return false; } -} HB_FUNCOBJ (hb_any); +} +HB_FUNCOBJ (hb_any); struct { template - bool - operator () (Iterable&& c) const + typename Pred = decltype ((hb_identity)), + typename Proj = decltype ((hb_identity)), + hb_requires (hb_is_iterable (Iterable))> + bool operator () (Iterable&& c, + Pred&& p = hb_identity, + Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (*it) + if (hb_match (hb_forward (p), hb_get (hb_forward (f), *it))) return false; return true; } -} HB_FUNCOBJ (hb_none); +} +HB_FUNCOBJ (hb_none); /* * Algorithms operating on iterators. */ template + hb_requires (hb_is_iterable (C))> inline void hb_fill (C& c, const V &v) { diff --git a/src/hb-map.hh b/src/hb-map.hh index bbb1bef5d..26e4930a5 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -43,8 +43,8 @@ struct hb_hashmap_t hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - static_assert (hb_is_integer (K) || hb_is_pointer (K), ""); - static_assert (hb_is_integer (V) || hb_is_pointer (V), ""); + static_assert (hb_is_integral (K) || hb_is_pointer (K), ""); + static_assert (hb_is_integral (V) || hb_is_pointer (V), ""); /* TODO If key type is a pointer, keep hash in item_t and use to: * 1. avoid rehashing when resizing table, and @@ -57,11 +57,12 @@ struct hb_hashmap_t void clear () { key = kINVALID; value = vINVALID; } - bool operator == (K o) { return hb_deref_pointer (key) == hb_deref_pointer (o); } + bool operator == (K o) { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) { return *this == o.key; } bool is_unused () const { return key == kINVALID; } bool is_tombstone () const { return key != kINVALID && value == vINVALID; } bool is_real () const { return key != kINVALID && value != vINVALID; } + hb_pair_t get_pair() const { return hb_pair_t (key, value); } }; hb_object_header_t header; @@ -181,7 +182,12 @@ struct hb_hashmap_t static constexpr V SENTINEL = vINVALID; typedef V value_t; value_t operator [] (K k) const { return get (k); } - bool has (K k) const { return (*this)[k] != SENTINEL; } + bool has (K k, V *vp = nullptr) const + { + V v = (*this)[k]; + if (vp) *vp = v; + return v != SENTINEL; + } /* Projection. */ V operator () (K k) const { return get (k); } @@ -201,6 +207,34 @@ struct hb_hashmap_t unsigned int get_population () const { return population; } + /* + * Iterator + */ + auto iter () const HB_AUTO_RETURN + ( + + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real) + | hb_map (&item_t::get_pair) + ) + auto keys () const HB_AUTO_RETURN + ( + + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real) + | hb_map (&item_t::key) + | hb_map (hb_ridentity) + ) + auto values () const HB_AUTO_RETURN + ( + + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real) + | hb_map (&item_t::value) + | hb_map (hb_ridentity) + ) + + /* Sink interface. */ + hb_hashmap_t& operator << (const hb_pair_t& v) + { set (v.first, v.second); return *this; } + protected: unsigned int bucket_for (K key) const @@ -211,9 +245,9 @@ struct hb_hashmap_t while (!items[i].is_unused ()) { if (items[i] == key) - return i; + return i; if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) - tombstone = i; + tombstone = i; i = (i + ++step) & mask; } return tombstone == (unsigned) -1 ? i : tombstone; diff --git a/src/hb-meta.hh b/src/hb-meta.hh index b80358c2a..df8ebd175 100644 --- a/src/hb-meta.hh +++ b/src/hb-meta.hh @@ -35,28 +35,38 @@ */ /* Void! For when we need a expression-type of void. */ -struct hb_void_t { typedef void value; }; +struct hb_empty_t {}; -/* Void meta-function ala std::void_t - * https://en.cppreference.com/w/cpp/types/void_t */ -template struct _hb_void_tt { typedef void type; }; -template using hb_void_tt = typename _hb_void_tt::type; +/* https://en.cppreference.com/w/cpp/types/void_t */ +template struct _hb_void_t { typedef void type; }; +template using hb_void_t = typename _hb_void_t::type; -template struct _hb_head_tt { typedef Head type; }; -template using hb_head_tt = typename _hb_head_tt::type; +template struct _hb_head_t { typedef Head type; }; +template using hb_head_t = typename _hb_head_t::type; -/* Bool! For when we need to evaluate type-dependent expressions - * in a template argument. */ -template struct hb_bool_tt { enum { value = b }; }; -typedef hb_bool_tt hb_true_t; -typedef hb_bool_tt hb_false_t; +template struct hb_integral_constant { static constexpr T value = v; }; +template using hb_bool_constant = hb_integral_constant; +using hb_true_type = hb_bool_constant; +using hb_false_type = hb_bool_constant; +/* Basic type SFINAE. */ + +template struct hb_enable_if {}; +template struct hb_enable_if { typedef T type; }; +#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr +/* Concepts/Requires alias: */ +#define hb_requires(Cond) hb_enable_if((Cond)) + +template struct hb_is_same : hb_false_type {}; +template struct hb_is_same : hb_true_type {}; +#define hb_is_same(T, T2) hb_is_same::value + /* Function overloading SFINAE and priority. */ -#define HB_RETURN(Ret, E) -> hb_head_tt { return (E); } +#define HB_RETURN(Ret, E) -> hb_head_t { return (E); } #define HB_AUTO_RETURN(E) -> decltype ((E)) { return (E); } -#define HB_VOID_RETURN(E) -> hb_void_tt { (E); } +#define HB_VOID_RETURN(E) -> hb_void_t { (E); } template struct hb_priority : hb_priority {}; template <> struct hb_priority<0> {}; @@ -65,13 +75,13 @@ template <> struct hb_priority<0> {}; #define HB_FUNCOBJ(x) static_const x HB_UNUSED -template struct hb_match_identity { typedef T type; }; -template using hb_type_identity = typename hb_match_identity::type; +template struct hb_type_identity_t { typedef T type; }; +template using hb_type_identity = typename hb_type_identity_t::type; struct { template - T* operator () (const T& arg) const + T* operator () (T& arg) const { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" @@ -81,32 +91,82 @@ struct reinterpret_cast (arg))); #pragma GCC diagnostic pop } -} HB_FUNCOBJ (hb_addressof); +} +HB_FUNCOBJ (hb_addressof); template static inline T hb_declval (); #define hb_declval(T) (hb_declval ()) -template struct hb_match_const { typedef T type; enum { value = false }; }; -template struct hb_match_const { typedef T type; enum { value = true }; }; +template struct hb_match_const : hb_type_identity_t, hb_bool_constant{}; +template struct hb_match_const : hb_type_identity_t, hb_bool_constant {}; template using hb_remove_const = typename hb_match_const::type; +template using hb_add_const = const T; #define hb_is_const(T) hb_match_const::value -template struct hb_match_reference { typedef T type; enum { value = false }; }; -template struct hb_match_reference { typedef T type; enum { value = true }; }; +template struct hb_match_reference : hb_type_identity_t, hb_bool_constant{}; +template struct hb_match_reference : hb_type_identity_t, hb_bool_constant {}; +template struct hb_match_reference : hb_type_identity_t, hb_bool_constant {}; template using hb_remove_reference = typename hb_match_reference::type; +template auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity; +template auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity; +template using hb_add_lvalue_reference = decltype (_hb_try_add_lvalue_reference (hb_prioritize)); +template auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity; +template auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity; +template using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference (hb_prioritize)); #define hb_is_reference(T) hb_match_reference::value -template struct hb_match_pointer { typedef T type; enum { value = false }; }; -template struct hb_match_pointer { typedef T type; enum { value = true }; }; +template struct hb_match_pointer : hb_type_identity_t, hb_bool_constant{}; +template struct hb_match_pointer : hb_type_identity_t, hb_bool_constant {}; template using hb_remove_pointer = typename hb_match_pointer::type; +template auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity*>; +template auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity; +template using hb_add_pointer = decltype (_hb_try_add_pointer (hb_prioritize)); #define hb_is_pointer(T) hb_match_pointer::value + /* TODO Add feature-parity to std::decay. */ template using hb_decay = hb_remove_const>; -#define hb_is_cr_convertible_to(A, B) ( \ - hb_is_same (hb_decay, hb_decay) && \ - hb_is_const (A) <= hb_is_const (B) && \ - hb_is_reference (A) >= hb_is_reference (B)) +template +struct _hb_conditional { typedef T type; }; +template +struct _hb_conditional { typedef F type; }; +template +using hb_conditional = typename _hb_conditional::type; + + +template +struct hb_is_convertible +{ + private: + static constexpr bool from_void = hb_is_same (void, hb_decay); + static constexpr bool to_void = hb_is_same (void, hb_decay ); + static constexpr bool either_void = from_void || to_void; + static constexpr bool both_void = from_void && to_void; + + static hb_true_type impl2 (hb_conditional); + + template + static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T))); + template + static hb_false_type impl (hb_priority<0>); + public: + static constexpr bool value = both_void || + (!either_void && + decltype (impl> (hb_prioritize))::value); +}; +#define hb_is_convertible(From,To) hb_is_convertible::value + +template +using hb_is_base_of = hb_is_convertible *, hb_decay *>; +#define hb_is_base_of(Base,Derived) hb_is_base_of::value + +template +using hb_is_cr_convertible = hb_bool_constant< + hb_is_same (hb_decay, hb_decay) && + (!hb_is_const (From) || hb_is_const (To)) && + (!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To)) +>; +#define hb_is_cr_convertible(From,To) hb_is_cr_convertible::value /* std::move and std::forward */ @@ -125,56 +185,216 @@ struct template auto operator () (T *v) const HB_AUTO_RETURN (*v) +} +HB_FUNCOBJ (hb_deref); -} HB_FUNCOBJ (hb_deref_pointer); +struct +{ + template auto + operator () (T&& v) const HB_AUTO_RETURN (hb_forward (v)) + + template auto + operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v)) +} +HB_FUNCOBJ (hb_ref); + +template +struct hb_reference_wrapper +{ + hb_reference_wrapper (T v) : v (v) {} + bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } + bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } + operator T () const { return v; } + T get () const { return v; } + T v; +}; +template +struct hb_reference_wrapper +{ + hb_reference_wrapper (T& v) : v (hb_addressof (v)) {} + bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } + bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } + operator T& () const { return *v; } + T& get () const { return *v; } + T* v; +}; -template struct hb_enable_if {}; -template struct hb_enable_if { typedef T type; }; -#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr +template +using hb_is_integral = hb_bool_constant< + hb_is_same (hb_decay, char) || + hb_is_same (hb_decay, signed char) || + hb_is_same (hb_decay, unsigned char) || + hb_is_same (hb_decay, signed int) || + hb_is_same (hb_decay, unsigned int) || + hb_is_same (hb_decay, signed short) || + hb_is_same (hb_decay, unsigned short) || + hb_is_same (hb_decay, signed long) || + hb_is_same (hb_decay, unsigned long) || + hb_is_same (hb_decay, signed long long) || + hb_is_same (hb_decay, unsigned long long) || + false +>; +#define hb_is_integral(T) hb_is_integral::value +template +using hb_is_floating_point = hb_bool_constant< + hb_is_same (hb_decay, float) || + hb_is_same (hb_decay, double) || + hb_is_same (hb_decay, long double) || + false +>; +#define hb_is_floating_point(T) hb_is_floating_point::value +template +using hb_is_arithmetic = hb_bool_constant< + hb_is_integral (T) || + hb_is_floating_point (T) || + false +>; +#define hb_is_arithmetic(T) hb_is_arithmetic::value -template struct hb_is_same : hb_false_t {}; -template struct hb_is_same : hb_true_t {}; -#define hb_is_same(T, T2) hb_is_same::value -template struct hb_is_signed; -template <> struct hb_is_signed { enum { value = CHAR_MIN < 0 }; }; -template <> struct hb_is_signed { enum { value = true }; }; -template <> struct hb_is_signed { enum { value = false }; }; -template <> struct hb_is_signed { enum { value = true }; }; -template <> struct hb_is_signed { enum { value = false }; }; -template <> struct hb_is_signed { enum { value = true }; }; -template <> struct hb_is_signed { enum { value = false }; }; -template <> struct hb_is_signed { enum { value = true }; }; -template <> struct hb_is_signed { enum { value = false }; }; -template <> struct hb_is_signed { enum { value = true }; }; -template <> struct hb_is_signed { enum { value = false }; }; +template +using hb_is_signed = hb_conditional, + hb_false_type>; #define hb_is_signed(T) hb_is_signed::value +template +using hb_is_unsigned = hb_conditional, + hb_false_type>; +#define hb_is_unsigned(T) hb_is_unsigned::value -template struct hb_int_min { static constexpr T value = 0; }; -template <> struct hb_int_min { static constexpr char value = CHAR_MIN; }; -template <> struct hb_int_min { static constexpr int value = INT_MIN; }; -template <> struct hb_int_min { static constexpr long value = LONG_MIN; }; +template struct hb_int_min; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; +template <> struct hb_int_min : hb_integral_constant {}; #define hb_int_min(T) hb_int_min::value +template struct hb_int_max; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +template <> struct hb_int_max : hb_integral_constant {}; +#define hb_int_max(T) hb_int_max::value -template struct hb_signedness_int; -template <> struct hb_signedness_int { typedef unsigned int value; }; -template <> struct hb_signedness_int { typedef signed int value; }; -#define hb_signedness_int(T) hb_signedness_int::value -template struct hb_is_integer { enum { value = false }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -template <> struct hb_is_integer { enum { value = true }; }; -#define hb_is_integer(T) hb_is_integer::value + +template +struct _hb_is_destructible : hb_false_type {}; +template +struct _hb_is_destructible> : hb_true_type {}; +template +using hb_is_destructible = _hb_is_destructible; +#define hb_is_destructible(T) hb_is_destructible::value + +template +struct _hb_is_constructible : hb_false_type {}; +template +struct _hb_is_constructible, Ts...> : hb_true_type {}; +template +using hb_is_constructible = _hb_is_constructible; +#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value + +template +using hb_is_default_constructible = hb_is_constructible; +#define hb_is_default_constructible(T) hb_is_default_constructible::value + +template +using hb_is_copy_constructible = hb_is_constructible>>; +#define hb_is_copy_constructible(T) hb_is_copy_constructible::value + +template +using hb_is_move_constructible = hb_is_constructible>>; +#define hb_is_move_constructible(T) hb_is_move_constructible::value + +template +struct _hb_is_assignable : hb_false_type {}; +template +struct _hb_is_assignable> : hb_true_type {}; +template +using hb_is_assignable = _hb_is_assignable; +#define hb_is_assignable(T,U) hb_is_assignable::value + +template +using hb_is_copy_assignable = hb_is_assignable, + hb_add_lvalue_reference>>; +#define hb_is_copy_assignable(T) hb_is_copy_assignable::value + +template +using hb_is_move_assignable = hb_is_assignable, + hb_add_rvalue_reference>; +#define hb_is_move_assignable(T) hb_is_move_assignable::value + +/* Trivial versions. */ + +template union hb_trivial { T value; }; + +/* Don't know how to do the following. */ +template +using hb_is_trivially_destructible= hb_is_destructible>; +#define hb_is_trivially_destructible(T) hb_is_trivially_destructible::value + +/* Don't know how to do the following. */ +//template +//using hb_is_trivially_constructible= hb_is_constructible, hb_trivial...>; +//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value + +template +using hb_is_trivially_default_constructible= hb_is_default_constructible>; +#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible::value + +template +using hb_is_trivially_copy_constructible= hb_is_copy_constructible>; +#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible::value + +template +using hb_is_trivially_move_constructible= hb_is_move_constructible>; +#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible::value + +/* Don't know how to do the following. */ +//template +//using hb_is_trivially_assignable= hb_is_assignable, hb_trivial>; +//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable::value + +template +using hb_is_trivially_copy_assignable= hb_is_copy_assignable>; +#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable::value + +template +using hb_is_trivially_move_assignable= hb_is_move_assignable>; +#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable::value + +template +using hb_is_trivially_copyable= hb_bool_constant< + hb_is_trivially_destructible (T) && + (!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) && + (!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) && + (!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) && + (!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) && + true +>; +#define hb_is_trivially_copyable(T) hb_is_trivially_copyable::value + +template +using hb_is_trivial= hb_bool_constant< + hb_is_trivially_copyable (T) && + hb_is_trivially_default_constructible (T) +>; +#define hb_is_trivial(T) hb_is_trivial::value #endif /* HB_META_HH */ diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh index a760e7317..cbbfa2681 100644 --- a/src/hb-mutex.hh +++ b/src/hb-mutex.hh @@ -48,6 +48,17 @@ /* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ +#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) + +#include +typedef pthread_mutex_t hb_mutex_impl_t; +#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER +#define hb_mutex_impl_init(M) pthread_mutex_init (M, nullptr) +#define hb_mutex_impl_lock(M) pthread_mutex_lock (M) +#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M) +#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) + + #elif !defined(HB_NO_MT) && defined(_WIN32) #include @@ -63,17 +74,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t; #define hb_mutex_impl_finish(M) DeleteCriticalSection (M) -#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) - -#include -typedef pthread_mutex_t hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER -#define hb_mutex_impl_init(M) pthread_mutex_init (M, nullptr) -#define hb_mutex_impl_lock(M) pthread_mutex_lock (M) -#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M) -#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) - - #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) #if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD) diff --git a/src/hb-null.hh b/src/hb-null.hh index 1e20a47e9..674b4dffc 100644 --- a/src/hb-null.hh +++ b/src/hb-null.hh @@ -46,16 +46,13 @@ * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol */ -template -struct _hb_null_size -{ enum { value = sizeof (T) }; }; +template +struct _hb_null_size : hb_integral_constant {}; template -struct _hb_null_size > -{ enum { value = T::null_size }; }; +struct _hb_null_size> : hb_integral_constant {}; template -struct hb_null_size -{ enum { value = _hb_null_size::value }; }; +using hb_null_size = _hb_null_size; #define hb_null_size(T) hb_null_size::value /* These doesn't belong here, but since is copy/paste from above, put it here. */ @@ -63,16 +60,12 @@ struct hb_null_size /* hb_static_size (T) * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */ -template -struct _hb_static_size -{ enum { value = sizeof (T) }; }; +template +struct _hb_static_size : hb_integral_constant {}; template -struct _hb_static_size > -{ enum { value = T::static_size }; }; - +struct _hb_static_size> : hb_integral_constant {}; template -struct hb_static_size -{ enum { value = _hb_static_size::value }; }; +using hb_static_size = _hb_static_size; #define hb_static_size(T) hb_static_size::value @@ -95,7 +88,7 @@ struct Null { template struct NullHelper { - typedef hb_remove_const > Type; + typedef hb_remove_const> Type; static const Type & get_null () { return Null::get_null (); } }; #define Null(Type) NullHelper::get_null () @@ -148,7 +141,7 @@ static inline Type& Crap () { template struct CrapHelper { - typedef hb_remove_const > Type; + typedef hb_remove_const> Type; static Type & get_crap () { return Crap (); } }; #define Crap(Type) CrapHelper::get_crap () diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 7e916aeb6..5318c7fca 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -94,7 +94,7 @@ typedef struct OffsetTable if (start_offset >= tables.len) *table_count = 0; else - *table_count = MIN (*table_count, tables.len - start_offset); + *table_count = hb_min (*table_count, tables.len - start_offset); const TableRecord *sub_tables = tables.arrayZ + start_offset; unsigned int count = *table_count; @@ -222,7 +222,7 @@ struct TTCHeaderVersion1 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - LArrayOf > + LArrayOf> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: @@ -334,7 +334,7 @@ struct ResourceTypeRecord protected: Tag tag; /* Resource type. */ HBUINT16 resCountM1; /* Number of resources minus 1. */ - NNOffsetTo > + NNOffsetTo> resourcesZ; /* Offset from beginning of resource type list * to reference item list for this type. */ public: @@ -390,7 +390,7 @@ struct ResourceMap HBUINT32 reserved1; /* Reserved for handle to next resource map */ HBUINT16 resreved2; /* Reserved for file reference number */ HBUINT16 attrs; /* Resource fork attribute */ - NNOffsetTo > + NNOffsetTo> typeList; /* Offset from beginning of map to * resource type list */ Offset16 nameList; /* Offset from beginning of map to @@ -422,7 +422,7 @@ struct ResourceForkHeader } protected: - LNNOffsetTo > + LNNOffsetTo> data; /* Offset from beginning of resource fork * to resource data */ LNNOffsetTo diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 041b9843f..de2d25638 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -57,7 +57,7 @@ template struct IntType { typedef Type type; - typedef typename hb_signedness_int (hb_is_signed (Type)) wide_type; + typedef hb_conditional wide_type; IntType& operator = (wide_type i) { v = i; return *this; } operator wide_type () const { return v; } @@ -110,7 +110,7 @@ struct F2DOT14 : HBINT16 F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; } // 16384 means 1<<14 float to_float () const { return ((int32_t) v) / 16384.f; } - void set_float (float f) { v = round (f * 16384.f); } + void set_float (float f) { v = roundf (f * 16384.f); } public: DEFINE_SIZE_STATIC (2); }; @@ -121,7 +121,7 @@ struct Fixed : HBINT32 Fixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; } // 65536 means 1<<16 float to_float () const { return ((int32_t) v) / 65536.f; } - void set_float (float f) { v = round (f * 65536.f); } + void set_float (float f) { v = roundf (f * 65536.f); } public: DEFINE_SIZE_STATIC (4); }; @@ -279,32 +279,70 @@ struct OffsetTo : Offset return StructAtOffset (base, *this); } + template + friend const Type& operator + (const Base &base, const OffsetTo &offset) { return offset ((const void *) base); } + template + friend const Type& operator + (const OffsetTo &offset, const Base &base) { return offset ((const void *) base); } + template + friend Type& operator + (Base &&base, OffsetTo &offset) { return offset ((void *) base); } + template + friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); } + Type& serialize (hb_serialize_context_t *c, const void *base) { return * (Type *) Offset::serialize (c, base); } - template - bool serialize_subset (hb_subset_context_t *c, const T &src, const void *base, Ts &&...ds) + template + bool serialize_subset (hb_subset_context_t *c, + const OffsetTo& src, + const void *src_base, + const void *dst_base, + Ts&&... ds) { *this = 0; - if (has_null && &src == &Null (T)) + if (src.is_null ()) return false; auto *s = c->serializer; s->push (); - bool ret = src.subset (c, hb_forward (ds)...); + bool ret = c->dispatch (src_base+src, hb_forward (ds)...); if (ret || !has_null) - s->add_link (*this, s->pop_pack (), base); + s->add_link (*this, s->pop_pack (), dst_base); else s->pop_discard (); return ret; } + /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */ + template + bool serialize_copy (hb_serialize_context_t *c, + const OffsetTo& src, + const void *src_base, + const void *dst_base, + Ts&&... ds) + { + *this = 0; + if (src.is_null ()) + return false; + + c->push (); + + bool ret = c->copy (src_base+src, hb_forward (ds)...); + + c->add_link (*this, c->pop_pack (), dst_base); + + return ret; + } + bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -315,12 +353,12 @@ struct OffsetTo : Offset } template - bool sanitize (hb_sanitize_context_t *c, const void *base, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const { TRACE_SANITIZE (this); return_trace (sanitize_shallow (c, base) && (this->is_null () || - StructAtOffset (base, *this).sanitize (c, hb_forward (ds)...) || + c->dispatch (StructAtOffset (base, *this), hb_forward (ds)...) || neuter (c))); } @@ -340,11 +378,6 @@ using NNOffsetTo = OffsetTo; template using LNNOffsetTo = LOffsetTo; -template -static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } -template -static inline Type& operator + (Base &base, OffsetTo &offset) { return offset (base); } - /* * Array Types @@ -395,35 +428,42 @@ struct UnsizedArrayOf void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1) { as_array (len).qsort (start, end); } - bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + bool serialize (hb_serialize_context_t *c, unsigned int items_len) { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c, count))) return_trace (false); - - /* Note: for structs that do not reference other structs, - * we do not need to call their sanitize() as we already did - * a bound check on the aggregate array size. We just include - * a small unreachable expression to make sure the structs - * pointed to do have a simple sanitize() as well as an - * assignment opreator. This ensures that they do not - * reference other structs via offsets. - */ - if (false) - { - arrayZ[0].sanitize (c); - Type v; - v = arrayZ[0]; - } - + TRACE_SERIALIZE (this); + if (unlikely (!c->extend (*this, items_len))) return_trace (false); return_trace (true); } + template + bool serialize (hb_serialize_context_t *c, Iterator items) + { + TRACE_SERIALIZE (this); + unsigned count = items.len (); + if (unlikely (!serialize (c, count))) return_trace (false); + /* TODO Umm. Just exhaust the iterator instead? Being extra + * cautious right now.. */ + for (unsigned i = 0; i < count; i++, ++items) + arrayZ[i] = *items; + return_trace (true); + } + + UnsizedArrayOf* copy (hb_serialize_context_t *c, unsigned count) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!as_array (count).copy (c))) return_trace (nullptr); + return_trace (out); + } + template - bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c, count))) return_trace (false); + if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], hb_forward (ds)...))) return_trace (false); return_trace (true); } @@ -442,7 +482,7 @@ struct UnsizedArrayOf /* Unsized array of offset's */ template -using UnsizedOffsetArrayOf = UnsizedArrayOf >; +using UnsizedOffsetArrayOf = UnsizedArrayOf>; /* Unsized array of offsets relative to the beginning of the array itself. */ template @@ -464,7 +504,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf } template - bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); return_trace ((UnsizedOffsetArrayOf @@ -553,7 +593,7 @@ struct ArrayOf return_trace (true); } template + hb_requires (hb_is_source_of (Iterator, Type))> bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); @@ -561,41 +601,30 @@ struct ArrayOf if (unlikely (!serialize (c, count))) return_trace (false); /* TODO Umm. Just exhaust the iterator instead? Being extra * cautious right now.. */ - for (unsigned i = 0; i < count; i++, items++) + for (unsigned i = 0; i < count; i++, ++items) arrayZ[i] = *items; return_trace (true); } - bool sanitize (hb_sanitize_context_t *c) const + ArrayOf* copy (hb_serialize_context_t *c) const { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return_trace (false); - - /* Note: for structs that do not reference other structs, - * we do not need to call their sanitize() as we already did - * a bound check on the aggregate array size. We just include - * a small unreachable expression to make sure the structs - * pointed to do have a simple sanitize() as well as an - * assignment opreator. This ensures that they do not - * reference other structs via offsets. - */ - if (false) - { - arrayZ[0].sanitize (c); - Type v; - v = arrayZ[0]; - } - - return_trace (true); + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!c->extend_min (out))) return_trace (nullptr); + c->check_assign (out->len, len); + if (unlikely (!as_array ().copy (c))) return_trace (nullptr); + return_trace (out); } + template - bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); + if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); unsigned int count = len; for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], hb_forward (ds)...))) return_trace (false); return_trace (true); } @@ -628,9 +657,9 @@ using PString = ArrayOf; /* Array of Offset's */ template -using OffsetArrayOf = ArrayOf >; +using OffsetArrayOf = ArrayOf>; template -using LOffsetArrayOf = ArrayOf >; +using LOffsetArrayOf = ArrayOf>; template using LOffsetLArrayOf = ArrayOf, HBUINT32>; @@ -658,12 +687,12 @@ struct OffsetListOf : OffsetArrayOf if (unlikely (!out)) return_trace (false); unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) - out->arrayZ[i].serialize_subset (c, (*this)[i], out); + out->arrayZ[i].serialize_subset (c, this->arrayZ[i], this, out); return_trace (true); } template - bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); return_trace (OffsetArrayOf::sanitize (c, this, hb_forward (ds)...)); @@ -705,26 +734,16 @@ struct HeadlessArrayOf return_trace (true); } - bool sanitize (hb_sanitize_context_t *c) const + template + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - - /* Note: for structs that do not reference other structs, - * we do not need to call their sanitize() as we already did - * a bound check on the aggregate array size. We just include - * a small unreachable expression to make sure the structs - * pointed to do have a simple sanitize() as well as an - * assignment opreator. This ensures that they do not - * reference other structs via offsets. - */ - if (false) - { - arrayZ[0].sanitize (c); - Type v; - v = arrayZ[0]; - } - + if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + unsigned int count = lenP1 ? lenP1 - 1 : 0; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!c->dispatch (arrayZ[i], hb_forward (ds)...))) + return_trace (false); return_trace (true); } @@ -765,13 +784,13 @@ struct ArrayOfM1 { return lenM1.static_size + (lenM1 + 1) * Type::static_size; } template - bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); unsigned int count = lenM1 + 1; for (unsigned int i = 0; i < count; i++) - if (unlikely (!arrayZ[i].sanitize (c, hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], hb_forward (ds)...))) return_trace (false); return_trace (true); } @@ -822,7 +841,7 @@ struct SortedArrayOf : ArrayOf return_trace (ret); } template + hb_requires (hb_is_sorted_source_of (Iterator, Type))> bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); @@ -830,7 +849,6 @@ struct SortedArrayOf : ArrayOf return_trace (ret); } - template Type &bsearch (const T &x, Type ¬_found = Crap (Type)) { return *as_array ().bsearch (x, ¬_found); } @@ -863,7 +881,7 @@ struct BinSearchHeader { len = v; assert (len == v); - entrySelector = MAX (1u, hb_bit_storage (v)) - 1; + entrySelector = hb_max (1u, hb_bit_storage (v)) - 1; searchRange = 16 * (1u << entrySelector); rangeShift = v * 16 > searchRange ? 16 * v - searchRange @@ -882,7 +900,7 @@ struct BinSearchHeader }; template -using BinSearchArrayOf = SortedArrayOf >; +using BinSearchArrayOf = SortedArrayOf>; struct VarSizedBinSearchHeader @@ -947,33 +965,12 @@ struct VarSizedBinSearchArrayOf unsigned int get_size () const { return header.static_size + header.nUnits * header.unitSize; } - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return_trace (false); - - /* Note: for structs that do not reference other structs, - * we do not need to call their sanitize() as we already did - * a bound check on the aggregate array size. We just include - * a small unreachable expression to make sure the structs - * pointed to do have a simple sanitize() as well as an - * assignment opreator. This ensures that they do not - * reference other structs via offsets. - */ - if (false) - { - (*this)[0].sanitize (c); - Type v; - v = (*this)[0]; - } - - return_trace (true); - } template - bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); + if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); unsigned int count = get_length (); for (unsigned int i = 0; i < count; i++) if (unlikely (!(*this)[i].sanitize (c, hb_forward (ds)...))) diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index e84319502..555ade53e 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -97,12 +97,12 @@ struct CFFIndex unsigned int offset_array_size () const { return calculate_offset_array_size (offSize, count); } - static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize) + static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize) { if (count == 0) return COUNT::static_size; else - return min_size + calculate_offset_array_size (offSize, count) + dataSize; + return min_size + calculate_offset_array_size (offSize_, count) + dataSize; } bool serialize (hb_serialize_context_t *c, const CFFIndex &src) @@ -132,7 +132,7 @@ struct CFFIndex if (unlikely (!c->extend_min (*this))) return_trace (false); this->count = byteArray.length; this->offSize = offSize_; - if (!unlikely (c->allocate_size (offSize_ * (byteArray.length + 1)))) + if (unlikely (!c->allocate_size (offSize_ * (byteArray.length + 1)))) return_trace (false); /* serialize indices */ @@ -167,7 +167,7 @@ struct CFFIndex byteArray.resize (buffArray.length); for (unsigned int i = 0; i < byteArray.length; i++) { - byteArray[i] = byte_str_t (buffArray[i].arrayZ (), buffArray[i].length); + byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length); } bool result = this->serialize (c, offSize_, byteArray); byteArray.fini (); @@ -277,7 +277,7 @@ struct CFFIndexOf : CFFIndex if (unlikely (!c->extend_min (*this))) return_trace (false); this->count = dataArrayLen; this->offSize = offSize_; - if (!unlikely (c->allocate_size (offSize_ * (dataArrayLen + 1)))) + if (unlikely (!c->allocate_size (offSize_ * (dataArrayLen + 1)))) return_trace (false); /* serialize indices */ @@ -428,7 +428,7 @@ struct FDArray : CFFIndexOf if (unlikely (!c->extend_min (*this))) return_trace (false); this->count = fontDicts.length; this->offSize = offSize_; - if (!unlikely (c->allocate_size (offSize_ * (fontDicts.length + 1)))) + if (unlikely (!c->allocate_size (offSize_ * (fontDicts.length + 1)))) return_trace (false); /* serialize font dict offsets */ @@ -465,7 +465,7 @@ struct FDArray : CFFIndexOf if (unlikely (!c->extend_min (*this))) return_trace (false); this->count = fdCount; this->offSize = offSize_; - if (!unlikely (c->allocate_size (offSize_ * (fdCount + 1)))) + if (unlikely (!c->allocate_size (offSize_ * (fdCount + 1)))) return_trace (false); /* serialize font dict offsets */ @@ -604,9 +604,9 @@ struct FDSelect { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) && - (format == 0)? + ((format == 0)? u.format0.sanitize (c, fdcount): - u.format3.sanitize (c, fdcount))); + u.format3.sanitize (c, fdcount)))); } bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs) diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc index 1d97e5444..e6dd6a7b8 100644 --- a/src/hb-ot-cff1-table.cc +++ b/src/hb-ot-cff1-table.cc @@ -27,6 +27,8 @@ #include "hb-ot-cff1-table.hh" #include "hb-cff1-interp-cs.hh" +#ifndef HB_NO_CFF + using namespace CFF; /* SID to code */ @@ -305,6 +307,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { +#ifdef HB_NO_OT_FONT_CFF + /* XXX Remove check when this code moves to .hh file. */ + return true; +#endif + bounds_t bounds; if (!_get_bounds (this, glyph, bounds)) @@ -383,3 +390,5 @@ bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_code } return false; } + +#endif diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 3957d5daf..b1298b778 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -576,7 +576,7 @@ struct CFF1StringIndex : CFF1Index TRACE_SERIALIZE (this); if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0))) { - if (!unlikely (c->extend_min (this->count))) + if (unlikely (!c->extend_min (this->count))) return_trace (false); count = 0; return_trace (true); @@ -599,9 +599,9 @@ struct CFF1StringIndex : CFF1Index } /* in parallel to above */ - unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const hb_bimap_t &sidmap) const + unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_bimap_t &sidmap) const { - offSize = 0; + offSize_ = 0; if ((count == 0) || (sidmap.get_count () == 0)) return count.static_size; @@ -610,8 +610,8 @@ struct CFF1StringIndex : CFF1Index if (sidmap[i] != HB_MAP_VALUE_INVALID) dataSize += length_at (i); - offSize = calcOffSize(dataSize); - return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize); + offSize_ = calcOffSize(dataSize); + return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_count (), dataSize); } }; diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc index d2463d785..f1fa6ec30 100644 --- a/src/hb-ot-cff2-table.cc +++ b/src/hb-ot-cff2-table.cc @@ -27,6 +27,8 @@ #include "hb-ot-cff2-table.hh" #include "hb-cff2-interp-cs.hh" +#ifndef HB_NO_OT_FONT_CFF + using namespace CFF; struct extents_param_t @@ -99,6 +101,11 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { +#ifdef HB_NO_OT_FONT_CFF + /* XXX Remove check when this code moves to .hh file. */ + return true; +#endif + if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; unsigned int num_coords; @@ -134,3 +141,5 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, return true; } + +#endif diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index a7b0ba9be..74acc771a 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -56,11 +56,11 @@ struct CFF2FDSelect TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) && - (format == 0)? + ((format == 0)? u.format0.sanitize (c, fdcount): ((format == 3)? u.format3.sanitize (c, fdcount): - u.format4.sanitize (c, fdcount)))); + u.format4.sanitize (c, fdcount))))); } bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs) diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 0a7d1ef67..9e9679f8b 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -93,7 +93,7 @@ struct CmapSubtableFormat4 this->length = get_sub_table_size (segments); this->segCountX2 = segments.length * 2; - this->entrySelector = MAX (1u, hb_bit_storage (segments.length)) - 1; + this->entrySelector = hb_max (1u, hb_bit_storage (segments.length)) - 1; this->searchRange = 2 * (1u << this->entrySelector); this->rangeShift = segments.length * 2 > this->searchRange ? 2 * segments.length - this->searchRange @@ -142,7 +142,7 @@ struct CmapSubtableFormat4 for (unsigned int j = 0; j < num_codepoints; j++) { hb_codepoint_t cp = segments[i].start_code + j; - hb_codepoint_t new_gid; + hb_codepoint_t new_gid = 0; if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid))) return_trace (false); glyph_id_array[j] = new_gid; @@ -183,7 +183,7 @@ struct CmapSubtableFormat4 hb_codepoint_t cp = HB_SET_VALUE_INVALID; while (plan->unicodes->next (&cp)) { - hb_codepoint_t new_gid; + hb_codepoint_t new_gid = 0; if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid))) { DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp); @@ -348,7 +348,7 @@ struct CmapSubtableFormat4 /* Some broken fonts have too long of a "length" value. * If that is the case, just change the value to truncate * the subtable at the end of the blob. */ - uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535, + uint16_t new_length = (uint16_t) hb_min ((uintptr_t) 65535, (uintptr_t) (c->end - (char *) this)); if (!c->try_set (&length, new_length)) @@ -478,7 +478,7 @@ struct CmapSubtableLongSegmented { for (unsigned int i = 0; i < this->groups.len; i++) { out->add_range (this->groups[i].startCharCode, - MIN ((hb_codepoint_t) this->groups[i].endCharCode, + hb_min ((hb_codepoint_t) this->groups[i].endCharCode, (hb_codepoint_t) HB_UNICODE_MAX)); } } @@ -518,31 +518,31 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented bool serialize (hb_serialize_context_t *c, - const hb_sorted_vector_t &groups) + const hb_sorted_vector_t &groups_data) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); this->format = 12; this->reserved = 0; - this->length = get_sub_table_size (groups); + this->length = get_sub_table_size (groups_data); - return_trace (CmapSubtableLongSegmented::serialize (c, groups)); + return_trace (CmapSubtableLongSegmented::serialize (c, groups_data)); } - static size_t get_sub_table_size (const hb_sorted_vector_t &groups) + static size_t get_sub_table_size (const hb_sorted_vector_t &groups_data) { - return 16 + 12 * groups.length; + return 16 + 12 * groups_data.length; } static bool create_sub_table_plan (const hb_subset_plan_t *plan, - hb_sorted_vector_t *groups) + hb_sorted_vector_t *groups_out) { CmapSubtableLongGroup *group = nullptr; hb_codepoint_t cp = HB_SET_VALUE_INVALID; while (plan->unicodes->next (&cp)) { - hb_codepoint_t new_gid; + hb_codepoint_t new_gid = 0; if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid))) { DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp); @@ -551,7 +551,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented if (!group || !_is_gid_consecutive (group, cp, new_gid)) { - group = groups->push (); + group = groups_out->push (); group->startCharCode = cp; group->endCharCode = cp; group->glyphID = new_gid; @@ -560,8 +560,8 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented } DEBUG_MSG(SUBSET, nullptr, "cmap"); - for (unsigned int i = 0; i < groups->length; i++) { - CmapSubtableLongGroup& group = (*groups)[i]; + for (unsigned int i = 0; i < groups_out->length; i++) { + CmapSubtableLongGroup& group = (*groups_out)[i]; DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode)); } @@ -623,7 +623,7 @@ struct DefaultUVS : SortedArrayOf for (unsigned int i = 0; i < count; i++) { hb_codepoint_t first = arrayZ[i].startUnicodeValue; - hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount), + hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount), (hb_codepoint_t) HB_UNICODE_MAX); out->add_range (first, last); } @@ -863,6 +863,7 @@ struct cmap if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments))) return false; + if (!find_subtable (12)) return true; return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups); } @@ -881,8 +882,7 @@ struct cmap table->version = 0; - if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3))) - return false; + if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ cmap_subset_plan.format12_groups ? 3 : 2))) return false; // TODO(grieger): Convert the below to a for loop @@ -897,9 +897,12 @@ struct cmap format4_plat3_rec.encodingID = 1; // Unicode BMP // Format 12 Encoding Record - EncodingRecord &format12_rec = table->encodingRecord[2]; - format12_rec.platformID = 3; // Windows - format12_rec.encodingID = 10; // Unicode UCS-4 + if (cmap_subset_plan.format12_groups) + { + EncodingRecord &format12_rec = table->encodingRecord[2]; + format12_rec.platformID = 3; // Windows + format12_rec.encodingID = 10; // Unicode UCS-4 + } // Write out format 4 sub table { @@ -913,7 +916,9 @@ struct cmap } // Write out format 12 sub table. + if (cmap_subset_plan.format12_groups) { + EncodingRecord &format12_rec = table->encodingRecord[2]; CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table); subtable.u.format = 12; @@ -1154,6 +1159,18 @@ struct cmap return &(this+result.subtable); } + bool find_subtable (unsigned format) const + { + auto it = + + hb_iter (encodingRecord) + | hb_map (&EncodingRecord::subtable) + | hb_map (hb_add (this)) + | hb_filter ([&] (const CmapSubtable& _) { return _.u.format == format; }) + ; + + return it.len (); + } + public: bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index 333ceaaba..7955cf651 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -144,7 +144,7 @@ struct IndexSubtableFormat1Or3 } IndexSubtableHeader header; - UnsizedArrayOf > + UnsizedArrayOf> offsetArrayZ; public: DEFINE_SIZE_ARRAY(8, offsetArrayZ); @@ -349,15 +349,15 @@ struct CBLC if (unlikely (!count)) return Null(BitmapSizeTable); - unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem); + unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem); if (!requested_ppem) requested_ppem = 1<<30; /* Choose largest strike. */ unsigned int best_i = 0; - unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY); + unsigned int best_ppem = hb_max (sizeTables[0].ppemX, sizeTables[0].ppemY); for (unsigned int i = 1; i < count; i++) { - unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY); + unsigned int ppem = hb_max (sizeTables[i].ppemX, sizeTables[i].ppemY); if ((requested_ppem <= ppem && ppem < best_ppem) || (requested_ppem > best_ppem && ppem > best_ppem)) { @@ -442,12 +442,12 @@ struct CBDT } /* Convert to font units. */ - double x_scale = upem / (double) strike.ppemX; - double y_scale = upem / (double) strike.ppemY; - extents->x_bearing = round (extents->x_bearing * x_scale); - extents->y_bearing = round (extents->y_bearing * y_scale); - extents->width = round (extents->width * x_scale); - extents->height = round (extents->height * y_scale); + float x_scale = upem / (float) strike.ppemX; + float y_scale = upem / (float) strike.ppemY; + extents->x_bearing = roundf (extents->x_bearing * x_scale); + extents->y_bearing = roundf (extents->y_bearing * y_scale); + extents->width = roundf (extents->width * x_scale); + extents->height = roundf (extents->height * y_scale); return true; } diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index a57911ad0..90f89d583 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -125,9 +125,9 @@ struct COLR protected: HBUINT16 version; /* Table version number (starts at 0). */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ - LNNOffsetTo > + LNNOffsetTo> baseGlyphsZ; /* Offset to Base Glyph records. */ - LNNOffsetTo > + LNNOffsetTo> layersZ; /* Offset to Layer Records. */ HBUINT16 numLayers; /* Number of Layer Records. */ public: diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 407049350..9ec2957ea 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -87,15 +87,15 @@ struct CPALV1Tail } protected: - LNNOffsetTo > + LNNOffsetTo> paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LNNOffsetTo > + LNNOffsetTo> paletteLabelsZ; /* Offset from the beginning of CPAL table to * the palette labels array. Set to 0 if no * array is provided. */ - LNNOffsetTo > + LNNOffsetTo> colorLabelsZ; /* Offset from the beginning of CPAL table to * the color labels array. Set to 0 * if no array is provided. */ @@ -144,7 +144,7 @@ struct CPAL { hb_array_t segment_colors = palette_colors.sub_array (start_offset, *color_count); /* Always return numColors colors per palette even if it has out-of-bounds start index. */ - unsigned int count = MIN (MAX (numColors - start_offset, 0), *color_count); + unsigned int count = hb_min ((unsigned) hb_max ((int) (numColors - start_offset), 0), *color_count); *color_count = count; for (unsigned int i = 0; i < count; i++) colors[i] = segment_colors[i]; /* Bound-checked read. */ @@ -176,7 +176,7 @@ struct CPAL HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ - LNNOffsetTo > + LNNOffsetTo> colorRecordsZ; /* Offset from the beginning of CPAL table to * the first ColorRecord. */ UnsizedArrayOf diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index f6bdbb3dd..9b725c46e 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -121,7 +121,7 @@ struct SBIXStrike HBUINT16 resolution; /* The device pixel density (in PPI) for which this * strike was designed. (E.g., 96 PPI, 192 PPI.) */ protected: - UnsizedArrayOf > + UnsizedArrayOf> imageOffsetsZ; /* Offset from the beginning of the strike data header * to bitmap data for an individual glyph ID. */ public: @@ -175,7 +175,7 @@ struct sbix if (unlikely (!count)) return Null(SBIXStrike); - unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem); + unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem); if (!requested_ppem) requested_ppem = 1<<30; /* Choose largest strike. */ /* TODO Add DPI sensitivity as well? */ @@ -242,11 +242,11 @@ struct sbix /* Convert to font units. */ if (strike_ppem) { - double scale = font->face->get_upem () / (double) strike_ppem; - extents->x_bearing = round (extents->x_bearing * scale); - extents->y_bearing = round (extents->y_bearing * scale); - extents->width = round (extents->width * scale); - extents->height = round (extents->height * scale); + float scale = font->face->get_upem () / (float) strike_ppem; + extents->x_bearing = roundf (extents->x_bearing * scale); + extents->y_bearing = roundf (extents->y_bearing * scale); + extents->width = roundf (extents->width * scale); + extents->height = roundf (extents->height * scale); } hb_blob_destroy (blob); diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index 6e8eddf24..926d61e0f 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -62,7 +62,7 @@ struct SVGDocumentIndexEntry * this index entry. */ HBUINT16 endGlyphID; /* The last glyph ID in the range described by * this index entry. Must be >= startGlyphID. */ - LNNOffsetTo > + LNNOffsetTo> svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ HBUINT32 svgDocLength; /* Length of the SVG document. @@ -107,7 +107,7 @@ struct SVG protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo > + LOffsetTo> svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ /* Array of SVG Document Index Entries. */ diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 791135b10..20c602cdc 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -47,6 +47,8 @@ * @include: hb-ot.h * * Functions for fetching color-font information from OpenType font faces. + * + * HarfBuzz supports `COLR`/`CPAL`, `sbix`, `CBDT`, and `SVG` color fonts. **/ @@ -57,42 +59,54 @@ /** * hb_ot_color_has_palettes: - * @face: a font face. + * @face: #hb_face_t to work upon * - * Returns: whether CPAL table is available. + * Tests whether a face includes a `CPAL` color-palette table. + * + * Return value: true if data found, false otherwise * * Since: 2.1.0 */ hb_bool_t hb_ot_color_has_palettes (hb_face_t *face) { +#ifdef HB_NO_COLOR + return false; +#endif return face->table.CPAL->has_data (); } /** * hb_ot_color_palette_get_count: - * @face: a font face. + * @face: #hb_face_t to work upon * - * Returns: the number of color palettes in @face, or zero if @face has - * no colors. + * Fetches the number of color palettes in a face. + * + * Return value: the number of palettes found * * Since: 2.1.0 */ unsigned int hb_ot_color_palette_get_count (hb_face_t *face) { +#ifdef HB_NO_COLOR + return 0; +#endif return face->table.CPAL->get_palette_count (); } /** * hb_ot_color_palette_get_name_id: - * @face: a font face. - * @palette_index: the index of the color palette whose name is being requested. + * @face: #hb_face_t to work upon + * @palette_index: The index of the color palette * - * Retrieves the name id of a color palette. For example, a color font can - * have themed palettes like "Spring", "Summer", "Fall", and "Winter". + * Fetches the `name` table Name ID that provides display names for + * a `CPAL` color palette. * - * Returns: an identifier within @face's `name` table. + * Palette display names can be generic (e.g., "Default") or provide + * specific, themed names (e.g., "Spring", "Summer", "Fall", and "Winter"). + * + * Return value: the Named ID found for the palette. * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID. * * Since: 2.1.0 @@ -101,15 +115,24 @@ hb_ot_name_id_t hb_ot_color_palette_get_name_id (hb_face_t *face, unsigned int palette_index) { +#ifdef HB_NO_COLOR + return HB_OT_NAME_ID_INVALID; +#endif return face->table.CPAL->get_palette_name_id (palette_index); } /** * hb_ot_color_palette_color_get_name_id: - * @face: a font face. - * @color_index: palette entry index. + * @face: #hb_face_t to work upon + * @color_index: The index of the color * - * Returns: Name ID associated with a palette entry, e.g. eye color + * Fetches the `name` table Name ID that provides display names for + * the specificed color in a face's `CPAL` color palette. + * + * Display names can be generic (e.g., "Background") or specific + * (e.g., "Eye color"). + * + * Return value: the Name ID found for the color. * * Since: 2.1.0 */ @@ -117,15 +140,20 @@ hb_ot_name_id_t hb_ot_color_palette_color_get_name_id (hb_face_t *face, unsigned int color_index) { +#ifdef HB_NO_COLOR + return HB_OT_NAME_ID_INVALID; +#endif return face->table.CPAL->get_color_name_id (color_index); } /** * hb_ot_color_palette_get_flags: - * @face: a font face - * @palette_index: the index of the color palette whose flags are being requested + * @face: #hb_face_t to work upon + * @palette_index: The index of the color palette * - * Returns: the flags for the requested color palette. + * Fetches the flags defined for a color palette. + * + * Return value: the #hb_ot_color_palette_flags_t of the requested color palette * * Since: 2.1.0 */ @@ -133,30 +161,30 @@ hb_ot_color_palette_flags_t hb_ot_color_palette_get_flags (hb_face_t *face, unsigned int palette_index) { +#ifdef HB_NO_COLOR + return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; +#endif return face->table.CPAL->get_palette_flags (palette_index); } /** * hb_ot_color_palette_get_colors: - * @face: a font face. - * @palette_index:the index of the color palette whose colors - * are being requested. - * @start_offset: the index of the first color being requested. - * @color_count: (inout) (optional): on input, how many colors - * can be maximally stored into the @colors array; - * on output, how many colors were actually stored. - * @colors: (array length=color_count) (out) (optional): - * an array of #hb_color_t records. After calling - * this function, @colors will be filled with - * the palette colors. If @colors is NULL, the function - * will just return the number of total colors - * without storing any actual colors; this can be used - * for allocating a buffer of suitable size before calling - * hb_ot_color_palette_get_colors() a second time. + * @face: #hb_face_t to work upon + * @palette_index: the index of the color palette to query + * @start_offset: offset of the first color to retrieve + * @color_count: (inout) (optional): Input = the maximum number of colors to return; + * Output = the actual number of colors returned (may be zero) + * @colors: (out) (array length=color_count) (nullable): The array of #hb_color_t records found * - * Retrieves the colors in a color palette. + * Fetches a list of the colors in a color palette. * - * Returns: the total number of colors in the palette. + * After calling this function, @colors will be filled with the palette + * colors. If @colors is NULL, the function will just return the number + * of total colors without storing any actual colors; this can be used + * for allocating a buffer of suitable size before calling + * hb_ot_color_palette_get_colors() a second time. + * + * Return value: the total number of colors in the palette * * Since: 2.1.0 */ @@ -167,6 +195,11 @@ hb_ot_color_palette_get_colors (hb_face_t *face, unsigned int *colors_count /* IN/OUT. May be NULL. */, hb_color_t *colors /* OUT. May be NULL. */) { +#ifdef HB_NO_COLOR + if (colors_count) + *colors_count = 0; + return 0; +#endif return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors); } @@ -177,28 +210,36 @@ hb_ot_color_palette_get_colors (hb_face_t *face, /** * hb_ot_color_has_layers: - * @face: a font face. + * @face: #hb_face_t to work upon * - * Returns: whether COLR table is available. + * Tests whether a face includes any `COLR` color layers. + * + * Return value: true if data found, false otherwise * * Since: 2.1.0 */ hb_bool_t hb_ot_color_has_layers (hb_face_t *face) { +#ifdef HB_NO_COLOR + return false; +#endif return face->table.COLR->has_data (); } /** * hb_ot_color_glyph_get_layers: - * @face: a font face. - * @glyph: a layered color glyph id. - * @start_offset: starting offset of layers. - * @count: (inout) (optional): gets number of layers available to be written on buffer - * and returns number of written layers. - * @layers: (array length=count) (out) (optional): layers buffer to buffer. + * @face: #hb_face_t to work upon + * @glyph: The glyph index to query + * @start_offset: offset of the first layer to retrieve + * @layer_count: (inout) (optional): Input = the maximum number of layers to return; + * Output = the actual number of layers returned (may be zero) + * @layers: (out) (array length=layer_count) (nullable): The array of layers found * - * Returns: Total number of layers a layered color glyph have. + * Fetches a list of all color layers for the specified glyph index in the specified + * face. The list returned will begin at the offset provided. + * + * Return value: Total number of layers available for the glyph index queried * * Since: 2.1.0 */ @@ -206,10 +247,15 @@ unsigned int hb_ot_color_glyph_get_layers (hb_face_t *face, hb_codepoint_t glyph, unsigned int start_offset, - unsigned int *count, /* IN/OUT. May be NULL. */ + unsigned int *layer_count, /* IN/OUT. May be NULL. */ hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { - return face->table.COLR->get_glyph_layers (glyph, start_offset, count, layers); +#ifdef HB_NO_COLOR + if (layer_count) + *layer_count = 0; + return 0; +#endif + return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers); } @@ -219,34 +265,40 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, /** * hb_ot_color_has_svg: - * @face: a font face. + * @face: #hb_face_t to work upon. * - * Check whether @face has SVG glyph images. + * Tests whether a face includes any `SVG` glyph images. * - * Returns true if available, false otherwise. + * Return value: true if data found, false otherwise. * * Since: 2.1.0 */ hb_bool_t hb_ot_color_has_svg (hb_face_t *face) { +#ifdef HB_NO_COLOR + return false; +#endif return face->table.SVG->has_data (); } /** * hb_ot_color_glyph_reference_svg: - * @face: a font face. - * @glyph: a svg glyph index. + * @face: #hb_face_t to work upon + * @glyph: a svg glyph index * - * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded. + * Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded. * - * Returns: (transfer full): respective svg blob of the glyph, if available. + * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available * * Since: 2.1.0 */ hb_blob_t * hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) { +#ifdef HB_NO_COLOR + return hb_blob_get_empty (); +#endif return face->table.SVG->reference_blob_for_glyph (glyph); } @@ -257,36 +309,43 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) /** * hb_ot_color_has_png: - * @face: a font face. + * @face: #hb_face_t to work upon * - * Check whether @face has PNG glyph images (either CBDT or sbix tables). + * Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables). * - * Returns true if available, false otherwise. + * Return value: true if data found, false otherwise * * Since: 2.1.0 */ hb_bool_t hb_ot_color_has_png (hb_face_t *face) { +#ifdef HB_NO_COLOR + return false; +#endif return face->table.CBDT->has_data () || face->table.sbix->has_data (); } /** * hb_ot_color_glyph_reference_png: - * @font: a font object, not face. upem should be set on - * that font object if one wants to get optimal png blob, otherwise - * return the biggest one - * @glyph: a glyph index. + * @font: #hb_font_t to work upon + * @glyph: a glyph index * - * Get PNG image for a glyph. + * Fetches the PNG image for a glyph. This function takes a font object, not a face object, + * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font + * object. If UPEM is unset, the blob returned will be the largest PNG available. * - * Returns: (transfer full): respective PNG blob of the glyph, if available. + * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available * * Since: 2.1.0 */ hb_blob_t * hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph) { +#ifdef HB_NO_COLOR + return hb_blob_get_empty (); +#endif + hb_blob_t *blob = hb_blob_get_empty (); if (font->face->table.sbix->has_data ()) diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 49646bf3a..63ef20a1a 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -59,11 +59,11 @@ hb_ot_color_palette_color_get_name_id (hb_face_t *face, /** * hb_ot_color_palette_flags_t: - * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special + * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: Default indicating that there is nothing special * to note about a color palette. - * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color + * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: Flag indicating that the color * palette is appropriate to use when displaying the font on a light background such as white. - * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color + * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color * palette is appropriate to use when displaying the font on a dark background such as black. * * Since: 2.1.0 @@ -110,7 +110,7 @@ HB_EXTERN unsigned int hb_ot_color_glyph_get_layers (hb_face_t *face, hb_codepoint_t glyph, unsigned int start_offset, - unsigned int *count, /* IN/OUT. May be NULL. */ + unsigned int *layer_count, /* IN/OUT. May be NULL. */ hb_ot_color_layer_t *layers /* OUT. May be NULL. */); /* diff --git a/src/hb-ot-deprecated.h b/src/hb-ot-deprecated.h index bce51b71e..bc72f8a70 100644 --- a/src/hb-ot-deprecated.h +++ b/src/hb-ot-deprecated.h @@ -40,6 +40,10 @@ HB_BEGIN_DECLS #ifndef HB_DISABLE_DEPRECATED +/* https://github.com/harfbuzz/harfbuzz/issues/1734 */ +#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER + + /* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */ HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t hb_ot_layout_table_choose_script (hb_face_t *face, diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 01d456369..21ca3c08d 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -181,19 +181,20 @@ hb_ot_get_glyph_extents (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; - bool ret = ot_face->sbix->get_extents (font, glyph, extents); - if (!ret) - ret = ot_face->glyf->get_extents (font, glyph, extents); -#if !defined(HB_NO_OT_FONT_CFF) - if (!ret) - ret = ot_face->cff1->get_extents (glyph, extents); - if (!ret) - ret = ot_face->cff2->get_extents (font, glyph, extents); + bool ret = false; + +#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) + if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents); #endif -#if !defined(HB_NO_OT_FONT_BITMAP) - if (!ret) - ret = ot_face->CBDT->get_extents (font, glyph, extents); + if (!ret) ret = ot_face->glyf->get_extents (glyph, extents); +#ifndef HB_NO_OT_FONT_CFF + if (!ret) ret = ot_face->cff1->get_extents (glyph, extents); + if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents); #endif +#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) + if (!ret) ret = ot_face->CBDT->get_extents (font, glyph, extents); +#endif + // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index b65fdddb1..90addc46b 100644 --- a/src/hb-ot-glyf-table.hh +++ b/src/hb-ot-glyf-table.hh @@ -21,7 +21,7 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * Google Author(s): Behdad Esfahbod +* Google Author(s): Behdad Esfahbod, Garret Rieger, Roderick Sheeter * Adobe Author(s): Michiharu Ariza */ @@ -32,7 +32,6 @@ #include "hb-ot-head-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-var-gvar-table.hh" -#include "hb-subset-glyf.hh" #include @@ -63,7 +62,7 @@ struct loca public: DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always * check the size externally, allow Null() object of it by - * defining it MIN() instead. */ + * defining it _MIN instead. */ }; @@ -86,26 +85,172 @@ struct glyf return_trace (true); } - bool subset (hb_subset_plan_t *plan) const + template + static bool + _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets) { - hb_blob_t *glyf_prime = nullptr; - hb_blob_t *loca_prime = nullptr; + unsigned max_offset = + padded_offsets | hb_reduce(hb_add, 0); + unsigned num_offsets = padded_offsets.len () + 1; + bool use_short_loca = max_offset < 0x1FFFF; + unsigned entry_size = use_short_loca ? 2 : 4; + char *loca_prime_data = (char *) calloc (entry_size, num_offsets); - bool success = true; - bool use_short_loca = false; - if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) { - success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime); - success = success && plan->add_table (HB_OT_TAG_loca, loca_prime); - success = success && _add_head_and_set_loca_version (plan, use_short_loca); - } else { - success = false; - } - hb_blob_destroy (loca_prime); - hb_blob_destroy (glyf_prime); + if (unlikely (!loca_prime_data)) return false; - return success; + DEBUG_MSG(SUBSET, nullptr, "loca entry_size %d num_offsets %d max_offset %d size %d", entry_size, num_offsets, max_offset, entry_size * num_offsets); + + if (use_short_loca) + _write_loca (padded_offsets, 1, hb_array ((HBUINT16*) loca_prime_data, num_offsets)); + else + _write_loca (padded_offsets, 0, hb_array ((HBUINT32*) loca_prime_data, num_offsets)); + + hb_blob_t * loca_blob = hb_blob_create (loca_prime_data, + entry_size * num_offsets, + HB_MEMORY_MODE_WRITABLE, + loca_prime_data, + free); + + bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) + && _add_head_and_set_loca_version(plan, use_short_loca); + + hb_blob_destroy (loca_blob); + return result; } + template + static void + _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest) + { + unsigned int offset = 0; + dest << 0; + + it + | hb_map ([=, &offset] (unsigned int padded_size) { + offset += padded_size; + DEBUG_MSG(SUBSET, nullptr, "loca entry offset %d", offset); + return offset >> right_shift; + }) + | hb_sink (dest) + ; + } + + // requires source of SubsetGlyph complains the identifier isn't declared + template + bool serialize(hb_serialize_context_t *c, + Iterator it, + const hb_subset_plan_t *plan) + { + TRACE_SERIALIZE (this); + + + it + | hb_apply ([=] (const SubsetGlyph& _) { _.serialize (c, plan); }) + ; + + return_trace (true); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + + glyf *glyf_prime = c->serializer->start_embed (); + if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); + + // Byte region(s) per glyph to output + // unpadded, hints removed if so requested + // If we fail to process a glyph we produce an empty (0-length) glyph + hb_vector_t glyphs; + _populate_subset_glyphs (c->plan, &glyphs); + + glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan); + + auto padded_offsets = + + hb_iter (glyphs) + | hb_map (&SubsetGlyph::padded_size) + ; + + if (c->serializer->in_error ()) return_trace (false); + return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, padded_offsets))); + } + + template + void + _populate_subset_glyphs (const hb_subset_plan_t * plan, + hb_vector_t * glyphs /* OUT */) const + { + OT::glyf::accelerator_t glyf; + glyf.init (plan->source); + + + hb_range (plan->num_output_glyphs ()) + | hb_map ([&] (hb_codepoint_t new_gid) { + SubsetGlyph subset_glyph; + subset_glyph.new_gid = new_gid; + + // should never fail: all old gids should be mapped + if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph; + + subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, subset_glyph.old_gid); + if (plan->drop_hints) subset_glyph.drop_hints (glyf); + else subset_glyph.dest_start = subset_glyph.source_glyph; + + return subset_glyph; + }) + | hb_sink (glyphs) + ; + + glyf.fini(); + } + + static void + _fix_component_gids (const hb_subset_plan_t *plan, + hb_bytes_t glyph) + { + OT::glyf::CompositeGlyphHeader::Iterator iterator; + if (OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, + glyph.length, + &iterator)) + { + do + { + hb_codepoint_t new_gid; + if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex, + &new_gid)) + continue; + ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid; + } while (iterator.move_to_next ()); + } + } + + static void + _zero_instruction_length (hb_bytes_t glyph) + { + const GlyphHeader &glyph_header = StructAtOffset (&glyph, 0); + int16_t num_contours = (int16_t) glyph_header.numberOfContours; + if (num_contours <= 0) return; // only for simple glyphs + + const HBUINT16 &instruction_length = StructAtOffset (&glyph, GlyphHeader::static_size + 2 * num_contours); + (HBUINT16 &) instruction_length = 0; + } + + static bool _remove_composite_instruction_flag (hb_bytes_t glyph) + { + const GlyphHeader &glyph_header = StructAtOffset (&glyph, 0); + if (glyph_header.numberOfContours >= 0) return true; // only for composites + + /* remove WE_HAVE_INSTRUCTIONS from flags in dest */ + OT::glyf::CompositeGlyphHeader::Iterator composite_it; + if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false; + const OT::glyf::CompositeGlyphHeader *composite_header; + do { + composite_header = composite_it.current; + OT::HBUINT16 *flags = const_cast (&composite_header->flags); + *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS; + } while (composite_it.move_to_next ()); + return true; +} + static bool _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) { @@ -261,6 +406,7 @@ struct glyf } public: + // TODO rewrite using new iterator framework if possible struct Iterator { const char *glyph_start; @@ -330,7 +476,7 @@ struct glyf loca_table = hb_sanitize_context_t ().reference_table (face); glyf_table = hb_sanitize_context_t ().reference_table (face); - num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; + num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; gvar_accel.init (face); hmtx_accel.init (face); @@ -690,7 +836,7 @@ struct glyf public: /* based on FontTools _g_l_y_f.py::trim */ bool remove_padding (unsigned int start_offset, - unsigned int *end_offset) const + unsigned int *end_offset) const { if (*end_offset - start_offset < GlyphHeader::static_size) return true; @@ -788,61 +934,55 @@ struct glyf return true; } - bool get_instruction_offsets (unsigned int start_offset, - unsigned int end_offset, - unsigned int *instruction_start /* OUT */, - unsigned int *instruction_end /* OUT */) const + bool get_instruction_length (hb_bytes_t glyph, + unsigned int * length /* OUT */) const { - if (end_offset - start_offset < GlyphHeader::static_size) + /* Empty glyph; no instructions. */ + if (glyph.length < GlyphHeader::static_size) { - *instruction_start = 0; - *instruction_end = 0; - return true; /* Empty glyph; no instructions. */ + *length = 0; + // only 0 byte glyphs are healthy when missing GlyphHeader + return glyph.length == 0; } - const GlyphHeader &glyph_header = StructAtOffset (glyf_table, start_offset); + const GlyphHeader &glyph_header = StructAtOffset (&glyph, 0); int16_t num_contours = (int16_t) glyph_header.numberOfContours; if (num_contours < 0) { + unsigned int start = glyph.length; + unsigned int end = glyph.length; + unsigned int glyph_offset = &glyph - glyf_table; CompositeGlyphHeader::Iterator composite_it; - if (unlikely (!CompositeGlyphHeader::get_iterator ( - (const char*) this->glyf_table + start_offset, - end_offset - start_offset, &composite_it))) return false; + if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false; const CompositeGlyphHeader *last; do { last = composite_it.current; } while (composite_it.move_to_next ()); if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS) - *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size (); - else - *instruction_start = end_offset; - *instruction_end = end_offset; - if (unlikely (*instruction_start > *instruction_end)) + start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size () - glyph_offset; + if (unlikely (start > end)) { - DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset); + DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside %d byte buffer", start, glyph.length); return false; } + *length = end - start; } else { - unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours; - if (unlikely (instruction_length_offset + 2 > end_offset)) + unsigned int instruction_length_offset = GlyphHeader::static_size + 2 * num_contours; + if (unlikely (instruction_length_offset + 2 > glyph.length)) { DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength."); return false; } - const HBUINT16 &instruction_length = StructAtOffset (glyf_table, instruction_length_offset); - unsigned int start = instruction_length_offset + 2; - unsigned int end = start + (uint16_t) instruction_length; - if (unlikely (end > end_offset)) // Out of bounds of the current glyph + const HBUINT16 &instruction_length = StructAtOffset (&glyph, instruction_length_offset); + if (unlikely (instruction_length_offset + instruction_length > glyph.length)) // Out of bounds of the current glyph { DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries."); return false; } - - *instruction_start = start; - *instruction_end = end; + *length = (uint16_t) instruction_length; } return true; } @@ -896,15 +1036,34 @@ struct glyf const GlyphHeader &glyph_header = StructAtOffset (glyf_table, start_offset); /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */ - /* extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); */ + /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */ extents->x_bearing = hmtx_accel.get_side_bearing (glyph); - extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); - extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - MIN (glyph_header.xMin, glyph_header.xMax); - extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; + extents->y_bearing = hb_max (glyph_header.yMin, glyph_header.yMax); + extents->width = hb_max (glyph_header.xMin, glyph_header.xMax) - hb_min (glyph_header.xMin, glyph_header.xMax); + extents->height = hb_min (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; return true; } + hb_bytes_t bytes_for_glyph (const char * glyf, hb_codepoint_t gid) + { + unsigned int start_offset, end_offset; + if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) && + remove_padding (start_offset, &end_offset)))) + { + DEBUG_MSG(SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid); + return hb_bytes_t (); + } + hb_bytes_t glyph = hb_bytes_t (glyf + start_offset, end_offset - start_offset); + if (glyph.length == 0) return glyph; + if (unlikely (glyph.length < GlyphHeader::static_size)) + { + DEBUG_MSG(SUBSET, nullptr, "Glyph size smaller than minimum header %d", gid); + return hb_bytes_t (); + } + return glyph; + } + private: bool short_offset; unsigned int num_glyphs; @@ -917,12 +1076,99 @@ struct glyf vmtx::accelerator_t vmtx_accel; }; + + struct SubsetGlyph + { + hb_codepoint_t new_gid; + hb_codepoint_t old_gid; + hb_bytes_t source_glyph; + hb_bytes_t dest_start; // region of source_glyph to copy first + hb_bytes_t dest_end; // region of source_glyph to copy second + + + bool serialize (hb_serialize_context_t *c, + const hb_subset_plan_t *plan) const + { + TRACE_SERIALIZE (this); + + hb_bytes_t dest_glyph = dest_start.copy(c); + dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy(c).length); + unsigned int pad_length = padding (); + DEBUG_MSG(SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length); + + HBUINT8 pad; + pad = 0; + while (pad_length > 0) + { + c->embed(pad); + pad_length--; + } + + if (dest_glyph.length) + { + _fix_component_gids (plan, dest_glyph); + if (plan->drop_hints) + { + _zero_instruction_length (dest_glyph); + c->check_success (_remove_composite_instruction_flag (dest_glyph)); + } + } + + return_trace (true); + } + + void drop_hints (const OT::glyf::accelerator_t& glyf) + { + if (source_glyph.length == 0) return; + + unsigned int instruction_length = 0; + if (!glyf.get_instruction_length (source_glyph, &instruction_length)) + { + DEBUG_MSG(SUBSET, nullptr, "Unable to read instruction length for new_gid %d", new_gid); + return ; + } + + const GlyphHeader& header = StructAtOffset (&source_glyph, 0); + int16_t num_contours = (int16_t) header.numberOfContours; + DEBUG_MSG(SUBSET, nullptr, "new_gid %d (%d contours) drop %d instruction bytes from %d byte source glyph", new_gid, num_contours, instruction_length, source_glyph.length); + if (num_contours < 0) + { + // composite, just chop instructions off the end + dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_length); + } + else + { + // simple glyph + dest_start = hb_bytes_t (&source_glyph, GlyphHeader::static_size + 2 * header.numberOfContours + 2); + dest_end = hb_bytes_t (&source_glyph + dest_start.length + instruction_length, + source_glyph.length - dest_start.length - instruction_length); +DEBUG_MSG(SUBSET, nullptr, "source_len %d start len %d instruction_len %d end len %d", source_glyph.length, dest_start.length, instruction_length, dest_end.length); + } + } + + unsigned int length () const + { + return dest_start.length + dest_end.length; + } + + // pad to 2 to ensure 2-byte loca will be ok + unsigned int padding () const + { + return length () % 2; + } + + unsigned int padded_size () const + { + return length () + padding (); + } + }; + protected: UnsizedArrayOf dataZ; /* Glyphs data. */ public: DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always * check the size externally, allow Null() object of it by - * defining it MIN() instead. */ + * defining it _MIN instead. */ }; struct glyf_accelerator_t : glyf::accelerator_t {}; diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 847b32657..96c1d1f63 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -41,71 +41,31 @@ namespace OT { struct DeviceRecord { - struct SubsetView - { - const DeviceRecord *source_device_record; - unsigned int sizeDeviceRecord; - hb_subset_plan_t *subset_plan; - - void init (const DeviceRecord *source_device_record, - unsigned int sizeDeviceRecord, - hb_subset_plan_t *subset_plan) - { - this->source_device_record = source_device_record; - this->sizeDeviceRecord = sizeDeviceRecord; - this->subset_plan = subset_plan; - } - - unsigned int len () const - { return this->subset_plan->num_output_glyphs (); } - - const HBUINT8* operator [] (unsigned int new_gid) const - { - if (unlikely (new_gid >= len ())) return nullptr; - - hb_codepoint_t old_gid; - if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid)) - return &Null(HBUINT8); - - if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size) - return nullptr; - return &(this->source_device_record->widthsZ[old_gid]); - } - }; - - static unsigned int get_size (unsigned int count) + static unsigned int get_size (unsigned count) { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); } - bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + template + bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it) { TRACE_SERIALIZE (this); - unsigned int size = get_size (subset_view.len ()); - if (unlikely (!c->allocate_size (size))) - { - DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.", - size); - return_trace (false); - } + unsigned length = it.len (); - this->pixelSize = subset_view.source_device_record->pixelSize; - this->maxWidth = subset_view.source_device_record->maxWidth; + if (unlikely (!c->extend (*this, length))) return_trace (false); - for (unsigned int i = 0; i < subset_view.len (); i++) - { - const HBUINT8 *width = subset_view[i]; - if (!width) - { - DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i); - return_trace (false); - } - widthsZ[i] = *width; - } + this->pixelSize = pixelSize; + this->maxWidth = + + it + | hb_reduce (hb_max, 0u); + + + it + | hb_sink (widthsZ.as_array (length)); return_trace (true); } - bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const + bool sanitize (hb_sanitize_context_t *c, unsigned sizeDeviceRecord) const { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && @@ -135,62 +95,63 @@ struct hdmx return StructAtOffset (&this->firstDeviceRecord, i * sizeDeviceRecord); } - bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan) + template + bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min ((*this)))) return_trace (false); - this->version = source_hdmx->version; - this->numRecords = source_hdmx->numRecords; - this->sizeDeviceRecord = DeviceRecord::get_size (plan->num_output_glyphs ()); + this->version = version; + this->numRecords = it.len (); + this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0); - for (unsigned int i = 0; i < source_hdmx->numRecords; i++) - { - DeviceRecord::SubsetView subset_view; - subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan); + + it + | hb_apply ([c] (const hb_item_type& _) { + c->start_embed ()->serialize (c, _.first, _.second); + }) + ; - if (!c->start_embed ()->serialize (c, subset_view)) - return_trace (false); - } + return_trace (c->successful); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + + hdmx *hdmx_prime = c->serializer->start_embed (); + if (unlikely (!hdmx_prime)) return_trace (false); + + auto it = + + hb_range ((unsigned) numRecords) + | hb_map ([c, this] (unsigned _) + { + const DeviceRecord *device_record = + &StructAtOffset (&firstDeviceRecord, + _ * sizeDeviceRecord); + auto row = + + hb_range (c->plan->num_output_glyphs ()) + | hb_map (c->plan->reverse_glyph_map) + | hb_map ([=] (hb_codepoint_t _) + { + if (c->plan->is_empty_glyph (_)) + return Null(HBUINT8); + return device_record->widthsZ.as_array (get_num_glyphs ()) [_]; + }) + ; + return hb_pair ((unsigned) device_record->pixelSize, +row); + }) + ; + + hdmx_prime->serialize (c->serializer, version, it); return_trace (true); } - static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan) + unsigned get_num_glyphs () const { - return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->num_output_glyphs ()); - } - - bool subset (hb_subset_plan_t *plan) const - { - size_t dest_size = get_subsetted_size (this, plan); - hdmx *dest = (hdmx *) malloc (dest_size); - if (unlikely (!dest)) - { - DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size); - return false; - } - - hb_serialize_context_t c (dest, dest_size); - hdmx *hdmx_prime = c.start_serialize (); - if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan)) - { - free (dest); - DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx."); - return false; - } - c.end_serialize (); - - hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest, - dest_size, - HB_MEMORY_MODE_READONLY, - dest, - free); - bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob); - hb_blob_destroy (hdmx_prime_blob); - - return result; + return sizeDeviceRecord - DeviceRecord::min_size; } bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 9a2b842d7..1b09d8d9c 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -92,74 +92,71 @@ struct hmtxvmtx return result; } - bool subset (hb_subset_plan_t *plan) const + template + void serialize (hb_serialize_context_t *c, + Iterator it, + unsigned num_advances) { - typename T::accelerator_t _mtx; - _mtx.init (plan->source); + unsigned idx = 0; + + it + | hb_apply ([c, &idx, num_advances] (const hb_item_type& _) + { + if (idx < num_advances) + { + LongMetric lm; + lm.advance = _.first; + lm.sb = _.second; + if (unlikely (!c->embed (&lm))) return; + } + else + { + FWORD *sb = c->allocate_size (FWORD::static_size); + if (unlikely (!sb)) return; + *sb = _.second; + } + idx++; + }) + ; + } - /* All the trailing glyphs with the same advance can use one LongMetric - * and just keep LSB */ - unsigned int num_output_glyphs = plan->num_output_glyphs (); - unsigned int num_advances = _mtx.num_advances_for_subset (plan); + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); - /* alloc the new table */ - size_t dest_sz = num_advances * 4 - + (num_output_glyphs - num_advances) * 2; - void *dest = (void *) malloc (dest_sz); - if (unlikely (!dest)) - { - return false; - } - DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances); - DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", - HB_UNTAG(T::tableTag), num_advances, num_output_glyphs - num_advances, (unsigned int) dest_sz); + T *table_prime = c->serializer->start_embed (); + if (unlikely (!table_prime)) return_trace (false); - // Copy everything over - char * dest_pos = (char *) dest; + accelerator_t _mtx; + _mtx.init (c->plan->source); + unsigned num_advances = _mtx.num_advances_for_subset (c->plan); - bool failed = false; - for (unsigned int i = 0; i < num_output_glyphs; i++) - { - int side_bearing = 0; - unsigned int advance = 0; - hb_codepoint_t old_gid; - if (plan->old_gid_for_new_gid (i, &old_gid)) - { - // Glyph is not an empty glyph so copy advance and side bearing - // from the input font. - side_bearing = _mtx.get_side_bearing (old_gid); - advance = _mtx.get_advance (old_gid); - } + auto it = + + hb_range (c->plan->num_output_glyphs ()) + | hb_map ([c, &_mtx] (unsigned _) + { + hb_codepoint_t old_gid; + if (c->plan->old_gid_for_new_gid (_, &old_gid)) + return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid)); + else + return hb_pair (0u, 0u); + }) + ; + + table_prime->serialize (c->serializer, it, num_advances); - bool has_advance = i < num_advances; - if (has_advance) - { - ((LongMetric *) dest_pos)->advance = advance; - ((LongMetric *) dest_pos)->sb = side_bearing; - } - else - { - *((FWORD *) dest_pos) = side_bearing; - } - dest_pos += (has_advance ? 4 : 2); - } _mtx.fini (); + if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ())) + return_trace (false); + // Amend header num hmetrics - if (failed || unlikely (!subset_update_header (plan, num_advances))) + if (unlikely (!subset_update_header (c->plan, num_advances))) { - free (dest); - return false; + return_trace (false); } - hb_blob_t *result = hb_blob_create ((const char *)dest, - dest_sz, - HB_MEMORY_MODE_READONLY, - dest, - free); - bool success = plan->add_table (T::tableTag, result); - hb_blob_destroy (result); - return success; + return_trace (true); } struct accelerator_t : hmtxvmtx_accelerator_base_t @@ -264,7 +261,7 @@ struct hmtxvmtx return default_advance; } - return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance; + return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance; } unsigned int get_advance (hb_codepoint_t glyph, diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index ec6a3c84c..ae2bcc92d 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -47,9 +47,9 @@ struct KernSubTableFormat3 int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const { hb_array_t kernValue = kernValueZ.as_array (kernValueCount); - hb_array_t leftClass = StructAfter > (kernValue).as_array (glyphCount); - hb_array_t rightClass = StructAfter > (leftClass).as_array (glyphCount); - hb_array_t kernIndex = StructAfter > (rightClass).as_array (leftClassCount * rightClassCount); + hb_array_t leftClass = StructAfter> (kernValue).as_array (glyphCount); + hb_array_t rightClass = StructAfter> (leftClass).as_array (glyphCount); + hb_array_t kernIndex = StructAfter> (rightClass).as_array (leftClassCount * rightClassCount); unsigned int leftC = leftClass[left]; unsigned int rightC = rightClass[right]; @@ -121,16 +121,20 @@ struct KernSubTable } } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { case 0: return_trace (c->dispatch (u.format0)); - case 1: return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ()); +#ifndef HB_NO_SHAPE_AAT + case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward (ds)...) : c->default_return_value ()); +#endif case 2: return_trace (c->dispatch (u.format2)); - case 3: return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ()); +#ifndef HB_NO_SHAPE_AAT + case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward (ds)...) : c->default_return_value ()); +#endif default: return_trace (c->default_return_value ()); } } @@ -278,7 +282,9 @@ struct kern { switch (get_type ()) { case 0: return u.ot.has_state_machine (); +#ifndef HB_NO_SHAPE_AAT case 1: return u.aat.has_state_machine (); +#endif default:return false; } } @@ -287,7 +293,9 @@ struct kern { switch (get_type ()) { case 0: return u.ot.has_cross_stream (); +#ifndef HB_NO_SHAPE_AAT case 1: return u.aat.has_cross_stream (); +#endif default:return false; } } @@ -296,7 +304,9 @@ struct kern { switch (get_type ()) { case 0: return u.ot.get_h_kerning (left, right); +#ifndef HB_NO_SHAPE_AAT case 1: return u.aat.get_h_kerning (left, right); +#endif default:return 0; } } @@ -304,14 +314,16 @@ struct kern bool apply (AAT::hb_aat_apply_context_t *c) const { return dispatch (c); } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case 0: return_trace (c->dispatch (u.ot)); - case 1: return_trace (c->dispatch (u.aat)); + case 0: return_trace (c->dispatch (u.ot, hb_forward (ds)...)); +#ifndef HB_NO_SHAPE_AAT + case 1: return_trace (c->dispatch (u.aat, hb_forward (ds)...)); +#endif default: return_trace (c->default_return_value ()); } } @@ -328,7 +340,9 @@ struct kern HBUINT32 version32; HBUINT16 major; KernOT ot; +#ifndef HB_NO_SHAPE_AAT KernAAT aat; +#endif } u; public: DEFINE_SIZE_UNION (4, version32); diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 7ef573ea8..091236294 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -447,7 +447,7 @@ struct Axis } protected: - OffsetTo > + OffsetTo> baseTagList; /* Offset to BaseTagList table, from beginning * of Axis table (may be NULL) * Array of 4-byte baseline identification tags — must diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index ea01c5a5e..a6d91855a 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -104,7 +104,7 @@ struct Record }; template -struct RecordArrayOf : SortedArrayOf > +struct RecordArrayOf : SortedArrayOf> { const OffsetTo& get_offset (unsigned int i) const { return (*this)[i].offset; } @@ -139,11 +139,11 @@ struct RecordListOf : RecordArrayOf bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct RecordListOf *out = c->serializer->embed (*this); + auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) - out->get_offset (i).serialize_subset (c, (*this)[i], out); + out->get_offset (i).serialize_subset (c, this->get_offset (i), this, out); return_trace (true); } @@ -227,13 +227,13 @@ struct LangSys { if (reqFeatureIndex == 0xFFFFu) return Index::NOT_FOUND_INDEX; - return reqFeatureIndex;; + return reqFeatureIndex; } - bool subset (hb_subset_context_t *c) const + LangSys* copy (hb_serialize_context_t *c) const { - TRACE_SUBSET (this); - return_trace (c->serializer->embed (*this)); + TRACE_SERIALIZE (this); + return_trace (c->embed (*this)); } bool sanitize (hb_sanitize_context_t *c, @@ -278,12 +278,12 @@ struct Script bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct Script *out = c->serializer->embed (*this); + auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); - out->defaultLangSys.serialize_subset (c, this+defaultLangSys, out); + out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out); unsigned int count = langSys.len; for (unsigned int i = 0; i < count; i++) - out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, out); + out->langSys.arrayZ[i].offset.serialize_copy (c->serializer, langSys[i].offset, this, out); return_trace (true); } @@ -560,7 +560,7 @@ struct Feature bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct Feature *out = c->serializer->embed (*this); + auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); out->featureParams = 0; /* TODO(subset) FeatureParams. */ return_trace (true); @@ -648,16 +648,19 @@ struct Lookup { unsigned int get_subtable_count () const { return subTable.len; } - template - const TSubTable& get_subtable (unsigned int i) const - { return this+CastR > (subTable)[i]; } - template const OffsetArrayOf& get_subtables () const - { return CastR > (subTable); } + { return CastR> (subTable); } template OffsetArrayOf& get_subtables () - { return CastR > (subTable); } + { return CastR> (subTable); } + + template + const TSubTable& get_subtable (unsigned int i) const + { return this+get_subtables ()[i]; } + template + TSubTable& get_subtable (unsigned int i) + { return this+get_subtables ()[i]; } unsigned int get_size () const { @@ -683,14 +686,14 @@ struct Lookup return flag; } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { unsigned int lookup_type = get_type (); TRACE_DISPATCH (this, lookup_type); unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { - typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type); + typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type, hb_forward (ds)...); if (c->stop_sublookup_iteration (r)) return_trace (r); } @@ -716,28 +719,11 @@ struct Lookup return_trace (true); } - /* Older compilers need this to NOT be locally defined in a function. */ - template - struct SubTableSubsetWrapper - { - SubTableSubsetWrapper (const TSubTable &subtable_, - unsigned int lookup_type_) : - subtable (subtable_), - lookup_type (lookup_type_) {} - - bool subset (hb_subset_context_t *c) const - { return subtable.dispatch (c, lookup_type); } - - private: - const TSubTable &subtable; - unsigned int lookup_type; - }; - template bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct Lookup *out = c->serializer->embed (*this); + auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); /* Subset the actual subtables. */ @@ -747,23 +733,11 @@ struct Lookup OffsetArrayOf& out_subtables = out->get_subtables (); unsigned int count = subTable.len; for (unsigned int i = 0; i < count; i++) - { - SubTableSubsetWrapper wrapper (this+subtables[i], get_type ()); - - out_subtables[i].serialize_subset (c, wrapper, out); - } + out_subtables[i].serialize_subset (c, subtables[i], this, out, get_type ()); return_trace (true); } - /* Older compilers need this to NOT be locally defined in a function. */ - template - struct SubTableSanitizeWrapper : TSubTable - { - bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const - { return this->dispatch (c, lookup_type); } - }; - template bool sanitize (hb_sanitize_context_t *c) const { @@ -775,16 +749,21 @@ struct Lookup if (!markFilteringSet.sanitize (c)) return_trace (false); } - if (unlikely (!CastR > > (subTable) - .sanitize (c, this, get_type ()))) + if (unlikely (!get_subtables ().sanitize (c, this, get_type ()))) return_trace (false); - if (unlikely (get_type () == TSubTable::Extension)) + if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ())) { /* The spec says all subtables of an Extension lookup should * have the same type, which shall not be the Extension type * itself (but we already checked for that). - * This is specially important if one has a reverse type! */ + * This is specially important if one has a reverse type! + * + * We only do this if sanitizer edit_count is zero. Otherwise, + * some of the subtables might have become insane after they + * were sanity-checked by the edits of subsequent subtables. + * https://bugs.chromium.org/p/chromium/issues/detail?id=960331 + */ unsigned int type = get_subtable (0).u.extension.get_type (); unsigned int count = get_subtable_count (); for (unsigned int i = 1; i < count; i++) @@ -792,7 +771,6 @@ struct Lookup return_trace (false); } return_trace (true); - return_trace (true); } private: @@ -827,7 +805,7 @@ struct CoverageFormat1 } template + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator glyphs) { TRACE_SERIALIZE (this); @@ -865,6 +843,8 @@ struct CoverageFormat1 bool more () const { return i < c->glyphArray.len; } void next () { i++; } hb_codepoint_t get_glyph () const { return c->glyphArray[i]; } + bool operator != (const iter_t& o) const + { return i != o.i || c != o.c; } private: const struct CoverageFormat1 *c; @@ -894,7 +874,7 @@ struct CoverageFormat2 } template + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator glyphs) { TRACE_SERIALIZE (this); @@ -905,30 +885,36 @@ struct CoverageFormat2 rangeRecord.len = 0; return_trace (true); } - /* TODO(iter) Port to non-random-access iterator interface. */ - unsigned int count = glyphs.len (); - unsigned int num_ranges = 1; - for (unsigned int i = 1; i < count; i++) - if (glyphs[i - 1] + 1 != glyphs[i]) - num_ranges++; - rangeRecord.len = num_ranges; - if (unlikely (!c->extend (rangeRecord))) return_trace (false); + /* TODO(iter) Write more efficiently? */ - unsigned int range = 0; - rangeRecord[range].start = glyphs[0]; - rangeRecord[range].value = 0; - for (unsigned int i = 1; i < count; i++) + unsigned num_ranges = 0; + hb_codepoint_t last = (hb_codepoint_t) -2; + for (auto g: glyphs) { - if (glyphs[i - 1] + 1 != glyphs[i]) - { - rangeRecord[range].end = glyphs[i - 1]; - range++; - rangeRecord[range].start = glyphs[i]; - rangeRecord[range].value = i; - } + if (last + 1 != g) + num_ranges++; + last = g; } - rangeRecord[range].end = glyphs[count - 1]; + + if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false); + + unsigned count = 0; + unsigned range = (unsigned) -1; + last = (hb_codepoint_t) -2; + for (auto g: glyphs) + { + if (last + 1 != g) + { + range++; + rangeRecord[range].start = g; + rangeRecord[range].value = count; + } + rangeRecord[range].end = g; + last = g; + count++; + } + return_trace (true); } @@ -1017,6 +1003,8 @@ struct CoverageFormat2 j++; } hb_codepoint_t get_glyph () const { return j; } + bool operator != (const iter_t& o) const + { return i != o.i || j != o.j || c != o.c; } private: const struct CoverageFormat2 *c; @@ -1056,18 +1044,22 @@ struct Coverage } template + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> bool serialize (hb_serialize_context_t *c, Iterator glyphs) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - /* TODO(iter) Port to non-random-access iterator interface. */ - unsigned int count = glyphs.len (); - unsigned int num_ranges = 1; - for (unsigned int i = 1; i < count; i++) - if (glyphs[i - 1] + 1 != glyphs[i]) - num_ranges++; + unsigned count = 0; + unsigned num_ranges = 0; + hb_codepoint_t last = (hb_codepoint_t) -2; + for (auto g: glyphs) + { + if (last + 1 != g) + num_ranges++; + last = g; + count++; + } u.format = count * 2 < num_ranges * 3 ? 1 : 2; switch (u.format) @@ -1166,6 +1158,16 @@ struct Coverage default:return 0; } } + bool operator != (const iter_t& o) const + { + if (format != o.format) return true; + switch (format) + { + case 1: return u.format1 != o.u.format1; + case 2: return u.format2 != o.u.format2; + default:return false; + } + } private: unsigned int format; @@ -1223,7 +1225,7 @@ struct ClassDefFormat1 hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u); startGlyph = glyph_min; - classValue.len = glyph_max - glyph_min + 1; + c->check_assign (classValue.len, glyph_max - glyph_min + 1); if (unlikely (!c->extend (classValue))) return_trace (false); for (unsigned int i = 0; i < glyphs.length; i++) @@ -2163,10 +2165,10 @@ struct FeatureVariations return (this+record.substitutions).find_substitute (feature_index); } - bool subset (hb_subset_context_t *c) const + FeatureVariations* copy (hb_serialize_context_t *c) const { - TRACE_SUBSET (this); - return_trace (c->serializer->embed (*this)); + TRACE_SERIALIZE (this); + return_trace (c->embed (*this)); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index dc8b9b847..0fca9947d 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -220,7 +220,7 @@ struct LigGlyph { if (caret_count) { - hb_array_t > array = carets.sub_array (start_offset, caret_count); + hb_array_t > array = carets.sub_array (start_offset, caret_count); unsigned int count = array.length; for (unsigned int i = 0; i < count; i++) caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store); @@ -296,7 +296,7 @@ struct MarkGlyphSetsFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - ArrayOf > + ArrayOf> coverage; /* Array of long offsets to mark set * coverage tables */ public: @@ -439,19 +439,19 @@ struct GDEF bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct GDEF *out = c->serializer->embed (*this); + auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); - out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out); - out->attachList = 0;//TODO(subset) serialize_subset (c, this+attachList, out); - out->ligCaretList = 0;//TODO(subset) serialize_subset (c, this+ligCaretList, out); - out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out); + out->glyphClassDef.serialize_subset (c, glyphClassDef, this, out); + out->attachList = 0;//TODO(subset) serialize_subset (c, attachList, this, out); + out->ligCaretList = 0;//TODO(subset) serialize_subset (c, ligCaretList, this, out); + out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, out); if (version.to_int () >= 0x00010002u) - out->markGlyphSetsDef = 0;// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out); + out->markGlyphSetsDef = 0;// TODO(subset) serialize_subset (c, markGlyphSetsDef, this, out); if (version.to_int () >= 0x00010003u) - out->varStore = 0;// TODO(subset) serialize_subset (c, this+varStore, out); + out->varStore = 0;// TODO(subset) serialize_subset (c, varStore, this, out); return_trace (true); } diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index a7257dfbb..86c45be29 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -174,11 +174,11 @@ struct ValueFormat : HBUINT16 } HB_INTERNAL static OffsetTo& get_device (Value* value) - { return *CastP > (value); } + { return *CastP> (value); } HB_INTERNAL static const OffsetTo& get_device (const Value* value, bool *worked=nullptr) { if (worked) *worked |= bool (*value); - return *CastP > (value); + return *CastP> (value); } HB_INTERNAL static const HBINT16& get_short (const Value* value, bool *worked=nullptr) @@ -393,7 +393,7 @@ struct AnchorMatrix HBUINT16 rows; /* Number of rows */ protected: - UnsizedArrayOf > + UnsizedArrayOf> matrixZ; /* Matrix of offsets to Anchor tables-- * from beginning of AnchorMatrix table */ public: @@ -446,8 +446,8 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage orde glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); hb_glyph_position_t &o = buffer->cur_pos(); - o.x_offset = round (base_x - mark_x); - o.y_offset = round (base_y - mark_y); + o.x_offset = roundf (base_x - mark_x); + o.y_offset = roundf (base_y - mark_y); o.attach_type() = ATTACH_TYPE_MARK; o.attach_chain() = (int) glyph_pos - (int) buffer->idx; buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; @@ -576,14 +576,14 @@ struct SinglePosFormat2 struct SinglePos { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); - case 2: return_trace (c->dispatch (u.format2)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -726,7 +726,7 @@ struct PairPosFormat1 + hb_zip (this+coverage, pairSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([&] (const OffsetTo &_) -> bool + | hb_map ([=] (const OffsetTo &_) { return (this+_).intersects (glyphs, valueFormat); }) | hb_any ; @@ -907,14 +907,14 @@ struct PairPosFormat2 struct PairPos { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); - case 2: return_trace (c->dispatch (u.format2)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -993,32 +993,32 @@ struct CursivePosFormat1 /* Main-direction adjustment */ switch (c->direction) { case HB_DIRECTION_LTR: - pos[i].x_advance = round (exit_x) + pos[i].x_offset; + pos[i].x_advance = roundf (exit_x) + pos[i].x_offset; - d = round (entry_x) + pos[j].x_offset; + d = roundf (entry_x) + pos[j].x_offset; pos[j].x_advance -= d; pos[j].x_offset -= d; break; case HB_DIRECTION_RTL: - d = round (exit_x) + pos[i].x_offset; + d = roundf (exit_x) + pos[i].x_offset; pos[i].x_advance -= d; pos[i].x_offset -= d; - pos[j].x_advance = round (entry_x) + pos[j].x_offset; + pos[j].x_advance = roundf (entry_x) + pos[j].x_offset; break; case HB_DIRECTION_TTB: - pos[i].y_advance = round (exit_y) + pos[i].y_offset; + pos[i].y_advance = roundf (exit_y) + pos[i].y_offset; - d = round (entry_y) + pos[j].y_offset; + d = roundf (entry_y) + pos[j].y_offset; pos[j].y_advance -= d; pos[j].y_offset -= d; break; case HB_DIRECTION_BTT: - d = round (exit_y) + pos[i].y_offset; + d = roundf (exit_y) + pos[i].y_offset; pos[i].y_advance -= d; pos[i].y_offset -= d; - pos[j].y_advance = round (entry_y); + pos[j].y_advance = roundf (entry_y); break; case HB_DIRECTION_INVALID: default: @@ -1092,13 +1092,13 @@ struct CursivePosFormat1 struct CursivePos { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1208,13 +1208,13 @@ struct MarkBasePosFormat1 struct MarkBasePos { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1287,7 +1287,7 @@ struct MarkLigPosFormat1 unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur()); unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); if (lig_id && lig_id == mark_id && mark_comp > 0) - comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1; + comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1; else comp_index = comp_count - 1; @@ -1333,13 +1333,13 @@ struct MarkLigPosFormat1 struct MarkLigPos { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1455,13 +1455,13 @@ struct MarkMarkPosFormat1 struct MarkMarkPos { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1507,20 +1507,20 @@ struct PosLookupSubTable Extension = 9 }; - template - typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + template + typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const { TRACE_DISPATCH (this, lookup_type); switch (lookup_type) { - case Single: return_trace (u.single.dispatch (c)); - case Pair: return_trace (u.pair.dispatch (c)); - case Cursive: return_trace (u.cursive.dispatch (c)); - case MarkBase: return_trace (u.markBase.dispatch (c)); - case MarkLig: return_trace (u.markLig.dispatch (c)); - case MarkMark: return_trace (u.markMark.dispatch (c)); - case Context: return_trace (u.context.dispatch (c)); - case ChainContext: return_trace (u.chainContext.dispatch (c)); - case Extension: return_trace (u.extension.dispatch (c)); + case Single: return_trace (u.single.dispatch (c, hb_forward (ds)...)); + case Pair: return_trace (u.pair.dispatch (c, hb_forward (ds)...)); + case Cursive: return_trace (u.cursive.dispatch (c, hb_forward (ds)...)); + case MarkBase: return_trace (u.markBase.dispatch (c, hb_forward (ds)...)); + case MarkLig: return_trace (u.markLig.dispatch (c, hb_forward (ds)...)); + case MarkMark: return_trace (u.markMark.dispatch (c, hb_forward (ds)...)); + case Context: return_trace (u.context.dispatch (c, hb_forward (ds)...)); + case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward (ds)...)); + case Extension: return_trace (u.extension.dispatch (c, hb_forward (ds)...)); default: return_trace (c->default_return_value ()); } } @@ -1581,9 +1581,9 @@ struct PosLookup : Lookup template static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); - template - typename context_t::return_t dispatch (context_t *c) const - { return Lookup::dispatch (c); } + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { return Lookup::dispatch (c, hb_forward (ds)...); } bool subset (hb_subset_context_t *c) const { return Lookup::subset (c); } diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 10c35e32c..f532f9dff 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -34,10 +34,12 @@ namespace OT { +typedef hb_pair_t hb_codepoint_pair_t; +template static inline void SingleSubst_serialize (hb_serialize_context_t *c, - hb_sorted_array_t glyphs, - hb_array_t substitutes); + Iterator it); + struct SingleSubstFormat1 { @@ -46,9 +48,10 @@ struct SingleSubstFormat1 void closure (hb_closure_context_t *c) const { + unsigned d = deltaGlyphID; + hb_iter (this+coverage) | hb_filter (*c->glyphs) - | hb_map ([&] (hb_codepoint_t g) -> hb_codepoint_t { return (g + deltaGlyphID) & 0xFFFFu; }) + | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) | hb_sink (c->output) ; } @@ -56,9 +59,9 @@ struct SingleSubstFormat1 void collect_glyphs (hb_collect_glyphs_context_t *c) const { if (unlikely (!(this+coverage).add_coverage (c->input))) return; - + unsigned d = deltaGlyphID; + hb_iter (this+coverage) - | hb_map ([&] (hb_codepoint_t g) -> hb_codepoint_t { return (g + deltaGlyphID) & 0xFFFFu; }) + | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) | hb_sink (c->output) ; } @@ -83,8 +86,10 @@ struct SingleSubstFormat1 return_trace (true); } + template bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t glyphs, + Iterator glyphs, unsigned delta) { TRACE_SERIALIZE (this); @@ -97,23 +102,22 @@ struct SingleSubstFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; - hb_sorted_vector_t from; - hb_vector_t to; hb_codepoint_t delta = deltaGlyphID; + auto it = + hb_iter (this+coverage) | hb_filter (glyphset) - | hb_map ([&] (hb_codepoint_t g) -> hb_pair_t - { return hb_pair (glyph_map[g], - glyph_map[(g + delta) & 0xFFFF]); }) - | hb_unzip (from, to); + | hb_map_retains_sorting ([&] (hb_codepoint_t g) { + return hb_codepoint_pair_t (glyph_map[g], + glyph_map[(g + delta) & 0xFFFF]); }) + ; - c->serializer->propagate_error (from, to); - SingleSubst_serialize (c->serializer, from, to); - return_trace (from.length); + bool ret = bool (it); + SingleSubst_serialize (c->serializer, it); + return_trace (ret); } bool sanitize (hb_sanitize_context_t *c) const @@ -174,11 +178,21 @@ struct SingleSubstFormat2 return_trace (true); } + template bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t glyphs, - hb_array_t substitutes) + Iterator it) { TRACE_SERIALIZE (this); + auto substitutes = + + it + | hb_map (hb_second) + ; + auto glyphs = + + it + | hb_map_retains_sorting (hb_first) + ; if (unlikely (!c->extend_min (*this))) return_trace (false); if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false); if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false); @@ -188,21 +202,19 @@ struct SingleSubstFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; - hb_sorted_vector_t from; - hb_vector_t to; - + auto it = + hb_zip (this+coverage, substitute) | hb_filter (glyphset, hb_first) - | hb_map ([&] (hb_pair_t p) -> hb_pair_t - { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) - | hb_unzip (from, to); + | hb_map_retains_sorting ([&] (hb_pair_t p) -> hb_codepoint_pair_t + { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) + ; - c->serializer->propagate_error (from, to); - SingleSubst_serialize (c->serializer, from, to); - return_trace (from.length); + bool ret = bool (it); + SingleSubst_serialize (c->serializer, it); + return_trace (ret); } bool sanitize (hb_sanitize_context_t *c) const @@ -225,40 +237,45 @@ struct SingleSubstFormat2 struct SingleSubst { + + template bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t glyphs, - hb_array_t substitutes) + Iterator glyphs) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned format = 2; unsigned delta = 0; - if (glyphs.length) + if (glyphs.len ()) { format = 1; - delta = (unsigned) (substitutes[0] - glyphs[0]) & 0xFFFF; - for (unsigned int i = 1; i < glyphs.length; i++) - if (delta != ((unsigned) (substitutes[i] - glyphs[i]) & 0xFFFF)) { - format = 2; - break; - } + auto get_delta = [=] (hb_codepoint_pair_t _) { + return (unsigned) (_.second - _.first) & 0xFFFF; + }; + delta = get_delta (*glyphs); + if (!hb_all (++(+glyphs), delta, get_delta)) format = 2; } u.format = format; switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, delta)); - case 2: return_trace (u.format2.serialize (c, glyphs, substitutes)); + case 1: return_trace (u.format1.serialize (c, + + glyphs + | hb_map_retains_sorting (hb_first), + delta)); + case 2: return_trace (u.format2.serialize (c, glyphs)); default:return_trace (false); } } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); - case 2: return_trace (c->dispatch (u.format2)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -271,11 +288,11 @@ struct SingleSubst } u; }; +template static inline void SingleSubst_serialize (hb_serialize_context_t *c, - hb_sorted_array_t glyphs, - hb_array_t substitutes) -{ c->start_embed ()->serialize (c, glyphs, substitutes); } + Iterator it) +{ c->start_embed ()->serialize (c, it); } struct Sequence { @@ -321,8 +338,10 @@ struct Sequence return_trace (true); } + template bool serialize (hb_serialize_context_t *c, - hb_array_t subst) + Iterator subst) { TRACE_SERIALIZE (this); return_trace (substitute.serialize (c, subst)); @@ -351,7 +370,8 @@ struct MultipleSubstFormat1 + hb_zip (this+coverage, sequence) | hb_filter (*c->glyphs, hb_first) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Sequence &_) { _.closure (c); }) ; } @@ -360,7 +380,8 @@ struct MultipleSubstFormat1 if (unlikely (!(this+coverage).add_coverage (c->input))) return; + hb_zip (this+coverage, sequence) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); }) ; } @@ -440,13 +461,13 @@ struct MultipleSubst } } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -484,7 +505,7 @@ struct AlternateSet unsigned int shift = hb_ctz (lookup_mask); unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); - /* If alt_index is MAX, randomize feature if it is the rand feature. */ + /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */ if (alt_index == HB_OT_MAP_MAX_VALUE && c->random) alt_index = c->random_number () % count + 1; @@ -495,8 +516,10 @@ struct AlternateSet return_trace (true); } + template bool serialize (hb_serialize_context_t *c, - hb_array_t alts) + Iterator alts) { TRACE_SERIALIZE (this); return_trace (alternates.serialize (c, alts)); @@ -525,7 +548,8 @@ struct AlternateSubstFormat1 { + hb_zip (this+coverage, alternateSet) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) ; } @@ -534,7 +558,8 @@ struct AlternateSubstFormat1 if (unlikely (!(this+coverage).add_coverage (c->input))) return; + hb_zip (this+coverage, alternateSet) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); }) ; } @@ -614,13 +639,13 @@ struct AlternateSubst } } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -640,7 +665,7 @@ struct Ligature unsigned int count = component.lenP1; for (unsigned int i = 1; i < count; i++) if (!glyphs->has (component[i])) - return false; + return false; return true; } @@ -707,9 +732,11 @@ struct Ligature return_trace (true); } + template bool serialize (hb_serialize_context_t *c, GlyphID ligature, - hb_array_t components /* Starting from second */) + Iterator components /* Starting from second */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); @@ -741,7 +768,8 @@ struct LigatureSet { return + hb_iter (ligature) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).intersects (glyphs); }) + | hb_map (hb_add (this)) + | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); }) | hb_any ; } @@ -749,14 +777,16 @@ struct LigatureSet void closure (hb_closure_context_t *c) const { + hb_iter (ligature) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Ligature &_) { _.closure (c); }) ; } void collect_glyphs (hb_collect_glyphs_context_t *c) const { + hb_iter (ligature) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); }) ; } @@ -764,7 +794,8 @@ struct LigatureSet { return + hb_iter (ligature) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).would_apply (c); }) + | hb_map (hb_add (this)) + | hb_map ([c] (const Ligature &_) { return _.would_apply (c); }) | hb_any ; } @@ -792,7 +823,7 @@ struct LigatureSet if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false); for (unsigned int i = 0; i < ligatures.length; i++) { - unsigned int component_count = MAX (component_count_list[i] - 1, 0); + unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0); if (unlikely (!ligature[i].serialize (c, this) .serialize (c, ligatures[i], @@ -825,7 +856,7 @@ struct LigatureSubstFormat1 + hb_zip (this+coverage, ligatureSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([&] (const OffsetTo &_) -> bool + | hb_map ([this, glyphs] (const OffsetTo &_) { return (this+_).intersects (glyphs); }) | hb_any ; @@ -836,7 +867,8 @@ struct LigatureSubstFormat1 + hb_zip (this+coverage, ligatureSet) | hb_filter (*c->glyphs, hb_first) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) ; } @@ -846,7 +878,8 @@ struct LigatureSubstFormat1 + hb_zip (this+coverage, ligatureSet) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c); }) + | hb_map (hb_add (this)) + | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); }) ; } @@ -945,13 +978,13 @@ struct LigatureSubst } } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -983,19 +1016,19 @@ struct ReverseChainSingleSubstFormat1 if (!(this+coverage).intersects (glyphs)) return false; - const OffsetArrayOf &lookahead = StructAfter > (backtrack); + const OffsetArrayOf &lookahead = StructAfter> (backtrack); unsigned int count; count = backtrack.len; for (unsigned int i = 0; i < count; i++) if (!(this+backtrack[i]).intersects (glyphs)) - return false; + return false; count = lookahead.len; for (unsigned int i = 0; i < count; i++) if (!(this+lookahead[i]).intersects (glyphs)) - return false; + return false; return true; } @@ -1004,8 +1037,8 @@ struct ReverseChainSingleSubstFormat1 { if (!intersects (c->glyphs)) return; - const OffsetArrayOf &lookahead = StructAfter > (backtrack); - const ArrayOf &substitute = StructAfter > (lookahead); + const OffsetArrayOf &lookahead = StructAfter> (backtrack); + const ArrayOf &substitute = StructAfter> (lookahead); + hb_zip (this+coverage, substitute) | hb_filter (*c->glyphs, hb_first) @@ -1024,12 +1057,12 @@ struct ReverseChainSingleSubstFormat1 for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return; - const OffsetArrayOf &lookahead = StructAfter > (backtrack); + const OffsetArrayOf &lookahead = StructAfter> (backtrack); count = lookahead.len; for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return; - const ArrayOf &substitute = StructAfter > (lookahead); + const ArrayOf &substitute = StructAfter> (lookahead); count = substitute.len; c->output->add_array (substitute.arrayZ, substitute.len); } @@ -1048,15 +1081,15 @@ struct ReverseChainSingleSubstFormat1 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const OffsetArrayOf &lookahead = StructAfter > (backtrack); - const ArrayOf &substitute = StructAfter > (lookahead); + const OffsetArrayOf &lookahead = StructAfter> (backtrack); + const ArrayOf &substitute = StructAfter> (lookahead); unsigned int start_index = 0, end_index = 0; if (match_backtrack (c, backtrack.len, (HBUINT16 *) backtrack.arrayZ, match_coverage, this, &start_index) && - match_lookahead (c, + match_lookahead (c, lookahead.len, (HBUINT16 *) lookahead.arrayZ, match_coverage, this, 1, &end_index)) @@ -1084,10 +1117,10 @@ struct ReverseChainSingleSubstFormat1 TRACE_SANITIZE (this); if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) return_trace (false); - const OffsetArrayOf &lookahead = StructAfter > (backtrack); + const OffsetArrayOf &lookahead = StructAfter> (backtrack); if (!lookahead.sanitize (c, this)) return_trace (false); - const ArrayOf &substitute = StructAfter > (lookahead); + const ArrayOf &substitute = StructAfter> (lookahead); return_trace (substitute.sanitize (c)); } @@ -1113,13 +1146,13 @@ struct ReverseChainSingleSubstFormat1 struct ReverseChainSingleSubst { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1153,19 +1186,19 @@ struct SubstLookupSubTable ReverseChainSingle = 8 }; - template - typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + template + typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const { TRACE_DISPATCH (this, lookup_type); switch (lookup_type) { - case Single: return_trace (u.single.dispatch (c)); - case Multiple: return_trace (u.multiple.dispatch (c)); - case Alternate: return_trace (u.alternate.dispatch (c)); - case Ligature: return_trace (u.ligature.dispatch (c)); - case Context: return_trace (u.context.dispatch (c)); - case ChainContext: return_trace (u.chainContext.dispatch (c)); - case Extension: return_trace (u.extension.dispatch (c)); - case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c)); + case Single: return_trace (u.single.dispatch (c, hb_forward (ds)...)); + case Multiple: return_trace (u.multiple.dispatch (c, hb_forward (ds)...)); + case Alternate: return_trace (u.alternate.dispatch (c, hb_forward (ds)...)); + case Ligature: return_trace (u.ligature.dispatch (c, hb_forward (ds)...)); + case Context: return_trace (u.context.dispatch (c, hb_forward (ds)...)); + case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward (ds)...)); + case Extension: return_trace (u.extension.dispatch (c, hb_forward (ds)...)); + case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward (ds)...)); default: return_trace (c->default_return_value ()); } } @@ -1254,17 +1287,18 @@ struct SubstLookup : Lookup HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index); SubTable& serialize_subtable (hb_serialize_context_t *c, - unsigned int i) + unsigned int i) { return get_subtables ()[i].serialize (c, this); } bool serialize_single (hb_serialize_context_t *c, uint32_t lookup_props, - hb_sorted_array_t glyphs, - hb_array_t substitutes) + hb_sorted_array_t glyphs, + hb_array_t substitutes) { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes)); + return_trace (serialize_subtable (c, 0).u.single. + serialize (c, hb_zip (glyphs, substitutes))); } bool serialize_multiple (hb_serialize_context_t *c, @@ -1275,10 +1309,11 @@ struct SubstLookup : Lookup { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.multiple.serialize (c, - glyphs, - substitute_len_list, - substitute_glyphs_list)); + return_trace (serialize_subtable (c, 0).u.multiple. + serialize (c, + glyphs, + substitute_len_list, + substitute_glyphs_list)); } bool serialize_alternate (hb_serialize_context_t *c, @@ -1289,10 +1324,11 @@ struct SubstLookup : Lookup { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.alternate.serialize (c, - glyphs, - alternate_len_list, - alternate_glyphs_list)); + return_trace (serialize_subtable (c, 0).u.alternate. + serialize (c, + glyphs, + alternate_len_list, + alternate_glyphs_list)); } bool serialize_ligature (hb_serialize_context_t *c, @@ -1305,12 +1341,13 @@ struct SubstLookup : Lookup { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.ligature.serialize (c, - first_glyphs, - ligature_per_first_glyph_count_list, - ligatures_list, - component_count_list, - component_list)); + return_trace (serialize_subtable (c, 0).u.ligature. + serialize (c, + first_glyphs, + ligature_per_first_glyph_count_list, + ligatures_list, + component_count_list, + component_list)); } template @@ -1319,7 +1356,7 @@ struct SubstLookup : Lookup HB_INTERNAL static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) { if (!c->should_visit_lookup (lookup_index)) - return hb_void_t (); + return hb_empty_t (); hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index); @@ -1331,9 +1368,9 @@ struct SubstLookup : Lookup return ret; } - template - typename context_t::return_t dispatch (context_t *c) const - { return Lookup::dispatch (c); } + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { return Lookup::dispatch (c, hb_forward (ds)...); } bool subset (hb_subset_context_t *c) const { return Lookup::subset (c); } diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 840c142ab..4bc3d7e15 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -59,13 +59,13 @@ struct hb_intersects_context_t : }; struct hb_closure_context_t : - hb_dispatch_context_t + hb_dispatch_context_t { const char *get_name () { return "CLOSURE"; } typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); template - return_t dispatch (const T &obj) { obj.closure (this); return hb_void_t (); } - static return_t default_return_value () { return hb_void_t (); } + return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); } + static return_t default_return_value () { return hb_empty_t (); } void recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) @@ -151,13 +151,13 @@ struct hb_would_apply_context_t : struct hb_collect_glyphs_context_t : - hb_dispatch_context_t + hb_dispatch_context_t { const char *get_name () { return "COLLECT_GLYPHS"; } typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); template - return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_void_t (); } - static return_t default_return_value () { return hb_void_t (); } + return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_empty_t (); } + static return_t default_return_value () { return hb_empty_t (); } void recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) @@ -610,7 +610,7 @@ struct hb_ot_apply_context_t : struct hb_get_subtables_context_t : - hb_dispatch_context_t + hb_dispatch_context_t { template HB_INTERNAL static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c) @@ -652,9 +652,9 @@ struct hb_get_subtables_context_t : { hb_applicable_t *entry = array.push(); entry->init (obj, apply_to); - return hb_void_t (); + return hb_empty_t (); } - static return_t default_return_value () { return hb_void_t (); } + static return_t default_return_value () { return hb_empty_t (); } hb_get_subtables_context_t (array_t &array_) : array (array_), @@ -708,7 +708,7 @@ static inline bool intersects_array (const hb_set_t *glyphs, { return + hb_iter (values, count) - | hb_map ([&] (const HBUINT16 &_) -> bool { return intersects_func (glyphs, _, intersects_data); }) + | hb_map ([&] (const HBUINT16 &_) { return intersects_func (glyphs, _, intersects_data); }) | hb_any ; } @@ -849,7 +849,7 @@ static inline bool match_input (hb_ot_apply_context_t *c, if (ligbase == LIGBASE_NOT_CHECKED) { bool found = false; - const hb_glyph_info_t *out = buffer->out_info; + const auto *out = buffer->out_info; unsigned int j = buffer->out_len; while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) { @@ -973,7 +973,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c, if (this_comp == 0) this_comp = last_num_components; unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (this_comp, last_num_components); + hb_min (this_comp, last_num_components); _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); } buffer->next_glyph (); @@ -995,7 +995,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c, if (!this_comp) break; unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (this_comp, last_num_components); + hb_min (this_comp, last_num_components); _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp); } else break; @@ -1173,7 +1173,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, else { /* NOTE: delta is negative. */ - delta = MAX (delta, (int) next - (int) count); + delta = hb_max (delta, (int) next - (int) count); next -= delta; } @@ -1299,7 +1299,7 @@ struct Rule void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { - const UnsizedArrayOf &lookupRecord = StructAfter > + const UnsizedArrayOf &lookupRecord = StructAfter> (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); context_closure_lookup (c, inputCount, inputZ.arrayZ, @@ -1310,7 +1310,7 @@ struct Rule void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const { - const UnsizedArrayOf &lookupRecord = StructAfter > + const UnsizedArrayOf &lookupRecord = StructAfter> (inputZ.as_array (inputCount ? inputCount - 1 : 0)); context_collect_glyphs_lookup (c, inputCount, inputZ.arrayZ, @@ -1321,7 +1321,7 @@ struct Rule bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const { - const UnsizedArrayOf &lookupRecord = StructAfter > + const UnsizedArrayOf &lookupRecord = StructAfter> (inputZ.as_array (inputCount ? inputCount - 1 : 0)); return context_would_apply_lookup (c, inputCount, inputZ.arrayZ, @@ -1333,7 +1333,7 @@ struct Rule ContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const UnsizedArrayOf &lookupRecord = StructAfter > + const UnsizedArrayOf &lookupRecord = StructAfter> (inputZ.as_array (inputCount ? inputCount - 1 : 0)); return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context)); } @@ -1371,7 +1371,8 @@ struct RuleSet { return + hb_iter (rule) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).intersects (glyphs, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const Rule &_) { return _.intersects (glyphs, lookup_context); }) | hb_any ; } @@ -1381,7 +1382,8 @@ struct RuleSet { return + hb_iter (rule) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const Rule &_) { _.closure (c, lookup_context); }) ; } @@ -1390,7 +1392,8 @@ struct RuleSet { return + hb_iter (rule) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const Rule &_) { _.collect_glyphs (c, lookup_context); }) ; } @@ -1399,7 +1402,8 @@ struct RuleSet { return + hb_iter (rule) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).would_apply (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const Rule &_) { return _.would_apply (c, lookup_context); }) | hb_any ; } @@ -1410,7 +1414,8 @@ struct RuleSet TRACE_APPLY (this); return_trace ( + hb_iter (rule) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).apply (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); }) | hb_any ) ; @@ -1444,7 +1449,8 @@ struct ContextFormat1 + hb_zip (this+coverage, ruleSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).intersects (glyphs, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const RuleSet &_) { return _.intersects (glyphs, lookup_context); }) | hb_any ; } @@ -1459,7 +1465,8 @@ struct ContextFormat1 + hb_zip (this+coverage, ruleSet) | hb_filter (*c->glyphs, hb_first) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); }) ; } @@ -1473,7 +1480,8 @@ struct ContextFormat1 }; + hb_iter (ruleSet) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); }) ; } @@ -1546,7 +1554,7 @@ struct ContextFormat2 return + hb_enumerate (ruleSet) - | hb_map ([&] (const hb_pair_t &> p) -> bool + | hb_map ([&] (const hb_pair_t &> p) { return class_def.intersects_class (glyphs, p.first) && (this+p.second).intersects (glyphs, lookup_context); }) | hb_any @@ -1567,11 +1575,12 @@ struct ContextFormat2 return + hb_enumerate (ruleSet) - | hb_filter ([&] (unsigned _) -> bool + | hb_filter ([&] (unsigned _) { return class_def.intersects_class (c->glyphs, _); }, hb_first) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); }) ; } @@ -1586,7 +1595,8 @@ struct ContextFormat2 }; + hb_iter (ruleSet) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); }) ; } @@ -1751,7 +1761,7 @@ struct ContextFormat3 HBUINT16 glyphCount; /* Number of glyphs in the input glyph * sequence */ HBUINT16 lookupCount; /* Number of LookupRecords */ - UnsizedArrayOf > + UnsizedArrayOf> coverageZ; /* Array of offsets to Coverage * table in glyph sequence order */ /*UnsizedArrayOf @@ -1763,15 +1773,15 @@ struct ContextFormat3 struct Context { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); - case 2: return_trace (c->dispatch (u.format2)); - case 3: return_trace (c->dispatch (u.format3)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); + case 3: return_trace (c->dispatch (u.format3, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1923,8 +1933,8 @@ struct ChainRule { bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const { - const HeadlessArrayOf &input = StructAfter > (backtrack); - const ArrayOf &lookahead = StructAfter > (input); + const HeadlessArrayOf &input = StructAfter> (backtrack); + const ArrayOf &lookahead = StructAfter> (input); return chain_context_intersects (glyphs, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -1935,9 +1945,9 @@ struct ChainRule void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const { - const HeadlessArrayOf &input = StructAfter > (backtrack); - const ArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const HeadlessArrayOf &input = StructAfter> (backtrack); + const ArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); chain_context_closure_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -1949,9 +1959,9 @@ struct ChainRule void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const { - const HeadlessArrayOf &input = StructAfter > (backtrack); - const ArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const HeadlessArrayOf &input = StructAfter> (backtrack); + const ArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); chain_context_collect_glyphs_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -1963,9 +1973,9 @@ struct ChainRule bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const { - const HeadlessArrayOf &input = StructAfter > (backtrack); - const ArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const HeadlessArrayOf &input = StructAfter> (backtrack); + const ArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); return chain_context_would_apply_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -1976,9 +1986,9 @@ struct ChainRule bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const HeadlessArrayOf &input = StructAfter > (backtrack); - const ArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const HeadlessArrayOf &input = StructAfter> (backtrack); + const ArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); return_trace (chain_context_apply_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -1990,11 +2000,11 @@ struct ChainRule { TRACE_SANITIZE (this); if (!backtrack.sanitize (c)) return_trace (false); - const HeadlessArrayOf &input = StructAfter > (backtrack); + const HeadlessArrayOf &input = StructAfter> (backtrack); if (!input.sanitize (c)) return_trace (false); - const ArrayOf &lookahead = StructAfter > (input); + const ArrayOf &lookahead = StructAfter> (input); if (!lookahead.sanitize (c)) return_trace (false); - const ArrayOf &lookup = StructAfter > (lookahead); + const ArrayOf &lookup = StructAfter> (lookahead); return_trace (lookup.sanitize (c)); } @@ -2022,7 +2032,8 @@ struct ChainRuleSet { return + hb_iter (rule) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).intersects (glyphs, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const ChainRule &_) { return _.intersects (glyphs, lookup_context); }) | hb_any ; } @@ -2030,7 +2041,8 @@ struct ChainRuleSet { return + hb_iter (rule) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const ChainRule &_) { _.closure (c, lookup_context); }) ; } @@ -2038,7 +2050,8 @@ struct ChainRuleSet { return + hb_iter (rule) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const ChainRule &_) { _.collect_glyphs (c, lookup_context); }) ; } @@ -2046,7 +2059,8 @@ struct ChainRuleSet { return + hb_iter (rule) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).would_apply (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const ChainRule &_) { return _.would_apply (c, lookup_context); }) | hb_any ; } @@ -2056,7 +2070,8 @@ struct ChainRuleSet TRACE_APPLY (this); return_trace ( + hb_iter (rule) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).apply (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); }) | hb_any ) ; @@ -2089,7 +2104,8 @@ struct ChainContextFormat1 + hb_zip (this+coverage, ruleSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([&] (const OffsetTo &_) -> bool { return (this+_).intersects (glyphs, lookup_context); }) + | hb_map (hb_add (this)) + | hb_map ([&] (const ChainRuleSet &_) { return _.intersects (glyphs, lookup_context); }) | hb_any ; } @@ -2104,7 +2120,8 @@ struct ChainContextFormat1 + hb_zip (this+coverage, ruleSet) | hb_filter (*c->glyphs, hb_first) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); }) ; } @@ -2118,7 +2135,8 @@ struct ChainContextFormat1 }; + hb_iter (ruleSet) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); }) ; } @@ -2193,9 +2211,9 @@ struct ChainContextFormat2 return + hb_enumerate (ruleSet) - | hb_map ([&] (const hb_pair_t &> p) -> bool - { return input_class_def.intersects_class (glyphs, p.first) && - (this+p.second).intersects (glyphs, lookup_context); }) + | hb_map ([&] (const hb_pair_t &> p) + { return input_class_def.intersects_class (glyphs, p.first) && + (this+p.second).intersects (glyphs, lookup_context); }) | hb_any ; } @@ -2217,11 +2235,12 @@ struct ChainContextFormat2 return + hb_enumerate (ruleSet) - | hb_filter ([&] (unsigned _) -> bool + | hb_filter ([&] (unsigned _) { return input_class_def.intersects_class (c->glyphs, _); }, hb_first) | hb_map (hb_second) - | hb_apply ([&] (const OffsetTo &_) { (this+_).closure (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); }) ; } @@ -2241,7 +2260,8 @@ struct ChainContextFormat2 }; + hb_iter (ruleSet) - | hb_apply ([&] (const OffsetTo &_) { (this+_).collect_glyphs (c, lookup_context); }) + | hb_map (hb_add (this)) + | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); }) ; } @@ -2330,12 +2350,12 @@ struct ChainContextFormat3 { bool intersects (const hb_set_t *glyphs) const { - const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &input = StructAfter> (backtrack); if (!(this+input[0]).intersects (glyphs)) return false; - const OffsetArrayOf &lookahead = StructAfter > (input); + const OffsetArrayOf &lookahead = StructAfter> (input); struct ChainContextClosureLookupContext lookup_context = { {intersects_coverage}, {this, this, this} @@ -2349,13 +2369,13 @@ struct ChainContextFormat3 void closure (hb_closure_context_t *c) const { - const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &input = StructAfter> (backtrack); if (!(this+input[0]).intersects (c->glyphs)) return; - const OffsetArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const OffsetArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); struct ChainContextClosureLookupContext lookup_context = { {intersects_coverage}, {this, this, this} @@ -2370,12 +2390,12 @@ struct ChainContextFormat3 void collect_glyphs (hb_collect_glyphs_context_t *c) const { - const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &input = StructAfter> (backtrack); (this+input[0]).add_coverage (c->input); - const OffsetArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const OffsetArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); struct ChainContextCollectGlyphsLookupContext lookup_context = { {collect_coverage}, {this, this, this} @@ -2390,9 +2410,9 @@ struct ChainContextFormat3 bool would_apply (hb_would_apply_context_t *c) const { - const OffsetArrayOf &input = StructAfter > (backtrack); - const OffsetArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const OffsetArrayOf &input = StructAfter> (backtrack); + const OffsetArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); struct ChainContextApplyLookupContext lookup_context = { {match_coverage}, {this, this, this} @@ -2406,20 +2426,20 @@ struct ChainContextFormat3 const Coverage &get_coverage () const { - const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &input = StructAfter> (backtrack); return this+input[0]; } bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &input = StructAfter> (backtrack); unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const OffsetArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); + const OffsetArrayOf &lookahead = StructAfter> (input); + const ArrayOf &lookup = StructAfter> (lookahead); struct ChainContextApplyLookupContext lookup_context = { {match_coverage}, {this, this, this} @@ -2442,12 +2462,12 @@ struct ChainContextFormat3 { TRACE_SANITIZE (this); if (!backtrack.sanitize (c, this)) return_trace (false); - const OffsetArrayOf &input = StructAfter > (backtrack); + const OffsetArrayOf &input = StructAfter> (backtrack); if (!input.sanitize (c, this)) return_trace (false); if (!input.len) return_trace (false); /* To be consistent with Context. */ - const OffsetArrayOf &lookahead = StructAfter > (input); + const OffsetArrayOf &lookahead = StructAfter> (input); if (!lookahead.sanitize (c, this)) return_trace (false); - const ArrayOf &lookup = StructAfter > (lookahead); + const ArrayOf &lookup = StructAfter> (lookahead); return_trace (lookup.sanitize (c)); } @@ -2474,15 +2494,15 @@ struct ChainContextFormat3 struct ChainContext { - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1)); - case 2: return_trace (c->dispatch (u.format2)); - case 3: return_trace (c->dispatch (u.format3)); + case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); + case 3: return_trace (c->dispatch (u.format3, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2504,18 +2524,14 @@ struct ExtensionFormat1 template const X& get_subtable () const - { - unsigned int offset = extensionOffset; - if (unlikely (!offset)) return Null(typename T::SubTable); - return StructAtOffset (this, offset); - } + { return this + CastR> (extensionOffset); } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, format); if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ()); - return_trace (get_subtable ().dispatch (c, get_type ())); + return_trace (get_subtable ().dispatch (c, get_type (), hb_forward (ds)...)); } /* This is called from may_dispatch() above with hb_sanitize_context_t. */ @@ -2523,7 +2539,6 @@ struct ExtensionFormat1 { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - extensionOffset != 0 && extensionLookupType != T::SubTable::Extension); } @@ -2532,7 +2547,7 @@ struct ExtensionFormat1 HBUINT16 extensionLookupType; /* Lookup type of subtable referenced * by ExtensionOffset (i.e. the * extension subtable). */ - HBUINT32 extensionOffset; /* Offset to the extension subtable, + Offset32 extensionOffset; /* Offset to the extension subtable, * of lookup type subtable. */ public: DEFINE_SIZE_STATIC (8); @@ -2557,13 +2572,13 @@ struct Extension } } - template - typename context_t::return_t dispatch (context_t *c) const + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (u.format1.dispatch (c)); + case 1: return_trace (u.format1.dispatch (c, hb_forward (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2666,21 +2681,22 @@ struct GSUBGPOS bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct GSUBGPOS *out = c->serializer->embed (*this); + auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); - out->scriptList.serialize_subset (c, this+scriptList, out); - out->featureList.serialize_subset (c, this+featureList, out); + out->scriptList.serialize_subset (c, scriptList, this, out); + out->featureList.serialize_subset (c, featureList, this, out); typedef OffsetListOf TLookupList; /* TODO Use intersects() to count how many subtables survive? */ - CastR > (out->lookupList) + CastR> (out->lookupList) .serialize_subset (c, - this+CastR > (lookupList), + CastR> (lookupList), + this, out); if (version.to_int () >= 0x00010001u) - out->featureVars.serialize_subset (c, this+featureVars, out); + out->featureVars.serialize_copy (c->serializer, featureVars, this, out); return_trace (true); } @@ -2700,7 +2716,7 @@ struct GSUBGPOS likely (version.major == 1) && scriptList.sanitize (c, this) && featureList.sanitize (c, this) && - CastR > (lookupList).sanitize (c, this) && + CastR> (lookupList).sanitize (c, this) && (version.to_int () < 0x00010001u || featureVars.sanitize (c, this))); } diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 1e2d159b5..1945df4fe 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -138,7 +138,7 @@ bool OT::GDEF::is_blacklisted (hb_blob_t *blob, hb_face_t *face) const { -#if defined(HB_NO_OT_LAYOUT_BLACKLIST) +#ifdef HB_NO_OT_LAYOUT_BLACKLIST return false; #endif /* The ugly business of blacklisting individual fonts' tables happen here! @@ -158,84 +158,82 @@ OT::GDEF::is_blacklisted (hb_blob_t *blob, * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 */ -#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z)) - switch ENCODE(blob->length, - face->table.GSUB->table.get_length (), - face->table.GPOS->table.get_length ()) + switch HB_CODEPOINT_ENCODE3(blob->length, + face->table.GSUB->table.get_length (), + face->table.GPOS->table.get_length ()) { /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ - case ENCODE (442, 2874, 42038): + case HB_CODEPOINT_ENCODE3 (442, 2874, 42038): /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ - case ENCODE (430, 2874, 40662): + case HB_CODEPOINT_ENCODE3 (430, 2874, 40662): /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ - case ENCODE (442, 2874, 39116): + case HB_CODEPOINT_ENCODE3 (442, 2874, 39116): /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ - case ENCODE (430, 2874, 39374): + case HB_CODEPOINT_ENCODE3 (430, 2874, 39374): /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ - case ENCODE (490, 3046, 41638): + case HB_CODEPOINT_ENCODE3 (490, 3046, 41638): /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ - case ENCODE (478, 3046, 41902): + case HB_CODEPOINT_ENCODE3 (478, 3046, 41902): /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ - case ENCODE (898, 12554, 46470): + case HB_CODEPOINT_ENCODE3 (898, 12554, 46470): /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ - case ENCODE (910, 12566, 47732): + case HB_CODEPOINT_ENCODE3 (910, 12566, 47732): /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ - case ENCODE (928, 23298, 59332): + case HB_CODEPOINT_ENCODE3 (928, 23298, 59332): /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ - case ENCODE (940, 23310, 60732): + case HB_CODEPOINT_ENCODE3 (940, 23310, 60732): /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - case ENCODE (964, 23836, 60072): + case HB_CODEPOINT_ENCODE3 (964, 23836, 60072): /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - case ENCODE (976, 23832, 61456): + case HB_CODEPOINT_ENCODE3 (976, 23832, 61456): /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ - case ENCODE (994, 24474, 60336): + case HB_CODEPOINT_ENCODE3 (994, 24474, 60336): /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ - case ENCODE (1006, 24470, 61740): + case HB_CODEPOINT_ENCODE3 (1006, 24470, 61740): /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - case ENCODE (1006, 24576, 61346): + case HB_CODEPOINT_ENCODE3 (1006, 24576, 61346): /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ - case ENCODE (1018, 24572, 62828): + case HB_CODEPOINT_ENCODE3 (1018, 24572, 62828): /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ - case ENCODE (1006, 24576, 61352): + case HB_CODEPOINT_ENCODE3 (1006, 24576, 61352): /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ - case ENCODE (1018, 24572, 62834): + case HB_CODEPOINT_ENCODE3 (1018, 24572, 62834): /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ - case ENCODE (832, 7324, 47162): + case HB_CODEPOINT_ENCODE3 (832, 7324, 47162): /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ - case ENCODE (844, 7302, 45474): + case HB_CODEPOINT_ENCODE3 (844, 7302, 45474): /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ - case ENCODE (180, 13054, 7254): + case HB_CODEPOINT_ENCODE3 (180, 13054, 7254): /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ - case ENCODE (192, 12638, 7254): + case HB_CODEPOINT_ENCODE3 (192, 12638, 7254): /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ - case ENCODE (192, 12690, 7254): + case HB_CODEPOINT_ENCODE3 (192, 12690, 7254): /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ - case ENCODE (188, 248, 3852): + case HB_CODEPOINT_ENCODE3 (188, 248, 3852): /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ - case ENCODE (188, 264, 3426): + case HB_CODEPOINT_ENCODE3 (188, 264, 3426): /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ - case ENCODE (1058, 47032, 11818): + case HB_CODEPOINT_ENCODE3 (1058, 47032, 11818): /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ - case ENCODE (1046, 47030, 12600): + case HB_CODEPOINT_ENCODE3 (1046, 47030, 12600): /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ - case ENCODE (1058, 71796, 16770): + case HB_CODEPOINT_ENCODE3 (1058, 71796, 16770): /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ - case ENCODE (1046, 71790, 17862): + case HB_CODEPOINT_ENCODE3 (1046, 71790, 17862): /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ - case ENCODE (1046, 71788, 17112): + case HB_CODEPOINT_ENCODE3 (1046, 71788, 17112): /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ - case ENCODE (1058, 71794, 17514): + case HB_CODEPOINT_ENCODE3 (1058, 71794, 17514): /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ - case ENCODE (1330, 109904, 57938): + case HB_CODEPOINT_ENCODE3 (1330, 109904, 57938): /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ - case ENCODE (1330, 109904, 58972): + case HB_CODEPOINT_ENCODE3 (1330, 109904, 58972): /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ - case ENCODE (1004, 59092, 14836): + case HB_CODEPOINT_ENCODE3 (1004, 59092, 14836): return true; -#undef ENCODE } return false; } @@ -335,6 +333,12 @@ hb_ot_layout_get_attach_points (hb_face_t *face, unsigned int *point_count /* IN/OUT */, unsigned int *point_array /* OUT */) { +#ifdef HB_NO_LAYOUT_UNUSED + if (point_count) + *point_count = 0; + return 0; +#endif + return face->table.GDEF->table->get_attach_points (glyph, start_offset, point_count, @@ -364,6 +368,12 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) { +#ifdef HB_NO_LAYOUT_UNUSED + if (caret_count) + *caret_count = 0; + return 0; +#endif + unsigned int result_caret_count = 0; unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array); if (result) @@ -384,7 +394,7 @@ bool OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED, hb_face_t *face) const { -#if defined(HB_NO_OT_LAYOUT_BLACKLIST) +#ifdef HB_NO_OT_LAYOUT_BLACKLIST return false; #endif /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts, @@ -412,7 +422,7 @@ bool OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED, hb_face_t *face HB_UNUSED) const { -#if defined(HB_NO_OT_LAYOUT_BLACKLIST) +#ifdef HB_NO_OT_LAYOUT_BLACKLIST return false; #endif return false; @@ -500,6 +510,7 @@ hb_ot_layout_table_find_script (hb_face_t *face, return false; } +#ifndef HB_DISABLE_DEPRECATED /** * hb_ot_layout_table_choose_script: * @face: #hb_face_t to work upon @@ -521,6 +532,7 @@ hb_ot_layout_table_choose_script (hb_face_t *face, for (t = script_tags; *t; t++); return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script); } +#endif /** * hb_ot_layout_table_select_script: @@ -672,6 +684,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, } +#ifndef HB_DISABLE_DEPRECATED /** * hb_ot_layout_script_find_language: * @face: #hb_face_t to work upon @@ -685,6 +698,8 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, * * Return value: true if the language tag is found, false otherwise * + * Since: ?? + * Deprecated: ?? **/ hb_bool_t hb_ot_layout_script_find_language (hb_face_t *face, @@ -700,6 +715,7 @@ hb_ot_layout_script_find_language (hb_face_t *face, &language_tag, language_index); } +#endif /** @@ -716,7 +732,6 @@ hb_ot_layout_script_find_language (hb_face_t *face, * * Return value: true if the language tag is found, false otherwise * - * * Since: 2.0.0 **/ hb_bool_t @@ -1735,7 +1750,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, unsigned int len = 0; if (char_count && characters && start_offset < cv_params.characters.len) { - len = MIN (cv_params.characters.len - start_offset, *char_count); + len = hb_min (cv_params.characters.len - start_offset, *char_count); for (unsigned int i = 0; i < len; ++i) characters[i] = cv_params.characters[start_offset + i]; } diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 359ee1b6f..3b9a78eaf 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -94,7 +94,7 @@ HB_EXTERN hb_bool_t hb_ot_layout_has_glyph_classes (hb_face_t *face); /** - * hb_ot_layout_get_glyph_class: + * hb_ot_layout_glyph_class_t: * @HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: Glyphs not matching the other classifications * @HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: Spacing, single characters, capable of accepting marks * @HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: Glyphs that represent ligation of multiple characters diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 846414c9b..92d70bb41 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -188,12 +188,12 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, feature_infos[j].default_value = feature_infos[i].default_value; } else { feature_infos[j].flags &= ~F_GLOBAL; - feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value); + feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value); /* Inherit default_value from j */ } feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK); - feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]); - feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]); + feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]); + feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]); } feature_infos.shrink (j + 1); } @@ -213,7 +213,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, bits_needed = 0; else /* Limit bits per feature. */ - bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value)); + bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value)); if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) continue; /* Feature disabled, or not enough bits. */ diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh index 62bf072e9..0b16e0b9b 100644 --- a/src/hb-ot-math-table.hh +++ b/src/hb-ot-math-table.hh @@ -462,7 +462,7 @@ struct MathGlyphPartRecord out.end_connector_length = font->em_scale (endConnectorLength, scale); out.full_advance = font->em_scale (fullAdvance, scale); - static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == + static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER == (unsigned int) PartFlags::Extender, ""); out.flags = (hb_ot_math_glyph_part_flags_t) @@ -664,7 +664,7 @@ struct MathVariants /* Array of offsets to MathGlyphConstruction tables - from the beginning of the MathVariants table, for shapes growing in vertical/horizontal direction. */ - UnsizedArrayOf > + UnsizedArrayOf> glyphConstruction; public: diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index bd31bf565..7f2792327 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -37,6 +37,11 @@ * @include: hb-ot.h * * Functions for fetching mathematics layout data from OpenType fonts. + * + * HarfBuzz itself does not implement a math layout solution. The + * functions and types provided can be used by client programs to access + * the font data necessary for typesetting OpenType Math layout. + * **/ @@ -48,31 +53,36 @@ * hb_ot_math_has_data: * @face: #hb_face_t to test * - * This function allows to verify the presence of an OpenType MATH table on the - * face. + * Tests whether a face has a `MATH` table. * - * Return value: true if face has a MATH table, false otherwise + * Return value: true if the table is found, false otherwise * * Since: 1.3.3 **/ hb_bool_t hb_ot_math_has_data (hb_face_t *face) { +#ifdef HB_NO_MATH + return false; +#endif + return face->table.MATH->has_data (); } /** * hb_ot_math_get_constant: - * @font: #hb_font_t from which to retrieve the value + * @font: #hb_font_t to work upon * @constant: #hb_ot_math_constant_t the constant to retrieve * - * This function returns the requested math constants as a #hb_position_t. - * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, - * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or - * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is - * actually an integer between 0 and 100 representing that percentage. + * Fetches the specified math constant. For most constants, the value returned + * is an #hb_position_t. * - * Return value: the requested constant or 0 + * However, if the requested constant is #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, + * #HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or + * #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, then the return value is + * an integer between 0 and 100 representing that percentage. + * + * Return value: the requested constant or zero * * Since: 1.3.3 **/ @@ -80,15 +90,22 @@ hb_position_t hb_ot_math_get_constant (hb_font_t *font, hb_ot_math_constant_t constant) { +#ifdef HB_NO_MATH + return 0; +#endif + return font->face->table.MATH->get_constant(constant, font); } /** * hb_ot_math_get_glyph_italics_correction: - * @font: #hb_font_t from which to retrieve the value - * @glyph: glyph index from which to retrieve the value + * @font: #hb_font_t to work upon + * @glyph: The glyph index from which to retrieve the value * - * Return value: the italics correction of the glyph or 0 + * Fetches an italics-correction value (if one exists) for the specified + * glyph index. + * + * Return value: the italics correction of the glyph or zero * * Since: 1.3.3 **/ @@ -96,15 +113,29 @@ hb_position_t hb_ot_math_get_glyph_italics_correction (hb_font_t *font, hb_codepoint_t glyph) { +#ifdef HB_NO_MATH + return 0; +#endif + return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font); } /** * hb_ot_math_get_glyph_top_accent_attachment: - * @font: #hb_font_t from which to retrieve the value - * @glyph: glyph index from which to retrieve the value + * @font: #hb_font_t to work upon + * @glyph: The glyph index from which to retrieve the value * - * Return value: the top accent attachment of the glyph or 0 + * Fetches a top-accent-attachment value (if one exists) for the specified + * glyph index. + * + * For any glyph that does not have a top-accent-attachment value - that is, + * a glyph not covered by the `MathTopAccentAttachment` table (or, when + * @font has no `MathTopAccentAttachment` table or no `MATH` table, any + * glyph) - the function synthesizes a value, returning the position at + * one-half the glyph's advance width. + * + * Return value: the top accent attachment of the glyph or 0.5 * the advance + * width of @glyph * * Since: 1.3.3 **/ @@ -112,13 +143,19 @@ hb_position_t hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { +#ifdef HB_NO_MATH + return 0; +#endif + return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font); } /** * hb_ot_math_is_glyph_extended_shape: - * @face: a #hb_face_t to test - * @glyph: a glyph index to test + * @face: #hb_face_t to work upon + * @glyph: The glyph index to test + * + * Tests whether the given glyph index is an extended shape in the face. * * Return value: true if the glyph is an extended shape, false otherwise * @@ -128,23 +165,29 @@ hb_bool_t hb_ot_math_is_glyph_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { +#ifdef HB_NO_MATH + return false; +#endif + return face->table.MATH->get_glyph_info().is_extended_shape (glyph); } /** * hb_ot_math_get_glyph_kerning: - * @font: #hb_font_t from which to retrieve the value - * @glyph: glyph index from which to retrieve the value - * @kern: the #hb_ot_math_kern_t from which to retrieve the value + * @font: #hb_font_t to work upon + * @glyph: The glyph index from which to retrieve the value + * @kern: The #hb_ot_math_kern_t from which to retrieve the value * @correction_height: the correction height to use to determine the kerning. * - * This function tries to retrieve the MathKern table for the specified font, - * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the - * MathKern table to find one value that is greater or equal to specified - * correction_height. If one is found the corresponding value from the list of - * kerns is returned and otherwise the last kern value is returned. + * Fetches the math kerning (cut-ins) value for the specified font, glyph index, and + * @kern. * - * Return value: requested kerning or 0 + * If the MathKern table is found, the function examines it to find a height + * value that is greater or equal to @correction_height. If such a height + * value is found, corresponding kerning value from the table is returned. If + * no such height value is found, the last kerning value is returned. + * + * Return value: requested kerning value or zero * * Since: 1.3.3 **/ @@ -154,6 +197,10 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, hb_ot_math_kern_t kern, hb_position_t correction_height) { +#ifdef HB_NO_MATH + return 0; +#endif + return font->face->table.MATH->get_glyph_info().get_kerning (glyph, kern, correction_height, @@ -162,20 +209,24 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, /** * hb_ot_math_get_glyph_variants: - * @font: #hb_font_t from which to retrieve the values - * @glyph: index of the glyph to stretch - * @direction: direction of the stretching + * @font: #hb_font_t to work upon + * @glyph: The index of the glyph to stretch + * @direction: The direction of the stretching (horizontal or vertical) * @start_offset: offset of the first variant to retrieve - * @variants_count: maximum number of variants to retrieve after start_offset - * (IN) and actual number of variants retrieved (OUT) - * @variants: array of size at least @variants_count to store the result + * @variants_count: (inout): Input = the maximum number of variants to return; + * Output = the actual number of variants returned + * @variants: (out) (array length=variants_count): array of variants returned * - * This function tries to retrieve the MathGlyphConstruction for the specified - * font, glyph and direction. Note that only the value of - * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list - * of size variants as an array of hb_ot_math_glyph_variant_t structs. + * Fetches the MathGlyphConstruction for the specified font, glyph index, and + * direction. The corresponding list of size variants is returned as a list of + * #hb_ot_math_glyph_variant_t structs. * - * Return value: the total number of size variants available or 0 + * The @direction parameter is only used to select between horizontal + * or vertical directions for the construction. Even though all #hb_direction_t + * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is + * considered. + * + * Return value: the total number of size variants available or zero * * Since: 1.3.3 **/ @@ -187,6 +238,12 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, unsigned int *variants_count, /* IN/OUT */ hb_ot_math_glyph_variant_t *variants /* OUT */) { +#ifdef HB_NO_MATH + if (variants_count) + *variants_count = 0; + return 0; +#endif + return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font, start_offset, variants_count, @@ -195,15 +252,19 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, /** * hb_ot_math_get_min_connector_overlap: - * @font: #hb_font_t from which to retrieve the value - * @direction: direction of the stretching + * @font: #hb_font_t to work upon + * @direction: direction of the stretching (horizontal or vertical) * - * This function tries to retrieve the MathVariants table for the specified - * font and returns the minimum overlap of connecting glyphs to draw a glyph - * assembly in the specified direction. Note that only the value of - * #HB_DIRECTION_IS_HORIZONTAL is considered. + * Fetches the MathVariants table for the specified font and returns the + * minimum overlap of connecting glyphs that are required to draw a glyph + * assembly in the specified direction. * - * Return value: requested min connector overlap or 0 + * The @direction parameter is only used to select between horizontal + * or vertical directions for the construction. Even though all #hb_direction_t + * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is + * considered. + * + * Return value: requested minimum connector overlap or zero * * Since: 1.3.3 **/ @@ -211,24 +272,33 @@ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, hb_direction_t direction) { +#ifdef HB_NO_MATH + return 0; +#endif + return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font); } /** * hb_ot_math_get_glyph_assembly: - * @font: #hb_font_t from which to retrieve the values - * @glyph: index of the glyph to stretch - * @direction: direction of the stretching + * @font: #hb_font_t to work upon + * @glyph: The index of the glyph to stretch + * @direction: direction of the stretching (horizontal or vertical) * @start_offset: offset of the first glyph part to retrieve - * @parts_count: maximum number of glyph parts to retrieve after start_offset - * (IN) and actual number of parts retrieved (OUT) - * @parts: array of size at least @parts_count to store the result - * @italics_correction: italic correction of the glyph assembly + * @parts_count: (inout): Input = maximum number of glyph parts to return; + * Output = actual number of parts returned + * @parts: (out) (array length=parts_count): the glyph parts returned + * @italics_correction: (out): italics correction of the glyph assembly * - * This function tries to retrieve the GlyphAssembly for the specified font, - * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL - * is considered. It provides the information necessary to draw the glyph - * assembly as an array of #hb_ot_math_glyph_part_t. + * Fetches the GlyphAssembly for the specified font, glyph index, and direction. + * Returned are a list of #hb_ot_math_glyph_part_t glyph parts that can be + * used to draw the glyph and an italics-correction value (if one is defined + * in the font). + * + * The @direction parameter is only used to select between horizontal + * or vertical directions for the construction. Even though all #hb_direction_t + * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is + * considered. * * Return value: the total number of parts in the glyph assembly * @@ -243,6 +313,12 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_ot_math_glyph_part_t *parts, /* OUT */ hb_position_t *italics_correction /* OUT */) { +#ifdef HB_NO_MATH + if (parts_count) + *parts_count = 0; + return 0; +#endif + return font->face->table.MATH->get_variants().get_glyph_parts (glyph, direction, font, diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 521a5ca03..7b2befbce 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -50,6 +50,9 @@ HB_BEGIN_DECLS /** * hb_ot_math_constant_t: * + * The 'MATH' table constants specified at + * https://docs.microsoft.com/en-us/typography/opentype/spec/math + * * Since: 1.3.3 */ typedef enum { @@ -114,6 +117,9 @@ typedef enum { /** * hb_ot_math_kern_t: * + * The math kerning-table types defined for the four corners + * of a glyph. + * * Since: 1.3.3 */ typedef enum { @@ -125,6 +131,10 @@ typedef enum { /** * hb_ot_math_glyph_variant_t: + * @glyph: The glyph index of the variant + * @advance: The advance width of the variant + * + * Data type to hold math-variant information for a glyph. * * Since: 1.3.3 */ @@ -136,14 +146,25 @@ typedef struct hb_ot_math_glyph_variant_t { /** * hb_ot_math_glyph_part_flags_t: * + * Flags for math glyph parts. + * * Since: 1.3.3 */ typedef enum { /*< flags >*/ - HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ + HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ } hb_ot_math_glyph_part_flags_t; /** * hb_ot_math_glyph_part_t: + * @glyph: The glyph index of the variant part + * @start_connector_length: The length of the connector on the starting side of the variant part + * @end_connection_length: The length of the connector on the ending side of the variant part + * @full_advance: The total advance of the part + * @flags: #hb_ot_math_glyph_part_flags_t flags for the part + * + * Data type to hold information for a "part" component of a math-variant glyph. + * Large variants for stretchable math glyphs (such as parentheses) can be constructed + * on the fly from parts. * * Since: 1.3.3 */ diff --git a/src/hb-ot-name-language-static.hh b/src/hb-ot-name-language-static.hh index fac317856..580e7637b 100644 --- a/src/hb-ot-name-language-static.hh +++ b/src/hb-ot-name-language-static.hh @@ -430,6 +430,9 @@ _hb_ot_name_language_for (unsigned int code, const hb_ot_language_map_t *array, unsigned int len) { +#ifdef HB_NO_OT_NAME_LANGUAGE + return HB_LANGUAGE_INVALID; +#endif const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *) hb_bsearch (&code, array, diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index 72deb10b4..68d7b3a65 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -51,6 +51,7 @@ struct NameRecord { hb_language_t language (hb_face_t *face) const { +#ifndef HB_NO_OT_NAME_LANGUAGE unsigned int p = platformID; unsigned int l = languageID; @@ -60,11 +61,12 @@ struct NameRecord if (p == 1) return _hb_ot_name_language_for_mac_code (l); -#if !defined(HB_NO_NAME_TABLE_AAT) +#ifndef HB_NO_OT_NAME_LANGUAGE_AAT if (p == 0) return _hb_aat_language_get (face, l); #endif +#endif return HB_LANGUAGE_INVALID; } @@ -95,11 +97,21 @@ struct NameRecord return UNSUPPORTED; } + NameRecord* copy (hb_serialize_context_t *c, + const void *src_base, + const void *dst_base) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + out->offset.serialize_copy (c, offset, src_base, dst_base, length); + return_trace (out); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - /* We can check from base all the way up to the end of string... */ - return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset)); + return_trace (c->check_struct (this) && offset.sanitize (c, base, length)); } HBUINT16 platformID; /* Platform ID. */ @@ -107,7 +119,8 @@ struct NameRecord HBUINT16 languageID; /* Language ID. */ HBUINT16 nameID; /* Name ID. */ HBUINT16 length; /* String length (in bytes). */ - HBUINT16 offset; /* String offset from start of storage area (in bytes). */ + NNOffsetTo> + offset; /* String offset from start of storage area (in bytes). */ public: DEFINE_SIZE_STATIC (12); }; @@ -158,159 +171,58 @@ struct name unsigned int get_size () const { return min_size + count * nameRecordZ.item_size; } - void get_subsetted_ids (const name *source_name, - const hb_subset_plan_t *plan, - hb_vector_t& name_record_idx_to_retain) const - { - for(unsigned int i = 0; i < count; i++) - { - if (format == 0 && (unsigned int) source_name->nameRecordZ[i].nameID > 25) - continue; - if (!hb_set_is_empty (plan->name_ids) && - !hb_set_has (plan->name_ids, source_name->nameRecordZ[i].nameID)) - continue; - name_record_idx_to_retain.push (i); - } - } - - bool serialize_name_record (hb_serialize_context_t *c, - const name *source_name, - const hb_vector_t& name_record_idx_to_retain) - { - for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++) - { - unsigned int idx = name_record_idx_to_retain[i]; - if (unlikely (idx >= source_name->count)) - { - DEBUG_MSG (SUBSET, nullptr, "Invalid index: %d.", idx); - return false; - } - - c->push (); - - NameRecord *p = c->embed (source_name->nameRecordZ[idx]); - if (!p) - return false; - p->offset = 0; - } - - return true; - } - - bool serialize_strings (hb_serialize_context_t *c, - const name *source_name, - const hb_subset_plan_t *plan, - const hb_vector_t& name_record_idx_to_retain) - { - hb_face_t *face = plan->source; - accelerator_t acc; - acc.init (face); - - for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++) - { - unsigned int idx = name_record_idx_to_retain[i]; - unsigned int size = acc.get_name (idx).get_size (); - - c->push (); - char *new_pos = c->allocate_size (size); - - if (unlikely (new_pos == nullptr)) - { - acc.fini (); - DEBUG_MSG (SUBSET, nullptr, "Couldn't allocate enough space for Name string: %u.", - size); - return false; - } - - const HBUINT8* source_string_pool = (source_name + source_name->stringOffset).arrayZ; - unsigned int name_record_offset = source_name->nameRecordZ[idx].offset; - - memcpy (new_pos, source_string_pool + name_record_offset, size); - } - - acc.fini (); - return true; - } - - bool pack_record_and_strings (name *dest_name_unpacked, - hb_serialize_context_t *c, - unsigned length) - { - hb_hashmap_t id_str_idx_map; - for (int i = length-1; i >= 0; i--) - { - unsigned objidx = c->pop_pack (); - id_str_idx_map.set ((unsigned)i, objidx); - } - - const void *base = & (dest_name_unpacked->nameRecordZ[length]); - for (int i = length-1; i >= 0; i--) - { - unsigned str_idx = id_str_idx_map.get ((unsigned)i); - NameRecord& namerecord = dest_name_unpacked->nameRecordZ[i]; - c->add_link (namerecord.offset, str_idx, base); - c->pop_pack (); - } - - if (c->in_error ()) - return false; - - return true; - } - + template bool serialize (hb_serialize_context_t *c, - const name *source_name, - const hb_subset_plan_t *plan, - const hb_vector_t& name_record_idx_to_retain) + Iterator it, + const void *src_string_pool) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min ((*this)))) return_trace (false); - this->format = source_name->format; - this->count = name_record_idx_to_retain.length; - this->stringOffset = min_size + name_record_idx_to_retain.length * NameRecord::static_size; + this->format = 0; + this->count = it.len (); + auto snap = c->snapshot (); + this->nameRecordZ.serialize (c, this->count); + if (unlikely (!c->check_assign (this->stringOffset, c->length ()))) return_trace (false); + c->revert (snap); - if (!serialize_name_record (c, source_name, name_record_idx_to_retain)) - return_trace (false); + const void *dst_string_pool = &(this + this->stringOffset); - if (!serialize_strings (c, source_name, plan, name_record_idx_to_retain)) - return_trace (false); + + it + | hb_apply ([=] (const NameRecord& _) { c->copy (_, src_string_pool, dst_string_pool); }) + ; - if (!pack_record_and_strings (this, c, name_record_idx_to_retain.length)) - return_trace (false); + if (unlikely (c->ran_out_of_room)) return_trace (false); + + assert (this->stringOffset == c->length ()); return_trace (true); } bool subset (hb_subset_context_t *c) const { - hb_subset_plan_t *plan = c->plan; - hb_vector_t name_record_idx_to_retain; + TRACE_SUBSET (this); - get_subsetted_ids (this, plan, name_record_idx_to_retain); + name *name_prime = c->serializer->start_embed (); + if (unlikely (!name_prime)) return_trace (false); - hb_serialize_context_t *serializer = c->serializer; - name *name_prime = serializer->start_embed (); - if (!name_prime || !name_prime->serialize (serializer, this, plan, name_record_idx_to_retain)) - { - DEBUG_MSG (SUBSET, nullptr, "Failed to serialize write new name."); - return false; - } - - return true; + auto it = + + nameRecordZ.as_array (count) + | hb_filter (c->plan->name_ids, &NameRecord::nameID) + ; + + name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset)); + return_trace (name_prime->count); } bool sanitize_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); const void *string_pool = (this+stringOffset).arrayZ; - unsigned int _count = count; - /* Move to run-time?! */ - for (unsigned int i = 0; i < _count; i++) - if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false); - return_trace (true); + return_trace (nameRecordZ.sanitize (c, count, string_pool)); } bool sanitize (hb_sanitize_context_t *c) const @@ -319,7 +231,8 @@ struct name return_trace (c->check_struct (this) && likely (format == 0 || format == 1) && c->check_array (nameRecordZ.arrayZ, count) && - c->check_range (this, stringOffset)); + c->check_range (this, stringOffset) && + sanitize_records (c)); } struct accelerator_t @@ -409,7 +322,7 @@ struct name /* We only implement format 0 for now. */ HBUINT16 format; /* Format selector (=0/1). */ HBUINT16 count; /* Number of name records. */ - NNOffsetTo > + NNOffsetTo> stringOffset; /* Offset to start of string storage (from start of table). */ UnsizedArrayOf nameRecordZ; /* The name records where count is the number of records. */ diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc index 907ae6ab5..5cd1cc118 100644 --- a/src/hb-ot-name.cc +++ b/src/hb-ot-name.cc @@ -58,6 +58,11 @@ const hb_ot_name_entry_t * hb_ot_name_list_names (hb_face_t *face, unsigned int *num_entries /* OUT */) { +#ifdef HB_NO_NAME + if (num_entries) + *num_entries = 0; + return 0; +#endif const OT::name_accelerator_t &name = *face->table.name; if (num_entries) *num_entries = name.names.length; return (const hb_ot_name_entry_t *) name.names; @@ -93,7 +98,7 @@ hb_ot_name_convert_utf (hb_bytes_t bytes, dst = dst_next; src = src_next; - }; + } *text_size = dst - text; *dst = 0; /* NUL-terminate. */ @@ -105,7 +110,7 @@ hb_ot_name_convert_utf (hb_bytes_t bytes, { src = in_utf_t::next (src, src_end, &unicode, replacement); dst_len += out_utf_t::encode_len (unicode); - }; + } return dst_len; } @@ -167,6 +172,11 @@ hb_ot_name_get_utf8 (hb_face_t *face, unsigned int *text_size /* IN/OUT */, char *text /* OUT */) { +#ifdef HB_NO_NAME + if (text_size) + *text_size = 0; + return 0; +#endif return hb_ot_name_get_utf (face, name_id, language, text_size, (hb_utf8_t::codepoint_t *) text); } @@ -194,6 +204,11 @@ hb_ot_name_get_utf16 (hb_face_t *face, unsigned int *text_size /* IN/OUT */, uint16_t *text /* OUT */) { +#ifdef HB_NO_NAME + if (text_size) + *text_size = 0; + return 0; +#endif return hb_ot_name_get_utf (face, name_id, language, text_size, text); } @@ -220,5 +235,10 @@ hb_ot_name_get_utf32 (hb_face_t *face, unsigned int *text_size /* IN/OUT */, uint32_t *text /* OUT */) { +#ifdef HB_NO_NAME + if (text_size) + *text_size = 0; + return 0; +#endif return hb_ot_name_get_utf (face, name_id, language, text_size, text); } diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index 21aa94dad..970bbe68a 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -131,7 +131,7 @@ struct post hb_bytes_t s = find_glyph_name (glyph); if (!s.length) return false; if (!buf_len) return true; - unsigned int len = MIN (buf_len - 1, s.length); + unsigned int len = hb_min (buf_len - 1, s.length); strncpy (buf, s.arrayZ, len); buf[len] = '\0'; return true; @@ -168,8 +168,8 @@ struct post } hb_bytes_t st (name, len); - const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count, - sizeof (gids[0]), cmp_key, (void *) this); + const uint16_t *gid = (const uint16_t *) hb_bsearch (hb_addressof (st), gids, count, + sizeof (gids[0]), cmp_key, (void *) this); if (gid) { *glyph = *gid; diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 4daf2a666..3212e0c96 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -383,7 +383,7 @@ arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { -#if defined(HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK) +#ifdef HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK return; #endif diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc index db8801814..14989730f 100644 --- a/src/hb-ot-shape-complex-hebrew.cc +++ b/src/hb-ot-shape-complex-hebrew.cc @@ -70,7 +70,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, bool found = (bool) c->unicode->compose (a, b, ab); -#if defined(HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK) +#ifdef HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK return found; #endif diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh index 08b90e913..ca26ecbae 100644 --- a/src/hb-ot-shape-complex-indic-machine.hh +++ b/src/hb-ot-shape-complex-indic-machine.hh @@ -34,788 +34,284 @@ #line 36 "hb-ot-shape-complex-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { - 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, - 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, - 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, - 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, - 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, - 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, - 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, - 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, - 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, - 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, - 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, - 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u, - 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, - 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, - 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, - 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, - 5u, 8u, 8u, 8u, 1u, 19u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, - 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, - 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, - 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, - 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, - 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, - 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, - 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, - 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, - 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, - 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, - 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, - 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, - 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, - 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, - 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, - 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, - 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, - 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, - 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, - 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, - 1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, - 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, - 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, - 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, - 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, - 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, - 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, - 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, - 1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, - 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, - 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0 + 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, + 4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, + 4u, 8u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, + 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, + 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 5u, 8u, 8u, 8u, 1u, 19u, + 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, + 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, + 3u, 10u, 5u, 10u, 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, + 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, + 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, + 5u, 10u, 3u, 17u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, + 3u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, + 4u, 10u, 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, + 3u, 17u, 4u, 13u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, + 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, + 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 1u, 17u, + 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, + 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0 }; static const char _indic_syllable_machine_key_spans[] = { - 1, 5, 3, 1, 4, 3, 1, 4, - 3, 1, 4, 3, 1, 5, 1, 1, - 5, 1, 1, 5, 1, 1, 5, 1, - 1, 10, 5, 10, 5, 10, 5, 10, - 5, 10, 1, 5, 3, 1, 4, 3, - 1, 4, 3, 1, 4, 3, 1, 5, - 1, 1, 5, 1, 1, 5, 1, 1, - 5, 1, 1, 10, 5, 10, 5, 10, - 5, 10, 5, 10, 1, 5, 3, 1, - 4, 3, 1, 4, 3, 1, 4, 3, - 1, 5, 1, 1, 5, 1, 1, 5, - 1, 1, 5, 1, 1, 10, 5, 10, - 5, 10, 5, 10, 5, 1, 5, 3, - 1, 4, 3, 1, 4, 3, 1, 4, - 3, 1, 5, 1, 1, 5, 1, 1, - 5, 1, 1, 5, 1, 1, 10, 5, - 10, 5, 10, 5, 10, 5, 10, 10, - 4, 1, 19, 15, 15, 14, 16, 15, - 15, 14, 16, 15, 15, 14, 16, 15, - 15, 14, 16, 15, 15, 14, 6, 6, - 6, 1, 1, 1, 6, 8, 6, 8, - 7, 6, 8, 7, 6, 8, 7, 6, - 8, 7, 7, 15, 15, 16, 16, 16, - 15, 15, 16, 16, 16, 15, 15, 16, - 16, 16, 15, 15, 16, 16, 16, 15, - 15, 15, 15, 14, 16, 15, 15, 14, - 16, 15, 15, 14, 16, 15, 15, 14, - 16, 15, 15, 14, 6, 6, 6, 1, - 1, 1, 6, 8, 6, 8, 7, 6, - 8, 7, 6, 8, 7, 6, 8, 7, - 7, 15, 15, 16, 16, 16, 15, 15, - 16, 16, 16, 15, 15, 16, 16, 16, - 15, 15, 16, 16, 16, 5, 15, 15, - 14, 16, 15, 15, 14, 16, 15, 15, - 14, 16, 15, 15, 14, 16, 15, 15, - 14, 6, 6, 6, 1, 1, 1, 6, - 8, 6, 8, 7, 6, 8, 7, 6, - 8, 7, 6, 8, 7, 7, 15, 15, - 16, 16, 16, 15, 15, 16, 16, 16, - 15, 15, 16, 16, 16, 15, 15, 16, - 16, 16, 10, 15, 5, 15, 15, 14, - 16, 15, 15, 14, 16, 15, 15, 14, - 16, 15, 15, 14, 16, 15, 15, 14, - 6, 6, 6, 1, 1, 1, 6, 8, - 6, 8, 7, 6, 8, 7, 6, 8, - 7, 6, 8, 7, 7, 15, 15, 16, - 16, 16, 15, 15, 16, 16, 16, 15, - 15, 16, 16, 16, 15, 15, 16, 16, - 16, 15, 17, 15, 17, 10, 6, 1, - 1, 1, 6, 16, 8, 6, 6, 1, - 1, 1, 6, 16 + 1, 5, 3, 4, 5, 1, 1, 5, + 10, 5, 1, 3, 4, 5, 1, 1, + 5, 10, 10, 10, 1, 3, 4, 5, + 1, 1, 5, 5, 10, 1, 3, 4, + 5, 1, 1, 5, 5, 4, 1, 19, + 15, 15, 14, 16, 6, 6, 1, 6, + 16, 16, 16, 8, 7, 6, 7, 6, + 8, 6, 15, 15, 15, 15, 14, 16, + 15, 15, 14, 16, 6, 1, 6, 16, + 16, 8, 7, 6, 7, 6, 6, 8, + 6, 15, 15, 5, 15, 15, 14, 16, + 15, 16, 6, 1, 6, 16, 16, 8, + 7, 6, 15, 7, 6, 6, 8, 6, + 15, 10, 5, 15, 15, 14, 16, 15, + 16, 6, 1, 6, 16, 16, 8, 7, + 6, 15, 7, 6, 6, 8, 6, 17, + 15, 17, 10, 6, 1, 6, 16, 8, + 6, 6, 1, 6, 16 }; static const short _indic_syllable_machine_index_offsets[] = { - 0, 2, 8, 12, 14, 19, 23, 25, - 30, 34, 36, 41, 45, 47, 53, 55, - 57, 63, 65, 67, 73, 75, 77, 83, - 85, 87, 98, 104, 115, 121, 132, 138, - 149, 155, 166, 168, 174, 178, 180, 185, - 189, 191, 196, 200, 202, 207, 211, 213, - 219, 221, 223, 229, 231, 233, 239, 241, - 243, 249, 251, 253, 264, 270, 281, 287, - 298, 304, 315, 321, 332, 334, 340, 344, - 346, 351, 355, 357, 362, 366, 368, 373, - 377, 379, 385, 387, 389, 395, 397, 399, - 405, 407, 409, 415, 417, 419, 430, 436, - 447, 453, 464, 470, 481, 487, 489, 495, - 499, 501, 506, 510, 512, 517, 521, 523, - 528, 532, 534, 540, 542, 544, 550, 552, - 554, 560, 562, 564, 570, 572, 574, 585, - 591, 602, 608, 619, 625, 636, 642, 653, - 664, 669, 671, 691, 707, 723, 738, 755, - 771, 787, 802, 819, 835, 851, 866, 883, - 899, 915, 930, 947, 963, 979, 994, 1001, - 1008, 1015, 1017, 1019, 1021, 1028, 1037, 1044, - 1053, 1061, 1068, 1077, 1085, 1092, 1101, 1109, - 1116, 1125, 1133, 1141, 1157, 1173, 1190, 1207, - 1224, 1240, 1256, 1273, 1290, 1307, 1323, 1339, - 1356, 1373, 1390, 1406, 1422, 1439, 1456, 1473, - 1489, 1505, 1521, 1537, 1552, 1569, 1585, 1601, - 1616, 1633, 1649, 1665, 1680, 1697, 1713, 1729, - 1744, 1761, 1777, 1793, 1808, 1815, 1822, 1829, - 1831, 1833, 1835, 1842, 1851, 1858, 1867, 1875, - 1882, 1891, 1899, 1906, 1915, 1923, 1930, 1939, - 1947, 1955, 1971, 1987, 2004, 2021, 2038, 2054, - 2070, 2087, 2104, 2121, 2137, 2153, 2170, 2187, - 2204, 2220, 2236, 2253, 2270, 2287, 2293, 2309, - 2325, 2340, 2357, 2373, 2389, 2404, 2421, 2437, - 2453, 2468, 2485, 2501, 2517, 2532, 2549, 2565, - 2581, 2596, 2603, 2610, 2617, 2619, 2621, 2623, - 2630, 2639, 2646, 2655, 2663, 2670, 2679, 2687, - 2694, 2703, 2711, 2718, 2727, 2735, 2743, 2759, - 2775, 2792, 2809, 2826, 2842, 2858, 2875, 2892, - 2909, 2925, 2941, 2958, 2975, 2992, 3008, 3024, - 3041, 3058, 3075, 3086, 3102, 3108, 3124, 3140, - 3155, 3172, 3188, 3204, 3219, 3236, 3252, 3268, - 3283, 3300, 3316, 3332, 3347, 3364, 3380, 3396, - 3411, 3418, 3425, 3432, 3434, 3436, 3438, 3445, - 3454, 3461, 3470, 3478, 3485, 3494, 3502, 3509, - 3518, 3526, 3533, 3542, 3550, 3558, 3574, 3590, - 3607, 3624, 3641, 3657, 3673, 3690, 3707, 3724, - 3740, 3756, 3773, 3790, 3807, 3823, 3839, 3856, - 3873, 3890, 3906, 3924, 3940, 3958, 3969, 3976, - 3978, 3980, 3982, 3989, 4006, 4015, 4022, 4029, - 4031, 4033, 4035, 4042 + 0, 2, 8, 12, 17, 23, 25, 27, + 33, 44, 50, 52, 56, 61, 67, 69, + 71, 77, 88, 99, 110, 112, 116, 121, + 127, 129, 131, 137, 143, 154, 156, 160, + 165, 171, 173, 175, 181, 187, 192, 194, + 214, 230, 246, 261, 278, 285, 292, 294, + 301, 318, 335, 352, 361, 369, 376, 384, + 391, 400, 407, 423, 439, 455, 471, 486, + 503, 519, 535, 550, 567, 574, 576, 583, + 600, 617, 626, 634, 641, 649, 656, 663, + 672, 679, 695, 711, 717, 733, 749, 764, + 781, 797, 814, 821, 823, 830, 847, 864, + 873, 881, 888, 904, 912, 919, 926, 935, + 942, 958, 969, 975, 991, 1007, 1022, 1039, + 1055, 1072, 1079, 1081, 1088, 1105, 1122, 1131, + 1139, 1146, 1162, 1170, 1177, 1184, 1193, 1200, + 1218, 1234, 1252, 1263, 1270, 1272, 1279, 1296, + 1305, 1312, 1319, 1321, 1328 }; -static const short _indic_syllable_machine_indicies[] = { +static const unsigned char _indic_syllable_machine_indicies[] = { 1, 0, 2, 3, 3, 4, 1, 0, - 5, 5, 4, 0, 4, 0, 6, 6, - 7, 1, 0, 8, 8, 7, 0, 7, - 0, 9, 9, 10, 1, 0, 11, 11, - 10, 0, 10, 0, 12, 12, 13, 1, - 0, 14, 14, 13, 0, 13, 0, 15, - 0, 0, 0, 1, 0, 16, 0, 17, - 0, 18, 12, 12, 13, 1, 0, 19, - 0, 20, 0, 21, 9, 9, 10, 1, - 0, 22, 0, 23, 0, 24, 6, 6, - 7, 1, 0, 25, 0, 26, 0, 2, - 3, 3, 4, 1, 0, 0, 0, 0, - 27, 0, 28, 3, 3, 4, 1, 0, - 28, 3, 3, 4, 1, 0, 0, 0, - 0, 29, 0, 30, 3, 3, 4, 1, - 0, 30, 3, 3, 4, 1, 0, 0, - 0, 0, 31, 0, 32, 3, 3, 4, - 1, 0, 32, 3, 3, 4, 1, 0, - 0, 0, 0, 33, 0, 34, 3, 3, - 4, 1, 0, 34, 3, 3, 4, 1, - 0, 0, 0, 0, 35, 0, 37, 36, - 38, 39, 39, 40, 37, 36, 41, 41, - 40, 36, 40, 36, 42, 42, 43, 37, - 36, 44, 44, 43, 36, 43, 36, 45, - 45, 46, 37, 36, 47, 47, 46, 36, - 46, 36, 48, 48, 49, 37, 36, 50, - 50, 49, 36, 49, 36, 51, 36, 36, - 36, 37, 36, 52, 36, 53, 36, 54, - 48, 48, 49, 37, 36, 55, 36, 56, - 36, 57, 45, 45, 46, 37, 36, 58, - 36, 59, 36, 60, 42, 42, 43, 37, - 36, 61, 36, 62, 36, 38, 39, 39, - 40, 37, 36, 36, 36, 36, 63, 36, - 64, 39, 39, 40, 37, 36, 64, 39, - 39, 40, 37, 36, 36, 36, 36, 65, - 36, 66, 39, 39, 40, 37, 36, 66, - 39, 39, 40, 37, 36, 36, 36, 36, - 67, 36, 68, 39, 39, 40, 37, 36, - 68, 39, 39, 40, 37, 36, 36, 36, - 36, 69, 36, 70, 39, 39, 40, 37, - 36, 70, 39, 39, 40, 37, 36, 36, - 36, 36, 71, 36, 73, 72, 74, 75, - 75, 76, 73, 72, 78, 78, 76, 77, - 76, 77, 79, 79, 80, 73, 72, 81, - 81, 80, 72, 80, 72, 82, 82, 83, - 73, 72, 84, 84, 83, 72, 83, 72, - 85, 85, 86, 73, 72, 87, 87, 86, - 72, 86, 72, 88, 72, 72, 72, 73, - 72, 89, 72, 90, 72, 91, 85, 85, - 86, 73, 72, 92, 72, 93, 72, 94, - 82, 82, 83, 73, 72, 95, 72, 96, - 72, 97, 79, 79, 80, 73, 72, 98, - 72, 99, 72, 74, 75, 75, 76, 73, - 72, 72, 72, 72, 100, 72, 101, 75, - 75, 76, 73, 72, 101, 75, 75, 76, - 73, 72, 72, 72, 72, 102, 72, 103, - 75, 75, 76, 73, 72, 103, 75, 75, - 76, 73, 72, 72, 72, 72, 104, 72, - 105, 75, 75, 76, 73, 72, 105, 75, - 75, 76, 73, 72, 72, 72, 72, 106, - 72, 107, 75, 75, 76, 73, 72, 109, - 108, 110, 111, 111, 112, 109, 108, 113, - 113, 112, 108, 112, 108, 114, 114, 115, - 109, 108, 116, 116, 115, 108, 115, 108, - 117, 117, 118, 109, 108, 119, 119, 118, - 108, 118, 108, 120, 120, 121, 109, 108, - 122, 122, 121, 108, 121, 108, 123, 108, - 108, 108, 109, 108, 124, 108, 125, 108, - 126, 120, 120, 121, 109, 108, 127, 108, - 128, 108, 129, 117, 117, 118, 109, 108, - 130, 108, 131, 108, 132, 114, 114, 115, - 109, 108, 133, 108, 134, 108, 110, 111, - 111, 112, 109, 108, 108, 108, 108, 135, - 108, 136, 111, 111, 112, 109, 108, 136, - 111, 111, 112, 109, 108, 108, 108, 108, - 137, 108, 138, 111, 111, 112, 109, 108, - 138, 111, 111, 112, 109, 108, 108, 108, - 108, 139, 108, 140, 111, 111, 112, 109, - 108, 140, 111, 111, 112, 109, 108, 108, - 108, 108, 141, 108, 142, 111, 111, 112, - 109, 108, 142, 111, 111, 112, 109, 108, - 108, 108, 108, 143, 108, 107, 75, 75, - 76, 73, 72, 72, 72, 72, 144, 72, - 78, 78, 76, 1, 0, 146, 145, 148, - 149, 150, 151, 152, 153, 76, 73, 147, - 154, 155, 155, 144, 147, 156, 157, 158, - 159, 160, 147, 162, 163, 164, 165, 4, - 1, 161, 166, 161, 161, 35, 161, 161, - 161, 167, 161, 168, 163, 169, 169, 4, - 1, 161, 166, 161, 161, 161, 161, 161, - 161, 167, 161, 163, 169, 169, 4, 1, - 161, 166, 161, 161, 161, 161, 161, 161, - 167, 161, 170, 161, 161, 161, 17, 171, - 161, 1, 161, 166, 161, 161, 161, 161, - 161, 170, 161, 172, 173, 174, 175, 4, - 1, 161, 166, 161, 161, 33, 161, 161, - 161, 167, 161, 176, 173, 177, 177, 4, - 1, 161, 166, 161, 161, 161, 161, 161, - 161, 167, 161, 173, 177, 177, 4, 1, - 161, 166, 161, 161, 161, 161, 161, 161, - 167, 161, 178, 161, 161, 161, 17, 179, - 161, 1, 161, 166, 161, 161, 161, 161, - 161, 178, 161, 180, 181, 182, 183, 4, - 1, 161, 166, 161, 161, 31, 161, 161, - 161, 167, 161, 184, 181, 185, 185, 4, - 1, 161, 166, 161, 161, 161, 161, 161, - 161, 167, 161, 181, 185, 185, 4, 1, - 161, 166, 161, 161, 161, 161, 161, 161, - 167, 161, 186, 161, 161, 161, 17, 187, - 161, 1, 161, 166, 161, 161, 161, 161, - 161, 186, 161, 188, 189, 190, 191, 4, - 1, 161, 166, 161, 161, 29, 161, 161, - 161, 167, 161, 192, 189, 193, 193, 4, - 1, 161, 166, 161, 161, 161, 161, 161, - 161, 167, 161, 189, 193, 193, 4, 1, - 161, 166, 161, 161, 161, 161, 161, 161, - 167, 161, 194, 161, 161, 161, 17, 195, - 161, 1, 161, 166, 161, 161, 161, 161, - 161, 194, 161, 196, 197, 198, 199, 4, - 1, 161, 166, 161, 161, 27, 161, 161, - 161, 167, 161, 200, 197, 201, 201, 4, - 1, 161, 166, 161, 161, 161, 161, 161, - 161, 167, 161, 197, 201, 201, 4, 1, - 161, 166, 161, 161, 161, 161, 161, 161, - 167, 161, 17, 202, 161, 1, 161, 166, - 161, 203, 203, 161, 1, 161, 166, 161, - 204, 161, 161, 205, 161, 166, 161, 166, - 161, 206, 161, 207, 161, 204, 161, 161, - 161, 161, 166, 161, 17, 161, 203, 203, - 161, 1, 161, 166, 161, 203, 202, 161, - 1, 161, 166, 161, 208, 26, 209, 210, - 7, 1, 161, 166, 161, 26, 209, 210, - 7, 1, 161, 166, 161, 209, 209, 7, - 1, 161, 166, 161, 211, 23, 212, 213, - 10, 1, 161, 166, 161, 23, 212, 213, - 10, 1, 161, 166, 161, 212, 212, 10, - 1, 161, 166, 161, 214, 20, 215, 216, - 13, 1, 161, 166, 161, 20, 215, 216, - 13, 1, 161, 166, 161, 215, 215, 13, - 1, 161, 166, 161, 217, 17, 203, 218, - 161, 1, 161, 166, 161, 17, 203, 218, - 161, 1, 161, 166, 161, 197, 201, 201, - 4, 1, 161, 166, 161, 196, 197, 201, - 201, 4, 1, 161, 166, 161, 161, 161, - 161, 161, 161, 167, 161, 196, 197, 198, - 201, 4, 1, 161, 166, 161, 161, 27, - 161, 161, 161, 167, 161, 194, 161, 219, - 161, 203, 203, 161, 1, 161, 166, 161, - 161, 161, 161, 161, 194, 161, 194, 161, - 161, 161, 203, 203, 161, 1, 161, 166, - 161, 161, 161, 161, 161, 194, 161, 194, - 161, 161, 161, 203, 195, 161, 1, 161, - 166, 161, 161, 161, 161, 161, 194, 161, - 188, 189, 193, 193, 4, 1, 161, 166, - 161, 161, 161, 161, 161, 161, 167, 161, - 188, 189, 190, 193, 4, 1, 161, 166, - 161, 161, 29, 161, 161, 161, 167, 161, - 186, 161, 220, 161, 203, 203, 161, 1, - 161, 166, 161, 161, 161, 161, 161, 186, - 161, 186, 161, 161, 161, 203, 203, 161, - 1, 161, 166, 161, 161, 161, 161, 161, - 186, 161, 186, 161, 161, 161, 203, 187, - 161, 1, 161, 166, 161, 161, 161, 161, - 161, 186, 161, 180, 181, 185, 185, 4, - 1, 161, 166, 161, 161, 161, 161, 161, - 161, 167, 161, 180, 181, 182, 185, 4, - 1, 161, 166, 161, 161, 31, 161, 161, - 161, 167, 161, 178, 161, 221, 161, 203, - 203, 161, 1, 161, 166, 161, 161, 161, - 161, 161, 178, 161, 178, 161, 161, 161, - 203, 203, 161, 1, 161, 166, 161, 161, - 161, 161, 161, 178, 161, 178, 161, 161, - 161, 203, 179, 161, 1, 161, 166, 161, - 161, 161, 161, 161, 178, 161, 172, 173, - 177, 177, 4, 1, 161, 166, 161, 161, - 161, 161, 161, 161, 167, 161, 172, 173, - 174, 177, 4, 1, 161, 166, 161, 161, - 33, 161, 161, 161, 167, 161, 170, 161, - 222, 161, 203, 203, 161, 1, 161, 166, - 161, 161, 161, 161, 161, 170, 161, 170, - 161, 161, 161, 203, 203, 161, 1, 161, - 166, 161, 161, 161, 161, 161, 170, 161, - 170, 161, 161, 161, 203, 171, 161, 1, - 161, 166, 161, 161, 161, 161, 161, 170, - 161, 162, 163, 169, 169, 4, 1, 161, - 166, 161, 161, 161, 161, 161, 161, 167, - 161, 162, 163, 164, 169, 4, 1, 161, - 166, 161, 161, 35, 161, 161, 161, 167, - 161, 224, 225, 226, 227, 40, 37, 223, - 228, 223, 223, 71, 223, 223, 223, 229, - 223, 230, 225, 231, 227, 40, 37, 223, - 228, 223, 223, 223, 223, 223, 223, 229, - 223, 225, 231, 227, 40, 37, 223, 228, - 223, 223, 223, 223, 223, 223, 229, 223, - 232, 223, 223, 223, 53, 233, 223, 37, - 223, 228, 223, 223, 223, 223, 223, 232, - 223, 234, 235, 236, 237, 40, 37, 223, - 228, 223, 223, 69, 223, 223, 223, 229, - 223, 238, 235, 239, 239, 40, 37, 223, - 228, 223, 223, 223, 223, 223, 223, 229, - 223, 235, 239, 239, 40, 37, 223, 228, - 223, 223, 223, 223, 223, 223, 229, 223, - 240, 223, 223, 223, 53, 241, 223, 37, - 223, 228, 223, 223, 223, 223, 223, 240, - 223, 242, 243, 244, 245, 40, 37, 223, - 228, 223, 223, 67, 223, 223, 223, 229, - 223, 246, 243, 247, 247, 40, 37, 223, - 228, 223, 223, 223, 223, 223, 223, 229, - 223, 243, 247, 247, 40, 37, 223, 228, - 223, 223, 223, 223, 223, 223, 229, 223, - 248, 223, 223, 223, 53, 249, 223, 37, - 223, 228, 223, 223, 223, 223, 223, 248, - 223, 250, 251, 252, 253, 40, 37, 223, - 228, 223, 223, 65, 223, 223, 223, 229, - 223, 254, 251, 255, 255, 40, 37, 223, - 228, 223, 223, 223, 223, 223, 223, 229, - 223, 251, 255, 255, 40, 37, 223, 228, - 223, 223, 223, 223, 223, 223, 229, 223, - 256, 223, 223, 223, 53, 257, 223, 37, - 223, 228, 223, 223, 223, 223, 223, 256, - 223, 258, 259, 260, 261, 40, 37, 223, - 228, 223, 223, 63, 223, 223, 223, 229, - 223, 262, 259, 263, 263, 40, 37, 223, - 228, 223, 223, 223, 223, 223, 223, 229, - 223, 259, 263, 263, 40, 37, 223, 228, - 223, 223, 223, 223, 223, 223, 229, 223, - 53, 264, 223, 37, 223, 228, 223, 265, - 265, 223, 37, 223, 228, 223, 266, 223, - 223, 267, 223, 228, 223, 228, 223, 268, - 223, 269, 223, 266, 223, 223, 223, 223, - 228, 223, 53, 223, 265, 265, 223, 37, - 223, 228, 223, 265, 264, 223, 37, 223, - 228, 223, 270, 62, 271, 272, 43, 37, - 223, 228, 223, 62, 271, 272, 43, 37, - 223, 228, 223, 271, 271, 43, 37, 223, - 228, 223, 273, 59, 274, 275, 46, 37, - 223, 228, 223, 59, 274, 275, 46, 37, - 223, 228, 223, 274, 274, 46, 37, 223, - 228, 223, 276, 56, 277, 278, 49, 37, - 223, 228, 223, 56, 277, 278, 49, 37, - 223, 228, 223, 277, 277, 49, 37, 223, - 228, 223, 279, 53, 265, 280, 223, 37, - 223, 228, 223, 53, 265, 280, 223, 37, - 223, 228, 223, 259, 263, 263, 40, 37, - 223, 228, 223, 258, 259, 263, 263, 40, - 37, 223, 228, 223, 223, 223, 223, 223, - 223, 229, 223, 258, 259, 260, 263, 40, - 37, 223, 228, 223, 223, 63, 223, 223, - 223, 229, 223, 256, 223, 281, 223, 265, - 265, 223, 37, 223, 228, 223, 223, 223, - 223, 223, 256, 223, 256, 223, 223, 223, - 265, 265, 223, 37, 223, 228, 223, 223, - 223, 223, 223, 256, 223, 256, 223, 223, - 223, 265, 257, 223, 37, 223, 228, 223, - 223, 223, 223, 223, 256, 223, 250, 251, - 255, 255, 40, 37, 223, 228, 223, 223, - 223, 223, 223, 223, 229, 223, 250, 251, - 252, 255, 40, 37, 223, 228, 223, 223, - 65, 223, 223, 223, 229, 223, 248, 223, - 282, 223, 265, 265, 223, 37, 223, 228, - 223, 223, 223, 223, 223, 248, 223, 248, - 223, 223, 223, 265, 265, 223, 37, 223, - 228, 223, 223, 223, 223, 223, 248, 223, - 248, 223, 223, 223, 265, 249, 223, 37, - 223, 228, 223, 223, 223, 223, 223, 248, - 223, 242, 243, 247, 247, 40, 37, 223, - 228, 223, 223, 223, 223, 223, 223, 229, - 223, 242, 243, 244, 247, 40, 37, 223, - 228, 223, 223, 67, 223, 223, 223, 229, - 223, 240, 223, 283, 223, 265, 265, 223, - 37, 223, 228, 223, 223, 223, 223, 223, - 240, 223, 240, 223, 223, 223, 265, 265, - 223, 37, 223, 228, 223, 223, 223, 223, - 223, 240, 223, 240, 223, 223, 223, 265, - 241, 223, 37, 223, 228, 223, 223, 223, - 223, 223, 240, 223, 234, 235, 239, 239, - 40, 37, 223, 228, 223, 223, 223, 223, - 223, 223, 229, 223, 234, 235, 236, 239, - 40, 37, 223, 228, 223, 223, 69, 223, - 223, 223, 229, 223, 232, 223, 284, 223, - 265, 265, 223, 37, 223, 228, 223, 223, - 223, 223, 223, 232, 223, 232, 223, 223, - 223, 265, 265, 223, 37, 223, 228, 223, - 223, 223, 223, 223, 232, 223, 232, 223, - 223, 223, 265, 233, 223, 37, 223, 228, - 223, 223, 223, 223, 223, 232, 223, 70, - 39, 39, 40, 37, 223, 224, 225, 231, - 227, 40, 37, 223, 228, 223, 223, 223, - 223, 223, 223, 229, 223, 286, 151, 287, - 287, 76, 73, 285, 154, 285, 285, 285, - 285, 285, 285, 158, 285, 151, 287, 287, - 76, 73, 285, 154, 285, 285, 285, 285, - 285, 285, 158, 285, 288, 285, 285, 285, - 90, 289, 285, 73, 285, 154, 285, 285, - 285, 285, 285, 288, 285, 290, 291, 292, - 293, 76, 73, 285, 154, 285, 285, 106, - 285, 285, 285, 158, 285, 294, 291, 295, - 295, 76, 73, 285, 154, 285, 285, 285, - 285, 285, 285, 158, 285, 291, 295, 295, - 76, 73, 285, 154, 285, 285, 285, 285, - 285, 285, 158, 285, 296, 285, 285, 285, - 90, 297, 285, 73, 285, 154, 285, 285, - 285, 285, 285, 296, 285, 298, 299, 300, - 301, 76, 73, 285, 154, 285, 285, 104, - 285, 285, 285, 158, 285, 302, 299, 303, - 303, 76, 73, 285, 154, 285, 285, 285, - 285, 285, 285, 158, 285, 299, 303, 303, - 76, 73, 285, 154, 285, 285, 285, 285, - 285, 285, 158, 285, 304, 285, 285, 285, - 90, 305, 285, 73, 285, 154, 285, 285, - 285, 285, 285, 304, 285, 306, 307, 308, - 309, 76, 73, 285, 154, 285, 285, 102, - 285, 285, 285, 158, 285, 310, 307, 311, - 311, 76, 73, 285, 154, 285, 285, 285, - 285, 285, 285, 158, 285, 307, 311, 311, - 76, 73, 285, 154, 285, 285, 285, 285, - 285, 285, 158, 285, 312, 285, 285, 285, - 90, 313, 285, 73, 285, 154, 285, 285, - 285, 285, 285, 312, 285, 314, 315, 316, - 317, 76, 73, 285, 154, 285, 285, 100, - 285, 285, 285, 158, 285, 318, 315, 319, - 319, 76, 73, 285, 154, 285, 285, 285, - 285, 285, 285, 158, 285, 315, 319, 319, - 76, 73, 285, 154, 285, 285, 285, 285, - 285, 285, 158, 285, 90, 320, 285, 73, - 285, 154, 285, 321, 321, 285, 73, 285, - 154, 285, 322, 285, 285, 323, 285, 154, - 285, 154, 285, 324, 285, 325, 285, 322, - 285, 285, 285, 285, 154, 285, 90, 285, - 321, 321, 285, 73, 285, 154, 285, 321, - 320, 285, 73, 285, 154, 285, 326, 99, - 327, 328, 80, 73, 285, 154, 285, 99, - 327, 328, 80, 73, 285, 154, 285, 327, - 327, 80, 73, 285, 154, 285, 329, 96, - 330, 331, 83, 73, 285, 154, 285, 96, - 330, 331, 83, 73, 285, 154, 285, 330, - 330, 83, 73, 285, 154, 285, 332, 93, - 333, 334, 86, 73, 285, 154, 285, 93, - 333, 334, 86, 73, 285, 154, 285, 333, - 333, 86, 73, 285, 154, 285, 335, 90, - 321, 336, 285, 73, 285, 154, 285, 90, - 321, 336, 285, 73, 285, 154, 285, 315, - 319, 319, 76, 73, 285, 154, 285, 314, - 315, 319, 319, 76, 73, 285, 154, 285, - 285, 285, 285, 285, 285, 158, 285, 314, - 315, 316, 319, 76, 73, 285, 154, 285, - 285, 100, 285, 285, 285, 158, 285, 312, - 285, 337, 285, 321, 321, 285, 73, 285, - 154, 285, 285, 285, 285, 285, 312, 285, - 312, 285, 285, 285, 321, 321, 285, 73, - 285, 154, 285, 285, 285, 285, 285, 312, - 285, 312, 285, 285, 285, 321, 313, 285, - 73, 285, 154, 285, 285, 285, 285, 285, - 312, 285, 306, 307, 311, 311, 76, 73, - 285, 154, 285, 285, 285, 285, 285, 285, - 158, 285, 306, 307, 308, 311, 76, 73, - 285, 154, 285, 285, 102, 285, 285, 285, - 158, 285, 304, 285, 338, 285, 321, 321, - 285, 73, 285, 154, 285, 285, 285, 285, - 285, 304, 285, 304, 285, 285, 285, 321, - 321, 285, 73, 285, 154, 285, 285, 285, - 285, 285, 304, 285, 304, 285, 285, 285, - 321, 305, 285, 73, 285, 154, 285, 285, - 285, 285, 285, 304, 285, 298, 299, 303, - 303, 76, 73, 285, 154, 285, 285, 285, - 285, 285, 285, 158, 285, 298, 299, 300, - 303, 76, 73, 285, 154, 285, 285, 104, - 285, 285, 285, 158, 285, 296, 285, 339, - 285, 321, 321, 285, 73, 285, 154, 285, - 285, 285, 285, 285, 296, 285, 296, 285, - 285, 285, 321, 321, 285, 73, 285, 154, - 285, 285, 285, 285, 285, 296, 285, 296, - 285, 285, 285, 321, 297, 285, 73, 285, - 154, 285, 285, 285, 285, 285, 296, 285, - 290, 291, 295, 295, 76, 73, 285, 154, - 285, 285, 285, 285, 285, 285, 158, 285, - 290, 291, 292, 295, 76, 73, 285, 154, - 285, 285, 106, 285, 285, 285, 158, 285, - 288, 285, 340, 285, 321, 321, 285, 73, - 285, 154, 285, 285, 285, 285, 285, 288, - 285, 288, 285, 285, 285, 321, 321, 285, - 73, 285, 154, 285, 285, 285, 285, 285, - 288, 285, 288, 285, 285, 285, 321, 289, - 285, 73, 285, 154, 285, 285, 285, 285, - 285, 288, 285, 107, 75, 75, 76, 73, - 341, 341, 341, 341, 144, 341, 150, 151, - 287, 287, 76, 73, 285, 154, 285, 285, - 285, 285, 285, 285, 158, 285, 107, 75, - 75, 76, 73, 341, 343, 344, 345, 346, - 112, 109, 342, 347, 342, 342, 143, 342, - 342, 342, 348, 342, 349, 344, 346, 346, - 112, 109, 342, 347, 342, 342, 342, 342, - 342, 342, 348, 342, 344, 346, 346, 112, - 109, 342, 347, 342, 342, 342, 342, 342, - 342, 348, 342, 350, 342, 342, 342, 125, - 351, 342, 109, 342, 347, 342, 342, 342, - 342, 342, 350, 342, 352, 353, 354, 355, - 112, 109, 342, 347, 342, 342, 141, 342, - 342, 342, 348, 342, 356, 353, 357, 357, - 112, 109, 342, 347, 342, 342, 342, 342, - 342, 342, 348, 342, 353, 357, 357, 112, - 109, 342, 347, 342, 342, 342, 342, 342, - 342, 348, 342, 358, 342, 342, 342, 125, - 359, 342, 109, 342, 347, 342, 342, 342, - 342, 342, 358, 342, 360, 361, 362, 363, - 112, 109, 342, 347, 342, 342, 139, 342, - 342, 342, 348, 342, 364, 361, 365, 365, - 112, 109, 342, 347, 342, 342, 342, 342, - 342, 342, 348, 342, 361, 365, 365, 112, - 109, 342, 347, 342, 342, 342, 342, 342, - 342, 348, 342, 366, 342, 342, 342, 125, - 367, 342, 109, 342, 347, 342, 342, 342, - 342, 342, 366, 342, 368, 369, 370, 371, - 112, 109, 342, 347, 342, 342, 137, 342, - 342, 342, 348, 342, 372, 369, 373, 373, - 112, 109, 342, 347, 342, 342, 342, 342, - 342, 342, 348, 342, 369, 373, 373, 112, - 109, 342, 347, 342, 342, 342, 342, 342, - 342, 348, 342, 374, 342, 342, 342, 125, - 375, 342, 109, 342, 347, 342, 342, 342, - 342, 342, 374, 342, 376, 377, 378, 379, - 112, 109, 342, 347, 342, 342, 135, 342, - 342, 342, 348, 342, 380, 377, 381, 381, - 112, 109, 342, 347, 342, 342, 342, 342, - 342, 342, 348, 342, 377, 381, 381, 112, - 109, 342, 347, 342, 342, 342, 342, 342, - 342, 348, 342, 125, 382, 342, 109, 342, - 347, 342, 383, 383, 342, 109, 342, 347, - 342, 384, 342, 342, 385, 342, 347, 342, - 347, 342, 386, 342, 387, 342, 384, 342, - 342, 342, 342, 347, 342, 125, 342, 383, - 383, 342, 109, 342, 347, 342, 383, 382, - 342, 109, 342, 347, 342, 388, 134, 389, - 390, 115, 109, 342, 347, 342, 134, 389, - 390, 115, 109, 342, 347, 342, 389, 389, - 115, 109, 342, 347, 342, 391, 131, 392, - 393, 118, 109, 342, 347, 342, 131, 392, - 393, 118, 109, 342, 347, 342, 392, 392, - 118, 109, 342, 347, 342, 394, 128, 395, - 396, 121, 109, 342, 347, 342, 128, 395, - 396, 121, 109, 342, 347, 342, 395, 395, - 121, 109, 342, 347, 342, 397, 125, 383, - 398, 342, 109, 342, 347, 342, 125, 383, - 398, 342, 109, 342, 347, 342, 377, 381, - 381, 112, 109, 342, 347, 342, 376, 377, - 381, 381, 112, 109, 342, 347, 342, 342, - 342, 342, 342, 342, 348, 342, 376, 377, - 378, 381, 112, 109, 342, 347, 342, 342, - 135, 342, 342, 342, 348, 342, 374, 342, - 399, 342, 383, 383, 342, 109, 342, 347, - 342, 342, 342, 342, 342, 374, 342, 374, - 342, 342, 342, 383, 383, 342, 109, 342, - 347, 342, 342, 342, 342, 342, 374, 342, - 374, 342, 342, 342, 383, 375, 342, 109, - 342, 347, 342, 342, 342, 342, 342, 374, - 342, 368, 369, 373, 373, 112, 109, 342, - 347, 342, 342, 342, 342, 342, 342, 348, - 342, 368, 369, 370, 373, 112, 109, 342, - 347, 342, 342, 137, 342, 342, 342, 348, - 342, 366, 342, 400, 342, 383, 383, 342, - 109, 342, 347, 342, 342, 342, 342, 342, - 366, 342, 366, 342, 342, 342, 383, 383, - 342, 109, 342, 347, 342, 342, 342, 342, - 342, 366, 342, 366, 342, 342, 342, 383, - 367, 342, 109, 342, 347, 342, 342, 342, - 342, 342, 366, 342, 360, 361, 365, 365, - 112, 109, 342, 347, 342, 342, 342, 342, - 342, 342, 348, 342, 360, 361, 362, 365, - 112, 109, 342, 347, 342, 342, 139, 342, - 342, 342, 348, 342, 358, 342, 401, 342, - 383, 383, 342, 109, 342, 347, 342, 342, - 342, 342, 342, 358, 342, 358, 342, 342, - 342, 383, 383, 342, 109, 342, 347, 342, - 342, 342, 342, 342, 358, 342, 358, 342, - 342, 342, 383, 359, 342, 109, 342, 347, - 342, 342, 342, 342, 342, 358, 342, 352, - 353, 357, 357, 112, 109, 342, 347, 342, - 342, 342, 342, 342, 342, 348, 342, 352, - 353, 354, 357, 112, 109, 342, 347, 342, - 342, 141, 342, 342, 342, 348, 342, 350, - 342, 402, 342, 383, 383, 342, 109, 342, - 347, 342, 342, 342, 342, 342, 350, 342, - 350, 342, 342, 342, 383, 383, 342, 109, - 342, 347, 342, 342, 342, 342, 342, 350, - 342, 350, 342, 342, 342, 383, 351, 342, - 109, 342, 347, 342, 342, 342, 342, 342, - 350, 342, 343, 344, 346, 346, 112, 109, - 342, 347, 342, 342, 342, 342, 342, 342, - 348, 342, 148, 149, 150, 151, 403, 287, - 76, 73, 285, 154, 155, 155, 144, 285, - 285, 148, 158, 285, 162, 404, 164, 165, - 4, 1, 161, 166, 161, 161, 35, 161, - 161, 161, 167, 161, 170, 149, 150, 151, - 405, 406, 76, 407, 161, 408, 161, 155, - 144, 161, 161, 170, 158, 161, 107, 409, - 409, 76, 407, 161, 166, 161, 161, 144, - 161, 410, 161, 161, 411, 161, 408, 161, - 408, 161, 412, 161, 207, 161, 410, 161, - 161, 161, 161, 408, 161, 170, 161, 222, - 107, 409, 409, 76, 407, 161, 166, 161, - 161, 161, 161, 161, 170, 161, 414, 413, - 415, 415, 413, 146, 413, 416, 413, 415, - 415, 413, 146, 413, 416, 413, 417, 413, - 413, 418, 413, 416, 413, 416, 413, 419, - 413, 420, 413, 417, 413, 413, 413, 413, - 416, 413, 148, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 155, 341, 341, 341, - 341, 148, 341, 0 + 3, 3, 4, 0, 3, 3, 4, 1, + 0, 5, 3, 3, 4, 1, 0, 6, + 0, 7, 0, 8, 3, 3, 4, 1, + 0, 2, 3, 3, 4, 1, 0, 0, + 0, 0, 9, 0, 11, 12, 12, 13, + 14, 10, 14, 10, 12, 12, 13, 10, + 12, 12, 13, 14, 10, 15, 12, 12, + 13, 14, 10, 16, 10, 17, 10, 18, + 12, 12, 13, 14, 10, 11, 12, 12, + 13, 14, 10, 10, 10, 10, 19, 10, + 11, 12, 12, 13, 14, 10, 10, 10, + 10, 20, 10, 22, 23, 23, 24, 25, + 21, 21, 21, 21, 26, 21, 25, 21, + 23, 23, 24, 27, 23, 23, 24, 25, + 21, 28, 23, 23, 24, 25, 21, 29, + 21, 30, 21, 22, 23, 23, 24, 25, + 21, 31, 23, 23, 24, 25, 21, 33, + 34, 34, 35, 36, 32, 32, 32, 32, + 37, 32, 36, 32, 34, 34, 35, 32, + 34, 34, 35, 36, 32, 38, 34, 34, + 35, 36, 32, 39, 32, 40, 32, 33, + 34, 34, 35, 36, 32, 41, 34, 34, + 35, 36, 32, 23, 23, 24, 1, 0, + 43, 42, 45, 46, 47, 48, 49, 50, + 24, 25, 44, 51, 52, 52, 26, 44, + 53, 54, 55, 56, 57, 44, 59, 60, + 61, 62, 4, 1, 58, 63, 58, 58, + 9, 58, 58, 58, 64, 58, 65, 60, + 66, 66, 4, 1, 58, 63, 58, 58, + 58, 58, 58, 58, 64, 58, 60, 66, + 66, 4, 1, 58, 63, 58, 58, 58, + 58, 58, 58, 64, 58, 45, 58, 58, + 58, 67, 68, 58, 1, 58, 63, 58, + 58, 58, 58, 58, 45, 58, 69, 69, + 58, 1, 58, 63, 58, 63, 58, 58, + 70, 58, 63, 58, 63, 58, 63, 58, + 58, 58, 58, 63, 58, 45, 58, 71, + 58, 69, 69, 58, 1, 58, 63, 58, + 58, 58, 58, 58, 45, 58, 45, 58, + 58, 58, 69, 69, 58, 1, 58, 63, + 58, 58, 58, 58, 58, 45, 58, 45, + 58, 58, 58, 69, 68, 58, 1, 58, + 63, 58, 58, 58, 58, 58, 45, 58, + 72, 7, 73, 74, 4, 1, 58, 63, + 58, 7, 73, 74, 4, 1, 58, 63, + 58, 73, 73, 4, 1, 58, 63, 58, + 75, 76, 76, 4, 1, 58, 63, 58, + 67, 77, 58, 1, 58, 63, 58, 67, + 58, 69, 69, 58, 1, 58, 63, 58, + 69, 77, 58, 1, 58, 63, 58, 59, + 60, 66, 66, 4, 1, 58, 63, 58, + 58, 58, 58, 58, 58, 64, 58, 59, + 60, 61, 66, 4, 1, 58, 63, 58, + 58, 9, 58, 58, 58, 64, 58, 79, + 80, 81, 82, 13, 14, 78, 83, 78, + 78, 20, 78, 78, 78, 84, 78, 85, + 80, 86, 82, 13, 14, 78, 83, 78, + 78, 78, 78, 78, 78, 84, 78, 80, + 86, 82, 13, 14, 78, 83, 78, 78, + 78, 78, 78, 78, 84, 78, 87, 78, + 78, 78, 88, 89, 78, 14, 78, 83, + 78, 78, 78, 78, 78, 87, 78, 90, + 80, 91, 92, 13, 14, 78, 83, 78, + 78, 19, 78, 78, 78, 84, 78, 93, + 80, 86, 86, 13, 14, 78, 83, 78, + 78, 78, 78, 78, 78, 84, 78, 80, + 86, 86, 13, 14, 78, 83, 78, 78, + 78, 78, 78, 78, 84, 78, 87, 78, + 78, 78, 94, 89, 78, 14, 78, 83, + 78, 78, 78, 78, 78, 87, 78, 83, + 78, 78, 95, 78, 83, 78, 83, 78, + 83, 78, 78, 78, 78, 83, 78, 87, + 78, 96, 78, 94, 94, 78, 14, 78, + 83, 78, 78, 78, 78, 78, 87, 78, + 87, 78, 78, 78, 94, 94, 78, 14, + 78, 83, 78, 78, 78, 78, 78, 87, + 78, 97, 17, 98, 99, 13, 14, 78, + 83, 78, 17, 98, 99, 13, 14, 78, + 83, 78, 98, 98, 13, 14, 78, 83, + 78, 100, 101, 101, 13, 14, 78, 83, + 78, 88, 102, 78, 14, 78, 83, 78, + 94, 94, 78, 14, 78, 83, 78, 88, + 78, 94, 94, 78, 14, 78, 83, 78, + 94, 102, 78, 14, 78, 83, 78, 90, + 80, 86, 86, 13, 14, 78, 83, 78, + 78, 78, 78, 78, 78, 84, 78, 90, + 80, 91, 86, 13, 14, 78, 83, 78, + 78, 19, 78, 78, 78, 84, 78, 11, + 12, 12, 13, 14, 78, 79, 80, 86, + 82, 13, 14, 78, 83, 78, 78, 78, + 78, 78, 78, 84, 78, 104, 48, 105, + 105, 24, 25, 103, 51, 103, 103, 103, + 103, 103, 103, 55, 103, 48, 105, 105, + 24, 25, 103, 51, 103, 103, 103, 103, + 103, 103, 55, 103, 106, 103, 103, 103, + 107, 108, 103, 25, 103, 51, 103, 103, + 103, 103, 103, 106, 103, 47, 48, 109, + 110, 24, 25, 103, 51, 103, 103, 26, + 103, 103, 103, 55, 103, 106, 103, 103, + 103, 111, 108, 103, 25, 103, 51, 103, + 103, 103, 103, 103, 106, 103, 51, 103, + 103, 112, 103, 51, 103, 51, 103, 51, + 103, 103, 103, 103, 51, 103, 106, 103, + 113, 103, 111, 111, 103, 25, 103, 51, + 103, 103, 103, 103, 103, 106, 103, 106, + 103, 103, 103, 111, 111, 103, 25, 103, + 51, 103, 103, 103, 103, 103, 106, 103, + 114, 30, 115, 116, 24, 25, 103, 51, + 103, 30, 115, 116, 24, 25, 103, 51, + 103, 115, 115, 24, 25, 103, 51, 103, + 47, 48, 105, 105, 24, 25, 103, 51, + 103, 103, 103, 103, 103, 103, 55, 103, + 117, 118, 118, 24, 25, 103, 51, 103, + 107, 119, 103, 25, 103, 51, 103, 111, + 111, 103, 25, 103, 51, 103, 107, 103, + 111, 111, 103, 25, 103, 51, 103, 111, + 119, 103, 25, 103, 51, 103, 47, 48, + 109, 105, 24, 25, 103, 51, 103, 103, + 26, 103, 103, 103, 55, 103, 22, 23, + 23, 24, 25, 120, 120, 120, 120, 26, + 120, 22, 23, 23, 24, 25, 120, 122, + 123, 124, 125, 35, 36, 121, 126, 121, + 121, 37, 121, 121, 121, 127, 121, 128, + 123, 125, 125, 35, 36, 121, 126, 121, + 121, 121, 121, 121, 121, 127, 121, 123, + 125, 125, 35, 36, 121, 126, 121, 121, + 121, 121, 121, 121, 127, 121, 129, 121, + 121, 121, 130, 131, 121, 36, 121, 126, + 121, 121, 121, 121, 121, 129, 121, 122, + 123, 124, 52, 35, 36, 121, 126, 121, + 121, 37, 121, 121, 121, 127, 121, 129, + 121, 121, 121, 132, 131, 121, 36, 121, + 126, 121, 121, 121, 121, 121, 129, 121, + 126, 121, 121, 133, 121, 126, 121, 126, + 121, 126, 121, 121, 121, 121, 126, 121, + 129, 121, 134, 121, 132, 132, 121, 36, + 121, 126, 121, 121, 121, 121, 121, 129, + 121, 129, 121, 121, 121, 132, 132, 121, + 36, 121, 126, 121, 121, 121, 121, 121, + 129, 121, 135, 40, 136, 137, 35, 36, + 121, 126, 121, 40, 136, 137, 35, 36, + 121, 126, 121, 136, 136, 35, 36, 121, + 126, 121, 122, 123, 125, 125, 35, 36, + 121, 126, 121, 121, 121, 121, 121, 121, + 127, 121, 138, 139, 139, 35, 36, 121, + 126, 121, 130, 140, 121, 36, 121, 126, + 121, 132, 132, 121, 36, 121, 126, 121, + 130, 121, 132, 132, 121, 36, 121, 126, + 121, 132, 140, 121, 36, 121, 126, 121, + 45, 46, 47, 48, 109, 105, 24, 25, + 103, 51, 52, 52, 26, 103, 103, 45, + 55, 103, 59, 141, 61, 62, 4, 1, + 58, 63, 58, 58, 9, 58, 58, 58, + 64, 58, 45, 46, 47, 48, 142, 143, + 24, 144, 58, 145, 58, 52, 26, 58, + 58, 45, 55, 58, 22, 146, 146, 24, + 144, 58, 63, 58, 58, 26, 58, 145, + 58, 58, 147, 58, 145, 58, 145, 58, + 145, 58, 58, 58, 58, 145, 58, 45, + 58, 71, 22, 146, 146, 24, 144, 58, + 63, 58, 58, 58, 58, 58, 45, 58, + 149, 148, 150, 150, 148, 43, 148, 151, + 148, 150, 150, 148, 43, 148, 151, 148, + 151, 148, 148, 152, 148, 151, 148, 151, + 148, 151, 148, 148, 148, 148, 151, 148, + 45, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 52, 120, 120, 120, 120, 45, + 120, 0 }; -static const short _indic_syllable_machine_trans_targs[] = { - 138, 160, 166, 2, 167, 3, 5, 170, - 6, 8, 173, 9, 11, 176, 12, 14, - 15, 159, 17, 18, 175, 20, 21, 172, - 23, 24, 169, 179, 183, 184, 188, 189, - 193, 194, 198, 199, 138, 222, 228, 36, - 229, 37, 39, 232, 40, 42, 235, 43, - 45, 238, 46, 48, 49, 221, 51, 52, - 237, 54, 55, 234, 57, 58, 231, 241, - 245, 246, 250, 251, 255, 256, 260, 262, - 138, 283, 289, 70, 290, 138, 71, 73, - 293, 74, 76, 296, 77, 79, 299, 80, - 82, 83, 282, 85, 86, 298, 88, 89, - 295, 91, 92, 292, 302, 306, 307, 311, - 312, 316, 317, 321, 138, 346, 352, 103, - 353, 104, 106, 356, 107, 109, 359, 110, - 112, 362, 113, 115, 116, 345, 118, 119, - 361, 121, 122, 358, 124, 125, 355, 365, - 369, 370, 374, 375, 379, 380, 384, 385, - 323, 138, 398, 138, 139, 201, 263, 265, - 322, 324, 285, 325, 386, 387, 301, 396, - 403, 138, 140, 142, 33, 200, 162, 178, - 141, 32, 143, 196, 144, 146, 31, 195, - 145, 30, 147, 191, 148, 150, 29, 190, - 149, 28, 151, 186, 152, 154, 27, 185, - 153, 26, 155, 181, 156, 158, 25, 180, - 157, 1, 165, 0, 161, 164, 163, 138, - 168, 4, 22, 171, 7, 19, 174, 10, - 16, 177, 13, 182, 187, 192, 197, 138, - 202, 204, 67, 261, 224, 240, 203, 66, - 205, 258, 206, 208, 65, 257, 207, 64, - 209, 253, 210, 212, 63, 252, 211, 62, - 213, 248, 214, 216, 61, 247, 215, 60, - 217, 243, 218, 220, 59, 242, 219, 35, - 227, 34, 223, 226, 225, 138, 230, 38, - 56, 233, 41, 53, 236, 44, 50, 239, - 47, 244, 249, 254, 259, 138, 264, 100, - 266, 319, 267, 269, 99, 318, 268, 98, - 270, 314, 271, 273, 97, 313, 272, 96, - 274, 309, 275, 277, 95, 308, 276, 94, - 278, 304, 279, 281, 93, 303, 280, 69, - 288, 68, 284, 287, 286, 138, 291, 72, - 90, 294, 75, 87, 297, 78, 84, 300, - 81, 305, 310, 315, 320, 138, 138, 326, - 328, 134, 133, 348, 364, 327, 329, 382, - 330, 332, 132, 381, 331, 131, 333, 377, - 334, 336, 130, 376, 335, 129, 337, 372, - 338, 340, 128, 371, 339, 127, 341, 367, - 342, 344, 126, 366, 343, 102, 351, 101, - 347, 350, 349, 138, 354, 105, 123, 357, - 108, 120, 360, 111, 117, 363, 114, 368, - 373, 378, 383, 135, 388, 389, 395, 390, - 392, 136, 391, 394, 393, 138, 397, 137, - 400, 399, 402, 401, 138 +static const unsigned char _indic_syllable_machine_trans_targs[] = { + 39, 45, 50, 2, 51, 5, 6, 53, + 57, 58, 39, 67, 11, 73, 68, 14, + 15, 75, 80, 81, 84, 39, 89, 21, + 95, 90, 98, 39, 24, 25, 97, 103, + 39, 112, 30, 118, 113, 121, 33, 34, + 120, 126, 39, 137, 39, 40, 60, 85, + 87, 105, 106, 91, 107, 127, 128, 99, + 135, 140, 39, 41, 43, 8, 59, 46, + 54, 42, 1, 44, 48, 0, 47, 49, + 52, 3, 4, 55, 7, 56, 39, 61, + 63, 18, 83, 69, 76, 62, 9, 64, + 78, 71, 65, 17, 82, 66, 10, 70, + 72, 74, 12, 13, 77, 16, 79, 39, + 86, 26, 88, 101, 93, 19, 104, 20, + 92, 94, 96, 22, 23, 100, 27, 102, + 39, 39, 108, 110, 28, 35, 114, 122, + 109, 111, 124, 116, 29, 115, 117, 119, + 31, 32, 123, 36, 125, 129, 130, 134, + 131, 132, 37, 133, 39, 136, 38, 138, + 139 }; static const char _indic_syllable_machine_trans_actions[] = { 1, 0, 2, 0, 2, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 0, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 0, 2, 0, - 2, 0, 0, 2, 0, 0, 2, 0, - 0, 2, 0, 0, 0, 2, 0, 0, - 2, 0, 0, 2, 0, 0, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 4, 0, 2, 0, 2, 5, 0, 0, - 2, 0, 0, 2, 0, 0, 2, 0, - 0, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 0, 2, 6, 2, 6, 2, - 6, 2, 6, 2, 7, 0, 2, 0, - 2, 0, 0, 2, 0, 0, 2, 0, - 0, 2, 0, 0, 0, 2, 0, 0, - 2, 0, 0, 2, 0, 0, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 6, 8, 0, 11, 2, 2, 6, 0, - 12, 12, 0, 2, 6, 2, 6, 2, - 0, 13, 2, 0, 0, 2, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 2, 2, 0, 0, 2, - 2, 0, 2, 0, 0, 0, 0, 14, - 2, 0, 0, 2, 0, 0, 2, 0, - 0, 2, 0, 2, 2, 2, 2, 15, - 2, 0, 0, 2, 0, 2, 2, 0, - 2, 2, 2, 0, 0, 2, 2, 0, - 2, 2, 2, 0, 0, 2, 2, 0, - 2, 2, 2, 0, 0, 2, 2, 0, - 2, 2, 2, 0, 0, 2, 2, 0, - 2, 0, 0, 0, 0, 16, 2, 0, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 2, 2, 2, 2, 17, 6, 0, - 6, 2, 6, 0, 0, 6, 6, 0, - 6, 2, 6, 0, 0, 6, 6, 0, - 6, 2, 6, 0, 0, 6, 6, 0, - 6, 2, 6, 0, 0, 6, 6, 0, - 2, 0, 0, 0, 0, 18, 2, 0, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 2, 2, 2, 2, 19, 20, 2, - 0, 0, 0, 0, 2, 2, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 2, - 2, 0, 0, 2, 2, 0, 2, 0, - 0, 0, 0, 21, 2, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 2, - 2, 2, 2, 0, 0, 22, 22, 0, - 0, 0, 0, 0, 0, 23, 2, 0, - 0, 0, 0, 0, 24 + 2, 2, 3, 2, 0, 2, 0, 0, + 0, 2, 2, 2, 2, 4, 2, 0, + 5, 0, 5, 6, 0, 0, 5, 2, + 7, 2, 0, 2, 0, 2, 0, 0, + 2, 2, 8, 0, 11, 2, 2, 5, + 0, 12, 12, 0, 2, 5, 2, 5, + 2, 0, 13, 2, 0, 0, 2, 0, + 2, 2, 0, 2, 2, 0, 0, 2, + 2, 0, 0, 0, 0, 2, 14, 2, + 0, 0, 2, 0, 2, 2, 0, 2, + 2, 2, 2, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 0, 0, 2, 15, + 5, 0, 5, 2, 2, 0, 5, 0, + 0, 2, 5, 0, 0, 0, 0, 2, + 16, 17, 2, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 0, 0, 2, 2, + 0, 0, 0, 0, 2, 0, 18, 18, + 0, 0, 0, 0, 19, 2, 0, 0, + 0 }; static const char _indic_syllable_machine_to_state_actions[] = { @@ -823,6 +319,7 @@ static const char _indic_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -835,41 +332,7 @@ static const char _indic_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0 }; static const char _indic_syllable_machine_from_state_actions[] = { @@ -877,6 +340,7 @@ static const char _indic_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -889,102 +353,35 @@ static const char _indic_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0 }; static const short _indic_syllable_machine_eof_trans[] = { 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 73, 73, 78, 78, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 109, 109, 109, - 109, 109, 109, 109, 109, 109, 109, 109, - 109, 109, 109, 109, 109, 109, 109, 109, - 109, 109, 109, 109, 109, 109, 109, 109, - 109, 109, 109, 109, 109, 109, 109, 73, - 1, 146, 0, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, - 162, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 224, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 342, 286, 342, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 286, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 414, 414, 414, 414, - 414, 414, 414, 342 + 1, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 22, 22, 28, 22, 22, + 22, 22, 22, 22, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 1, 43, 0, + 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, + 104, 121, 121, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 104, + 59, 59, 59, 59, 59, 59, 59, 149, + 149, 149, 149, 149, 121 }; -static const int indic_syllable_machine_start = 138; -static const int indic_syllable_machine_first_final = 138; +static const int indic_syllable_machine_start = 39; +static const int indic_syllable_machine_first_final = 39; static const int indic_syllable_machine_error = -1; -static const int indic_syllable_machine_en_main = 138; +static const int indic_syllable_machine_en_main = 39; #line 36 "hb-ot-shape-complex-indic-machine.rl" @@ -1010,7 +407,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 1014 "hb-ot-shape-complex-indic-machine.hh" +#line 411 "hb-ot-shape-complex-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -1026,12 +423,12 @@ find_syllables (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 1030 "hb-ot-shape-complex-indic-machine.hh" +#line 427 "hb-ot-shape-complex-indic-machine.hh" { int _slen; int _trans; const unsigned char *_keys; - const short *_inds; + const unsigned char *_inds; if ( p == pe ) goto _test_eof; _resume: @@ -1040,7 +437,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 1044 "hb-ot-shape-complex-indic-machine.hh" +#line 441 "hb-ot-shape-complex-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1062,26 +459,6 @@ _eof_trans: #line 1 "NONE" {te = p+1;} break; - case 14: -#line 84 "hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ found_syllable (consonant_syllable); }} - break; - case 16: -#line 85 "hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ found_syllable (vowel_syllable); }} - break; - case 21: -#line 86 "hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ found_syllable (standalone_cluster); }} - break; - case 24: -#line 87 "hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ found_syllable (symbol_cluster); }} - break; - case 18: -#line 88 "hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ found_syllable (broken_cluster); }} - break; case 11: #line 89 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (non_indic_cluster); }} @@ -1090,23 +467,23 @@ _eof_trans: #line 84 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; - case 15: + case 14: #line 85 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (vowel_syllable); }} break; - case 20: + case 17: #line 86 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (standalone_cluster); }} break; - case 23: + case 19: #line 87 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; - case 17: + case 15: #line 88 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; - case 19: + case 16: #line 89 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (non_indic_cluster); }} break; @@ -1130,7 +507,7 @@ _eof_trans: #line 88 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; - case 5: + case 6: #line 1 "NONE" { switch( act ) { case 1: @@ -1145,13 +522,13 @@ _eof_trans: } } break; - case 22: + case 18: #line 1 "NONE" {te = p+1;} #line 84 "hb-ot-shape-complex-indic-machine.rl" {act = 1;} break; - case 6: + case 5: #line 1 "NONE" {te = p+1;} #line 88 "hb-ot-shape-complex-indic-machine.rl" @@ -1163,7 +540,7 @@ _eof_trans: #line 89 "hb-ot-shape-complex-indic-machine.rl" {act = 6;} break; -#line 1167 "hb-ot-shape-complex-indic-machine.hh" +#line 544 "hb-ot-shape-complex-indic-machine.hh" } _again: @@ -1172,7 +549,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1176 "hb-ot-shape-complex-indic-machine.hh" +#line 553 "hb-ot-shape-complex-indic-machine.hh" } if ( ++p != pe ) diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl index f7e022b98..a2a88af0d 100644 --- a/src/hb-ot-shape-complex-indic-machine.rl +++ b/src/hb-ot-shape-complex-indic-machine.rl @@ -64,14 +64,14 @@ reph = (Ra H | Repha); # possible reph cn = c.ZWJ?.n?; forced_rakar = ZWJ H ZWJ Ra; symbol = Symbol.N?; -matra_group = z{0,3}.M.N?.(H | forced_rakar)?; -syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}?; +matra_group = z*.M.N?.(H | forced_rakar)?; +syllable_tail = (z?.SM.SM?.ZWNJ?)? A*; halant_group = (z?.H.(ZWJ.N?)?); final_halant_group = halant_group | H.ZWNJ; medial_group = CM?; -halant_or_matra_group = (final_halant_group | matra_group{0,4}); +halant_or_matra_group = (final_halant_group | matra_group*); -complex_syllable_tail = (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail; +complex_syllable_tail = (halant_group.cn)* medial_group halant_or_matra_group syllable_tail; consonant_syllable = (Repha|CS)? cn complex_syllable_tail; vowel_syllable = reph? V.n? (ZWJ | complex_syllable_tail); diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 6d46fe33c..f8cb5741b 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -274,7 +274,11 @@ struct indic_shape_plan_t const indic_config_t *config; bool is_old_spec; +#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE bool uniscribe_bug_compatible; +#else + static constexpr bool uniscribe_bug_compatible = false; +#endif mutable hb_atomic_int_t virama_glyph; would_substitute_feature_t rphf; @@ -300,7 +304,9 @@ data_create_indic (const hb_ot_shape_plan_t *plan) } indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2'); +#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible; +#endif indic_plan->virama_glyph.set_relaxed (-1); /* Use zero-context would_substitute() matching for new-spec of the main @@ -645,7 +651,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Reorder characters */ for (unsigned int i = start; i < base; i++) - info[i].indic_position() = MIN (POS_PRE_C, (indic_position_t) info[i].indic_position()); + info[i].indic_position() = hb_min (POS_PRE_C, (indic_position_t) info[i].indic_position()); if (base < end) info[base].indic_position() = POS_BASE_C; @@ -801,7 +807,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, unsigned int j = start + info[i].syllable(); while (j != i) { - max = MAX (max, j); + max = hb_max (max, j); unsigned int next = start + info[j].syllable(); info[j].syllable() = 255; /* So we don't process j later again. */ j = next; @@ -918,11 +924,10 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, unsigned int start, unsigned int end) { - const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; - /* We treat placeholder/dotted-circle as if they are consonants, so we * should just chain. Only if not in compatibility mode that is... */ + const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; if (indic_plan->uniscribe_bug_compatible) { /* For dotted-circle, this is what Uniscribe does: @@ -1231,14 +1236,14 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* Note: this merge_clusters() is intentionally *after* the reordering. * Indic matra reordering is special and tricky... */ - buffer->merge_clusters (new_pos, MIN (end, base + 1)); + buffer->merge_clusters (new_pos, hb_min (end, base + 1)); new_pos--; } } else { for (unsigned int i = start; i < base; i++) if (info[i].indic_position () == POS_PRE_M) { - buffer->merge_clusters (i, MIN (end, base + 1)); + buffer->merge_clusters (i, hb_min (end, base + 1)); break; } } @@ -1371,13 +1376,15 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * TEST: U+0930,U+094D,U+0915,U+094B,U+094D */ if (!indic_plan->uniscribe_bug_compatible && - unlikely (is_halant (info[new_reph_pos]))) { + unlikely (is_halant (info[new_reph_pos]))) + { for (unsigned int i = base + 1; i < new_reph_pos; i++) if (info[i].indic_category() == OT_M) { /* Ok, got it. */ new_reph_pos--; } } + goto reph_move; } @@ -1590,11 +1597,10 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, * https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping */ + const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data; - hb_codepoint_t glyph; - - if (hb_options ().uniscribe_bug_compatible || + if (indic_plan->uniscribe_bug_compatible || (c->font->get_nominal_glyph (ab, &glyph) && indic_plan->pstf.would_substitute (&glyph, 1, c->font->face))) { diff --git a/src/hb-ot-shape-complex-indic.hh b/src/hb-ot-shape-complex-indic.hh index 13ab51679..dc8f8c7ce 100644 --- a/src/hb-ot-shape-complex-indic.hh +++ b/src/hb-ot-shape-complex-indic.hh @@ -278,7 +278,7 @@ matra_position_indic (hb_codepoint_t u, indic_position_t side) case POS_POST_C: return MATRA_POS_RIGHT (u); case POS_ABOVE_C: return MATRA_POS_TOP (u); case POS_BELOW_C: return MATRA_POS_BOTTOM (u); - }; + } return side; } diff --git a/src/hb-ot-shape-complex-khmer.hh b/src/hb-ot-shape-complex-khmer.hh index 622294588..21015c730 100644 --- a/src/hb-ot-shape-complex-khmer.hh +++ b/src/hb-ot-shape-complex-khmer.hh @@ -105,7 +105,7 @@ set_khmer_properties (hb_glyph_info_t &info) case POS_ABOVE_C: cat = OT_VAbv; break; case POS_POST_C: cat = OT_VPst; break; default: assert (0); - }; + } info.khmer_category() = cat; } diff --git a/src/hb-ot-shape-complex-myanmar-machine.hh b/src/hb-ot-shape-complex-myanmar-machine.hh index 0c19e4f68..b7b04cb6d 100644 --- a/src/hb-ot-shape-complex-myanmar-machine.hh +++ b/src/hb-ot-shape-complex-myanmar-machine.hh @@ -36,29 +36,31 @@ static const unsigned char _myanmar_syllable_machine_trans_keys[] = { 1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, - 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 32u, 8u, 8u, - 0 + 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, + 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, + 3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, + 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, + 3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0 }; static const char _myanmar_syllable_machine_key_spans[] = { 32, 28, 25, 4, 25, 23, 21, 21, 27, 27, 27, 27, 16, 27, 27, 27, - 27, 27, 28, 27, 27, 27, 27, 25, - 4, 25, 23, 21, 21, 27, 27, 27, - 27, 28, 27, 32, 27, 27, 27, 27, - 27, 28, 27, 27, 27, 27, 32, 1 + 27, 27, 28, 27, 27, 27, 27, 27, + 25, 4, 25, 23, 21, 21, 27, 27, + 27, 27, 16, 28, 27, 27, 27, 27, + 27, 28, 27, 27, 27, 27, 27, 28, + 27, 32, 32, 1 }; static const short _myanmar_syllable_machine_index_offsets[] = { 0, 33, 62, 88, 93, 119, 143, 165, 187, 215, 243, 271, 299, 316, 344, 372, 400, 428, 456, 485, 513, 541, 569, 597, - 623, 628, 654, 678, 700, 722, 750, 778, - 806, 834, 863, 891, 924, 952, 980, 1008, - 1036, 1064, 1093, 1121, 1149, 1177, 1205, 1238 + 625, 651, 656, 682, 706, 728, 750, 778, + 806, 834, 862, 879, 908, 936, 964, 992, + 1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217, + 1246, 1274, 1307, 1340 }; static const char _myanmar_syllable_machine_indicies[] = { @@ -124,120 +126,134 @@ static const char _myanmar_syllable_machine_indicies[] = { 21, 21, 21, 21, 21, 21, 32, 33, 34, 35, 36, 43, 21, 22, 21, 24, 24, 21, 25, 21, 26, 21, 21, 21, - 21, 21, 21, 21, 43, 21, 21, 28, + 21, 21, 21, 21, 21, 21, 21, 28, 21, 30, 21, 32, 33, 34, 35, 36, 21, 22, 21, 24, 24, 21, 25, 21, 26, 21, 21, 21, 21, 21, 21, 21, 43, 21, 21, 28, 21, 21, 21, 32, 33, 34, 35, 36, 21, 22, 21, 24, 24, 21, 25, 21, 26, 21, 21, 21, - 21, 21, 21, 21, 43, 21, 21, 28, + 21, 21, 21, 21, 44, 21, 21, 28, 29, 30, 21, 32, 33, 34, 35, 36, - 21, 22, 23, 24, 24, 21, 25, 21, + 21, 22, 21, 24, 24, 21, 25, 21, 26, 21, 21, 21, 21, 21, 21, 21, - 27, 21, 21, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 21, 3, 3, 44, - 5, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 45, 44, 44, 44, 44, 44, - 44, 14, 44, 44, 44, 18, 44, 3, - 3, 44, 5, 44, 3, 3, 44, 5, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, - 14, 44, 44, 44, 18, 44, 46, 44, - 3, 3, 44, 5, 44, 14, 44, 44, - 44, 44, 44, 44, 44, 47, 44, 44, - 44, 44, 44, 44, 14, 44, 3, 3, - 44, 5, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 47, 44, 44, 44, 44, - 44, 44, 14, 44, 3, 3, 44, 5, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, - 14, 44, 2, 44, 3, 3, 44, 5, - 44, 6, 44, 44, 44, 44, 44, 44, - 44, 48, 44, 44, 48, 44, 44, 44, - 14, 49, 44, 44, 18, 44, 2, 44, - 3, 3, 44, 5, 44, 6, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 14, 44, 44, 44, - 18, 44, 2, 44, 3, 3, 44, 5, - 44, 6, 44, 44, 44, 44, 44, 44, - 44, 48, 44, 44, 44, 44, 44, 44, - 14, 49, 44, 44, 18, 44, 2, 44, - 3, 3, 44, 5, 44, 6, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 14, 49, 44, 44, - 18, 44, 22, 23, 24, 24, 21, 25, - 21, 26, 21, 21, 21, 21, 21, 21, - 21, 50, 21, 21, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 21, 22, - 51, 24, 24, 21, 25, 21, 26, 21, - 21, 21, 21, 21, 21, 21, 27, 21, - 21, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 21, 1, 1, 2, 3, 3, - 3, 44, 5, 44, 6, 1, 44, 44, - 44, 44, 1, 44, 8, 44, 44, 10, + 21, 21, 21, 28, 29, 30, 21, 32, + 33, 34, 35, 36, 21, 22, 23, 24, + 24, 21, 25, 21, 26, 21, 21, 21, + 21, 21, 21, 21, 27, 21, 21, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 21, 46, 46, 45, 5, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 47, 45, + 45, 45, 45, 45, 45, 14, 45, 45, + 45, 18, 45, 46, 46, 45, 5, 45, + 46, 46, 45, 5, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 14, 45, 45, 45, + 18, 45, 48, 45, 46, 46, 45, 5, + 45, 14, 45, 45, 45, 45, 45, 45, + 45, 49, 45, 45, 45, 45, 45, 45, + 14, 45, 46, 46, 45, 5, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 49, + 45, 45, 45, 45, 45, 45, 14, 45, + 46, 46, 45, 5, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 14, 45, 2, 45, + 46, 46, 45, 5, 45, 6, 45, 45, + 45, 45, 45, 45, 45, 50, 45, 45, + 50, 45, 45, 45, 14, 51, 45, 45, + 18, 45, 2, 45, 46, 46, 45, 5, + 45, 6, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 14, 45, 45, 45, 18, 45, 2, 45, + 46, 46, 45, 5, 45, 6, 45, 45, + 45, 45, 45, 45, 45, 50, 45, 45, + 45, 45, 45, 45, 14, 51, 45, 45, + 18, 45, 2, 45, 46, 46, 45, 5, + 45, 6, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 14, 51, 45, 45, 18, 45, 52, 52, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 52, 45, 2, + 3, 46, 46, 45, 5, 45, 6, 45, + 45, 45, 45, 45, 45, 45, 8, 45, + 45, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 45, 2, 45, 46, 46, + 45, 5, 45, 6, 45, 45, 45, 45, + 45, 45, 45, 8, 45, 45, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 45, + 2, 45, 46, 46, 45, 5, 45, 6, + 45, 45, 45, 45, 45, 45, 45, 53, + 45, 45, 45, 45, 45, 45, 14, 15, + 16, 17, 18, 45, 2, 45, 46, 46, + 45, 5, 45, 6, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 14, 15, 16, 17, 18, 45, + 2, 45, 46, 46, 45, 5, 45, 6, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 14, 15, + 16, 45, 18, 45, 2, 45, 46, 46, + 45, 5, 45, 6, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 14, 45, 16, 45, 18, 45, + 2, 45, 46, 46, 45, 5, 45, 6, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 14, 15, + 16, 17, 18, 53, 45, 2, 45, 46, + 46, 45, 5, 45, 6, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 10, + 45, 12, 45, 14, 15, 16, 17, 18, + 45, 2, 45, 46, 46, 45, 5, 45, + 6, 45, 45, 45, 45, 45, 45, 45, + 53, 45, 45, 10, 45, 45, 45, 14, + 15, 16, 17, 18, 45, 2, 45, 46, + 46, 45, 5, 45, 6, 45, 45, 45, + 45, 45, 45, 45, 54, 45, 45, 10, + 11, 12, 45, 14, 15, 16, 17, 18, + 45, 2, 45, 46, 46, 45, 5, 45, + 6, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 10, 11, 12, 45, 14, + 15, 16, 17, 18, 45, 2, 3, 46, + 46, 45, 5, 45, 6, 45, 45, 45, + 45, 45, 45, 45, 8, 45, 45, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 44, 1, 44, 2, 44, 3, 3, - 44, 5, 44, 6, 44, 44, 44, 44, - 44, 44, 44, 8, 44, 44, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 44, - 2, 44, 3, 3, 44, 5, 44, 6, - 44, 44, 44, 44, 44, 44, 44, 52, - 44, 44, 44, 44, 44, 44, 14, 15, - 16, 17, 18, 44, 2, 44, 3, 3, - 44, 5, 44, 6, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 14, 15, 16, 17, 18, 44, - 2, 44, 3, 3, 44, 5, 44, 6, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 14, 15, - 16, 44, 18, 44, 2, 44, 3, 3, - 44, 5, 44, 6, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 14, 44, 16, 44, 18, 44, - 2, 44, 3, 3, 44, 5, 44, 6, - 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 14, 15, - 16, 17, 18, 52, 44, 2, 44, 3, - 3, 44, 5, 44, 6, 44, 44, 44, - 44, 44, 44, 44, 52, 44, 44, 10, - 44, 12, 44, 14, 15, 16, 17, 18, - 44, 2, 44, 3, 3, 44, 5, 44, - 6, 44, 44, 44, 44, 44, 44, 44, - 52, 44, 44, 10, 44, 44, 44, 14, - 15, 16, 17, 18, 44, 2, 44, 3, - 3, 44, 5, 44, 6, 44, 44, 44, - 44, 44, 44, 44, 52, 44, 44, 10, - 11, 12, 44, 14, 15, 16, 17, 18, - 44, 2, 3, 3, 3, 44, 5, 44, - 6, 44, 44, 44, 44, 44, 44, 44, - 8, 44, 44, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 44, 1, 1, 53, - 53, 53, 53, 53, 53, 53, 53, 1, - 53, 53, 53, 53, 1, 53, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 53, 53, 53, 53, 1, 53, 54, 53, - 0 + 45, 22, 23, 24, 24, 21, 25, 21, + 26, 21, 21, 21, 21, 21, 21, 21, + 55, 21, 21, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 21, 22, 56, + 24, 24, 21, 25, 21, 26, 21, 21, + 21, 21, 21, 21, 21, 27, 21, 21, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 21, 1, 1, 2, 3, 46, 46, + 45, 5, 45, 6, 1, 45, 45, 45, + 45, 1, 45, 8, 45, 45, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 45, 1, 45, 1, 1, 57, 57, 57, + 57, 57, 57, 57, 57, 1, 57, 57, + 57, 57, 1, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 1, 57, 58, 57, 0 }; static const char _myanmar_syllable_machine_trans_targs[] = { - 0, 1, 23, 0, 0, 24, 30, 33, - 36, 46, 37, 42, 43, 44, 26, 39, - 40, 41, 29, 45, 47, 0, 2, 12, + 0, 1, 24, 34, 0, 25, 31, 47, + 36, 50, 37, 42, 43, 44, 27, 39, + 40, 41, 30, 46, 51, 0, 2, 12, 0, 3, 9, 13, 14, 19, 20, 21, - 5, 16, 17, 18, 8, 22, 4, 6, - 7, 10, 11, 15, 0, 25, 27, 28, - 31, 32, 34, 35, 38, 0, 0 + 5, 16, 17, 18, 8, 23, 4, 6, + 7, 10, 11, 15, 22, 0, 0, 26, + 28, 29, 32, 33, 35, 38, 45, 48, + 49, 0, 0 }; static const char _myanmar_syllable_machine_trans_actions[] = { - 3, 0, 0, 4, 5, 0, 0, 0, + 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 6, 0, 0, - 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 10 + 0, 0, 0, 0, 0, 7, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 10 }; static const char _myanmar_syllable_machine_to_state_actions[] = { @@ -246,7 +262,8 @@ static const char _myanmar_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 }; static const char _myanmar_syllable_machine_from_state_actions[] = { @@ -255,16 +272,18 @@ static const char _myanmar_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 }; static const short _myanmar_syllable_machine_eof_trans[] = { 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 22, 22, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 54, 54 + 22, 22, 22, 22, 22, 22, 22, 22, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 22, + 22, 46, 58, 58 }; static const int myanmar_syllable_machine_start = 0; @@ -297,7 +316,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 301 "hb-ot-shape-complex-myanmar-machine.hh" +#line 320 "hb-ot-shape-complex-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -313,7 +332,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 317 "hb-ot-shape-complex-myanmar-machine.hh" +#line 336 "hb-ot-shape-complex-myanmar-machine.hh" { int _slen; int _trans; @@ -327,7 +346,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 331 "hb-ot-shape-complex-myanmar-machine.hh" +#line 350 "hb-ot-shape-complex-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -345,11 +364,11 @@ _eof_trans: goto _again; switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { - case 7: + case 6: #line 86 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (consonant_syllable); }} break; - case 5: + case 4: #line 87 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (non_myanmar_cluster); }} break; @@ -357,7 +376,7 @@ _eof_trans: #line 88 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (punctuation_cluster); }} break; - case 4: + case 8: #line 89 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; @@ -365,11 +384,11 @@ _eof_trans: #line 90 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (non_myanmar_cluster); }} break; - case 6: + case 5: #line 86 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; - case 8: + case 7: #line 89 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; @@ -377,7 +396,7 @@ _eof_trans: #line 90 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (non_myanmar_cluster); }} break; -#line 381 "hb-ot-shape-complex-myanmar-machine.hh" +#line 400 "hb-ot-shape-complex-myanmar-machine.hh" } _again: @@ -386,7 +405,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 390 "hb-ot-shape-complex-myanmar-machine.hh" +#line 409 "hb-ot-shape-complex-myanmar-machine.hh" } if ( ++p != pe ) diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl index 7845a86d4..665998938 100644 --- a/src/hb-ot-shape-complex-myanmar-machine.rl +++ b/src/hb-ot-shape-complex-myanmar-machine.rl @@ -69,15 +69,15 @@ k = (Ra As H); # Kinzi c = C|Ra; # is_consonant -medial_group = MY? MR? MW? MH? As?; +medial_group = MY? As? MR? ((MW MH? | MH) As?)?; main_vowel_group = (VPre.VS?)* VAbv* VBlw* A* (DB As?)?; post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?; pwo_tone_group = PT A* DB? As?; complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?; -syllable_tail = (H | complex_syllable_tail); +syllable_tail = (H (c|IV).VS?)* (H | complex_syllable_tail); -consonant_syllable = (k|CS)? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail; +consonant_syllable = (k|CS)? (c|IV|D|GB).VS? syllable_tail; punctuation_cluster = P V; broken_cluster = k? VS? syllable_tail; other = any; diff --git a/src/hb-ot-shape-complex-myanmar.hh b/src/hb-ot-shape-complex-myanmar.hh index 3e9537a64..9ec78ef89 100644 --- a/src/hb-ot-shape-complex-myanmar.hh +++ b/src/hb-ot-shape-complex-myanmar.hh @@ -146,7 +146,7 @@ set_myanmar_properties (hb_glyph_info_t &info) break; case 0xAA74u: case 0xAA75u: case 0xAA76u: - /* https://github.com/roozbehp/unicode-data/issues/3 */ + /* https://github.com/harfbuzz/harfbuzz/issues/218 */ cat = OT_C; break; } diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc index 130ea1c98..22d4aa3ab 100644 --- a/src/hb-ot-shape-complex-thai.cc +++ b/src/hb-ot-shape-complex-thai.cc @@ -218,7 +218,7 @@ do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, hb_font_t *font) { -#if defined(HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK) +#ifdef HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK return; #endif diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh index c9410e4e5..01fe3d788 100644 --- a/src/hb-ot-shape-complex-use-machine.hh +++ b/src/hb-ot-shape-complex-use-machine.hh @@ -36,326 +36,344 @@ #line 38 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u, - 1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, - 8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u, - 8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, - 8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u, - 41u, 42u, 42u, 42u, 1u, 5u, 0 + 12u, 48u, 1u, 15u, 1u, 1u, 12u, 48u, 1u, 1u, 0u, 48u, 21u, 21u, 11u, 48u, + 11u, 48u, 1u, 15u, 1u, 1u, 11u, 48u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, + 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, + 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, + 1u, 48u, 11u, 48u, 13u, 21u, 4u, 4u, 13u, 13u, 11u, 48u, 11u, 48u, 41u, 42u, + 42u, 42u, 11u, 48u, 11u, 48u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, + 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, + 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, 1u, 48u, 1u, 15u, + 4u, 4u, 13u, 21u, 13u, 13u, 12u, 48u, 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, + 21u, 42u, 1u, 5u, 0 }; static const char _use_syllable_machine_key_spans[] = { - 33, 15, 1, 33, 45, 1, 37, 37, - 15, 1, 37, 37, 32, 19, 19, 19, - 32, 32, 32, 37, 37, 37, 37, 37, - 37, 37, 37, 39, 37, 9, 1, 1, - 37, 37, 37, 32, 19, 19, 19, 32, - 32, 32, 37, 37, 37, 37, 37, 37, - 37, 37, 39, 15, 33, 44, 37, 22, - 2, 1, 5 + 37, 15, 1, 37, 1, 49, 1, 38, + 38, 15, 1, 38, 27, 26, 24, 23, + 22, 2, 1, 25, 25, 25, 1, 25, + 26, 26, 26, 27, 27, 27, 27, 38, + 48, 38, 9, 1, 1, 38, 38, 2, + 1, 38, 38, 27, 26, 24, 23, 22, + 2, 1, 25, 25, 25, 25, 26, 26, + 26, 27, 27, 27, 27, 38, 48, 15, + 1, 9, 1, 37, 48, 38, 2, 1, + 22, 5 }; static const short _use_syllable_machine_index_offsets[] = { - 0, 34, 50, 52, 86, 132, 134, 172, - 210, 226, 228, 266, 304, 337, 357, 377, - 397, 430, 463, 496, 534, 572, 610, 648, - 686, 724, 762, 800, 840, 878, 888, 890, - 892, 930, 968, 1006, 1039, 1059, 1079, 1099, - 1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388, - 1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675, - 1698, 1701, 1703 + 0, 38, 54, 56, 94, 96, 146, 148, + 187, 226, 242, 244, 283, 311, 338, 363, + 387, 410, 413, 415, 441, 467, 493, 495, + 521, 548, 575, 602, 630, 658, 686, 714, + 753, 802, 841, 851, 853, 855, 894, 933, + 936, 938, 977, 1016, 1044, 1071, 1096, 1120, + 1143, 1146, 1148, 1174, 1200, 1226, 1252, 1279, + 1306, 1333, 1361, 1389, 1417, 1445, 1484, 1533, + 1549, 1551, 1561, 1563, 1601, 1650, 1689, 1692, + 1694, 1717 }; static const char _use_syllable_machine_indicies[] = { - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 3, 2, 2, 2, 2, 2, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 4, 2, 3, 2, 6, 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, 5, 7, 8, - 9, 7, 10, 8, 9, 9, 11, 9, - 9, 3, 12, 9, 9, 13, 7, 7, - 14, 15, 9, 9, 16, 17, 18, 19, - 20, 21, 22, 16, 23, 24, 25, 26, - 27, 28, 9, 29, 30, 31, 9, 9, - 9, 32, 33, 9, 35, 34, 37, 36, - 36, 38, 1, 36, 36, 39, 36, 36, - 36, 36, 36, 40, 41, 42, 43, 44, - 45, 46, 47, 41, 48, 40, 49, 50, - 51, 52, 36, 53, 54, 55, 36, 36, - 36, 36, 56, 36, 37, 36, 36, 38, - 1, 36, 36, 39, 36, 36, 36, 36, - 36, 57, 41, 42, 43, 44, 45, 46, - 47, 41, 48, 49, 49, 50, 51, 52, - 36, 53, 54, 55, 36, 36, 36, 36, - 56, 36, 38, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, - 59, 58, 38, 58, 37, 36, 36, 38, - 1, 36, 36, 39, 36, 36, 36, 36, - 36, 36, 41, 42, 43, 44, 45, 46, - 47, 41, 48, 49, 49, 50, 51, 52, - 36, 53, 54, 55, 36, 36, 36, 36, - 56, 36, 37, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 41, 42, 43, 44, 45, 36, 36, 36, - 36, 36, 36, 50, 51, 52, 36, 53, - 54, 55, 36, 36, 36, 36, 42, 36, - 37, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 42, - 43, 44, 45, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 53, 54, 55, - 36, 37, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 43, 44, 45, 36, 37, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 44, 45, - 36, 37, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 45, 36, 37, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 43, 44, 45, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 53, 54, 55, 36, 37, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 43, 44, - 45, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 54, 55, 36, 37, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 43, - 44, 45, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 55, 36, - 37, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 42, - 43, 44, 45, 36, 36, 36, 36, 36, - 36, 50, 51, 52, 36, 53, 54, 55, - 36, 36, 36, 36, 42, 36, 37, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 42, 43, 44, - 45, 36, 36, 36, 36, 36, 36, 36, - 51, 52, 36, 53, 54, 55, 36, 36, - 36, 36, 42, 36, 37, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 42, 43, 44, 45, 36, - 36, 36, 36, 36, 36, 36, 36, 52, - 36, 53, 54, 55, 36, 36, 36, 36, - 42, 36, 37, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 41, 42, 43, 44, 45, 36, 47, 41, - 36, 36, 36, 50, 51, 52, 36, 53, - 54, 55, 36, 36, 36, 36, 42, 36, - 37, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 41, 42, - 43, 44, 45, 36, 60, 41, 36, 36, - 36, 50, 51, 52, 36, 53, 54, 55, - 36, 36, 36, 36, 42, 36, 37, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 41, 42, 43, 44, - 45, 36, 36, 41, 36, 36, 36, 50, - 51, 52, 36, 53, 54, 55, 36, 36, - 36, 36, 42, 36, 37, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 41, 42, 43, 44, 45, 46, - 47, 41, 36, 36, 36, 50, 51, 52, - 36, 53, 54, 55, 36, 36, 36, 36, - 42, 36, 37, 36, 36, 38, 1, 36, - 36, 39, 36, 36, 36, 36, 36, 36, - 41, 42, 43, 44, 45, 46, 47, 41, - 48, 36, 49, 50, 51, 52, 36, 53, - 54, 55, 36, 36, 36, 36, 56, 36, - 38, 58, 58, 58, 58, 58, 58, 37, - 58, 58, 58, 58, 58, 58, 59, 58, - 58, 58, 58, 58, 58, 58, 42, 43, - 44, 45, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 53, 54, 55, 58, - 37, 36, 36, 38, 1, 36, 36, 39, - 36, 36, 36, 36, 36, 36, 41, 42, - 43, 44, 45, 46, 47, 41, 48, 40, - 49, 50, 51, 52, 36, 53, 54, 55, - 36, 36, 36, 36, 56, 36, 62, 61, - 61, 61, 61, 61, 61, 61, 63, 61, - 10, 64, 62, 61, 11, 65, 65, 3, - 6, 65, 65, 66, 65, 65, 65, 65, - 65, 67, 16, 17, 18, 19, 20, 21, - 22, 16, 23, 25, 25, 26, 27, 28, - 65, 29, 30, 31, 65, 65, 65, 65, - 33, 65, 11, 65, 65, 3, 6, 65, - 65, 66, 65, 65, 65, 65, 65, 65, - 16, 17, 18, 19, 20, 21, 22, 16, - 23, 25, 25, 26, 27, 28, 65, 29, - 30, 31, 65, 65, 65, 65, 33, 65, - 11, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 16, 17, - 18, 19, 20, 65, 65, 65, 65, 65, - 65, 26, 27, 28, 65, 29, 30, 31, - 65, 65, 65, 65, 17, 65, 11, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 17, 18, 19, - 20, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 29, 30, 31, 65, 11, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 18, - 19, 20, 65, 11, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 19, 20, 65, 11, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 20, 65, 11, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 18, 19, 20, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 29, 30, 31, 65, 11, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 18, 19, 20, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 30, 31, 65, 11, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 18, 19, 20, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 31, 65, 11, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 17, 18, 19, - 20, 65, 65, 65, 65, 65, 65, 26, - 27, 28, 65, 29, 30, 31, 65, 65, - 65, 65, 17, 65, 11, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 17, 18, 19, 20, 65, - 65, 65, 65, 65, 65, 65, 27, 28, - 65, 29, 30, 31, 65, 65, 65, 65, - 17, 65, 11, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 17, 18, 19, 20, 65, 65, 65, - 65, 65, 65, 65, 65, 28, 65, 29, - 30, 31, 65, 65, 65, 65, 17, 65, - 11, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 16, 17, - 18, 19, 20, 65, 22, 16, 65, 65, - 65, 26, 27, 28, 65, 29, 30, 31, - 65, 65, 65, 65, 17, 65, 11, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 16, 17, 18, 19, - 20, 65, 68, 16, 65, 65, 65, 26, - 27, 28, 65, 29, 30, 31, 65, 65, - 65, 65, 17, 65, 11, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 16, 17, 18, 19, 20, 65, - 65, 16, 65, 65, 65, 26, 27, 28, - 65, 29, 30, 31, 65, 65, 65, 65, - 17, 65, 11, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 16, 17, 18, 19, 20, 21, 22, 16, - 65, 65, 65, 26, 27, 28, 65, 29, - 30, 31, 65, 65, 65, 65, 17, 65, - 11, 65, 65, 3, 6, 65, 65, 66, - 65, 65, 65, 65, 65, 65, 16, 17, - 18, 19, 20, 21, 22, 16, 23, 65, - 25, 26, 27, 28, 65, 29, 30, 31, - 65, 65, 65, 65, 33, 65, 3, 65, - 65, 65, 65, 65, 65, 11, 65, 65, - 65, 65, 65, 65, 4, 65, 65, 65, - 65, 65, 65, 65, 17, 18, 19, 20, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 29, 30, 31, 65, 3, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 4, 69, 6, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 6, 69, - 8, 65, 65, 65, 8, 65, 65, 11, - 65, 65, 3, 6, 65, 65, 66, 65, - 65, 65, 65, 65, 65, 16, 17, 18, - 19, 20, 21, 22, 16, 23, 24, 25, - 26, 27, 28, 65, 29, 30, 31, 65, - 65, 65, 65, 33, 65, 11, 65, 65, - 3, 6, 65, 65, 66, 65, 65, 65, - 65, 65, 65, 16, 17, 18, 19, 20, - 21, 22, 16, 23, 24, 25, 26, 27, - 28, 65, 29, 30, 31, 65, 65, 65, - 65, 33, 65, 71, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 71, - 72, 70, 71, 72, 70, 72, 70, 8, - 69, 69, 69, 8, 69, 0 + 2, 2, 2, 2, 4, 2, 3, 2, + 6, 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, 5, 5, 5, 6, 5, 7, 5, + 8, 9, 10, 8, 11, 12, 10, 10, + 10, 10, 10, 3, 13, 14, 10, 15, + 8, 8, 16, 17, 10, 10, 18, 19, + 20, 21, 22, 23, 24, 18, 25, 26, + 27, 28, 29, 30, 10, 31, 32, 33, + 10, 34, 35, 36, 37, 38, 39, 40, + 13, 10, 42, 41, 44, 1, 43, 43, + 45, 43, 43, 43, 43, 43, 46, 47, + 48, 49, 50, 51, 52, 53, 47, 54, + 46, 55, 56, 57, 58, 43, 59, 60, + 61, 43, 43, 43, 43, 62, 63, 64, + 65, 1, 43, 44, 1, 43, 43, 45, + 43, 43, 43, 43, 43, 66, 47, 48, + 49, 50, 51, 52, 53, 47, 54, 55, + 55, 56, 57, 58, 43, 59, 60, 61, + 43, 43, 43, 43, 62, 63, 64, 65, + 1, 43, 44, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, + 68, 67, 44, 67, 44, 1, 43, 43, + 45, 43, 43, 43, 43, 43, 43, 47, + 48, 49, 50, 51, 52, 53, 47, 54, + 55, 55, 56, 57, 58, 43, 59, 60, + 61, 43, 43, 43, 43, 62, 63, 64, + 65, 1, 43, 47, 48, 49, 50, 51, + 43, 43, 43, 43, 43, 43, 56, 57, + 58, 43, 59, 60, 61, 43, 43, 43, + 43, 48, 63, 64, 65, 69, 43, 48, + 49, 50, 51, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 59, 60, 61, + 43, 43, 43, 43, 43, 63, 64, 65, + 69, 43, 49, 50, 51, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 63, + 64, 65, 43, 50, 51, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 63, + 64, 65, 43, 51, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 63, 64, + 65, 43, 63, 64, 43, 64, 43, 49, + 50, 51, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 59, 60, 61, 43, + 43, 43, 43, 43, 63, 64, 65, 69, + 43, 49, 50, 51, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 60, + 61, 43, 43, 43, 43, 43, 63, 64, + 65, 69, 43, 49, 50, 51, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 61, 43, 43, 43, 43, 43, + 63, 64, 65, 69, 43, 71, 70, 49, + 50, 51, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 63, 64, 65, 69, + 43, 48, 49, 50, 51, 43, 43, 43, + 43, 43, 43, 56, 57, 58, 43, 59, + 60, 61, 43, 43, 43, 43, 48, 63, + 64, 65, 69, 43, 48, 49, 50, 51, + 43, 43, 43, 43, 43, 43, 43, 57, + 58, 43, 59, 60, 61, 43, 43, 43, + 43, 48, 63, 64, 65, 69, 43, 48, + 49, 50, 51, 43, 43, 43, 43, 43, + 43, 43, 43, 58, 43, 59, 60, 61, + 43, 43, 43, 43, 48, 63, 64, 65, + 69, 43, 47, 48, 49, 50, 51, 43, + 53, 47, 43, 43, 43, 56, 57, 58, + 43, 59, 60, 61, 43, 43, 43, 43, + 48, 63, 64, 65, 69, 43, 47, 48, + 49, 50, 51, 43, 72, 47, 43, 43, + 43, 56, 57, 58, 43, 59, 60, 61, + 43, 43, 43, 43, 48, 63, 64, 65, + 69, 43, 47, 48, 49, 50, 51, 43, + 43, 47, 43, 43, 43, 56, 57, 58, + 43, 59, 60, 61, 43, 43, 43, 43, + 48, 63, 64, 65, 69, 43, 47, 48, + 49, 50, 51, 52, 53, 47, 43, 43, + 43, 56, 57, 58, 43, 59, 60, 61, + 43, 43, 43, 43, 48, 63, 64, 65, + 69, 43, 44, 1, 43, 43, 45, 43, + 43, 43, 43, 43, 43, 47, 48, 49, + 50, 51, 52, 53, 47, 54, 43, 55, + 56, 57, 58, 43, 59, 60, 61, 43, + 43, 43, 43, 62, 63, 64, 65, 1, + 43, 44, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 68, + 67, 67, 67, 67, 67, 67, 67, 48, + 49, 50, 51, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 59, 60, 61, + 67, 67, 67, 67, 67, 63, 64, 65, + 69, 67, 44, 1, 43, 43, 45, 43, + 43, 43, 43, 43, 43, 47, 48, 49, + 50, 51, 52, 53, 47, 54, 46, 55, + 56, 57, 58, 43, 59, 60, 61, 43, + 43, 43, 43, 62, 63, 64, 65, 1, + 43, 74, 73, 73, 73, 73, 73, 73, + 73, 75, 73, 11, 76, 74, 73, 44, + 1, 43, 43, 45, 43, 43, 43, 43, + 43, 77, 47, 48, 49, 50, 51, 52, + 53, 47, 54, 46, 55, 56, 57, 58, + 43, 59, 60, 61, 43, 78, 79, 43, + 62, 63, 64, 65, 1, 43, 44, 1, + 43, 43, 45, 43, 43, 43, 43, 43, + 43, 47, 48, 49, 50, 51, 52, 53, + 47, 54, 46, 55, 56, 57, 58, 43, + 59, 60, 61, 43, 78, 79, 43, 62, + 63, 64, 65, 1, 43, 78, 79, 80, + 79, 80, 3, 6, 81, 81, 82, 81, + 81, 81, 81, 81, 83, 18, 19, 20, + 21, 22, 23, 24, 18, 25, 27, 27, + 28, 29, 30, 81, 31, 32, 33, 81, + 81, 81, 81, 37, 38, 39, 40, 6, + 81, 3, 6, 81, 81, 82, 81, 81, + 81, 81, 81, 81, 18, 19, 20, 21, + 22, 23, 24, 18, 25, 27, 27, 28, + 29, 30, 81, 31, 32, 33, 81, 81, + 81, 81, 37, 38, 39, 40, 6, 81, + 18, 19, 20, 21, 22, 81, 81, 81, + 81, 81, 81, 28, 29, 30, 81, 31, + 32, 33, 81, 81, 81, 81, 19, 38, + 39, 40, 84, 81, 19, 20, 21, 22, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 31, 32, 33, 81, 81, 81, + 81, 81, 38, 39, 40, 84, 81, 20, + 21, 22, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 38, 39, 40, 81, + 21, 22, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 38, 39, 40, 81, + 22, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 38, 39, 40, 81, 38, + 39, 81, 39, 81, 20, 21, 22, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 31, 32, 33, 81, 81, 81, 81, + 81, 38, 39, 40, 84, 81, 20, 21, + 22, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 32, 33, 81, 81, + 81, 81, 81, 38, 39, 40, 84, 81, + 20, 21, 22, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 33, + 81, 81, 81, 81, 81, 38, 39, 40, + 84, 81, 20, 21, 22, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 38, + 39, 40, 84, 81, 19, 20, 21, 22, + 81, 81, 81, 81, 81, 81, 28, 29, + 30, 81, 31, 32, 33, 81, 81, 81, + 81, 19, 38, 39, 40, 84, 81, 19, + 20, 21, 22, 81, 81, 81, 81, 81, + 81, 81, 29, 30, 81, 31, 32, 33, + 81, 81, 81, 81, 19, 38, 39, 40, + 84, 81, 19, 20, 21, 22, 81, 81, + 81, 81, 81, 81, 81, 81, 30, 81, + 31, 32, 33, 81, 81, 81, 81, 19, + 38, 39, 40, 84, 81, 18, 19, 20, + 21, 22, 81, 24, 18, 81, 81, 81, + 28, 29, 30, 81, 31, 32, 33, 81, + 81, 81, 81, 19, 38, 39, 40, 84, + 81, 18, 19, 20, 21, 22, 81, 85, + 18, 81, 81, 81, 28, 29, 30, 81, + 31, 32, 33, 81, 81, 81, 81, 19, + 38, 39, 40, 84, 81, 18, 19, 20, + 21, 22, 81, 81, 18, 81, 81, 81, + 28, 29, 30, 81, 31, 32, 33, 81, + 81, 81, 81, 19, 38, 39, 40, 84, + 81, 18, 19, 20, 21, 22, 23, 24, + 18, 81, 81, 81, 28, 29, 30, 81, + 31, 32, 33, 81, 81, 81, 81, 19, + 38, 39, 40, 84, 81, 3, 6, 81, + 81, 82, 81, 81, 81, 81, 81, 81, + 18, 19, 20, 21, 22, 23, 24, 18, + 25, 81, 27, 28, 29, 30, 81, 31, + 32, 33, 81, 81, 81, 81, 37, 38, + 39, 40, 6, 81, 3, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 4, 81, 81, 81, 81, 81, + 81, 81, 19, 20, 21, 22, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 31, 32, 33, 81, 81, 81, 81, 81, + 38, 39, 40, 84, 81, 3, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 4, 86, 87, 81, 14, + 81, 81, 81, 81, 81, 81, 81, 88, + 81, 14, 81, 6, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 6, 86, 86, 86, 6, + 86, 9, 81, 81, 81, 9, 81, 81, + 81, 81, 81, 3, 6, 14, 81, 82, + 81, 81, 81, 81, 81, 81, 18, 19, + 20, 21, 22, 23, 24, 18, 25, 26, + 27, 28, 29, 30, 81, 31, 32, 33, + 81, 34, 35, 81, 37, 38, 39, 40, + 6, 81, 3, 6, 81, 81, 82, 81, + 81, 81, 81, 81, 81, 18, 19, 20, + 21, 22, 23, 24, 18, 25, 26, 27, + 28, 29, 30, 81, 31, 32, 33, 81, + 81, 81, 81, 37, 38, 39, 40, 6, + 81, 34, 35, 81, 35, 81, 78, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 78, 79, 80, 9, 86, 86, + 86, 9, 86, 0 }; static const char _use_syllable_machine_trans_targs[] = { - 4, 8, 4, 32, 2, 4, 1, 5, - 6, 4, 29, 4, 51, 52, 53, 55, - 34, 35, 36, 37, 38, 45, 46, 48, - 54, 49, 42, 43, 44, 39, 40, 41, - 58, 50, 4, 4, 4, 4, 7, 0, - 28, 11, 12, 13, 14, 15, 22, 23, - 25, 26, 19, 20, 21, 16, 17, 18, - 27, 10, 4, 9, 24, 4, 30, 31, - 4, 4, 3, 33, 47, 4, 4, 56, - 57 + 5, 9, 5, 41, 2, 5, 1, 53, + 6, 7, 5, 34, 37, 63, 64, 67, + 68, 72, 43, 44, 45, 46, 47, 57, + 58, 60, 69, 61, 54, 55, 56, 50, + 51, 52, 70, 71, 73, 62, 48, 49, + 5, 5, 5, 5, 8, 0, 33, 12, + 13, 14, 15, 16, 27, 28, 30, 31, + 24, 25, 26, 19, 20, 21, 32, 17, + 18, 5, 11, 5, 10, 22, 5, 23, + 29, 5, 35, 36, 5, 38, 39, 40, + 5, 5, 3, 42, 4, 59, 5, 65, + 66 }; static const char _use_syllable_machine_trans_actions[] = { - 1, 0, 2, 3, 0, 4, 0, 0, - 7, 8, 0, 9, 10, 10, 3, 0, + 1, 0, 2, 3, 0, 4, 0, 5, + 0, 5, 8, 0, 5, 9, 0, 9, + 3, 0, 5, 5, 0, 0, 0, 5, + 5, 5, 3, 3, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 3, 0, 0, + 10, 11, 12, 13, 5, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 0, 0, 0, 0, - 0, 3, 11, 12, 13, 14, 7, 0, - 7, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 0, 0, 0, 0, 0, 0, - 0, 7, 15, 0, 0, 16, 0, 0, - 17, 18, 0, 3, 0, 19, 20, 0, + 0, 14, 5, 15, 0, 0, 16, 0, + 0, 17, 0, 0, 18, 5, 0, 0, + 19, 20, 0, 3, 0, 5, 21, 0, 0 }; static const char _use_syllable_machine_to_state_actions[] = { - 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 }; static const char _use_syllable_machine_from_state_actions[] = { - 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 }; static const short _use_syllable_machine_eof_trans[] = { - 1, 3, 3, 6, 0, 35, 37, 37, - 59, 59, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 59, 37, 62, 65, 62, - 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 70, 70, 66, 66, 71, - 71, 71, 70 + 1, 3, 3, 6, 6, 0, 42, 44, + 44, 68, 68, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 71, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 68, 44, 74, 77, 74, 44, 44, 81, + 81, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 87, + 82, 82, 82, 87, 82, 82, 82, 82, + 81, 87 }; -static const int use_syllable_machine_start = 4; -static const int use_syllable_machine_first_final = 4; +static const int use_syllable_machine_start = 5; +static const int use_syllable_machine_first_final = 5; static const int use_syllable_machine_error = -1; -static const int use_syllable_machine_en_main = 4; +static const int use_syllable_machine_en_main = 5; #line 38 "hb-ot-shape-complex-use-machine.rl" -#line 143 "hb-ot-shape-complex-use-machine.rl" +#line 162 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ @@ -374,7 +392,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 378 "hb-ot-shape-complex-use-machine.hh" +#line 396 "hb-ot-shape-complex-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -382,7 +400,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 163 "hb-ot-shape-complex-use-machine.rl" +#line 182 "hb-ot-shape-complex-use-machine.rl" p = 0; @@ -390,7 +408,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 394 "hb-ot-shape-complex-use-machine.hh" +#line 412 "hb-ot-shape-complex-use-machine.hh" { int _slen; int _trans; @@ -400,11 +418,11 @@ find_syllables (hb_buffer_t *buffer) goto _test_eof; _resume: switch ( _use_syllable_machine_from_state_actions[cs] ) { - case 6: + case 7: #line 1 "NONE" {ts = p;} break; -#line 408 "hb-ot-shape-complex-use-machine.hh" +#line 426 "hb-ot-shape-complex-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -422,73 +440,77 @@ _eof_trans: goto _again; switch ( _use_syllable_machine_trans_actions[_trans] ) { - case 7: + case 5: #line 1 "NONE" {te = p+1;} break; case 12: -#line 132 "hb-ot-shape-complex-use-machine.rl" +#line 150 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (independent_cluster); }} break; case 14: -#line 134 "hb-ot-shape-complex-use-machine.rl" +#line 153 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (standard_cluster); }} break; - case 9: -#line 138 "hb-ot-shape-complex-use-machine.rl" + case 10: +#line 157 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 8: -#line 139 "hb-ot-shape-complex-use-machine.rl" +#line 158 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (non_cluster); }} break; case 11: -#line 132 "hb-ot-shape-complex-use-machine.rl" +#line 150 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (independent_cluster); }} break; case 15: -#line 133 "hb-ot-shape-complex-use-machine.rl" +#line 151 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (virama_terminated_cluster); }} break; + case 16: +#line 152 "hb-ot-shape-complex-use-machine.rl" + {te = p;p--;{ found_syllable (sakot_terminated_cluster); }} + break; case 13: -#line 134 "hb-ot-shape-complex-use-machine.rl" +#line 153 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (standard_cluster); }} break; - case 17: -#line 135 "hb-ot-shape-complex-use-machine.rl" + case 18: +#line 154 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }} break; - case 16: -#line 136 "hb-ot-shape-complex-use-machine.rl" + case 17: +#line 155 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (numeral_cluster); }} break; - case 20: -#line 137 "hb-ot-shape-complex-use-machine.rl" + case 19: +#line 156 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; - case 18: -#line 138 "hb-ot-shape-complex-use-machine.rl" + case 20: +#line 157 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; - case 19: -#line 139 "hb-ot-shape-complex-use-machine.rl" + case 21: +#line 158 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (non_cluster); }} break; case 1: -#line 134 "hb-ot-shape-complex-use-machine.rl" +#line 153 "hb-ot-shape-complex-use-machine.rl" {{p = ((te))-1;}{ found_syllable (standard_cluster); }} break; case 4: -#line 138 "hb-ot-shape-complex-use-machine.rl" +#line 157 "hb-ot-shape-complex-use-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; case 2: #line 1 "NONE" { switch( act ) { - case 7: + case 8: {{p = ((te))-1;} found_syllable (broken_cluster); } break; - case 8: + case 9: {{p = ((te))-1;} found_syllable (non_cluster); } break; } @@ -497,25 +519,25 @@ _eof_trans: case 3: #line 1 "NONE" {te = p+1;} -#line 138 "hb-ot-shape-complex-use-machine.rl" - {act = 7;} - break; - case 10: -#line 1 "NONE" - {te = p+1;} -#line 139 "hb-ot-shape-complex-use-machine.rl" +#line 157 "hb-ot-shape-complex-use-machine.rl" {act = 8;} break; -#line 510 "hb-ot-shape-complex-use-machine.hh" + case 9: +#line 1 "NONE" + {te = p+1;} +#line 158 "hb-ot-shape-complex-use-machine.rl" + {act = 9;} + break; +#line 532 "hb-ot-shape-complex-use-machine.hh" } _again: switch ( _use_syllable_machine_to_state_actions[cs] ) { - case 5: + case 6: #line 1 "NONE" {ts = 0;} break; -#line 519 "hb-ot-shape-complex-use-machine.hh" +#line 541 "hb-ot-shape-complex-use-machine.hh" } if ( ++p != pe ) @@ -531,7 +553,7 @@ _again: } -#line 171 "hb-ot-shape-complex-use-machine.rl" +#line 190 "hb-ot-shape-complex-use-machine.rl" } diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl index 7702cd94d..aca7ea683 100644 --- a/src/hb-ot-shape-complex-use-machine.rl +++ b/src/hb-ot-shape-complex-use-machine.rl @@ -49,7 +49,7 @@ N = 4; # BASE_NUM GB = 5; # BASE_OTHER CGJ = 6; # CGJ #F = 7; # CONS_FINAL -FM = 8; # CONS_FINAL_MOD +#FM = 8; # CONS_FINAL_MOD #M = 9; # CONS_MED #CM = 10; # CONS_MOD SUB = 11; # CONS_SUB @@ -66,6 +66,9 @@ S = 19; # SYM VS = 21; # VARIATION_SELECTOR #V = 36; # VOWEL #VM = 40; # VOWEL_MOD +CS = 43; # CONS_WITH_STACKER +HVM = 44; # HALANT_OR_VOWEL_MODIFIER +Sk = 48; # SAKOT FAbv = 24; # CONS_FINAL_ABOVE FBlw = 25; # CONS_FINAL_BELOW @@ -86,11 +89,11 @@ VMPst = 39; # VOWEL_MOD_POST VMPre = 23; # VOWEL_MOD_PRE SMAbv = 41; # SYM_MOD_ABOVE SMBlw = 42; # SYM_MOD_BELOW -CS = 43; # CONS_WITH_STACKER +FMAbv = 45; # CONS_FINAL_MOD UIPC = Top +FMBlw = 46; # CONS_FINAL_MOD UIPC = Bottom +FMPst = 47; # CONS_FINAL_MOD UIPC = Not_Applicable -HVM = 44; # HALANT_OR_VOWEL_MODIFIER - -h = H | HVM; # https://github.com/harfbuzz/harfbuzz/issues/1102 +h = H | HVM | Sk; # Override: Adhoc ZWJ placement. https://github.com/harfbuzz/harfbuzz/issues/542#issuecomment-353169729 consonant_modifiers = CMAbv* CMBlw* ((ZWJ?.h.ZWJ? B | SUB) VS? CMAbv? CMBlw*)*; @@ -98,39 +101,55 @@ consonant_modifiers = CMAbv* CMBlw* ((ZWJ?.h.ZWJ? B | SUB) VS? CMAbv? CMBlw*)*; medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?; dependent_vowels = VPre* VAbv* VBlw* VPst*; vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*; -final_consonants = FAbv* FBlw* FPst* FM?; +final_consonants = FAbv* FBlw* FPst*; +final_modifiers = FMAbv* FMBlw* | FMPst?; -complex_syllable_tail = +complex_syllable_start = (R | CS)? (B | GB) VS?; +complex_syllable_middle = consonant_modifiers medial_consonants dependent_vowels vowel_modifiers - final_consonants + (Sk B)* ; +complex_syllable_tail = + complex_syllable_middle + final_consonants + final_modifiers +; +number_joiner_terminated_cluster_tail = (HN N VS?)* HN; +numeral_cluster_tail = (HN N VS?)+; +symbol_cluster_tail = SMAbv+ SMBlw* | SMBlw+; virama_terminated_cluster = - (R|CS)? (B | GB) VS? + complex_syllable_start consonant_modifiers ZWJ?.h.ZWJ? ; +sakot_terminated_cluster = + complex_syllable_start + complex_syllable_middle + Sk +; standard_cluster = - (R|CS)? (B | GB) VS? + complex_syllable_start complex_syllable_tail ; broken_cluster = R? - complex_syllable_tail + (complex_syllable_tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail | symbol_cluster_tail) ; -number_joiner_terminated_cluster = N VS? (HN N VS?)* HN; -numeral_cluster = N VS? (HN N VS?)*; -symbol_cluster = S VS? SMAbv* SMBlw*; +number_joiner_terminated_cluster = N VS? number_joiner_terminated_cluster_tail; +numeral_cluster = N VS? numeral_cluster_tail?; +symbol_cluster = (S | GB) VS? symbol_cluster_tail?; independent_cluster = (IND | O | Rsv | WJ) VS?; other = any; main := |* independent_cluster => { found_syllable (independent_cluster); }; virama_terminated_cluster => { found_syllable (virama_terminated_cluster); }; + sakot_terminated_cluster => { found_syllable (sakot_terminated_cluster); }; standard_cluster => { found_syllable (standard_cluster); }; number_joiner_terminated_cluster => { found_syllable (number_joiner_terminated_cluster); }; numeral_cluster => { found_syllable (numeral_cluster); }; diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc index ddf7053db..024746989 100644 --- a/src/hb-ot-shape-complex-use-table.cc +++ b/src/hb-ot-shape-complex-use-table.cc @@ -22,7 +22,6 @@ #define B USE_B /* BASE */ #define CGJ USE_CGJ /* CGJ */ #define CS USE_CS /* CONS_WITH_STACKER */ -#define FM USE_FM /* CONS_FINAL_MOD */ #define GB USE_GB /* BASE_OTHER */ #define H USE_H /* HALANT */ #define HN USE_HN /* HALANT_NUM */ @@ -34,6 +33,7 @@ #define Rsv USE_Rsv /* Reserved */ #define S USE_S /* SYM */ #define SUB USE_SUB /* CONS_SUB */ +#define Sk USE_Sk /* SAKOT */ #define VS USE_VS /* VARIATION_SELECTOR */ #define WJ USE_WJ /* Word_Joiner */ #define ZWJ USE_ZWJ /* ZWJ */ @@ -43,6 +43,9 @@ #define FBlw USE_FBlw #define FPst USE_FPst #define FAbv USE_FAbv +#define FMBlw USE_FMBlw +#define FMPst USE_FMPst +#define FMAbv USE_FMAbv #define MPre USE_MPre #define MBlw USE_MBlw #define MPst USE_MPst @@ -75,7 +78,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Latin-1 Supplement */ /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 00B0 */ O, O, FM, FM, O, O, O, O, O, O, O, O, O, O, O, O, + /* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O, /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 00D0 */ O, O, O, O, O, O, O, GB, @@ -108,7 +111,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPst, VPst, H, IND, O, /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FM, O, + /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, O, /* Gurmukhi */ @@ -204,7 +207,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Tibetan */ VBlw, VBlw, O, O, O, O, O, O, /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0F30 */ B, B, B, B, O, FM, O, FM, O, CMAbv, O, O, O, O, VPst, VPre, + /* 0F30 */ B, B, B, B, O, FMBlw, O, FMBlw, O, CMAbv, O, O, O, O, VPst, VPre, /* 0F40 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B, /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, @@ -213,7 +216,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, O, O, - /* 0FC0 */ O, O, O, O, O, O, FM, O, + /* 0FC0 */ O, O, O, O, O, O, FMBlw, O, #define use_offset_0x1000u 1536 @@ -260,8 +263,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPst, VPst, - /* 17C0 */ VPst, VPre, VPre, VPre, VPst, VPst, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM, - /* 17D0 */ FM, VAbv, H, FM, O, O, O, O, O, O, O, O, B, FM, O, O, + /* 17C0 */ VPst, VPre, VPre, VPre, VPst, VPst, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, FMAbv, + /* 17D0 */ FMAbv, VAbv, H, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, O, O, /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, #define use_offset_0x1900u 1936 @@ -272,7 +275,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, O, O, O, O, - /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VAbv, FM, O, O, O, O, + /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VAbv, FMBlw, O, O, O, O, /* 1940 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, /* Tai Le */ @@ -302,9 +305,9 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, FAbv, SUB, SUB, SUB, SUB, O, - /* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, - /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, FM, FM, O, O, FBlw, + /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, O, + /* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, + /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, FMAbv, FMAbv, O, O, FMBlw, /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -319,7 +322,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, /* 1B40 */ VPst, VPst, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O, /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB, - /* 1B60 */ O, O, GB, O, O, O, O, O, GB, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, + /* 1B60 */ O, S, GB, S, S, S, S, S, GB, S, S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O, /* Sundanese */ @@ -341,7 +344,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPst, VPst, VPst, VBlw, FAbv, FAbv, FAbv, - /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FM, CMBlw, O, O, O, O, O, O, O, O, + /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, O, O, O, O, O, O, O, O, /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B, #define use_offset_0x1cd0u 2688 @@ -357,7 +360,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Combining Diacritical Marks Supplement */ - O, O, O, FM, O, O, O, O, + O, O, O, FMAbv, O, O, O, O, #define use_offset_0x2008u 2744 @@ -372,8 +375,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Superscripts and Subscripts */ - /* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O, - /* 2080 */ O, O, FM, FM, FM, O, O, O, + /* 2070 */ O, O, O, O, FMPst, O, O, O, O, O, O, O, O, O, O, O, + /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O, #define use_offset_0x20f0u 2800 @@ -547,7 +550,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, - /* 111C0 */ H, B, R, R, O, O, O, O, GB, FBlw, CMBlw, VAbv, VBlw, O, O, O, + /* 111C0 */ H, B, R, R, O, O, O, O, GB, FMBlw, CMBlw, VAbv, VBlw, O, O, O, /* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* Sinhala Archaic Numbers */ @@ -600,7 +603,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O, - /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, FM, B, + /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, FMAbv, B, /* 11460 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, @@ -683,7 +686,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B, /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11A30 */ B, B, B, FM, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, + /* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, /* 11A40 */ O, O, O, O, O, GB, O, H, O, O, O, O, O, O, O, O, /* Soyombo */ @@ -809,7 +812,6 @@ hb_use_get_category (hb_codepoint_t u) #undef B #undef CGJ #undef CS -#undef FM #undef GB #undef H #undef HN @@ -821,6 +823,7 @@ hb_use_get_category (hb_codepoint_t u) #undef Rsv #undef S #undef SUB +#undef Sk #undef VS #undef WJ #undef ZWJ @@ -830,6 +833,9 @@ hb_use_get_category (hb_codepoint_t u) #undef FBlw #undef FPst #undef FAbv +#undef FMBlw +#undef FMPst +#undef FMAbv #undef MPre #undef MBlw #undef MPst diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index ec4d4aa7e..2cc5ea278 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -246,6 +246,7 @@ data_destroy_use (void *data) enum syllable_type_t { independent_cluster, virama_terminated_cluster, + sakot_terminated_cluster, standard_cluster, number_joiner_terminated_cluster, numeral_cluster, @@ -294,7 +295,7 @@ setup_rphf_mask (const hb_ot_shape_plan_t *plan, foreach_syllable (buffer, start, end) { - unsigned int limit = info[start].use_category() == USE_R ? 1 : MIN (3u, end - start); + unsigned int limit = info[start].use_category() == USE_R ? 1 : hb_min (3u, end - start); for (unsigned int i = start; i < start + limit; i++) info[i].mask |= mask; } @@ -337,6 +338,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, break; case virama_terminated_cluster: + case sakot_terminated_cluster: case standard_cluster: case number_joiner_terminated_cluster: case numeral_cluster: @@ -443,6 +445,7 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) /* Only a few syllable types need reordering. */ if (unlikely (!(FLAG_UNSAFE (syllable_type) & (FLAG (virama_terminated_cluster) | + FLAG (sakot_terminated_cluster) | FLAG (standard_cluster) | FLAG (broken_cluster) | 0)))) diff --git a/src/hb-ot-shape-complex-use.hh b/src/hb-ot-shape-complex-use.hh index ab56e1b8f..ce6645ecd 100644 --- a/src/hb-ot-shape-complex-use.hh +++ b/src/hb-ot-shape-complex-use.hh @@ -68,6 +68,12 @@ enum use_category_t { USE_VS = 21, /* VARIATION_SELECTOR */ // USE_V = 36, /* VOWEL */ // USE_VM = 40, /* VOWEL_MOD */ + USE_CS = 43, /* CONS_WITH_STACKER */ + + /* https://github.com/harfbuzz/harfbuzz/issues/1102 */ + USE_HVM = 44, /* HALANT_OR_VOWEL_MODIFIER */ + + USE_Sk = 48, /* SAKOT */ USE_FAbv = 24, /* CONS_FINAL_ABOVE */ USE_FBlw = 25, /* CONS_FINAL_BELOW */ @@ -88,10 +94,9 @@ enum use_category_t { USE_VMPre = 23, /* VOWEL_MOD_PRE */ USE_SMAbv = 41, /* SYM_MOD_ABOVE */ USE_SMBlw = 42, /* SYM_MOD_BELOW */ - USE_CS = 43, /* CONS_WITH_STACKER */ - - /* https://github.com/harfbuzz/harfbuzz/issues/1102 */ - USE_HVM = 44, /* HALANT_OR_VOWEL_MODIFIER */ + USE_FMAbv = 45, /* CONS_FINAL_MOD UIPC = Top */ + USE_FMBlw = 46, /* CONS_FINAL_MOD UIPC = Bottom */ + USE_FMPst = 47, /* CONS_FINAL_MOD UIPC = Not_Applicable */ }; HB_INTERNAL USE_TABLE_ELEMENT_TYPE diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc index 2eb313ae4..912ee35b4 100644 --- a/src/hb-ot-shape-complex-vowel-constraints.cc +++ b/src/hb-ot-shape-complex-vowel-constraints.cc @@ -34,7 +34,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, hb_font_t *font HB_UNUSED) { -#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS) +#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS return; #endif if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc index b10eec666..573af8ec6 100644 --- a/src/hb-ot-shape-fallback.cc +++ b/src/hb-ot-shape-fallback.cc @@ -166,7 +166,7 @@ _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { -#if defined(HB_NO_OT_SHAPE_FALLBACK) +#ifdef HB_NO_OT_SHAPE_FALLBACK return; #endif @@ -438,7 +438,7 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, bool adjust_offsets_when_zeroing) { -#if defined(HB_NO_OT_SHAPE_FALLBACK) +#ifdef HB_NO_OT_SHAPE_FALLBACK return; #endif @@ -456,6 +456,7 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan, } +#ifndef HB_DISABLE_DEPRECATED struct hb_ot_shape_fallback_kern_driver_t { hb_ot_shape_fallback_kern_driver_t (hb_font_t *font_, @@ -474,6 +475,7 @@ struct hb_ot_shape_fallback_kern_driver_t hb_font_t *font; hb_direction_t direction; }; +#endif /* Performs font-assisted kerning. */ void @@ -481,10 +483,11 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { -#if defined(HB_NO_OT_SHAPE_FALLBACK) +#ifdef HB_NO_OT_SHAPE_FALLBACK return; #endif +#ifndef HB_DISABLE_DEPRECATED if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? !font->has_glyph_h_kerning_func () : !font->has_glyph_v_kerning_func ()) @@ -501,6 +504,7 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, if (reverse) buffer->reverse (); +#endif } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 7fff3059e..c63c3adee 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -55,7 +55,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, const hb_feature_t *user_features, unsigned int num_user_features); -static bool +#ifndef HB_NO_SHAPE_AAT +static inline bool _hb_apply_morx (hb_face_t *face) { if (hb_options ().aat && @@ -69,14 +70,17 @@ _hb_apply_morx (hb_face_t *face) 0, nullptr, nullptr)) && hb_aat_layout_has_substitution (face); } +#endif hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face, const hb_segment_properties_t *props) : face (face), props (*props), map (face, props), - aat_map (face, props), - apply_morx (_hb_apply_morx (face)) + aat_map (face, props) +#ifndef HB_NO_SHAPE_AAT + , apply_morx (_hb_apply_morx (face)) +#endif { shaper = hb_ot_shape_complex_categorize (this); @@ -124,24 +128,36 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, * Decide who does substitutions. GSUB, morx, or fallback. */ +#ifndef HB_NO_SHAPE_AAT plan.apply_morx = apply_morx; +#endif /* * Decide who does positioning. GPOS, kerx, kern, or fallback. */ - if (hb_options ().aat && hb_aat_layout_has_positioning (face)) + if (0) + ; +#ifndef HB_NO_SHAPE_AAT + else if (hb_options ().aat && hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; +#endif else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face)) plan.apply_gpos = true; +#ifndef HB_NO_SHAPE_AAT else if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; +#endif if (!plan.apply_kerx && !has_gpos_kern) { /* Apparently Apple applies kerx if GPOS kern was not applied. */ - if (hb_aat_layout_has_positioning (face)) + if (0) + ; +#ifndef HB_NO_SHAPE_AAT + else if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; +#endif else if (hb_ot_layout_has_kerning (face)) plan.apply_kern = true; } @@ -158,8 +174,10 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing && script_fallback_mark_positioning; +#ifndef HB_NO_SHAPE_AAT /* Currently we always apply trak. */ plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); +#endif } bool @@ -962,12 +980,12 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR))) { - c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR, + c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR, (unsigned) HB_BUFFER_MAX_LEN_MIN); } if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR))) { - c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR, + c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR, (unsigned) HB_BUFFER_MAX_OPS_MIN); } diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 73a11e1af..b7c0f1065 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -80,10 +80,16 @@ struct hb_ot_shape_plan_t bool adjust_mark_positioning_when_zeroing : 1; bool apply_gpos : 1; - bool apply_kerx : 1; bool apply_kern : 1; +#ifndef HB_NO_SHAPE_AAT + bool apply_kerx : 1; bool apply_morx : 1; bool apply_trak : 1; +#else + static constexpr bool apply_kerx = false; + static constexpr bool apply_morx = false; + static constexpr bool apply_trak = false; +#endif void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const { @@ -113,7 +119,11 @@ struct hb_ot_shape_planner_t hb_segment_properties_t props; hb_ot_map_builder_t map; hb_aat_map_builder_t aat_map; +#ifndef HB_NO_SHAPE_AAT bool apply_morx : 1; +#else + static constexpr bool apply_morx = false; +#endif bool script_zero_marks : 1; bool script_fallback_mark_positioning : 1; const struct hb_ot_complex_shaper_t *shaper; diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh index 04a2ee99e..03604a0ad 100644 --- a/src/hb-ot-stat-table.hh +++ b/src/hb-ot-stat-table.hh @@ -65,6 +65,8 @@ struct AxisValueFormat1 return_trace (likely (c->check_struct (this))); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + protected: HBUINT16 format; /* Format identifier — set to 1. */ HBUINT16 axisIndex; /* Zero-base index into the axis record array @@ -88,6 +90,8 @@ struct AxisValueFormat2 return_trace (likely (c->check_struct (this))); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + protected: HBUINT16 format; /* Format identifier — set to 2. */ HBUINT16 axisIndex; /* Zero-base index into the axis record array @@ -115,6 +119,8 @@ struct AxisValueFormat3 return_trace (likely (c->check_struct (this))); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + protected: HBUINT16 format; /* Format identifier — set to 3. */ HBUINT16 axisIndex; /* Zero-base index into the axis record array @@ -157,6 +163,8 @@ struct AxisValueFormat4 return_trace (likely (c->check_struct (this))); } + hb_ot_name_id_t get_value_name_id () const { return valueNameID; } + protected: HBUINT16 format; /* Format identifier — set to 4. */ HBUINT16 axisCount; /* The total number of axes contributing to @@ -178,7 +186,7 @@ struct AxisValue bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (c->check_struct (this))) + if (unlikely (!c->check_struct (this))) return_trace (false); switch (u.format) @@ -191,6 +199,18 @@ struct AxisValue } } + hb_ot_name_id_t get_value_name_id () const + { + switch (u.format) + { + case 1: return u.format1.get_value_name_id (); + case 2: return u.format2.get_value_name_id (); + case 3: return u.format3.get_value_name_id (); + case 4: return u.format4.get_value_name_id (); + default: return HB_OT_NAME_ID_INVALID; + } + } + protected: union { @@ -212,6 +232,8 @@ struct StatAxisRecord return_trace (likely (c->check_struct (this))); } + hb_ot_name_id_t get_name_id () const { return nameID; } + protected: Tag tag; /* A tag identifying the axis of design variation. */ NameID nameID; /* The name ID for entries in the 'name' table that @@ -231,17 +253,59 @@ struct STAT { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - majorVersion == 1 && - minorVersion > 0 && + version.major == 1 && + version.minor > 0 && designAxesOffset.sanitize (c, this, designAxisCount) && offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets)))); } + bool has_data () const { return version.to_int (); } + + unsigned get_design_axis_count () const { return designAxisCount; } + + hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const + { + if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID; + const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index]; + return axis_record.get_name_id (); + } + + unsigned get_axis_value_count () const { return axisValueCount; } + + hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const + { + if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID; + const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]); + return axis_value.get_value_name_id (); + } + + void collect_name_ids (hb_set_t *nameids_to_retain) const + { + if (!has_data ()) return; + + + get_design_axes () + | hb_map (&StatAxisRecord::get_name_id) + | hb_sink (nameids_to_retain) + ; + + + get_axis_value_offsets () + | hb_map (hb_add (&(this + offsetToAxisValueOffsets))) + | hb_map (&AxisValue::get_value_name_id) + | hb_sink (nameids_to_retain) + ; + } + protected: - HBUINT16 majorVersion; /* Major version number of the style attributes - * table — set to 1. */ - HBUINT16 minorVersion; /* Minor version number of the style attributes - * table — set to 2. */ + hb_array_t const get_design_axes () const + { return (this+designAxesOffset).as_array (designAxisCount); } + + hb_array_t> const get_axis_value_offsets () const + { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); } + + + protected: + FixedVersion<>version; /* Version of the stat table + * initially set to 0x00010002u */ HBUINT16 designAxisSize; /* The size in bytes of each axis record. */ HBUINT16 designAxisCount;/* The number of design axis records. In a * font with an 'fvar' table, this value must be @@ -249,7 +313,7 @@ struct STAT * in the 'fvar' table. In all fonts, must * be greater than zero if axisValueCount * is greater than zero. */ - LNNOffsetTo > + LNNOffsetTo> designAxesOffset; /* Offset in bytes from the beginning of * the STAT table to the start of the design @@ -257,7 +321,7 @@ struct STAT * set to zero; if designAxisCount is greater * than zero, must be greater than zero. */ HBUINT16 axisValueCount; /* The number of axis value tables. */ - LNNOffsetTo > > + LNNOffsetTo>> offsetToAxisValueOffsets; /* Offset in bytes from the beginning of * the STAT table to the start of the design diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index c57c688d4..ad3635bda 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -113,6 +113,7 @@ hb_ot_new_tag_to_script (hb_tag_t tag) return HB_SCRIPT_UNKNOWN; } +#ifndef HB_DISABLE_DEPRECATED void hb_ot_tags_from_script (hb_script_t script, hb_tag_t *script_tag_1, @@ -124,6 +125,7 @@ hb_ot_tags_from_script (hb_script_t script, *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT; *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT; } +#endif /* * Complete list at: @@ -212,7 +214,7 @@ struct LangTag p = strchr (b, '-'); db = p ? (unsigned int) (p - b) : strlen (b); - return strncmp (a, b, MAX (da, db)); + return strncmp (a, b, hb_max (da, db)); } int cmp (const LangTag *that) const { return cmp (that->language); } @@ -230,6 +232,7 @@ struct LangTag /*{"??", {HB_TAG('Y','I','C',' ')}},*/ /* Yi Classic */ /*{"zh?", {HB_TAG('Z','H','P',' ')}},*/ /* Chinese Phonetic */ +#ifndef HB_DISABLE_DEPRECATED hb_tag_t hb_ot_tag_from_language (hb_language_t language) { @@ -238,6 +241,7 @@ hb_ot_tag_from_language (hb_language_t language) hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags); return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE; } +#endif static void hb_ot_tags_from_language (const char *lang_str, diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh index c4a192dc9..57a3a6d16 100644 --- a/src/hb-ot-var-avar-table.hh +++ b/src/hb-ot-var-avar-table.hh @@ -123,7 +123,7 @@ struct avar void map_coords (int *coords, unsigned int coords_length) const { - unsigned int count = MIN (coords_length, axisCount); + unsigned int count = hb_min (coords_length, axisCount); const SegmentMaps *map = &firstAxisSegmentMaps; for (unsigned int i = 0; i < count; i++) diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh index 78cb3c867..7df81428f 100644 --- a/src/hb-ot-var-fvar-table.hh +++ b/src/hb-ot-var-fvar-table.hh @@ -114,17 +114,19 @@ struct fvar unsigned int get_axis_count () const { return axisCount; } +#ifndef HB_DISABLE_DEPRECATED void get_axis_deprecated (unsigned int axis_index, hb_ot_var_axis_t *info) const { const AxisRecord &axis = get_axes ()[axis_index]; info->tag = axis.axisTag; info->name_id = axis.axisNameID; - info->default_value = axis.defaultValue / 65536.; + info->default_value = axis.defaultValue / 65536.f; /* Ensure order, to simplify client math. */ - info->min_value = MIN (info->default_value, axis.minValue / 65536.); - info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + info->min_value = hb_min (info->default_value, axis.minValue / 65536.f); + info->max_value = hb_max (info->default_value, axis.maxValue / 65536.f); } +#endif void get_axis_info (unsigned int axis_index, hb_ot_var_axis_info_t *info) const @@ -134,13 +136,14 @@ struct fvar info->tag = axis.axisTag; info->name_id = axis.axisNameID; info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags; - info->default_value = axis.defaultValue / 65536.; + info->default_value = axis.defaultValue / 65536.f; /* Ensure order, to simplify client math. */ - info->min_value = MIN (info->default_value, axis.minValue / 65536.); - info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + info->min_value = hb_min (info->default_value, axis.minValue / 65536.f); + info->max_value = hb_max (info->default_value, axis.maxValue / 65536.f); info->reserved = 0; } +#ifndef HB_DISABLE_DEPRECATED unsigned int get_axes_deprecated (unsigned int start_offset, unsigned int *axes_count /* IN/OUT */, hb_ot_var_axis_t *axes_array /* OUT */) const @@ -149,12 +152,12 @@ struct fvar { /* TODO Rewrite as hb_array_t<>::sub-array() */ unsigned int count = axisCount; - start_offset = MIN (start_offset, count); + start_offset = hb_min (start_offset, count); count -= start_offset; axes_array += start_offset; - count = MIN (count, *axes_count); + count = hb_min (count, *axes_count); *axes_count = count; for (unsigned int i = 0; i < count; i++) @@ -162,6 +165,7 @@ struct fvar } return axisCount; } +#endif unsigned int get_axis_infos (unsigned int start_offset, unsigned int *axes_count /* IN/OUT */, @@ -171,12 +175,12 @@ struct fvar { /* TODO Rewrite as hb_array_t<>::sub-array() */ unsigned int count = axisCount; - start_offset = MIN (start_offset, count); + start_offset = hb_min (start_offset, count); count -= start_offset; axes_array += start_offset; - count = MIN (count, *axes_count); + count = hb_min (count, *axes_count); *axes_count = count; for (unsigned int i = 0; i < count; i++) @@ -185,6 +189,7 @@ struct fvar return axisCount; } +#ifndef HB_DISABLE_DEPRECATED bool find_axis_deprecated (hb_tag_t tag, unsigned int *axis_index, hb_ot_var_axis_t *info) const @@ -203,6 +208,7 @@ struct fvar *axis_index = HB_OT_VAR_NO_AXIS_INDEX; return false; } +#endif bool find_axis_info (hb_tag_t tag, hb_ot_var_axis_info_t *info) const @@ -223,7 +229,7 @@ struct fvar hb_ot_var_axis_info_t axis; get_axis_info (axis_index, &axis); - v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */ + v = hb_max (hb_min (v, axis.max_value), axis.min_value); /* Clamp. */ if (v == axis.default_value) return 0; @@ -253,8 +259,8 @@ struct fvar } unsigned int get_instance_coords (unsigned int instance_index, - unsigned int *coords_length, /* IN/OUT */ - float *coords /* OUT */) const + unsigned int *coords_length, /* IN/OUT */ + float *coords /* OUT */) const { const InstanceRecord *instance = get_instance (instance_index); if (unlikely (!instance)) @@ -274,6 +280,27 @@ struct fvar return axisCount; } + void collect_name_ids (hb_set_t *nameids) const + { + if (!has_data ()) return; + + + get_axes () + | hb_map (&AxisRecord::axisNameID) + | hb_sink (nameids) + ; + + + hb_range ((unsigned) instanceCount) + | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); }) + | hb_sink (nameids) + ; + + + hb_range ((unsigned) instanceCount) + | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); }) + | hb_sink (nameids) + ; + } + + protected: hb_array_t get_axes () const { return hb_array (&(this+firstAxis), axisCount); } diff --git a/src/hb-ot-var-mvar-table.hh b/src/hb-ot-var-mvar-table.hh index 0dd63e510..5a9d2afb7 100644 --- a/src/hb-ot-var-mvar-table.hh +++ b/src/hb-ot-var-mvar-table.hh @@ -77,9 +77,9 @@ struct MVAR const int *coords, unsigned int coord_count) const { const VariationValueRecord *record; - record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ, - valueRecordCount, valueRecordSize, - tag_compare); + record = (VariationValueRecord *) hb_bsearch (&tag, valuesZ.arrayZ, + valueRecordCount, valueRecordSize, + tag_compare); if (!record) return 0.; diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index e327fb762..25a246a21 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -75,6 +75,7 @@ hb_ot_var_get_axis_count (hb_face_t *face) return face->table.fvar->get_axis_count (); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_ot_var_get_axes: * @@ -104,6 +105,7 @@ hb_ot_var_find_axis (hb_face_t *face, { return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info); } +#endif /** * hb_ot_var_get_axis_infos: diff --git a/src/hb-sanitize.hh b/src/hb-sanitize.hh index e58202cf7..5f5b4bdc9 100644 --- a/src/hb-sanitize.hh +++ b/src/hb-sanitize.hh @@ -130,12 +130,23 @@ struct hb_sanitize_context_t : template bool may_dispatch (const T *obj HB_UNUSED, const F *format) { return format->sanitize (this); } - template - return_t dispatch (const T &obj) { return obj.sanitize (this); } static return_t default_return_value () { return true; } static return_t no_dispatch_return_value () { return false; } bool stop_sublookup_iteration (const return_t r) const { return !r; } + private: + template auto + _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN + ( obj.sanitize (this, hb_forward (ds)...) ) + template auto + _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN + ( obj.dispatch (this, hb_forward (ds)...) ) + public: + template auto + dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN + ( _dispatch (obj, hb_prioritize, hb_forward (ds)...) ) + + void init (hb_blob_t *b) { this->blob = hb_blob_reference (b); @@ -164,7 +175,7 @@ struct hb_sanitize_context_t : else { this->start = obj_start; - this->end = obj_start + MIN (this->end - obj_start, obj->get_size ()); + this->end = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ()); } } @@ -178,7 +189,7 @@ struct hb_sanitize_context_t : void start_processing () { reset_object (); - this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR, + this->max_ops = hb_max ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR, (unsigned) HB_SANITIZE_MAX_OPS_MIN); this->edit_count = 0; this->debug_depth = 0; @@ -200,6 +211,8 @@ struct hb_sanitize_context_t : this->start = this->end = nullptr; } + unsigned get_edit_count () { return edit_count; } + bool check_range (const void *base, unsigned int len) const { diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 7566881a8..76f701608 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -71,7 +71,7 @@ struct hb_serialize_context_t { bool is_wide: 1; unsigned position : 31; - int bias; + unsigned bias; objidx_t objidx; }; @@ -132,9 +132,9 @@ struct hb_serialize_context_t { return check_equal (v1 = v2, v2); } template bool propagate_error (T &&obj) - { return check_success (!hb_deref_pointer (obj).in_error ()); } + { return check_success (!hb_deref (obj).in_error ()); } - template bool propagate_error (T1 &&o1, Ts &&...os) + template bool propagate_error (T1 &&o1, Ts&&... os) { return propagate_error (hb_forward (o1)) && propagate_error (hb_forward (os)...); } @@ -165,7 +165,7 @@ struct hb_serialize_context_t /* Only "pack" if there exist other objects... Otherwise, don't bother. * Saves a move. */ - if (packed.length == 1) + if (packed.length <= 1) return; pop_pack (); @@ -285,27 +285,28 @@ struct hb_serialize_context_t void resolve_links () { + if (unlikely (in_error ())) return; + assert (!current); + assert (packed.length > 1); - for (auto obj_it = ++hb_iter (packed); obj_it; ++obj_it) + for (const object_t* parent : ++hb_iter (packed)) { - const object_t &parent = **obj_it; - - for (auto link_it = parent.links.iter (); link_it; ++link_it) + for (const object_t::link_t &link : parent->links) { - const object_t::link_t &link = *link_it; - const object_t &child = *packed[link.objidx]; - unsigned offset = (child.head - parent.head) - link.bias; + const object_t* child = packed[link.objidx]; + assert (link.bias <= (size_t) (parent->tail - parent->head)); + unsigned offset = (child->head - parent->head) - link.bias; if (link.is_wide) { - auto &off = * ((BEInt *) (parent.head + link.position)); + auto &off = * ((BEInt *) (parent->head + link.position)); assert (0 == off); check_assign (off, offset); } else { - auto &off = * ((BEInt *) (parent.head + link.position)); + auto &off = * ((BEInt *) (parent->head + link.position)); assert (0 == off); check_assign (off, offset); } @@ -322,12 +323,12 @@ struct hb_serialize_context_t allocate_size (alignment - l); } + template + Type *start_embed (const Type *obj HB_UNUSED = nullptr) const + { return reinterpret_cast (this->head); } template - Type *start_embed (const Type *_ HB_UNUSED = nullptr) const - { - Type *ret = reinterpret_cast (this->head); - return ret; - } + Type *start_embed (const Type &obj) const + { return start_embed (hb_addressof (obj)); } /* Following two functions exist to allow setting breakpoint on. */ void err_ran_out_of_room () { this->ran_out_of_room = true; } @@ -357,50 +358,67 @@ struct hb_serialize_context_t } template - Type *embed (const Type &obj) + Type *embed (const Type *obj) { - unsigned int size = obj.get_size (); + unsigned int size = obj->get_size (); Type *ret = this->allocate_size (size); if (unlikely (!ret)) return nullptr; - memcpy (ret, &obj, size); + memcpy (ret, obj, size); return ret; } + template + Type *embed (const Type &obj) + { return embed (hb_addressof (obj)); } + + template auto + _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN + (Type *, src.copy (this, hb_forward (ds)...)) template auto - _copy (const Type &obj, hb_priority<1>) const HB_RETURN (Type *, obj.copy (this)) - - template auto - _copy (const Type &obj, hb_priority<0>) const -> decltype (&(obj = obj)) + _copy (const Type &src, hb_priority<0>) -> decltype (&(src = src)) { Type *ret = this->allocate_size (sizeof (Type)); if (unlikely (!ret)) return nullptr; - *ret = obj; + *ret = src; return ret; } /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data * instead of memcpy(). */ - template - Type *copy (const Type &obj) { return _copy (obj, hb_prioritize); } + template + Type *copy (const Type &src, Ts&&... ds) + { return _copy (src, hb_prioritize, hb_forward (ds)...); } + template + Type *copy (const Type *src, Ts&&... ds) + { return copy (*src, hb_forward (ds)...); } template - hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; } + hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; } + template + Type *extend_size (Type *obj, unsigned int size) + { + assert (this->start <= (char *) obj); + assert ((char *) obj <= this->head); + assert ((char *) obj + size >= this->head); + if (unlikely (!this->allocate_size (((char *) obj) + size - this->head))) return nullptr; + return reinterpret_cast (obj); + } template Type *extend_size (Type &obj, unsigned int size) - { - assert (this->start <= (char *) &obj); - assert ((char *) &obj <= this->head); - assert ((char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return nullptr; - return reinterpret_cast (&obj); - } + { return extend_size (hb_addressof (obj), size); } template - Type *extend_min (Type &obj) { return extend_size (obj, obj.min_size); } - + Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); } template - Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); } + Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); } + + template + Type *extend (Type *obj, Ts&&... ds) + { return extend_size (obj, obj->get_size (hb_forward (ds)...)); } + template + Type *extend (Type &obj, Ts&&... ds) + { return extend (hb_addressof (obj), hb_forward (ds)...); } /* Output routines. */ hb_bytes_t copy_bytes () const diff --git a/src/hb-set.cc b/src/hb-set.cc index 068236264..fa9868809 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -389,6 +389,7 @@ hb_set_symmetric_difference (hb_set_t *set, set->symmetric_difference (other); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_set_invert: * @set: a set. @@ -403,6 +404,7 @@ void hb_set_invert (hb_set_t *set HB_UNUSED) { } +#endif /** * hb_set_get_population: diff --git a/src/hb-set.hh b/src/hb-set.hh index 76100f6bc..ad449d0ce 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -28,6 +28,7 @@ #define HB_SET_HH #include "hb.hh" +#include "hb-machinery.hh" /* @@ -308,7 +309,7 @@ struct hb_set_t { page->add (g); - array = (const T *) ((const char *) array + stride); + array = &StructAtOffsetUnaligned (array, stride); count--; } while (count && (g = *array, start <= g && g < end)); @@ -440,8 +441,8 @@ struct hb_set_t return true; } - template - void process (const hb_set_t *other) + template + void process (const Op& op, const hb_set_t *other) { if (unlikely (!successful)) return; @@ -495,7 +496,7 @@ struct hb_set_t b--; count--; page_map[count] = page_map[a]; - Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v); + page_at (count).v = op (page_at (a).v, other->page_at (b).v); } else if (page_map[a - 1].major > other->page_map[b - 1].major) { @@ -541,19 +542,19 @@ struct hb_set_t void union_ (const hb_set_t *other) { - process (other); + process (hb_bitwise_or, other); } void intersect (const hb_set_t *other) { - process (other); + process (hb_bitwise_and, other); } void subtract (const hb_set_t *other) { - process (other); + process (hb_bitwise_sub, other); } void symmetric_difference (const hb_set_t *other) { - process (other); + process (hb_bitwise_xor, other); } bool next (hb_codepoint_t *codepoint) const { @@ -701,6 +702,9 @@ struct hb_set_t void __next__ () { s->next (&v); if (l) l--; } void __prev__ () { s->previous (&v); } unsigned __len__ () const { return l; } + iter_t end () const { return iter_t (*s); } + bool operator != (const iter_t& o) const + { return s != o.s || v != o.v; } protected: const hb_set_t *s; diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc index 20a01a5dd..97205948a 100644 --- a/src/hb-subset-cff1.cc +++ b/src/hb-subset-cff1.cc @@ -32,6 +32,8 @@ #include "hb-subset-cff-common.hh" #include "hb-cff1-interp-cs.hh" +#ifndef HB_NO_SUBSET_CFF + using namespace CFF; struct remap_sid_t : hb_bimap_t @@ -351,7 +353,7 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_tadd_op (op, env.str_ref); param.current_parsed_str->set_parsed (); - env.returnFromSubr (); + env.return_from_subr (); param.set_current_str (env, false); break; @@ -382,7 +384,7 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_tadd_call_op (op, str_ref, env.context.subr_num); hb_set_add (closure, env.context.subr_num); param.set_current_str (env, true); @@ -394,8 +396,8 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t { - cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc, const hb_subset_plan_t *plan) - : subr_subsetter_t (acc, plan) {} + cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_) + : subr_subsetter_t (acc_, plan_) {} static void complete_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring) { @@ -909,7 +911,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan, /* top dict INDEX */ { assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start)); - CFF1IndexOf *dest = c.start_embed< CFF1IndexOf > (); + CFF1IndexOf *dest = c.start_embed< CFF1IndexOf> (); if (dest == nullptr) return false; cff1_top_dict_op_serializer_t topSzr; top_dict_modifiers_t modifier (plan.offsets, plan.topDictModSIDs); @@ -1061,7 +1063,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan, return true; } -static bool +static inline bool _hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc, const char *data, hb_subset_plan_t *plan, @@ -1115,3 +1117,5 @@ hb_subset_cff1 (hb_subset_plan_t *plan, return result; } + +#endif diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index b93e5d7b2..400f19fcf 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -32,6 +32,8 @@ #include "hb-subset-cff-common.hh" #include "hb-cff2-interp-cs.hh" +#ifndef HB_NO_SUBSET_CFF + using namespace CFF; struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t @@ -183,7 +185,7 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_tset_parsed (); - env.returnFromSubr (); + env.return_from_subr (); param.set_current_str (env, false); break; @@ -213,7 +215,7 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_tadd_call_op (op, str_ref, env.context.subr_num); hb_set_add (closure, env.context.subr_num); param.set_current_str (env, true); @@ -225,8 +227,8 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t { - cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc, const hb_subset_plan_t *plan) - : subr_subsetter_t (acc, plan) {} + cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_) + : subr_subsetter_t (acc_, plan_) {} static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring) { @@ -569,7 +571,7 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan, return true; } -static bool +static inline bool _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc, const char *data, hb_subset_plan_t *plan, @@ -624,3 +626,5 @@ hb_subset_cff2 (hb_subset_plan_t *plan, return result; } + +#endif diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc deleted file mode 100644 index 9095e9f76..000000000 --- a/src/hb-subset-glyf.cc +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright © 2018 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Garret Rieger, Roderick Sheeter - */ - -#include "hb-open-type.hh" -#include "hb-ot-glyf-table.hh" -#include "hb-set.h" -#include "hb-subset-glyf.hh" - -struct loca_data_t -{ - bool is_short; - void *data; - unsigned int size; - - inline bool - _write_loca_entry (unsigned int id, - unsigned int offset) - { - unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32); - if ((id + 1) * entry_size <= size) - { - if (is_short) { - ((OT::HBUINT16*) data) [id] = offset / 2; - } else { - ((OT::HBUINT32*) data) [id] = offset; - } - return true; - } - - // Offset was not written because the write is out of bounds. - DEBUG_MSG(SUBSET, - nullptr, - "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.", - id, - size); - return false; - } -}; - -/** - * If hints are being dropped find the range which in glyf at which - * the hinting instructions are located. Add them to the instruction_ranges - * vector. - */ -static bool -_add_instructions_range (const OT::glyf::accelerator_t &glyf, - hb_codepoint_t glyph_id, - unsigned int glyph_start_offset, - unsigned int glyph_end_offset, - bool drop_hints, - hb_vector_t *instruction_ranges /* OUT */) -{ - if (!instruction_ranges->resize (instruction_ranges->length + 2)) - { - DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges."); - return false; - } - unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2]; - *instruction_start = 0; - unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1]; - *instruction_end = 0; - - if (drop_hints) - { - if (unlikely (!glyf.get_instruction_offsets (glyph_start_offset, glyph_end_offset, - instruction_start, instruction_end))) - { - DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", glyph_id); - return false; - } - } - - return true; -} - -static bool -_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf, - const hb_subset_plan_t *plan, - loca_data_t *loca_data, /* OUT */ - unsigned int *glyf_size /* OUT */, - hb_vector_t *instruction_ranges /* OUT */) -{ - unsigned int total = 0; - - hb_codepoint_t next_glyph = HB_SET_VALUE_INVALID; - while (plan->glyphset ()->next (&next_glyph)) - { - unsigned int start_offset, end_offset; - if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) && - glyf.remove_padding (start_offset, &end_offset)))) - { - DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph); - start_offset = end_offset = 0; - } - - bool is_zero_length = end_offset - start_offset < OT::glyf::GlyphHeader::static_size; - if (!_add_instructions_range (glyf, - next_glyph, - start_offset, - end_offset, - plan->drop_hints && !is_zero_length, - instruction_ranges)) - return false; - - if (is_zero_length) - continue; /* 0-length glyph */ - - total += end_offset - start_offset - - ((*instruction_ranges)[instruction_ranges->length - 1] - - (*instruction_ranges)[instruction_ranges->length - 2]); - /* round2 so short loca will work */ - total += total % 2; - } - - *glyf_size = total; - loca_data->is_short = (total <= 131070); - loca_data->size = (plan->num_output_glyphs () + 1) - * (loca_data->is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32)); - - DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca", - total, - loca_data->size, - loca_data->is_short ? "short" : "long"); - return true; -} - -static void -_update_components (const hb_subset_plan_t *plan, - char *glyph_start, - unsigned int length) -{ - OT::glyf::CompositeGlyphHeader::Iterator iterator; - if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start, - length, - &iterator)) - { - do - { - hb_codepoint_t new_gid; - if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex, - &new_gid)) - continue; - - ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid; - } while (iterator.move_to_next ()); - } -} - -static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length) -{ - /* remove WE_HAVE_INSTRUCTIONS from flags in dest */ - OT::glyf::CompositeGlyphHeader::Iterator composite_it; - if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false; - const OT::glyf::CompositeGlyphHeader *glyph; - do { - glyph = composite_it.current; - OT::HBUINT16 *flags = const_cast (&glyph->flags); - *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS; - } while (composite_it.move_to_next ()); - return true; -} - -static bool -_write_glyf_and_loca_prime (const hb_subset_plan_t *plan, - const OT::glyf::accelerator_t &glyf, - const char *glyf_data, - hb_vector_t &instruction_ranges, - unsigned int glyf_prime_size, - char *glyf_prime_data /* OUT */, - loca_data_t *loca_prime /* OUT */) -{ - char *glyf_prime_data_next = glyf_prime_data; - - bool success = true; - - - unsigned int i = 0; - hb_codepoint_t new_gid; - for (new_gid = 0; new_gid < plan->num_output_glyphs (); new_gid++) - { - hb_codepoint_t old_gid; - if (!plan->old_gid_for_new_gid (new_gid, &old_gid)) - { - // Empty glyph, add a loca entry and carry on. - loca_prime->_write_loca_entry (new_gid, - glyf_prime_data_next - glyf_prime_data); - continue; - } - - - unsigned int start_offset, end_offset; - if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) && - glyf.remove_padding (start_offset, &end_offset)))) - end_offset = start_offset = 0; - - unsigned int instruction_start = instruction_ranges[i * 2]; - unsigned int instruction_end = instruction_ranges[i * 2 + 1]; - - int length = end_offset - start_offset - (instruction_end - instruction_start); - - if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size) - { - DEBUG_MSG(SUBSET, - nullptr, - "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)", - i, length); - return false; - } - - if (instruction_start == instruction_end) - memcpy (glyf_prime_data_next, glyf_data + start_offset, length); - else - { - memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset); - memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end); - /* if the instructions end at the end this was a composite glyph, else simple */ - if (instruction_end == end_offset) - { - if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false; - } - else - /* zero instruction length, which is just before instruction_start */ - memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2); - } - - success = success && loca_prime->_write_loca_entry (new_gid, - glyf_prime_data_next - glyf_prime_data); - _update_components (plan, glyf_prime_data_next, length); - - // TODO: don't align to two bytes if using long loca. - glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca. - - i++; - } - - // loca table has n+1 entries where the last entry signifies the end location of the last - // glyph. - success = success && loca_prime->_write_loca_entry (new_gid, - glyf_prime_data_next - glyf_prime_data); - return success; -} - -static bool -_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf, - const char *glyf_data, - hb_subset_plan_t *plan, - bool *use_short_loca, - hb_blob_t **glyf_prime_blob /* OUT */, - hb_blob_t **loca_prime_blob /* OUT */) -{ - // TODO(grieger): Sanity check allocation size for the new table. - loca_data_t loca_prime; - unsigned int glyf_prime_size; - hb_vector_t instruction_ranges; - instruction_ranges.init (); - - if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf, - plan, - &loca_prime, - &glyf_prime_size, - &instruction_ranges))) { - instruction_ranges.fini (); - return false; - } - *use_short_loca = loca_prime.is_short; - - char *glyf_prime_data = (char *) calloc (1, glyf_prime_size); - loca_prime.data = (void *) calloc (1, loca_prime.size); - if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data, - instruction_ranges, - glyf_prime_size, glyf_prime_data, - &loca_prime))) { - free (glyf_prime_data); - free (loca_prime.data); - instruction_ranges.fini (); - return false; - } - instruction_ranges.fini (); - - *glyf_prime_blob = hb_blob_create (glyf_prime_data, - glyf_prime_size, - HB_MEMORY_MODE_READONLY, - glyf_prime_data, - free); - *loca_prime_blob = hb_blob_create ((char *) loca_prime.data, - loca_prime.size, - HB_MEMORY_MODE_READONLY, - loca_prime.data, - free); - return true; -} - -/** - * hb_subset_glyf: - * Subsets the glyph table according to a provided plan. - * - * Return value: subsetted glyf table. - * - * Since: 1.7.5 - **/ -bool -hb_subset_glyf_and_loca (hb_subset_plan_t *plan, - bool *use_short_loca, /* OUT */ - hb_blob_t **glyf_prime, /* OUT */ - hb_blob_t **loca_prime /* OUT */) -{ - hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table (plan->source); - const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr); - - OT::glyf::accelerator_t glyf; - glyf.init (plan->source); - bool result = _hb_subset_glyf_and_loca (glyf, - glyf_data, - plan, - use_short_loca, - glyf_prime, - loca_prime); - - hb_blob_destroy (glyf_blob); - glyf.fini (); - - return result; -} diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh deleted file mode 100644 index 99cf8f071..000000000 --- a/src/hb-subset-glyf.hh +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright © 2018 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Garret Rieger - */ - -#ifndef HB_SUBSET_GLYF_HH -#define HB_SUBSET_GLYF_HH - -#include "hb.hh" - -#include "hb-subset.hh" - -HB_INTERNAL bool -hb_subset_glyf_and_loca (hb_subset_plan_t *plan, - bool *use_short_loca, /* OUT */ - hb_blob_t **glyf_prime /* OUT */, - hb_blob_t **loca_prime /* OUT */); - -#endif /* HB_SUBSET_GLYF_HH */ diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index b3b27d427..34f1cb863 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -45,11 +45,44 @@ hb_subset_input_create_or_fail () input->unicodes = hb_set_create (); input->glyphs = hb_set_create (); input->name_ids = hb_set_create (); + hb_set_add_range (input->name_ids, 0, 6); + input->drop_tables = hb_set_create (); input->drop_hints = false; - input->drop_layout = true; input->desubroutinize = false; input->retain_gids = false; + hb_tag_t default_drop_tables[] = { + // Layout disabled by default + HB_TAG ('G', 'S', 'U', 'B'), + HB_TAG ('G', 'P', 'O', 'S'), + HB_TAG ('G', 'D', 'E', 'F'), + HB_TAG ('m', 'o', 'r', 'x'), + HB_TAG ('m', 'o', 'r', 't'), + HB_TAG ('k', 'e', 'r', 'x'), + HB_TAG ('k', 'e', 'r', 'n'), + + // Copied from fontTools: + HB_TAG ('B', 'A', 'S', 'E'), + HB_TAG ('J', 'S', 'T', 'F'), + HB_TAG ('D', 'S', 'I', 'G'), + HB_TAG ('E', 'B', 'D', 'T'), + HB_TAG ('E', 'B', 'L', 'C'), + HB_TAG ('E', 'B', 'S', 'C'), + HB_TAG ('S', 'V', 'G', ' '), + HB_TAG ('P', 'C', 'L', 'T'), + HB_TAG ('L', 'T', 'S', 'H'), + // Graphite tables + HB_TAG ('F', 'e', 'a', 't'), + HB_TAG ('G', 'l', 'a', 't'), + HB_TAG ('G', 'l', 'o', 'c'), + HB_TAG ('S', 'i', 'l', 'f'), + HB_TAG ('S', 'i', 'l', 'l'), + // Colour + HB_TAG ('s', 'b', 'i', 'x') + }; + + input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables)); + return input; } @@ -83,6 +116,7 @@ hb_subset_input_destroy (hb_subset_input_t *subset_input) hb_set_destroy (subset_input->unicodes); hb_set_destroy (subset_input->glyphs); hb_set_destroy (subset_input->name_ids); + hb_set_destroy (subset_input->drop_tables); free (subset_input); } @@ -117,6 +151,12 @@ hb_subset_input_nameid_set (hb_subset_input_t *subset_input) return subset_input->name_ids; } +HB_EXTERN hb_set_t * +hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input) +{ + return subset_input->drop_tables; +} + HB_EXTERN void hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input, hb_bool_t drop_hints) @@ -130,19 +170,6 @@ hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input) return subset_input->drop_hints; } -HB_EXTERN void -hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input, - hb_bool_t drop_layout) -{ - subset_input->drop_layout = drop_layout; -} - -HB_EXTERN hb_bool_t -hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input) -{ - return subset_input->drop_layout; -} - HB_EXTERN void hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, hb_bool_t desubroutinize) diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh index d01fecee0..f6dd4ac31 100644 --- a/src/hb-subset-input.hh +++ b/src/hb-subset-input.hh @@ -41,11 +41,11 @@ struct hb_subset_input_t hb_set_t *unicodes; hb_set_t *glyphs; hb_set_t *name_ids; + hb_set_t *drop_tables; - bool drop_hints : 1; - bool drop_layout : 1; - bool desubroutinize : 1; - bool retain_gids : 1; + bool drop_hints; + bool desubroutinize; + bool retain_gids; /* TODO * * features diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index fe636b190..7c1ed872c 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -31,8 +31,10 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-cff1-table.hh" +#include "hb-ot-var-fvar-table.hh" +#include "hb-ot-stat-table.hh" -static void +static inline void _add_gid_and_children (const OT::glyf::accelerator_t &glyf, hb_codepoint_t gid, hb_set_t *gids_to_retain) @@ -53,7 +55,8 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf, } } -static void +#ifndef HB_NO_SUBSET_CFF +static inline void _add_cff_seac_components (const OT::cff1::accelerator_t &cff, hb_codepoint_t gid, hb_set_t *gids_to_retain) @@ -65,8 +68,10 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff, hb_set_add (gids_to_retain, accent_gid); } } +#endif -static void +#ifndef HB_NO_SUBSET_LAYOUT +static inline void _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain) { hb_set_t lookup_indices; @@ -80,8 +85,9 @@ _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain) &lookup_indices, gids_to_retain); } +#endif -static void +static inline void _remove_invalid_gids (hb_set_t *glyphs, unsigned int num_glyphs) { @@ -93,24 +99,21 @@ _remove_invalid_gids (hb_set_t *glyphs, } } -static hb_set_t * -_populate_gids_to_retain (hb_face_t *face, +static void +_populate_gids_to_retain (hb_subset_plan_t* plan, const hb_set_t *unicodes, const hb_set_t *input_glyphs_to_retain, - bool close_over_gsub, - hb_set_t *unicodes_to_retain, - hb_map_t *codepoint_to_glyph) + bool close_over_gsub) { OT::cmap::accelerator_t cmap; OT::glyf::accelerator_t glyf; OT::cff1::accelerator_t cff; - cmap.init (face); - glyf.init (face); - cff.init (face); + cmap.init (plan->source); + glyf.init (plan->source); + cff.init (plan->source); - hb_set_t *initial_gids_to_retain = hb_set_create (); - initial_gids_to_retain->add (0); // Not-def - hb_set_union (initial_gids_to_retain, input_glyphs_to_retain); + plan->_glyphset_gsub->add (0); // Not-def + hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain); hb_codepoint_t cp = HB_SET_VALUE_INVALID; while (unicodes->next (&cp)) @@ -121,67 +124,92 @@ _populate_gids_to_retain (hb_face_t *face, DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp); continue; } - unicodes_to_retain->add (cp); - codepoint_to_glyph->set (cp, gid); - initial_gids_to_retain->add (gid); + plan->unicodes->add (cp); + plan->codepoint_to_glyph->set (cp, gid); + plan->_glyphset_gsub->add (gid); } +#ifndef HB_NO_SUBSET_LAYOUT if (close_over_gsub) // Add all glyphs needed for GSUB substitutions. - _gsub_closure (face, initial_gids_to_retain); + _gsub_closure (plan->source, plan->_glyphset_gsub); +#endif + _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ()); // Populate a full set of glyphs to retain by adding all referenced // composite glyphs. hb_codepoint_t gid = HB_SET_VALUE_INVALID; - hb_set_t *all_gids_to_retain = hb_set_create (); - while (initial_gids_to_retain->next (&gid)) + while (plan->_glyphset_gsub->next (&gid)) { - _add_gid_and_children (glyf, gid, all_gids_to_retain); + _add_gid_and_children (glyf, gid, plan->_glyphset); +#ifndef HB_NO_SUBSET_CFF if (cff.is_valid ()) - _add_cff_seac_components (cff, gid, all_gids_to_retain); + _add_cff_seac_components (cff, gid, plan->_glyphset); +#endif } - hb_set_destroy (initial_gids_to_retain); - - _remove_invalid_gids (all_gids_to_retain, face->get_num_glyphs ()); + _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ()); cff.fini (); glyf.fini (); cmap.fini (); - - return all_gids_to_retain; } static void -_create_old_gid_to_new_gid_map (const hb_face_t *face, - bool retain_gids, - hb_set_t *all_gids_to_retain, - hb_map_t *glyph_map, /* OUT */ - hb_map_t *reverse_glyph_map, /* OUT */ - unsigned int *num_glyphs /* OUT */) +_create_old_gid_to_new_gid_map (const hb_face_t *face, + bool retain_gids, + const hb_set_t *all_gids_to_retain, + hb_map_t *glyph_map, /* OUT */ + hb_map_t *reverse_glyph_map, /* OUT */ + unsigned int *num_glyphs /* OUT */) { - hb_codepoint_t gid = HB_SET_VALUE_INVALID; - unsigned int length = 0; - for (unsigned int i = 0; all_gids_to_retain->next (&gid); i++) { - if (!retain_gids) - { - glyph_map->set (gid, i); - reverse_glyph_map->set (i, gid); - } - else - { - glyph_map->set (gid, gid); - reverse_glyph_map->set (gid, gid); - } - ++length; - } - if (!retain_gids || length == 0) + if (!retain_gids) { - *num_glyphs = length; + + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0) + | hb_sink (reverse_glyph_map) + ; + *num_glyphs = reverse_glyph_map->get_population (); + } else { + + hb_iter (all_gids_to_retain) + | hb_map ([] (hb_codepoint_t _) { + return hb_pair_t (_, _); + }) + | hb_sink (reverse_glyph_map) + ; + + unsigned max_glyph = + + hb_iter (all_gids_to_retain) + | hb_reduce (hb_max, 0) + ; + *num_glyphs = max_glyph + 1; } - else + + + reverse_glyph_map->iter () + | hb_map (&hb_pair_t::reverse) + | hb_sink (glyph_map) + ; +} + +static void +_nameid_closure (hb_face_t *face, + hb_set_t *nameids) +{ + hb_tag_t table_tags[32]; + unsigned count = ARRAY_LENGTH (table_tags); + hb_face_get_table_tags (face, 0, &count, table_tags); + for (unsigned int i = 0; i < count; i++) { - *num_glyphs = face->get_num_glyphs (); + hb_tag_t tag = table_tags[i]; + switch (tag) { + case HB_OT_TAG_STAT: + face->table.STAT->collect_name_ids (nameids); + break; + case HB_OT_TAG_fvar: + face->table.fvar->collect_name_ids (nameids); + break; + default: + break; + } } } @@ -202,22 +230,25 @@ hb_subset_plan_create (hb_face_t *face, hb_subset_plan_t *plan = hb_object_create (); plan->drop_hints = input->drop_hints; - plan->drop_layout = input->drop_layout; plan->desubroutinize = input->desubroutinize; plan->retain_gids = input->retain_gids; plan->unicodes = hb_set_create (); plan->name_ids = hb_set_reference (input->name_ids); + _nameid_closure (face, plan->name_ids); + plan->drop_tables = hb_set_reference (input->drop_tables); plan->source = hb_face_reference (face); plan->dest = hb_face_builder_create (); + + plan->_glyphset = hb_set_create (); + plan->_glyphset_gsub = hb_set_create (); plan->codepoint_to_glyph = hb_map_create (); plan->glyph_map = hb_map_create (); plan->reverse_glyph_map = hb_map_create (); - plan->_glyphset = _populate_gids_to_retain (face, - input->unicodes, - input->glyphs, - !plan->drop_layout, - plan->unicodes, - plan->codepoint_to_glyph); + + _populate_gids_to_retain (plan, + input->unicodes, + input->glyphs, + !input->drop_tables->has (HB_OT_TAG_GSUB)); _create_old_gid_to_new_gid_map (face, input->retain_gids, @@ -241,12 +272,14 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_set_destroy (plan->unicodes); hb_set_destroy (plan->name_ids); + hb_set_destroy (plan->drop_tables); hb_face_destroy (plan->source); hb_face_destroy (plan->dest); hb_map_destroy (plan->codepoint_to_glyph); hb_map_destroy (plan->glyph_map); hb_map_destroy (plan->reverse_glyph_map); hb_set_destroy (plan->_glyphset); + hb_set_destroy (plan->_glyphset_gsub); free (plan); } diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index abbab5e22..ee44b63a4 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -40,16 +40,18 @@ struct hb_subset_plan_t hb_object_header_t header; bool drop_hints : 1; - bool drop_layout : 1; bool desubroutinize : 1; bool retain_gids : 1; // For each cp that we'd like to retain maps to the corresponding gid. hb_set_t *unicodes; - //name_ids we would like to retain + // name_ids we would like to retain hb_set_t *name_ids; + // Tables which should be dropped. + hb_set_t *drop_tables; + // The glyph subset hb_map_t *codepoint_to_glyph; @@ -63,11 +65,14 @@ struct hb_subset_plan_t unsigned int _num_output_glyphs; hb_set_t *_glyphset; + hb_set_t *_glyphset_gsub; public: /* * The set of input glyph ids which will be retained in the subset. + * Does NOT include ids kept due to retain_gids. You probably want to use + * glyph_map/reverse_glyph_map. */ inline const hb_set_t * glyphset () const @@ -75,6 +80,15 @@ struct hb_subset_plan_t return _glyphset; } + /* + * The set of input glyph ids which will be retained in the subset. + */ + inline const hb_set_t * + glyphset_gsub () const + { + return _glyphset_gsub; + } + /* * The total number of output glyphs in the final subset. */ diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 80d1628ef..19f46d16d 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -28,7 +28,6 @@ #include "hb-open-type.hh" #include "hb-subset.hh" -#include "hb-subset-glyf.hh" #include "hb-open-file.hh" #include "hb-ot-cmap-table.hh" @@ -70,7 +69,7 @@ template static bool _subset2 (hb_subset_plan_t *plan) { - bool result = true; + bool result = false; hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table (plan->source); const TableType *table = source_blob->as (); @@ -78,6 +77,8 @@ _subset2 (hb_subset_plan_t *plan) if (source_blob->data) { hb_vector_t buf; + /* TODO Not all tables are glyph-related. 'name' table size for example should not be + * affected by number of glyphs. Accommodate that. */ unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length); DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); if (unlikely (!buf.alloc (buf_size))) @@ -156,10 +157,10 @@ _subset_table (hb_subset_plan_t *plan, bool result = true; switch (tag) { case HB_OT_TAG_glyf: - result = _subset (plan); + result = _subset2 (plan); break; case HB_OT_TAG_hdmx: - result = _subset (plan); + result = _subset2 (plan); break; case HB_OT_TAG_name: result = _subset2 (plan); @@ -173,13 +174,13 @@ _subset_table (hb_subset_plan_t *plan, DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx"); return true; case HB_OT_TAG_hmtx: - result = _subset (plan); + result = _subset2 (plan); break; case HB_OT_TAG_vhea: DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx"); return true; case HB_OT_TAG_vmtx: - result = _subset (plan); + result = _subset2 (plan); break; case HB_OT_TAG_maxp: result = _subset (plan); @@ -196,6 +197,8 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_post: result = _subset (plan); break; + +#ifndef HB_NO_SUBSET_CFF case HB_OT_TAG_cff1: result = _subset (plan); break; @@ -205,8 +208,9 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_VORG: result = _subset (plan); break; +#endif -#if !defined(HB_NO_SUBSET_LAYOUT) +#ifndef HB_NO_SUBSET_LAYOUT case HB_OT_TAG_GDEF: result = _subset2 (plan); break; @@ -243,6 +247,9 @@ _subset_table (hb_subset_plan_t *plan, static bool _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) { + if (plan->drop_tables->has (tag)) + return true; + switch (tag) { case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */ case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */ @@ -252,35 +259,18 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */ return plan->drop_hints; +#ifdef HB_NO_SUBSET_LAYOUT // Drop Layout Tables if requested. case HB_OT_TAG_GDEF: case HB_OT_TAG_GPOS: case HB_OT_TAG_GSUB: -#if defined(HB_NO_SUBSET_LAYOUT) + case HB_TAG ('m', 'o', 'r', 'x'): + case HB_TAG ('m', 'o', 'r', 't'): + case HB_TAG ('k', 'e', 'r', 'x'): + case HB_TAG ('k', 'e', 'r', 'n'): return true; #endif - return plan->drop_layout; - // Drop these tables below by default, list pulled - // from fontTools: - case HB_TAG ('B', 'A', 'S', 'E'): - case HB_TAG ('J', 'S', 'T', 'F'): - case HB_TAG ('D', 'S', 'I', 'G'): - case HB_TAG ('E', 'B', 'D', 'T'): - case HB_TAG ('E', 'B', 'L', 'C'): - case HB_TAG ('E', 'B', 'S', 'C'): - case HB_TAG ('S', 'V', 'G', ' '): - case HB_TAG ('P', 'C', 'L', 'T'): - case HB_TAG ('L', 'T', 'S', 'H'): - // Graphite tables: - case HB_TAG ('F', 'e', 'a', 't'): - case HB_TAG ('G', 'l', 'a', 't'): - case HB_TAG ('G', 'l', 'o', 'c'): - case HB_TAG ('S', 'i', 'l', 'f'): - case HB_TAG ('S', 'i', 'l', 'l'): - // Colour - case HB_TAG ('s', 'b', 'i', 'x'): - return true; default: return false; } diff --git a/src/hb-subset.h b/src/hb-subset.h index 50345061c..c778896a2 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -57,18 +57,15 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input); HB_EXTERN hb_set_t * hb_subset_input_nameid_set (hb_subset_input_t *subset_input); +HB_EXTERN hb_set_t * +hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input); + HB_EXTERN void hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input, hb_bool_t drop_hints); HB_EXTERN hb_bool_t hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input); -HB_EXTERN void -hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input, - hb_bool_t drop_layout); -HB_EXTERN hb_bool_t -hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input); - HB_EXTERN void hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, hb_bool_t desubroutinize); diff --git a/src/hb-subset.hh b/src/hb-subset.hh index 45cb763ec..b8dd07ab2 100644 --- a/src/hb-subset.hh +++ b/src/hb-subset.hh @@ -40,9 +40,19 @@ struct hb_subset_context_t : hb_dispatch_context_t { const char *get_name () { return "SUBSET"; } - template - bool dispatch (const T &obj) { return obj.subset (this); } - static bool default_return_value () { return true; } + static return_t default_return_value () { return true; } + + private: + template auto + _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN + ( obj.subset (this, hb_forward (ds)...) ) + template auto + _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN + ( obj.dispatch (this, hb_forward (ds)...) ) + public: + template auto + dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN + ( _dispatch (obj, hb_prioritize, hb_forward (ds)...) ) hb_subset_plan_t *plan; hb_serialize_context_t *serializer; diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh new file mode 100644 index 000000000..95c4bf86e --- /dev/null +++ b/src/hb-ucd-table.hh @@ -0,0 +1,5160 @@ +/* == Start of generated table == */ +/* + * The following table is generated by running: + * + * ./gen-ucd-table.py ucd.nonunihan.grouped.xml + * + * on file with this description: Unicode 12.1.0 + */ + +#ifndef HB_UCD_TABLE_HH +#define HB_UCD_TABLE_HH + + +#include "hb.hh" + +static const hb_script_t +_hb_ucd_sc_map[138] = +{ + HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED, + HB_SCRIPT_UNKNOWN, HB_SCRIPT_ARABIC, + HB_SCRIPT_ARMENIAN, HB_SCRIPT_BENGALI, + HB_SCRIPT_CYRILLIC, HB_SCRIPT_DEVANAGARI, + HB_SCRIPT_GEORGIAN, HB_SCRIPT_GREEK, + HB_SCRIPT_GUJARATI, HB_SCRIPT_GURMUKHI, + HB_SCRIPT_HANGUL, HB_SCRIPT_HAN, + HB_SCRIPT_HEBREW, HB_SCRIPT_HIRAGANA, + HB_SCRIPT_KANNADA, HB_SCRIPT_KATAKANA, + HB_SCRIPT_LAO, HB_SCRIPT_LATIN, + HB_SCRIPT_MALAYALAM, HB_SCRIPT_ORIYA, + HB_SCRIPT_TAMIL, HB_SCRIPT_TELUGU, + HB_SCRIPT_THAI, HB_SCRIPT_TIBETAN, + HB_SCRIPT_BOPOMOFO, HB_SCRIPT_BRAILLE, + HB_SCRIPT_CANADIAN_SYLLABICS, HB_SCRIPT_CHEROKEE, + HB_SCRIPT_ETHIOPIC, HB_SCRIPT_KHMER, + HB_SCRIPT_MONGOLIAN, HB_SCRIPT_MYANMAR, + HB_SCRIPT_OGHAM, HB_SCRIPT_RUNIC, + HB_SCRIPT_SINHALA, HB_SCRIPT_SYRIAC, + HB_SCRIPT_THAANA, HB_SCRIPT_YI, + HB_SCRIPT_DESERET, HB_SCRIPT_GOTHIC, + HB_SCRIPT_OLD_ITALIC, HB_SCRIPT_BUHID, + HB_SCRIPT_HANUNOO, HB_SCRIPT_TAGALOG, + HB_SCRIPT_TAGBANWA, HB_SCRIPT_CYPRIOT, + HB_SCRIPT_LIMBU, HB_SCRIPT_LINEAR_B, + HB_SCRIPT_OSMANYA, HB_SCRIPT_SHAVIAN, + HB_SCRIPT_TAI_LE, HB_SCRIPT_UGARITIC, + HB_SCRIPT_BUGINESE, HB_SCRIPT_COPTIC, + HB_SCRIPT_GLAGOLITIC, HB_SCRIPT_KHAROSHTHI, + HB_SCRIPT_NEW_TAI_LUE, HB_SCRIPT_OLD_PERSIAN, + HB_SCRIPT_SYLOTI_NAGRI, HB_SCRIPT_TIFINAGH, + HB_SCRIPT_BALINESE, HB_SCRIPT_CUNEIFORM, + HB_SCRIPT_NKO, HB_SCRIPT_PHAGS_PA, + HB_SCRIPT_PHOENICIAN, HB_SCRIPT_CARIAN, + HB_SCRIPT_CHAM, HB_SCRIPT_KAYAH_LI, + HB_SCRIPT_LEPCHA, HB_SCRIPT_LYCIAN, + HB_SCRIPT_LYDIAN, HB_SCRIPT_OL_CHIKI, + HB_SCRIPT_REJANG, HB_SCRIPT_SAURASHTRA, + HB_SCRIPT_SUNDANESE, HB_SCRIPT_VAI, + HB_SCRIPT_AVESTAN, HB_SCRIPT_BAMUM, + HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, HB_SCRIPT_IMPERIAL_ARAMAIC, + HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, + HB_SCRIPT_JAVANESE, HB_SCRIPT_KAITHI, + HB_SCRIPT_LISU, HB_SCRIPT_MEETEI_MAYEK, + HB_SCRIPT_OLD_SOUTH_ARABIAN, HB_SCRIPT_OLD_TURKIC, + HB_SCRIPT_SAMARITAN, HB_SCRIPT_TAI_THAM, + HB_SCRIPT_TAI_VIET, HB_SCRIPT_BATAK, + HB_SCRIPT_BRAHMI, HB_SCRIPT_MANDAIC, + HB_SCRIPT_CHAKMA, HB_SCRIPT_MEROITIC_CURSIVE, + HB_SCRIPT_MEROITIC_HIEROGLYPHS, HB_SCRIPT_MIAO, + HB_SCRIPT_SHARADA, HB_SCRIPT_SORA_SOMPENG, + HB_SCRIPT_TAKRI, HB_SCRIPT_BASSA_VAH, + HB_SCRIPT_CAUCASIAN_ALBANIAN, HB_SCRIPT_DUPLOYAN, + HB_SCRIPT_ELBASAN, HB_SCRIPT_GRANTHA, + HB_SCRIPT_KHOJKI, HB_SCRIPT_KHUDAWADI, + HB_SCRIPT_LINEAR_A, HB_SCRIPT_MAHAJANI, + HB_SCRIPT_MANICHAEAN, HB_SCRIPT_MENDE_KIKAKUI, + HB_SCRIPT_MODI, HB_SCRIPT_MRO, + HB_SCRIPT_NABATAEAN, HB_SCRIPT_OLD_NORTH_ARABIAN, + HB_SCRIPT_OLD_PERMIC, HB_SCRIPT_PAHAWH_HMONG, + HB_SCRIPT_PALMYRENE, HB_SCRIPT_PAU_CIN_HAU, + HB_SCRIPT_PSALTER_PAHLAVI, HB_SCRIPT_SIDDHAM, + HB_SCRIPT_TIRHUTA, HB_SCRIPT_WARANG_CITI, + HB_SCRIPT_AHOM, HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, + HB_SCRIPT_HATRAN, HB_SCRIPT_MULTANI, + HB_SCRIPT_OLD_HUNGARIAN, HB_SCRIPT_SIGNWRITING, + HB_SCRIPT_ADLAM, HB_SCRIPT_BHAIKSUKI, + HB_SCRIPT_MARCHEN, HB_SCRIPT_OSAGE, + HB_SCRIPT_TANGUT, HB_SCRIPT_NEWA, +}; +static const hb_codepoint_t +_hb_ucd_dm1_map[935] = +{ + 0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u, + 0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu, + 0x038Eu, 0x038Fu, 0x0390u, 0x03A9u, 0x03ACu, 0x03ADu, 0x03AEu, 0x03AFu, + 0x03B0u, 0x03B9u, 0x03CCu, 0x03CDu, 0x03CEu, 0x2002u, 0x2003u, 0x3008u, + 0x3009u, 0x349Eu, 0x34B9u, 0x34BBu, 0x34DFu, 0x3515u, 0x36EEu, 0x36FCu, + 0x3781u, 0x382Fu, 0x3862u, 0x387Cu, 0x38C7u, 0x38E3u, 0x391Cu, 0x393Au, + 0x3A2Eu, 0x3A6Cu, 0x3AE4u, 0x3B08u, 0x3B19u, 0x3B49u, 0x3B9Du, 0x3C18u, + 0x3C4Eu, 0x3D33u, 0x3D96u, 0x3EACu, 0x3EB8u, 0x3F1Bu, 0x3FFCu, 0x4008u, + 0x4018u, 0x4039u, 0x4046u, 0x4096u, 0x40E3u, 0x412Fu, 0x4202u, 0x4227u, + 0x42A0u, 0x4301u, 0x4334u, 0x4359u, 0x43D5u, 0x43D9u, 0x440Bu, 0x446Bu, + 0x452Bu, 0x455Du, 0x4561u, 0x456Bu, 0x45D7u, 0x45F9u, 0x4635u, 0x46BEu, + 0x46C7u, 0x4995u, 0x49E6u, 0x4A6Eu, 0x4A76u, 0x4AB2u, 0x4B33u, 0x4BCEu, + 0x4CCEu, 0x4CEDu, 0x4CF8u, 0x4D56u, 0x4E0Du, 0x4E26u, 0x4E32u, 0x4E38u, + 0x4E39u, 0x4E3Du, 0x4E41u, 0x4E82u, 0x4E86u, 0x4EAEu, 0x4EC0u, 0x4ECCu, + 0x4EE4u, 0x4F60u, 0x4F80u, 0x4F86u, 0x4F8Bu, 0x4FAEu, 0x4FBBu, 0x4FBFu, + 0x5002u, 0x502Bu, 0x507Au, 0x5099u, 0x50CFu, 0x50DAu, 0x50E7u, 0x5140u, + 0x5145u, 0x514Du, 0x5154u, 0x5164u, 0x5167u, 0x5168u, 0x5169u, 0x516Du, + 0x5177u, 0x5180u, 0x518Du, 0x5192u, 0x5195u, 0x5197u, 0x51A4u, 0x51ACu, + 0x51B5u, 0x51B7u, 0x51C9u, 0x51CCu, 0x51DCu, 0x51DEu, 0x51F5u, 0x5203u, + 0x5207u, 0x5217u, 0x5229u, 0x523Au, 0x523Bu, 0x5246u, 0x5272u, 0x5277u, + 0x5289u, 0x529Bu, 0x52A3u, 0x52B3u, 0x52C7u, 0x52C9u, 0x52D2u, 0x52DEu, + 0x52E4u, 0x52F5u, 0x52FAu, 0x5305u, 0x5306u, 0x5317u, 0x533Fu, 0x5349u, + 0x5351u, 0x535Au, 0x5373u, 0x5375u, 0x537Du, 0x537Fu, 0x53C3u, 0x53CAu, + 0x53DFu, 0x53E5u, 0x53EBu, 0x53F1u, 0x5406u, 0x540Fu, 0x541Du, 0x5438u, + 0x5442u, 0x5448u, 0x5468u, 0x549Eu, 0x54A2u, 0x54BDu, 0x54F6u, 0x5510u, + 0x5553u, 0x5555u, 0x5563u, 0x5584u, 0x5587u, 0x5599u, 0x559Du, 0x55ABu, + 0x55B3u, 0x55C0u, 0x55C2u, 0x55E2u, 0x5606u, 0x5651u, 0x5668u, 0x5674u, + 0x56F9u, 0x5716u, 0x5717u, 0x578Bu, 0x57CEu, 0x57F4u, 0x580Du, 0x5831u, + 0x5832u, 0x5840u, 0x585Au, 0x585Eu, 0x58A8u, 0x58ACu, 0x58B3u, 0x58D8u, + 0x58DFu, 0x58EEu, 0x58F2u, 0x58F7u, 0x5906u, 0x591Au, 0x5922u, 0x5944u, + 0x5948u, 0x5951u, 0x5954u, 0x5962u, 0x5973u, 0x59D8u, 0x59ECu, 0x5A1Bu, + 0x5A27u, 0x5A62u, 0x5A66u, 0x5AB5u, 0x5B08u, 0x5B28u, 0x5B3Eu, 0x5B85u, + 0x5BC3u, 0x5BD8u, 0x5BE7u, 0x5BEEu, 0x5BF3u, 0x5BFFu, 0x5C06u, 0x5C22u, + 0x5C3Fu, 0x5C60u, 0x5C62u, 0x5C64u, 0x5C65u, 0x5C6Eu, 0x5C8Du, 0x5CC0u, + 0x5D19u, 0x5D43u, 0x5D50u, 0x5D6Bu, 0x5D6Eu, 0x5D7Cu, 0x5DB2u, 0x5DBAu, + 0x5DE1u, 0x5DE2u, 0x5DFDu, 0x5E28u, 0x5E3Du, 0x5E69u, 0x5E74u, 0x5EA6u, + 0x5EB0u, 0x5EB3u, 0x5EB6u, 0x5EC9u, 0x5ECAu, 0x5ED2u, 0x5ED3u, 0x5ED9u, + 0x5EECu, 0x5EFEu, 0x5F04u, 0x5F22u, 0x5F53u, 0x5F62u, 0x5F69u, 0x5F6Bu, + 0x5F8Bu, 0x5F9Au, 0x5FA9u, 0x5FADu, 0x5FCDu, 0x5FD7u, 0x5FF5u, 0x5FF9u, + 0x6012u, 0x601Cu, 0x6075u, 0x6081u, 0x6094u, 0x60C7u, 0x60D8u, 0x60E1u, + 0x6108u, 0x6144u, 0x6148u, 0x614Cu, 0x614Eu, 0x6160u, 0x6168u, 0x617Au, + 0x618Eu, 0x6190u, 0x61A4u, 0x61AFu, 0x61B2u, 0x61DEu, 0x61F2u, 0x61F6u, + 0x6200u, 0x6210u, 0x621Bu, 0x622Eu, 0x6234u, 0x625Du, 0x62B1u, 0x62C9u, + 0x62CFu, 0x62D3u, 0x62D4u, 0x62FCu, 0x62FEu, 0x633Du, 0x6350u, 0x6368u, + 0x637Bu, 0x6383u, 0x63A0u, 0x63A9u, 0x63C4u, 0x63C5u, 0x63E4u, 0x641Cu, + 0x6422u, 0x6452u, 0x6469u, 0x6477u, 0x647Eu, 0x649Au, 0x649Du, 0x64C4u, + 0x654Fu, 0x6556u, 0x656Cu, 0x6578u, 0x6599u, 0x65C5u, 0x65E2u, 0x65E3u, + 0x6613u, 0x6649u, 0x6674u, 0x6688u, 0x6691u, 0x669Cu, 0x66B4u, 0x66C6u, + 0x66F4u, 0x66F8u, 0x6700u, 0x6717u, 0x671Bu, 0x6721u, 0x674Eu, 0x6753u, + 0x6756u, 0x675Eu, 0x677Bu, 0x6785u, 0x6797u, 0x67F3u, 0x67FAu, 0x6817u, + 0x681Fu, 0x6852u, 0x6881u, 0x6885u, 0x688Eu, 0x68A8u, 0x6914u, 0x6942u, + 0x69A3u, 0x69EAu, 0x6A02u, 0x6A13u, 0x6AA8u, 0x6AD3u, 0x6ADBu, 0x6B04u, + 0x6B21u, 0x6B54u, 0x6B72u, 0x6B77u, 0x6B79u, 0x6B9Fu, 0x6BAEu, 0x6BBAu, + 0x6BBBu, 0x6C4Eu, 0x6C67u, 0x6C88u, 0x6CBFu, 0x6CCCu, 0x6CCDu, 0x6CE5u, + 0x6D16u, 0x6D1Bu, 0x6D1Eu, 0x6D34u, 0x6D3Eu, 0x6D41u, 0x6D69u, 0x6D6Au, + 0x6D77u, 0x6D78u, 0x6D85u, 0x6DCBu, 0x6DDAu, 0x6DEAu, 0x6DF9u, 0x6E1Au, + 0x6E2Fu, 0x6E6Eu, 0x6E9Cu, 0x6EBAu, 0x6EC7u, 0x6ECBu, 0x6ED1u, 0x6EDBu, + 0x6F0Fu, 0x6F22u, 0x6F23u, 0x6F6Eu, 0x6FC6u, 0x6FEBu, 0x6FFEu, 0x701Bu, + 0x701Eu, 0x7039u, 0x704Au, 0x7070u, 0x7077u, 0x707Du, 0x7099u, 0x70ADu, + 0x70C8u, 0x70D9u, 0x7145u, 0x7149u, 0x716Eu, 0x719Cu, 0x71CEu, 0x71D0u, + 0x7210u, 0x721Bu, 0x7228u, 0x722Bu, 0x7235u, 0x7250u, 0x7262u, 0x7280u, + 0x7295u, 0x72AFu, 0x72C0u, 0x72FCu, 0x732Au, 0x7375u, 0x737Au, 0x7387u, + 0x738Bu, 0x73A5u, 0x73B2u, 0x73DEu, 0x7406u, 0x7409u, 0x7422u, 0x7447u, + 0x745Cu, 0x7469u, 0x7471u, 0x7485u, 0x7489u, 0x7498u, 0x74CAu, 0x7506u, + 0x7524u, 0x753Bu, 0x753Eu, 0x7559u, 0x7565u, 0x7570u, 0x75E2u, 0x7610u, + 0x761Du, 0x761Fu, 0x7642u, 0x7669u, 0x76CAu, 0x76DBu, 0x76E7u, 0x76F4u, + 0x7701u, 0x771Eu, 0x771Fu, 0x7740u, 0x774Au, 0x778Bu, 0x77A7u, 0x784Eu, + 0x786Bu, 0x788Cu, 0x7891u, 0x78CAu, 0x78CCu, 0x78FBu, 0x792Au, 0x793Cu, + 0x793Eu, 0x7948u, 0x7949u, 0x7950u, 0x7956u, 0x795Du, 0x795Eu, 0x7965u, + 0x797Fu, 0x798Du, 0x798Eu, 0x798Fu, 0x79AEu, 0x79CAu, 0x79EBu, 0x7A1Cu, + 0x7A40u, 0x7A4Au, 0x7A4Fu, 0x7A81u, 0x7AB1u, 0x7ACBu, 0x7AEEu, 0x7B20u, + 0x7BC0u, 0x7BC6u, 0x7BC9u, 0x7C3Eu, 0x7C60u, 0x7C7Bu, 0x7C92u, 0x7CBEu, + 0x7CD2u, 0x7CD6u, 0x7CE3u, 0x7CE7u, 0x7CE8u, 0x7D00u, 0x7D10u, 0x7D22u, + 0x7D2Fu, 0x7D5Bu, 0x7D63u, 0x7DA0u, 0x7DBEu, 0x7DC7u, 0x7DF4u, 0x7E02u, + 0x7E09u, 0x7E37u, 0x7E41u, 0x7E45u, 0x7F3Eu, 0x7F72u, 0x7F79u, 0x7F7Au, + 0x7F85u, 0x7F95u, 0x7F9Au, 0x7FBDu, 0x7FFAu, 0x8001u, 0x8005u, 0x8046u, + 0x8060u, 0x806Fu, 0x8070u, 0x807Eu, 0x808Bu, 0x80ADu, 0x80B2u, 0x8103u, + 0x813Eu, 0x81D8u, 0x81E8u, 0x81EDu, 0x8201u, 0x8204u, 0x8218u, 0x826Fu, + 0x8279u, 0x828Bu, 0x8291u, 0x829Du, 0x82B1u, 0x82B3u, 0x82BDu, 0x82E5u, + 0x82E6u, 0x831Du, 0x8323u, 0x8336u, 0x8352u, 0x8353u, 0x8363u, 0x83ADu, + 0x83BDu, 0x83C9u, 0x83CAu, 0x83CCu, 0x83DCu, 0x83E7u, 0x83EFu, 0x83F1u, + 0x843Du, 0x8449u, 0x8457u, 0x84EEu, 0x84F1u, 0x84F3u, 0x84FCu, 0x8516u, + 0x8564u, 0x85CDu, 0x85FAu, 0x8606u, 0x8612u, 0x862Du, 0x863Fu, 0x8650u, + 0x865Cu, 0x8667u, 0x8669u, 0x8688u, 0x86A9u, 0x86E2u, 0x870Eu, 0x8728u, + 0x876Bu, 0x8779u, 0x8786u, 0x87BAu, 0x87E1u, 0x8801u, 0x881Fu, 0x884Cu, + 0x8860u, 0x8863u, 0x88C2u, 0x88CFu, 0x88D7u, 0x88DEu, 0x88E1u, 0x88F8u, + 0x88FAu, 0x8910u, 0x8941u, 0x8964u, 0x8986u, 0x898Bu, 0x8996u, 0x8AA0u, + 0x8AAAu, 0x8ABFu, 0x8ACBu, 0x8AD2u, 0x8AD6u, 0x8AEDu, 0x8AF8u, 0x8AFEu, + 0x8B01u, 0x8B39u, 0x8B58u, 0x8B80u, 0x8B8Au, 0x8C48u, 0x8C55u, 0x8CABu, + 0x8CC1u, 0x8CC2u, 0x8CC8u, 0x8CD3u, 0x8D08u, 0x8D1Bu, 0x8D77u, 0x8DBCu, + 0x8DCBu, 0x8DEFu, 0x8DF0u, 0x8ECAu, 0x8ED4u, 0x8F26u, 0x8F2Au, 0x8F38u, + 0x8F3Bu, 0x8F62u, 0x8F9Eu, 0x8FB0u, 0x8FB6u, 0x9023u, 0x9038u, 0x9072u, + 0x907Cu, 0x908Fu, 0x9094u, 0x90CEu, 0x90DEu, 0x90F1u, 0x90FDu, 0x9111u, + 0x911Bu, 0x916Au, 0x9199u, 0x91B4u, 0x91CCu, 0x91CFu, 0x91D1u, 0x9234u, + 0x9238u, 0x9276u, 0x927Cu, 0x92D7u, 0x92D8u, 0x9304u, 0x934Au, 0x93F9u, + 0x9415u, 0x958Bu, 0x95ADu, 0x95B7u, 0x962Eu, 0x964Bu, 0x964Du, 0x9675u, + 0x9678u, 0x967Cu, 0x9686u, 0x96A3u, 0x96B7u, 0x96B8u, 0x96C3u, 0x96E2u, + 0x96E3u, 0x96F6u, 0x96F7u, 0x9723u, 0x9732u, 0x9748u, 0x9756u, 0x97DBu, + 0x97E0u, 0x97FFu, 0x980Bu, 0x9818u, 0x9829u, 0x983Bu, 0x985Eu, 0x98E2u, + 0x98EFu, 0x98FCu, 0x9928u, 0x9929u, 0x99A7u, 0x99C2u, 0x99F1u, 0x99FEu, + 0x9A6Au, 0x9B12u, 0x9B6Fu, 0x9C40u, 0x9C57u, 0x9CFDu, 0x9D67u, 0x9DB4u, + 0x9DFAu, 0x9E1Eu, 0x9E7Fu, 0x9E97u, 0x9E9Fu, 0x9EBBu, 0x9ECEu, 0x9EF9u, + 0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu, + 0x9F9Cu,0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu, + 0x20A2Cu,0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu, + 0x21DE4u,0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au, + 0x22B0Cu,0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u, + 0x233D5u,0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu, + 0x23ED1u,0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u, + 0x24814u,0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u, + 0x25119u,0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu, + 0x25AA7u,0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u, + 0x262D9u,0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu, + 0x26C36u,0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u, + 0x278AEu,0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu, + 0x28BFAu,0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u, + 0x29B30u,0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u, +}; +static const uint64_t +_hb_ucd_dm2_map[1025] = +{ + HB_CODEPOINT_ENCODE3 (0x003Cu, 0x0338u, 0x226Eu), HB_CODEPOINT_ENCODE3 (0x003Du, 0x0338u, 0x2260u), + HB_CODEPOINT_ENCODE3 (0x003Eu, 0x0338u, 0x226Fu), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0300u, 0x00C0u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x0301u, 0x00C1u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0302u, 0x00C2u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x0303u, 0x00C3u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0304u, 0x0100u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x0306u, 0x0102u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0307u, 0x0226u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x0308u, 0x00C4u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0309u, 0x1EA2u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Au, 0x00C5u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Cu, 0x01CDu), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Fu, 0x0200u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0311u, 0x0202u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x0323u, 0x1EA0u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0325u, 0x1E00u), + HB_CODEPOINT_ENCODE3 (0x0041u, 0x0328u, 0x0104u), HB_CODEPOINT_ENCODE3 (0x0042u, 0x0307u, 0x1E02u), + HB_CODEPOINT_ENCODE3 (0x0042u, 0x0323u, 0x1E04u), HB_CODEPOINT_ENCODE3 (0x0042u, 0x0331u, 0x1E06u), + HB_CODEPOINT_ENCODE3 (0x0043u, 0x0301u, 0x0106u), HB_CODEPOINT_ENCODE3 (0x0043u, 0x0302u, 0x0108u), + HB_CODEPOINT_ENCODE3 (0x0043u, 0x0307u, 0x010Au), HB_CODEPOINT_ENCODE3 (0x0043u, 0x030Cu, 0x010Cu), + HB_CODEPOINT_ENCODE3 (0x0043u, 0x0327u, 0x00C7u), HB_CODEPOINT_ENCODE3 (0x0044u, 0x0307u, 0x1E0Au), + HB_CODEPOINT_ENCODE3 (0x0044u, 0x030Cu, 0x010Eu), HB_CODEPOINT_ENCODE3 (0x0044u, 0x0323u, 0x1E0Cu), + HB_CODEPOINT_ENCODE3 (0x0044u, 0x0327u, 0x1E10u), HB_CODEPOINT_ENCODE3 (0x0044u, 0x032Du, 0x1E12u), + HB_CODEPOINT_ENCODE3 (0x0044u, 0x0331u, 0x1E0Eu), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0300u, 0x00C8u), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x0301u, 0x00C9u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0302u, 0x00CAu), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x0303u, 0x1EBCu), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0304u, 0x0112u), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x0306u, 0x0114u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0307u, 0x0116u), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x0308u, 0x00CBu), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0309u, 0x1EBAu), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Cu, 0x011Au), HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Fu, 0x0204u), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x0311u, 0x0206u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0323u, 0x1EB8u), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x0327u, 0x0228u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0328u, 0x0118u), + HB_CODEPOINT_ENCODE3 (0x0045u, 0x032Du, 0x1E18u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0330u, 0x1E1Au), + HB_CODEPOINT_ENCODE3 (0x0046u, 0x0307u, 0x1E1Eu), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0301u, 0x01F4u), + HB_CODEPOINT_ENCODE3 (0x0047u, 0x0302u, 0x011Cu), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0304u, 0x1E20u), + HB_CODEPOINT_ENCODE3 (0x0047u, 0x0306u, 0x011Eu), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0307u, 0x0120u), + HB_CODEPOINT_ENCODE3 (0x0047u, 0x030Cu, 0x01E6u), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0327u, 0x0122u), + HB_CODEPOINT_ENCODE3 (0x0048u, 0x0302u, 0x0124u), HB_CODEPOINT_ENCODE3 (0x0048u, 0x0307u, 0x1E22u), + HB_CODEPOINT_ENCODE3 (0x0048u, 0x0308u, 0x1E26u), HB_CODEPOINT_ENCODE3 (0x0048u, 0x030Cu, 0x021Eu), + HB_CODEPOINT_ENCODE3 (0x0048u, 0x0323u, 0x1E24u), HB_CODEPOINT_ENCODE3 (0x0048u, 0x0327u, 0x1E28u), + HB_CODEPOINT_ENCODE3 (0x0048u, 0x032Eu, 0x1E2Au), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0300u, 0x00CCu), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x0301u, 0x00CDu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0302u, 0x00CEu), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x0303u, 0x0128u), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0304u, 0x012Au), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x0306u, 0x012Cu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0307u, 0x0130u), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x0308u, 0x00CFu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0309u, 0x1EC8u), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Cu, 0x01CFu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Fu, 0x0208u), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x0311u, 0x020Au), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0323u, 0x1ECAu), + HB_CODEPOINT_ENCODE3 (0x0049u, 0x0328u, 0x012Eu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0330u, 0x1E2Cu), + HB_CODEPOINT_ENCODE3 (0x004Au, 0x0302u, 0x0134u), HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0301u, 0x1E30u), + HB_CODEPOINT_ENCODE3 (0x004Bu, 0x030Cu, 0x01E8u), HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0323u, 0x1E32u), + HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0327u, 0x0136u), HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0331u, 0x1E34u), + HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0301u, 0x0139u), HB_CODEPOINT_ENCODE3 (0x004Cu, 0x030Cu, 0x013Du), + HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0323u, 0x1E36u), HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0327u, 0x013Bu), + HB_CODEPOINT_ENCODE3 (0x004Cu, 0x032Du, 0x1E3Cu), HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0331u, 0x1E3Au), + HB_CODEPOINT_ENCODE3 (0x004Du, 0x0301u, 0x1E3Eu), HB_CODEPOINT_ENCODE3 (0x004Du, 0x0307u, 0x1E40u), + HB_CODEPOINT_ENCODE3 (0x004Du, 0x0323u, 0x1E42u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0300u, 0x01F8u), + HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0301u, 0x0143u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0303u, 0x00D1u), + HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0307u, 0x1E44u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x030Cu, 0x0147u), + HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0323u, 0x1E46u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0327u, 0x0145u), + HB_CODEPOINT_ENCODE3 (0x004Eu, 0x032Du, 0x1E4Au), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0331u, 0x1E48u), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0300u, 0x00D2u), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0301u, 0x00D3u), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0302u, 0x00D4u), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0303u, 0x00D5u), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0304u, 0x014Cu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0306u, 0x014Eu), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0307u, 0x022Eu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0308u, 0x00D6u), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0309u, 0x1ECEu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Bu, 0x0150u), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Cu, 0x01D1u), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Fu, 0x020Cu), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0311u, 0x020Eu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x031Bu, 0x01A0u), + HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0323u, 0x1ECCu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0328u, 0x01EAu), + HB_CODEPOINT_ENCODE3 (0x0050u, 0x0301u, 0x1E54u), HB_CODEPOINT_ENCODE3 (0x0050u, 0x0307u, 0x1E56u), + HB_CODEPOINT_ENCODE3 (0x0052u, 0x0301u, 0x0154u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x0307u, 0x1E58u), + HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Cu, 0x0158u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Fu, 0x0210u), + HB_CODEPOINT_ENCODE3 (0x0052u, 0x0311u, 0x0212u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x0323u, 0x1E5Au), + HB_CODEPOINT_ENCODE3 (0x0052u, 0x0327u, 0x0156u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x0331u, 0x1E5Eu), + HB_CODEPOINT_ENCODE3 (0x0053u, 0x0301u, 0x015Au), HB_CODEPOINT_ENCODE3 (0x0053u, 0x0302u, 0x015Cu), + HB_CODEPOINT_ENCODE3 (0x0053u, 0x0307u, 0x1E60u), HB_CODEPOINT_ENCODE3 (0x0053u, 0x030Cu, 0x0160u), + HB_CODEPOINT_ENCODE3 (0x0053u, 0x0323u, 0x1E62u), HB_CODEPOINT_ENCODE3 (0x0053u, 0x0326u, 0x0218u), + HB_CODEPOINT_ENCODE3 (0x0053u, 0x0327u, 0x015Eu), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0307u, 0x1E6Au), + HB_CODEPOINT_ENCODE3 (0x0054u, 0x030Cu, 0x0164u), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0323u, 0x1E6Cu), + HB_CODEPOINT_ENCODE3 (0x0054u, 0x0326u, 0x021Au), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0327u, 0x0162u), + HB_CODEPOINT_ENCODE3 (0x0054u, 0x032Du, 0x1E70u), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0331u, 0x1E6Eu), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0300u, 0x00D9u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0301u, 0x00DAu), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0302u, 0x00DBu), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0303u, 0x0168u), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0304u, 0x016Au), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0306u, 0x016Cu), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0308u, 0x00DCu), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0309u, 0x1EE6u), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Au, 0x016Eu), HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Bu, 0x0170u), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Cu, 0x01D3u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Fu, 0x0214u), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0311u, 0x0216u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x031Bu, 0x01AFu), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0323u, 0x1EE4u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0324u, 0x1E72u), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0328u, 0x0172u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x032Du, 0x1E76u), + HB_CODEPOINT_ENCODE3 (0x0055u, 0x0330u, 0x1E74u), HB_CODEPOINT_ENCODE3 (0x0056u, 0x0303u, 0x1E7Cu), + HB_CODEPOINT_ENCODE3 (0x0056u, 0x0323u, 0x1E7Eu), HB_CODEPOINT_ENCODE3 (0x0057u, 0x0300u, 0x1E80u), + HB_CODEPOINT_ENCODE3 (0x0057u, 0x0301u, 0x1E82u), HB_CODEPOINT_ENCODE3 (0x0057u, 0x0302u, 0x0174u), + HB_CODEPOINT_ENCODE3 (0x0057u, 0x0307u, 0x1E86u), HB_CODEPOINT_ENCODE3 (0x0057u, 0x0308u, 0x1E84u), + HB_CODEPOINT_ENCODE3 (0x0057u, 0x0323u, 0x1E88u), HB_CODEPOINT_ENCODE3 (0x0058u, 0x0307u, 0x1E8Au), + HB_CODEPOINT_ENCODE3 (0x0058u, 0x0308u, 0x1E8Cu), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0300u, 0x1EF2u), + HB_CODEPOINT_ENCODE3 (0x0059u, 0x0301u, 0x00DDu), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0302u, 0x0176u), + HB_CODEPOINT_ENCODE3 (0x0059u, 0x0303u, 0x1EF8u), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0304u, 0x0232u), + HB_CODEPOINT_ENCODE3 (0x0059u, 0x0307u, 0x1E8Eu), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0308u, 0x0178u), + HB_CODEPOINT_ENCODE3 (0x0059u, 0x0309u, 0x1EF6u), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0323u, 0x1EF4u), + HB_CODEPOINT_ENCODE3 (0x005Au, 0x0301u, 0x0179u), HB_CODEPOINT_ENCODE3 (0x005Au, 0x0302u, 0x1E90u), + HB_CODEPOINT_ENCODE3 (0x005Au, 0x0307u, 0x017Bu), HB_CODEPOINT_ENCODE3 (0x005Au, 0x030Cu, 0x017Du), + HB_CODEPOINT_ENCODE3 (0x005Au, 0x0323u, 0x1E92u), HB_CODEPOINT_ENCODE3 (0x005Au, 0x0331u, 0x1E94u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0300u, 0x00E0u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0301u, 0x00E1u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0302u, 0x00E2u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0303u, 0x00E3u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0304u, 0x0101u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0306u, 0x0103u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0307u, 0x0227u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0308u, 0x00E4u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0309u, 0x1EA3u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Au, 0x00E5u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Cu, 0x01CEu), HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Fu, 0x0201u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0311u, 0x0203u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0323u, 0x1EA1u), + HB_CODEPOINT_ENCODE3 (0x0061u, 0x0325u, 0x1E01u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0328u, 0x0105u), + HB_CODEPOINT_ENCODE3 (0x0062u, 0x0307u, 0x1E03u), HB_CODEPOINT_ENCODE3 (0x0062u, 0x0323u, 0x1E05u), + HB_CODEPOINT_ENCODE3 (0x0062u, 0x0331u, 0x1E07u), HB_CODEPOINT_ENCODE3 (0x0063u, 0x0301u, 0x0107u), + HB_CODEPOINT_ENCODE3 (0x0063u, 0x0302u, 0x0109u), HB_CODEPOINT_ENCODE3 (0x0063u, 0x0307u, 0x010Bu), + HB_CODEPOINT_ENCODE3 (0x0063u, 0x030Cu, 0x010Du), HB_CODEPOINT_ENCODE3 (0x0063u, 0x0327u, 0x00E7u), + HB_CODEPOINT_ENCODE3 (0x0064u, 0x0307u, 0x1E0Bu), HB_CODEPOINT_ENCODE3 (0x0064u, 0x030Cu, 0x010Fu), + HB_CODEPOINT_ENCODE3 (0x0064u, 0x0323u, 0x1E0Du), HB_CODEPOINT_ENCODE3 (0x0064u, 0x0327u, 0x1E11u), + HB_CODEPOINT_ENCODE3 (0x0064u, 0x032Du, 0x1E13u), HB_CODEPOINT_ENCODE3 (0x0064u, 0x0331u, 0x1E0Fu), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0300u, 0x00E8u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0301u, 0x00E9u), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0302u, 0x00EAu), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0303u, 0x1EBDu), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0304u, 0x0113u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0306u, 0x0115u), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0307u, 0x0117u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0308u, 0x00EBu), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0309u, 0x1EBBu), HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Cu, 0x011Bu), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Fu, 0x0205u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0311u, 0x0207u), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0323u, 0x1EB9u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0327u, 0x0229u), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0328u, 0x0119u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x032Du, 0x1E19u), + HB_CODEPOINT_ENCODE3 (0x0065u, 0x0330u, 0x1E1Bu), HB_CODEPOINT_ENCODE3 (0x0066u, 0x0307u, 0x1E1Fu), + HB_CODEPOINT_ENCODE3 (0x0067u, 0x0301u, 0x01F5u), HB_CODEPOINT_ENCODE3 (0x0067u, 0x0302u, 0x011Du), + HB_CODEPOINT_ENCODE3 (0x0067u, 0x0304u, 0x1E21u), HB_CODEPOINT_ENCODE3 (0x0067u, 0x0306u, 0x011Fu), + HB_CODEPOINT_ENCODE3 (0x0067u, 0x0307u, 0x0121u), HB_CODEPOINT_ENCODE3 (0x0067u, 0x030Cu, 0x01E7u), + HB_CODEPOINT_ENCODE3 (0x0067u, 0x0327u, 0x0123u), HB_CODEPOINT_ENCODE3 (0x0068u, 0x0302u, 0x0125u), + HB_CODEPOINT_ENCODE3 (0x0068u, 0x0307u, 0x1E23u), HB_CODEPOINT_ENCODE3 (0x0068u, 0x0308u, 0x1E27u), + HB_CODEPOINT_ENCODE3 (0x0068u, 0x030Cu, 0x021Fu), HB_CODEPOINT_ENCODE3 (0x0068u, 0x0323u, 0x1E25u), + HB_CODEPOINT_ENCODE3 (0x0068u, 0x0327u, 0x1E29u), HB_CODEPOINT_ENCODE3 (0x0068u, 0x032Eu, 0x1E2Bu), + HB_CODEPOINT_ENCODE3 (0x0068u, 0x0331u, 0x1E96u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0300u, 0x00ECu), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x0301u, 0x00EDu), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0302u, 0x00EEu), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x0303u, 0x0129u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0304u, 0x012Bu), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x0306u, 0x012Du), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0308u, 0x00EFu), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x0309u, 0x1EC9u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Cu, 0x01D0u), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Fu, 0x0209u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0311u, 0x020Bu), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x0323u, 0x1ECBu), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0328u, 0x012Fu), + HB_CODEPOINT_ENCODE3 (0x0069u, 0x0330u, 0x1E2Du), HB_CODEPOINT_ENCODE3 (0x006Au, 0x0302u, 0x0135u), + HB_CODEPOINT_ENCODE3 (0x006Au, 0x030Cu, 0x01F0u), HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0301u, 0x1E31u), + HB_CODEPOINT_ENCODE3 (0x006Bu, 0x030Cu, 0x01E9u), HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0323u, 0x1E33u), + HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0327u, 0x0137u), HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0331u, 0x1E35u), + HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0301u, 0x013Au), HB_CODEPOINT_ENCODE3 (0x006Cu, 0x030Cu, 0x013Eu), + HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0323u, 0x1E37u), HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0327u, 0x013Cu), + HB_CODEPOINT_ENCODE3 (0x006Cu, 0x032Du, 0x1E3Du), HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0331u, 0x1E3Bu), + HB_CODEPOINT_ENCODE3 (0x006Du, 0x0301u, 0x1E3Fu), HB_CODEPOINT_ENCODE3 (0x006Du, 0x0307u, 0x1E41u), + HB_CODEPOINT_ENCODE3 (0x006Du, 0x0323u, 0x1E43u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0300u, 0x01F9u), + HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0301u, 0x0144u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0303u, 0x00F1u), + HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0307u, 0x1E45u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x030Cu, 0x0148u), + HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0323u, 0x1E47u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0327u, 0x0146u), + HB_CODEPOINT_ENCODE3 (0x006Eu, 0x032Du, 0x1E4Bu), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0331u, 0x1E49u), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0300u, 0x00F2u), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0301u, 0x00F3u), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0302u, 0x00F4u), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0303u, 0x00F5u), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0304u, 0x014Du), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0306u, 0x014Fu), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0307u, 0x022Fu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0308u, 0x00F6u), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0309u, 0x1ECFu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Bu, 0x0151u), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Cu, 0x01D2u), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Fu, 0x020Du), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0311u, 0x020Fu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x031Bu, 0x01A1u), + HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0323u, 0x1ECDu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0328u, 0x01EBu), + HB_CODEPOINT_ENCODE3 (0x0070u, 0x0301u, 0x1E55u), HB_CODEPOINT_ENCODE3 (0x0070u, 0x0307u, 0x1E57u), + HB_CODEPOINT_ENCODE3 (0x0072u, 0x0301u, 0x0155u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x0307u, 0x1E59u), + HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Cu, 0x0159u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Fu, 0x0211u), + HB_CODEPOINT_ENCODE3 (0x0072u, 0x0311u, 0x0213u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x0323u, 0x1E5Bu), + HB_CODEPOINT_ENCODE3 (0x0072u, 0x0327u, 0x0157u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x0331u, 0x1E5Fu), + HB_CODEPOINT_ENCODE3 (0x0073u, 0x0301u, 0x015Bu), HB_CODEPOINT_ENCODE3 (0x0073u, 0x0302u, 0x015Du), + HB_CODEPOINT_ENCODE3 (0x0073u, 0x0307u, 0x1E61u), HB_CODEPOINT_ENCODE3 (0x0073u, 0x030Cu, 0x0161u), + HB_CODEPOINT_ENCODE3 (0x0073u, 0x0323u, 0x1E63u), HB_CODEPOINT_ENCODE3 (0x0073u, 0x0326u, 0x0219u), + HB_CODEPOINT_ENCODE3 (0x0073u, 0x0327u, 0x015Fu), HB_CODEPOINT_ENCODE3 (0x0074u, 0x0307u, 0x1E6Bu), + HB_CODEPOINT_ENCODE3 (0x0074u, 0x0308u, 0x1E97u), HB_CODEPOINT_ENCODE3 (0x0074u, 0x030Cu, 0x0165u), + HB_CODEPOINT_ENCODE3 (0x0074u, 0x0323u, 0x1E6Du), HB_CODEPOINT_ENCODE3 (0x0074u, 0x0326u, 0x021Bu), + HB_CODEPOINT_ENCODE3 (0x0074u, 0x0327u, 0x0163u), HB_CODEPOINT_ENCODE3 (0x0074u, 0x032Du, 0x1E71u), + HB_CODEPOINT_ENCODE3 (0x0074u, 0x0331u, 0x1E6Fu), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0300u, 0x00F9u), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x0301u, 0x00FAu), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0302u, 0x00FBu), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x0303u, 0x0169u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0304u, 0x016Bu), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x0306u, 0x016Du), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0308u, 0x00FCu), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x0309u, 0x1EE7u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Au, 0x016Fu), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Bu, 0x0171u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Cu, 0x01D4u), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Fu, 0x0215u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0311u, 0x0217u), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x031Bu, 0x01B0u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0323u, 0x1EE5u), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x0324u, 0x1E73u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0328u, 0x0173u), + HB_CODEPOINT_ENCODE3 (0x0075u, 0x032Du, 0x1E77u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0330u, 0x1E75u), + HB_CODEPOINT_ENCODE3 (0x0076u, 0x0303u, 0x1E7Du), HB_CODEPOINT_ENCODE3 (0x0076u, 0x0323u, 0x1E7Fu), + HB_CODEPOINT_ENCODE3 (0x0077u, 0x0300u, 0x1E81u), HB_CODEPOINT_ENCODE3 (0x0077u, 0x0301u, 0x1E83u), + HB_CODEPOINT_ENCODE3 (0x0077u, 0x0302u, 0x0175u), HB_CODEPOINT_ENCODE3 (0x0077u, 0x0307u, 0x1E87u), + HB_CODEPOINT_ENCODE3 (0x0077u, 0x0308u, 0x1E85u), HB_CODEPOINT_ENCODE3 (0x0077u, 0x030Au, 0x1E98u), + HB_CODEPOINT_ENCODE3 (0x0077u, 0x0323u, 0x1E89u), HB_CODEPOINT_ENCODE3 (0x0078u, 0x0307u, 0x1E8Bu), + HB_CODEPOINT_ENCODE3 (0x0078u, 0x0308u, 0x1E8Du), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0300u, 0x1EF3u), + HB_CODEPOINT_ENCODE3 (0x0079u, 0x0301u, 0x00FDu), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0302u, 0x0177u), + HB_CODEPOINT_ENCODE3 (0x0079u, 0x0303u, 0x1EF9u), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0304u, 0x0233u), + HB_CODEPOINT_ENCODE3 (0x0079u, 0x0307u, 0x1E8Fu), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0308u, 0x00FFu), + HB_CODEPOINT_ENCODE3 (0x0079u, 0x0309u, 0x1EF7u), HB_CODEPOINT_ENCODE3 (0x0079u, 0x030Au, 0x1E99u), + HB_CODEPOINT_ENCODE3 (0x0079u, 0x0323u, 0x1EF5u), HB_CODEPOINT_ENCODE3 (0x007Au, 0x0301u, 0x017Au), + HB_CODEPOINT_ENCODE3 (0x007Au, 0x0302u, 0x1E91u), HB_CODEPOINT_ENCODE3 (0x007Au, 0x0307u, 0x017Cu), + HB_CODEPOINT_ENCODE3 (0x007Au, 0x030Cu, 0x017Eu), HB_CODEPOINT_ENCODE3 (0x007Au, 0x0323u, 0x1E93u), + HB_CODEPOINT_ENCODE3 (0x007Au, 0x0331u, 0x1E95u), HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0300u, 0x1FEDu), + HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0301u, 0x0385u), HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0342u, 0x1FC1u), + HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0300u, 0x1EA6u), HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0301u, 0x1EA4u), + HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0303u, 0x1EAAu), HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0309u, 0x1EA8u), + HB_CODEPOINT_ENCODE3 (0x00C4u, 0x0304u, 0x01DEu), HB_CODEPOINT_ENCODE3 (0x00C5u, 0x0301u, 0x01FAu), + HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0301u, 0x01FCu), HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0304u, 0x01E2u), + HB_CODEPOINT_ENCODE3 (0x00C7u, 0x0301u, 0x1E08u), HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0300u, 0x1EC0u), + HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0301u, 0x1EBEu), HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0303u, 0x1EC4u), + HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0309u, 0x1EC2u), HB_CODEPOINT_ENCODE3 (0x00CFu, 0x0301u, 0x1E2Eu), + HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0300u, 0x1ED2u), HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0301u, 0x1ED0u), + HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0303u, 0x1ED6u), HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0309u, 0x1ED4u), + HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0301u, 0x1E4Cu), HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0304u, 0x022Cu), + HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0308u, 0x1E4Eu), HB_CODEPOINT_ENCODE3 (0x00D6u, 0x0304u, 0x022Au), + HB_CODEPOINT_ENCODE3 (0x00D8u, 0x0301u, 0x01FEu), HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0300u, 0x01DBu), + HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0301u, 0x01D7u), HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0304u, 0x01D5u), + HB_CODEPOINT_ENCODE3 (0x00DCu, 0x030Cu, 0x01D9u), HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0300u, 0x1EA7u), + HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0301u, 0x1EA5u), HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0303u, 0x1EABu), + HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0309u, 0x1EA9u), HB_CODEPOINT_ENCODE3 (0x00E4u, 0x0304u, 0x01DFu), + HB_CODEPOINT_ENCODE3 (0x00E5u, 0x0301u, 0x01FBu), HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0301u, 0x01FDu), + HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0304u, 0x01E3u), HB_CODEPOINT_ENCODE3 (0x00E7u, 0x0301u, 0x1E09u), + HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0300u, 0x1EC1u), HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0301u, 0x1EBFu), + HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0303u, 0x1EC5u), HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0309u, 0x1EC3u), + HB_CODEPOINT_ENCODE3 (0x00EFu, 0x0301u, 0x1E2Fu), HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0300u, 0x1ED3u), + HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0301u, 0x1ED1u), HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0303u, 0x1ED7u), + HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0309u, 0x1ED5u), HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0301u, 0x1E4Du), + HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0304u, 0x022Du), HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0308u, 0x1E4Fu), + HB_CODEPOINT_ENCODE3 (0x00F6u, 0x0304u, 0x022Bu), HB_CODEPOINT_ENCODE3 (0x00F8u, 0x0301u, 0x01FFu), + HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0300u, 0x01DCu), HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0301u, 0x01D8u), + HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0304u, 0x01D6u), HB_CODEPOINT_ENCODE3 (0x00FCu, 0x030Cu, 0x01DAu), + HB_CODEPOINT_ENCODE3 (0x0102u, 0x0300u, 0x1EB0u), HB_CODEPOINT_ENCODE3 (0x0102u, 0x0301u, 0x1EAEu), + HB_CODEPOINT_ENCODE3 (0x0102u, 0x0303u, 0x1EB4u), HB_CODEPOINT_ENCODE3 (0x0102u, 0x0309u, 0x1EB2u), + HB_CODEPOINT_ENCODE3 (0x0103u, 0x0300u, 0x1EB1u), HB_CODEPOINT_ENCODE3 (0x0103u, 0x0301u, 0x1EAFu), + HB_CODEPOINT_ENCODE3 (0x0103u, 0x0303u, 0x1EB5u), HB_CODEPOINT_ENCODE3 (0x0103u, 0x0309u, 0x1EB3u), + HB_CODEPOINT_ENCODE3 (0x0112u, 0x0300u, 0x1E14u), HB_CODEPOINT_ENCODE3 (0x0112u, 0x0301u, 0x1E16u), + HB_CODEPOINT_ENCODE3 (0x0113u, 0x0300u, 0x1E15u), HB_CODEPOINT_ENCODE3 (0x0113u, 0x0301u, 0x1E17u), + HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0300u, 0x1E50u), HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0301u, 0x1E52u), + HB_CODEPOINT_ENCODE3 (0x014Du, 0x0300u, 0x1E51u), HB_CODEPOINT_ENCODE3 (0x014Du, 0x0301u, 0x1E53u), + HB_CODEPOINT_ENCODE3 (0x015Au, 0x0307u, 0x1E64u), HB_CODEPOINT_ENCODE3 (0x015Bu, 0x0307u, 0x1E65u), + HB_CODEPOINT_ENCODE3 (0x0160u, 0x0307u, 0x1E66u), HB_CODEPOINT_ENCODE3 (0x0161u, 0x0307u, 0x1E67u), + HB_CODEPOINT_ENCODE3 (0x0168u, 0x0301u, 0x1E78u), HB_CODEPOINT_ENCODE3 (0x0169u, 0x0301u, 0x1E79u), + HB_CODEPOINT_ENCODE3 (0x016Au, 0x0308u, 0x1E7Au), HB_CODEPOINT_ENCODE3 (0x016Bu, 0x0308u, 0x1E7Bu), + HB_CODEPOINT_ENCODE3 (0x017Fu, 0x0307u, 0x1E9Bu), HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0300u, 0x1EDCu), + HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0301u, 0x1EDAu), HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0303u, 0x1EE0u), + HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0309u, 0x1EDEu), HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0323u, 0x1EE2u), + HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0300u, 0x1EDDu), HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0301u, 0x1EDBu), + HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0303u, 0x1EE1u), HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0309u, 0x1EDFu), + HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0323u, 0x1EE3u), HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0300u, 0x1EEAu), + HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0301u, 0x1EE8u), HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0303u, 0x1EEEu), + HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0309u, 0x1EECu), HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0323u, 0x1EF0u), + HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0300u, 0x1EEBu), HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0301u, 0x1EE9u), + HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0303u, 0x1EEFu), HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0309u, 0x1EEDu), + HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0323u, 0x1EF1u), HB_CODEPOINT_ENCODE3 (0x01B7u, 0x030Cu, 0x01EEu), + HB_CODEPOINT_ENCODE3 (0x01EAu, 0x0304u, 0x01ECu), HB_CODEPOINT_ENCODE3 (0x01EBu, 0x0304u, 0x01EDu), + HB_CODEPOINT_ENCODE3 (0x0226u, 0x0304u, 0x01E0u), HB_CODEPOINT_ENCODE3 (0x0227u, 0x0304u, 0x01E1u), + HB_CODEPOINT_ENCODE3 (0x0228u, 0x0306u, 0x1E1Cu), HB_CODEPOINT_ENCODE3 (0x0229u, 0x0306u, 0x1E1Du), + HB_CODEPOINT_ENCODE3 (0x022Eu, 0x0304u, 0x0230u), HB_CODEPOINT_ENCODE3 (0x022Fu, 0x0304u, 0x0231u), + HB_CODEPOINT_ENCODE3 (0x0292u, 0x030Cu, 0x01EFu), HB_CODEPOINT_ENCODE3 (0x0308u, 0x0301u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0391u, 0x0300u, 0x1FBAu), HB_CODEPOINT_ENCODE3 (0x0391u, 0x0301u, 0x0386u), + HB_CODEPOINT_ENCODE3 (0x0391u, 0x0304u, 0x1FB9u), HB_CODEPOINT_ENCODE3 (0x0391u, 0x0306u, 0x1FB8u), + HB_CODEPOINT_ENCODE3 (0x0391u, 0x0313u, 0x1F08u), HB_CODEPOINT_ENCODE3 (0x0391u, 0x0314u, 0x1F09u), + HB_CODEPOINT_ENCODE3 (0x0391u, 0x0345u, 0x1FBCu), HB_CODEPOINT_ENCODE3 (0x0395u, 0x0300u, 0x1FC8u), + HB_CODEPOINT_ENCODE3 (0x0395u, 0x0301u, 0x0388u), HB_CODEPOINT_ENCODE3 (0x0395u, 0x0313u, 0x1F18u), + HB_CODEPOINT_ENCODE3 (0x0395u, 0x0314u, 0x1F19u), HB_CODEPOINT_ENCODE3 (0x0397u, 0x0300u, 0x1FCAu), + HB_CODEPOINT_ENCODE3 (0x0397u, 0x0301u, 0x0389u), HB_CODEPOINT_ENCODE3 (0x0397u, 0x0313u, 0x1F28u), + HB_CODEPOINT_ENCODE3 (0x0397u, 0x0314u, 0x1F29u), HB_CODEPOINT_ENCODE3 (0x0397u, 0x0345u, 0x1FCCu), + HB_CODEPOINT_ENCODE3 (0x0399u, 0x0300u, 0x1FDAu), HB_CODEPOINT_ENCODE3 (0x0399u, 0x0301u, 0x038Au), + HB_CODEPOINT_ENCODE3 (0x0399u, 0x0304u, 0x1FD9u), HB_CODEPOINT_ENCODE3 (0x0399u, 0x0306u, 0x1FD8u), + HB_CODEPOINT_ENCODE3 (0x0399u, 0x0308u, 0x03AAu), HB_CODEPOINT_ENCODE3 (0x0399u, 0x0313u, 0x1F38u), + HB_CODEPOINT_ENCODE3 (0x0399u, 0x0314u, 0x1F39u), HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0300u, 0x1FF8u), + HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0301u, 0x038Cu), HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0313u, 0x1F48u), + HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0314u, 0x1F49u), HB_CODEPOINT_ENCODE3 (0x03A1u, 0x0314u, 0x1FECu), + HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0300u, 0x1FEAu), HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0301u, 0x038Eu), + HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0304u, 0x1FE9u), HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0306u, 0x1FE8u), + HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0308u, 0x03ABu), HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0314u, 0x1F59u), + HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0300u, 0x1FFAu), HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0301u, 0x038Fu), + HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0313u, 0x1F68u), HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0314u, 0x1F69u), + HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0345u, 0x1FFCu), HB_CODEPOINT_ENCODE3 (0x03ACu, 0x0345u, 0x1FB4u), + HB_CODEPOINT_ENCODE3 (0x03AEu, 0x0345u, 0x1FC4u), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0300u, 0x1F70u), + HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0301u, 0x03ACu), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0304u, 0x1FB1u), + HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0306u, 0x1FB0u), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0313u, 0x1F00u), + HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0314u, 0x1F01u), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0342u, 0x1FB6u), + HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0345u, 0x1FB3u), HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0300u, 0x1F72u), + HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0301u, 0x03ADu), HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0313u, 0x1F10u), + HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0314u, 0x1F11u), HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0300u, 0x1F74u), + HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0301u, 0x03AEu), HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0313u, 0x1F20u), + HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0314u, 0x1F21u), HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0342u, 0x1FC6u), + HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0345u, 0x1FC3u), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0300u, 0x1F76u), + HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0301u, 0x03AFu), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0304u, 0x1FD1u), + HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0306u, 0x1FD0u), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0308u, 0x03CAu), + HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0313u, 0x1F30u), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0314u, 0x1F31u), + HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0342u, 0x1FD6u), HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0300u, 0x1F78u), + HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0301u, 0x03CCu), HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0313u, 0x1F40u), + HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0314u, 0x1F41u), HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0313u, 0x1FE4u), + HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0314u, 0x1FE5u), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0300u, 0x1F7Au), + HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0301u, 0x03CDu), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0304u, 0x1FE1u), + HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0306u, 0x1FE0u), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0308u, 0x03CBu), + HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0313u, 0x1F50u), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0314u, 0x1F51u), + HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0342u, 0x1FE6u), HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0300u, 0x1F7Cu), + HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0301u, 0x03CEu), HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0313u, 0x1F60u), + HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0314u, 0x1F61u), HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0342u, 0x1FF6u), + HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0345u, 0x1FF3u), HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0300u, 0x1FD2u), + HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0301u, 0x0390u), HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0342u, 0x1FD7u), + HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0300u, 0x1FE2u), HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0301u, 0x03B0u), + HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0342u, 0x1FE7u), HB_CODEPOINT_ENCODE3 (0x03CEu, 0x0345u, 0x1FF4u), + HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0301u, 0x03D3u), HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0308u, 0x03D4u), + HB_CODEPOINT_ENCODE3 (0x0406u, 0x0308u, 0x0407u), HB_CODEPOINT_ENCODE3 (0x0410u, 0x0306u, 0x04D0u), + HB_CODEPOINT_ENCODE3 (0x0410u, 0x0308u, 0x04D2u), HB_CODEPOINT_ENCODE3 (0x0413u, 0x0301u, 0x0403u), + HB_CODEPOINT_ENCODE3 (0x0415u, 0x0300u, 0x0400u), HB_CODEPOINT_ENCODE3 (0x0415u, 0x0306u, 0x04D6u), + HB_CODEPOINT_ENCODE3 (0x0415u, 0x0308u, 0x0401u), HB_CODEPOINT_ENCODE3 (0x0416u, 0x0306u, 0x04C1u), + HB_CODEPOINT_ENCODE3 (0x0416u, 0x0308u, 0x04DCu), HB_CODEPOINT_ENCODE3 (0x0417u, 0x0308u, 0x04DEu), + HB_CODEPOINT_ENCODE3 (0x0418u, 0x0300u, 0x040Du), HB_CODEPOINT_ENCODE3 (0x0418u, 0x0304u, 0x04E2u), + HB_CODEPOINT_ENCODE3 (0x0418u, 0x0306u, 0x0419u), HB_CODEPOINT_ENCODE3 (0x0418u, 0x0308u, 0x04E4u), + HB_CODEPOINT_ENCODE3 (0x041Au, 0x0301u, 0x040Cu), HB_CODEPOINT_ENCODE3 (0x041Eu, 0x0308u, 0x04E6u), + HB_CODEPOINT_ENCODE3 (0x0423u, 0x0304u, 0x04EEu), HB_CODEPOINT_ENCODE3 (0x0423u, 0x0306u, 0x040Eu), + HB_CODEPOINT_ENCODE3 (0x0423u, 0x0308u, 0x04F0u), HB_CODEPOINT_ENCODE3 (0x0423u, 0x030Bu, 0x04F2u), + HB_CODEPOINT_ENCODE3 (0x0427u, 0x0308u, 0x04F4u), HB_CODEPOINT_ENCODE3 (0x042Bu, 0x0308u, 0x04F8u), + HB_CODEPOINT_ENCODE3 (0x042Du, 0x0308u, 0x04ECu), HB_CODEPOINT_ENCODE3 (0x0430u, 0x0306u, 0x04D1u), + HB_CODEPOINT_ENCODE3 (0x0430u, 0x0308u, 0x04D3u), HB_CODEPOINT_ENCODE3 (0x0433u, 0x0301u, 0x0453u), + HB_CODEPOINT_ENCODE3 (0x0435u, 0x0300u, 0x0450u), HB_CODEPOINT_ENCODE3 (0x0435u, 0x0306u, 0x04D7u), + HB_CODEPOINT_ENCODE3 (0x0435u, 0x0308u, 0x0451u), HB_CODEPOINT_ENCODE3 (0x0436u, 0x0306u, 0x04C2u), + HB_CODEPOINT_ENCODE3 (0x0436u, 0x0308u, 0x04DDu), HB_CODEPOINT_ENCODE3 (0x0437u, 0x0308u, 0x04DFu), + HB_CODEPOINT_ENCODE3 (0x0438u, 0x0300u, 0x045Du), HB_CODEPOINT_ENCODE3 (0x0438u, 0x0304u, 0x04E3u), + HB_CODEPOINT_ENCODE3 (0x0438u, 0x0306u, 0x0439u), HB_CODEPOINT_ENCODE3 (0x0438u, 0x0308u, 0x04E5u), + HB_CODEPOINT_ENCODE3 (0x043Au, 0x0301u, 0x045Cu), HB_CODEPOINT_ENCODE3 (0x043Eu, 0x0308u, 0x04E7u), + HB_CODEPOINT_ENCODE3 (0x0443u, 0x0304u, 0x04EFu), HB_CODEPOINT_ENCODE3 (0x0443u, 0x0306u, 0x045Eu), + HB_CODEPOINT_ENCODE3 (0x0443u, 0x0308u, 0x04F1u), HB_CODEPOINT_ENCODE3 (0x0443u, 0x030Bu, 0x04F3u), + HB_CODEPOINT_ENCODE3 (0x0447u, 0x0308u, 0x04F5u), HB_CODEPOINT_ENCODE3 (0x044Bu, 0x0308u, 0x04F9u), + HB_CODEPOINT_ENCODE3 (0x044Du, 0x0308u, 0x04EDu), HB_CODEPOINT_ENCODE3 (0x0456u, 0x0308u, 0x0457u), + HB_CODEPOINT_ENCODE3 (0x0474u, 0x030Fu, 0x0476u), HB_CODEPOINT_ENCODE3 (0x0475u, 0x030Fu, 0x0477u), + HB_CODEPOINT_ENCODE3 (0x04D8u, 0x0308u, 0x04DAu), HB_CODEPOINT_ENCODE3 (0x04D9u, 0x0308u, 0x04DBu), + HB_CODEPOINT_ENCODE3 (0x04E8u, 0x0308u, 0x04EAu), HB_CODEPOINT_ENCODE3 (0x04E9u, 0x0308u, 0x04EBu), + HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BFu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D2u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05D3u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D4u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05B9u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05D6u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D8u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05B4u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05DAu, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BFu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05DCu, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05DEu, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05E0u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05E1u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05E3u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05E4u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05E4u, 0x05BFu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05E6u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05E7u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05E8u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05C1u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05C2u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x05EAu, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05F2u, 0x05B7u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0627u, 0x0653u, 0x0622u), HB_CODEPOINT_ENCODE3 (0x0627u, 0x0654u, 0x0623u), + HB_CODEPOINT_ENCODE3 (0x0627u, 0x0655u, 0x0625u), HB_CODEPOINT_ENCODE3 (0x0648u, 0x0654u, 0x0624u), + HB_CODEPOINT_ENCODE3 (0x064Au, 0x0654u, 0x0626u), HB_CODEPOINT_ENCODE3 (0x06C1u, 0x0654u, 0x06C2u), + HB_CODEPOINT_ENCODE3 (0x06D2u, 0x0654u, 0x06D3u), HB_CODEPOINT_ENCODE3 (0x06D5u, 0x0654u, 0x06C0u), + HB_CODEPOINT_ENCODE3 (0x0915u, 0x093Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0916u, 0x093Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0917u, 0x093Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x091Cu, 0x093Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0921u, 0x093Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0922u, 0x093Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0928u, 0x093Cu, 0x0929u), HB_CODEPOINT_ENCODE3 (0x092Bu, 0x093Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x092Fu, 0x093Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0930u, 0x093Cu, 0x0931u), + HB_CODEPOINT_ENCODE3 (0x0933u, 0x093Cu, 0x0934u), HB_CODEPOINT_ENCODE3 (0x09A1u, 0x09BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x09A2u, 0x09BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x09AFu, 0x09BCu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x09C7u, 0x09BEu, 0x09CBu), HB_CODEPOINT_ENCODE3 (0x09C7u, 0x09D7u, 0x09CCu), + HB_CODEPOINT_ENCODE3 (0x0A16u, 0x0A3Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0A17u, 0x0A3Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0A1Cu, 0x0A3Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0A2Bu, 0x0A3Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0A32u, 0x0A3Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0A38u, 0x0A3Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0B21u, 0x0B3Cu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0B22u, 0x0B3Cu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B3Eu, 0x0B4Bu), HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B56u, 0x0B48u), + HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B57u, 0x0B4Cu), HB_CODEPOINT_ENCODE3 (0x0B92u, 0x0BD7u, 0x0B94u), + HB_CODEPOINT_ENCODE3 (0x0BC6u, 0x0BBEu, 0x0BCAu), HB_CODEPOINT_ENCODE3 (0x0BC6u, 0x0BD7u, 0x0BCCu), + HB_CODEPOINT_ENCODE3 (0x0BC7u, 0x0BBEu, 0x0BCBu), HB_CODEPOINT_ENCODE3 (0x0C46u, 0x0C56u, 0x0C48u), + HB_CODEPOINT_ENCODE3 (0x0CBFu, 0x0CD5u, 0x0CC0u), HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CC2u, 0x0CCAu), + HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CD5u, 0x0CC7u), HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CD6u, 0x0CC8u), + HB_CODEPOINT_ENCODE3 (0x0CCAu, 0x0CD5u, 0x0CCBu), HB_CODEPOINT_ENCODE3 (0x0D46u, 0x0D3Eu, 0x0D4Au), + HB_CODEPOINT_ENCODE3 (0x0D46u, 0x0D57u, 0x0D4Cu), HB_CODEPOINT_ENCODE3 (0x0D47u, 0x0D3Eu, 0x0D4Bu), + HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DCAu, 0x0DDAu), HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DCFu, 0x0DDCu), + HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DDFu, 0x0DDEu), HB_CODEPOINT_ENCODE3 (0x0DDCu, 0x0DCAu, 0x0DDDu), + HB_CODEPOINT_ENCODE3 (0x0F40u, 0x0FB5u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0F42u, 0x0FB7u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0F4Cu, 0x0FB7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0F51u, 0x0FB7u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0F56u, 0x0FB7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0F5Bu, 0x0FB7u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F72u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F74u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F80u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0F90u, 0x0FB5u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0F92u, 0x0FB7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0F9Cu, 0x0FB7u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0FA1u, 0x0FB7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0FA6u, 0x0FB7u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0FABu, 0x0FB7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x0FB2u, 0x0F80u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x0FB3u, 0x0F80u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1025u, 0x102Eu, 0x1026u), + HB_CODEPOINT_ENCODE3 (0x1B05u, 0x1B35u, 0x1B06u), HB_CODEPOINT_ENCODE3 (0x1B07u, 0x1B35u, 0x1B08u), + HB_CODEPOINT_ENCODE3 (0x1B09u, 0x1B35u, 0x1B0Au), HB_CODEPOINT_ENCODE3 (0x1B0Bu, 0x1B35u, 0x1B0Cu), + HB_CODEPOINT_ENCODE3 (0x1B0Du, 0x1B35u, 0x1B0Eu), HB_CODEPOINT_ENCODE3 (0x1B11u, 0x1B35u, 0x1B12u), + HB_CODEPOINT_ENCODE3 (0x1B3Au, 0x1B35u, 0x1B3Bu), HB_CODEPOINT_ENCODE3 (0x1B3Cu, 0x1B35u, 0x1B3Du), + HB_CODEPOINT_ENCODE3 (0x1B3Eu, 0x1B35u, 0x1B40u), HB_CODEPOINT_ENCODE3 (0x1B3Fu, 0x1B35u, 0x1B41u), + HB_CODEPOINT_ENCODE3 (0x1B42u, 0x1B35u, 0x1B43u), HB_CODEPOINT_ENCODE3 (0x1E36u, 0x0304u, 0x1E38u), + HB_CODEPOINT_ENCODE3 (0x1E37u, 0x0304u, 0x1E39u), HB_CODEPOINT_ENCODE3 (0x1E5Au, 0x0304u, 0x1E5Cu), + HB_CODEPOINT_ENCODE3 (0x1E5Bu, 0x0304u, 0x1E5Du), HB_CODEPOINT_ENCODE3 (0x1E62u, 0x0307u, 0x1E68u), + HB_CODEPOINT_ENCODE3 (0x1E63u, 0x0307u, 0x1E69u), HB_CODEPOINT_ENCODE3 (0x1EA0u, 0x0302u, 0x1EACu), + HB_CODEPOINT_ENCODE3 (0x1EA0u, 0x0306u, 0x1EB6u), HB_CODEPOINT_ENCODE3 (0x1EA1u, 0x0302u, 0x1EADu), + HB_CODEPOINT_ENCODE3 (0x1EA1u, 0x0306u, 0x1EB7u), HB_CODEPOINT_ENCODE3 (0x1EB8u, 0x0302u, 0x1EC6u), + HB_CODEPOINT_ENCODE3 (0x1EB9u, 0x0302u, 0x1EC7u), HB_CODEPOINT_ENCODE3 (0x1ECCu, 0x0302u, 0x1ED8u), + HB_CODEPOINT_ENCODE3 (0x1ECDu, 0x0302u, 0x1ED9u), HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0300u, 0x1F02u), + HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0301u, 0x1F04u), HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0342u, 0x1F06u), + HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0345u, 0x1F80u), HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0300u, 0x1F03u), + HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0301u, 0x1F05u), HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0342u, 0x1F07u), + HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0345u, 0x1F81u), HB_CODEPOINT_ENCODE3 (0x1F02u, 0x0345u, 0x1F82u), + HB_CODEPOINT_ENCODE3 (0x1F03u, 0x0345u, 0x1F83u), HB_CODEPOINT_ENCODE3 (0x1F04u, 0x0345u, 0x1F84u), + HB_CODEPOINT_ENCODE3 (0x1F05u, 0x0345u, 0x1F85u), HB_CODEPOINT_ENCODE3 (0x1F06u, 0x0345u, 0x1F86u), + HB_CODEPOINT_ENCODE3 (0x1F07u, 0x0345u, 0x1F87u), HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0300u, 0x1F0Au), + HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0301u, 0x1F0Cu), HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0342u, 0x1F0Eu), + HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0345u, 0x1F88u), HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0300u, 0x1F0Bu), + HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0301u, 0x1F0Du), HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0342u, 0x1F0Fu), + HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0345u, 0x1F89u), HB_CODEPOINT_ENCODE3 (0x1F0Au, 0x0345u, 0x1F8Au), + HB_CODEPOINT_ENCODE3 (0x1F0Bu, 0x0345u, 0x1F8Bu), HB_CODEPOINT_ENCODE3 (0x1F0Cu, 0x0345u, 0x1F8Cu), + HB_CODEPOINT_ENCODE3 (0x1F0Du, 0x0345u, 0x1F8Du), HB_CODEPOINT_ENCODE3 (0x1F0Eu, 0x0345u, 0x1F8Eu), + HB_CODEPOINT_ENCODE3 (0x1F0Fu, 0x0345u, 0x1F8Fu), HB_CODEPOINT_ENCODE3 (0x1F10u, 0x0300u, 0x1F12u), + HB_CODEPOINT_ENCODE3 (0x1F10u, 0x0301u, 0x1F14u), HB_CODEPOINT_ENCODE3 (0x1F11u, 0x0300u, 0x1F13u), + HB_CODEPOINT_ENCODE3 (0x1F11u, 0x0301u, 0x1F15u), HB_CODEPOINT_ENCODE3 (0x1F18u, 0x0300u, 0x1F1Au), + HB_CODEPOINT_ENCODE3 (0x1F18u, 0x0301u, 0x1F1Cu), HB_CODEPOINT_ENCODE3 (0x1F19u, 0x0300u, 0x1F1Bu), + HB_CODEPOINT_ENCODE3 (0x1F19u, 0x0301u, 0x1F1Du), HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0300u, 0x1F22u), + HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0301u, 0x1F24u), HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0342u, 0x1F26u), + HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0345u, 0x1F90u), HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0300u, 0x1F23u), + HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0301u, 0x1F25u), HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0342u, 0x1F27u), + HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0345u, 0x1F91u), HB_CODEPOINT_ENCODE3 (0x1F22u, 0x0345u, 0x1F92u), + HB_CODEPOINT_ENCODE3 (0x1F23u, 0x0345u, 0x1F93u), HB_CODEPOINT_ENCODE3 (0x1F24u, 0x0345u, 0x1F94u), + HB_CODEPOINT_ENCODE3 (0x1F25u, 0x0345u, 0x1F95u), HB_CODEPOINT_ENCODE3 (0x1F26u, 0x0345u, 0x1F96u), + HB_CODEPOINT_ENCODE3 (0x1F27u, 0x0345u, 0x1F97u), HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0300u, 0x1F2Au), + HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0301u, 0x1F2Cu), HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0342u, 0x1F2Eu), + HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0345u, 0x1F98u), HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0300u, 0x1F2Bu), + HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0301u, 0x1F2Du), HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0342u, 0x1F2Fu), + HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0345u, 0x1F99u), HB_CODEPOINT_ENCODE3 (0x1F2Au, 0x0345u, 0x1F9Au), + HB_CODEPOINT_ENCODE3 (0x1F2Bu, 0x0345u, 0x1F9Bu), HB_CODEPOINT_ENCODE3 (0x1F2Cu, 0x0345u, 0x1F9Cu), + HB_CODEPOINT_ENCODE3 (0x1F2Du, 0x0345u, 0x1F9Du), HB_CODEPOINT_ENCODE3 (0x1F2Eu, 0x0345u, 0x1F9Eu), + HB_CODEPOINT_ENCODE3 (0x1F2Fu, 0x0345u, 0x1F9Fu), HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0300u, 0x1F32u), + HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0301u, 0x1F34u), HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0342u, 0x1F36u), + HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0300u, 0x1F33u), HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0301u, 0x1F35u), + HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0342u, 0x1F37u), HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0300u, 0x1F3Au), + HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0301u, 0x1F3Cu), HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0342u, 0x1F3Eu), + HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0300u, 0x1F3Bu), HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0301u, 0x1F3Du), + HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0342u, 0x1F3Fu), HB_CODEPOINT_ENCODE3 (0x1F40u, 0x0300u, 0x1F42u), + HB_CODEPOINT_ENCODE3 (0x1F40u, 0x0301u, 0x1F44u), HB_CODEPOINT_ENCODE3 (0x1F41u, 0x0300u, 0x1F43u), + HB_CODEPOINT_ENCODE3 (0x1F41u, 0x0301u, 0x1F45u), HB_CODEPOINT_ENCODE3 (0x1F48u, 0x0300u, 0x1F4Au), + HB_CODEPOINT_ENCODE3 (0x1F48u, 0x0301u, 0x1F4Cu), HB_CODEPOINT_ENCODE3 (0x1F49u, 0x0300u, 0x1F4Bu), + HB_CODEPOINT_ENCODE3 (0x1F49u, 0x0301u, 0x1F4Du), HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0300u, 0x1F52u), + HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0301u, 0x1F54u), HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0342u, 0x1F56u), + HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0300u, 0x1F53u), HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0301u, 0x1F55u), + HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0342u, 0x1F57u), HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0300u, 0x1F5Bu), + HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0301u, 0x1F5Du), HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0342u, 0x1F5Fu), + HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0300u, 0x1F62u), HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0301u, 0x1F64u), + HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0342u, 0x1F66u), HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0345u, 0x1FA0u), + HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0300u, 0x1F63u), HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0301u, 0x1F65u), + HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0342u, 0x1F67u), HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0345u, 0x1FA1u), + HB_CODEPOINT_ENCODE3 (0x1F62u, 0x0345u, 0x1FA2u), HB_CODEPOINT_ENCODE3 (0x1F63u, 0x0345u, 0x1FA3u), + HB_CODEPOINT_ENCODE3 (0x1F64u, 0x0345u, 0x1FA4u), HB_CODEPOINT_ENCODE3 (0x1F65u, 0x0345u, 0x1FA5u), + HB_CODEPOINT_ENCODE3 (0x1F66u, 0x0345u, 0x1FA6u), HB_CODEPOINT_ENCODE3 (0x1F67u, 0x0345u, 0x1FA7u), + HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0300u, 0x1F6Au), HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0301u, 0x1F6Cu), + HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0342u, 0x1F6Eu), HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0345u, 0x1FA8u), + HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0300u, 0x1F6Bu), HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0301u, 0x1F6Du), + HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0342u, 0x1F6Fu), HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0345u, 0x1FA9u), + HB_CODEPOINT_ENCODE3 (0x1F6Au, 0x0345u, 0x1FAAu), HB_CODEPOINT_ENCODE3 (0x1F6Bu, 0x0345u, 0x1FABu), + HB_CODEPOINT_ENCODE3 (0x1F6Cu, 0x0345u, 0x1FACu), HB_CODEPOINT_ENCODE3 (0x1F6Du, 0x0345u, 0x1FADu), + HB_CODEPOINT_ENCODE3 (0x1F6Eu, 0x0345u, 0x1FAEu), HB_CODEPOINT_ENCODE3 (0x1F6Fu, 0x0345u, 0x1FAFu), + HB_CODEPOINT_ENCODE3 (0x1F70u, 0x0345u, 0x1FB2u), HB_CODEPOINT_ENCODE3 (0x1F74u, 0x0345u, 0x1FC2u), + HB_CODEPOINT_ENCODE3 (0x1F7Cu, 0x0345u, 0x1FF2u), HB_CODEPOINT_ENCODE3 (0x1FB6u, 0x0345u, 0x1FB7u), + HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0300u, 0x1FCDu), HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0301u, 0x1FCEu), + HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0342u, 0x1FCFu), HB_CODEPOINT_ENCODE3 (0x1FC6u, 0x0345u, 0x1FC7u), + HB_CODEPOINT_ENCODE3 (0x1FF6u, 0x0345u, 0x1FF7u), HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0300u, 0x1FDDu), + HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0301u, 0x1FDEu), HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0342u, 0x1FDFu), + HB_CODEPOINT_ENCODE3 (0x2190u, 0x0338u, 0x219Au), HB_CODEPOINT_ENCODE3 (0x2192u, 0x0338u, 0x219Bu), + HB_CODEPOINT_ENCODE3 (0x2194u, 0x0338u, 0x21AEu), HB_CODEPOINT_ENCODE3 (0x21D0u, 0x0338u, 0x21CDu), + HB_CODEPOINT_ENCODE3 (0x21D2u, 0x0338u, 0x21CFu), HB_CODEPOINT_ENCODE3 (0x21D4u, 0x0338u, 0x21CEu), + HB_CODEPOINT_ENCODE3 (0x2203u, 0x0338u, 0x2204u), HB_CODEPOINT_ENCODE3 (0x2208u, 0x0338u, 0x2209u), + HB_CODEPOINT_ENCODE3 (0x220Bu, 0x0338u, 0x220Cu), HB_CODEPOINT_ENCODE3 (0x2223u, 0x0338u, 0x2224u), + HB_CODEPOINT_ENCODE3 (0x2225u, 0x0338u, 0x2226u), HB_CODEPOINT_ENCODE3 (0x223Cu, 0x0338u, 0x2241u), + HB_CODEPOINT_ENCODE3 (0x2243u, 0x0338u, 0x2244u), HB_CODEPOINT_ENCODE3 (0x2245u, 0x0338u, 0x2247u), + HB_CODEPOINT_ENCODE3 (0x2248u, 0x0338u, 0x2249u), HB_CODEPOINT_ENCODE3 (0x224Du, 0x0338u, 0x226Du), + HB_CODEPOINT_ENCODE3 (0x2261u, 0x0338u, 0x2262u), HB_CODEPOINT_ENCODE3 (0x2264u, 0x0338u, 0x2270u), + HB_CODEPOINT_ENCODE3 (0x2265u, 0x0338u, 0x2271u), HB_CODEPOINT_ENCODE3 (0x2272u, 0x0338u, 0x2274u), + HB_CODEPOINT_ENCODE3 (0x2273u, 0x0338u, 0x2275u), HB_CODEPOINT_ENCODE3 (0x2276u, 0x0338u, 0x2278u), + HB_CODEPOINT_ENCODE3 (0x2277u, 0x0338u, 0x2279u), HB_CODEPOINT_ENCODE3 (0x227Au, 0x0338u, 0x2280u), + HB_CODEPOINT_ENCODE3 (0x227Bu, 0x0338u, 0x2281u), HB_CODEPOINT_ENCODE3 (0x227Cu, 0x0338u, 0x22E0u), + HB_CODEPOINT_ENCODE3 (0x227Du, 0x0338u, 0x22E1u), HB_CODEPOINT_ENCODE3 (0x2282u, 0x0338u, 0x2284u), + HB_CODEPOINT_ENCODE3 (0x2283u, 0x0338u, 0x2285u), HB_CODEPOINT_ENCODE3 (0x2286u, 0x0338u, 0x2288u), + HB_CODEPOINT_ENCODE3 (0x2287u, 0x0338u, 0x2289u), HB_CODEPOINT_ENCODE3 (0x2291u, 0x0338u, 0x22E2u), + HB_CODEPOINT_ENCODE3 (0x2292u, 0x0338u, 0x22E3u), HB_CODEPOINT_ENCODE3 (0x22A2u, 0x0338u, 0x22ACu), + HB_CODEPOINT_ENCODE3 (0x22A8u, 0x0338u, 0x22ADu), HB_CODEPOINT_ENCODE3 (0x22A9u, 0x0338u, 0x22AEu), + HB_CODEPOINT_ENCODE3 (0x22ABu, 0x0338u, 0x22AFu), HB_CODEPOINT_ENCODE3 (0x22B2u, 0x0338u, 0x22EAu), + HB_CODEPOINT_ENCODE3 (0x22B3u, 0x0338u, 0x22EBu), HB_CODEPOINT_ENCODE3 (0x22B4u, 0x0338u, 0x22ECu), + HB_CODEPOINT_ENCODE3 (0x22B5u, 0x0338u, 0x22EDu), HB_CODEPOINT_ENCODE3 (0x2ADDu, 0x0338u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x3046u, 0x3099u, 0x3094u), HB_CODEPOINT_ENCODE3 (0x304Bu, 0x3099u, 0x304Cu), + HB_CODEPOINT_ENCODE3 (0x304Du, 0x3099u, 0x304Eu), HB_CODEPOINT_ENCODE3 (0x304Fu, 0x3099u, 0x3050u), + HB_CODEPOINT_ENCODE3 (0x3051u, 0x3099u, 0x3052u), HB_CODEPOINT_ENCODE3 (0x3053u, 0x3099u, 0x3054u), + HB_CODEPOINT_ENCODE3 (0x3055u, 0x3099u, 0x3056u), HB_CODEPOINT_ENCODE3 (0x3057u, 0x3099u, 0x3058u), + HB_CODEPOINT_ENCODE3 (0x3059u, 0x3099u, 0x305Au), HB_CODEPOINT_ENCODE3 (0x305Bu, 0x3099u, 0x305Cu), + HB_CODEPOINT_ENCODE3 (0x305Du, 0x3099u, 0x305Eu), HB_CODEPOINT_ENCODE3 (0x305Fu, 0x3099u, 0x3060u), + HB_CODEPOINT_ENCODE3 (0x3061u, 0x3099u, 0x3062u), HB_CODEPOINT_ENCODE3 (0x3064u, 0x3099u, 0x3065u), + HB_CODEPOINT_ENCODE3 (0x3066u, 0x3099u, 0x3067u), HB_CODEPOINT_ENCODE3 (0x3068u, 0x3099u, 0x3069u), + HB_CODEPOINT_ENCODE3 (0x306Fu, 0x3099u, 0x3070u), HB_CODEPOINT_ENCODE3 (0x306Fu, 0x309Au, 0x3071u), + HB_CODEPOINT_ENCODE3 (0x3072u, 0x3099u, 0x3073u), HB_CODEPOINT_ENCODE3 (0x3072u, 0x309Au, 0x3074u), + HB_CODEPOINT_ENCODE3 (0x3075u, 0x3099u, 0x3076u), HB_CODEPOINT_ENCODE3 (0x3075u, 0x309Au, 0x3077u), + HB_CODEPOINT_ENCODE3 (0x3078u, 0x3099u, 0x3079u), HB_CODEPOINT_ENCODE3 (0x3078u, 0x309Au, 0x307Au), + HB_CODEPOINT_ENCODE3 (0x307Bu, 0x3099u, 0x307Cu), HB_CODEPOINT_ENCODE3 (0x307Bu, 0x309Au, 0x307Du), + HB_CODEPOINT_ENCODE3 (0x309Du, 0x3099u, 0x309Eu), HB_CODEPOINT_ENCODE3 (0x30A6u, 0x3099u, 0x30F4u), + HB_CODEPOINT_ENCODE3 (0x30ABu, 0x3099u, 0x30ACu), HB_CODEPOINT_ENCODE3 (0x30ADu, 0x3099u, 0x30AEu), + HB_CODEPOINT_ENCODE3 (0x30AFu, 0x3099u, 0x30B0u), HB_CODEPOINT_ENCODE3 (0x30B1u, 0x3099u, 0x30B2u), + HB_CODEPOINT_ENCODE3 (0x30B3u, 0x3099u, 0x30B4u), HB_CODEPOINT_ENCODE3 (0x30B5u, 0x3099u, 0x30B6u), + HB_CODEPOINT_ENCODE3 (0x30B7u, 0x3099u, 0x30B8u), HB_CODEPOINT_ENCODE3 (0x30B9u, 0x3099u, 0x30BAu), + HB_CODEPOINT_ENCODE3 (0x30BBu, 0x3099u, 0x30BCu), HB_CODEPOINT_ENCODE3 (0x30BDu, 0x3099u, 0x30BEu), + HB_CODEPOINT_ENCODE3 (0x30BFu, 0x3099u, 0x30C0u), HB_CODEPOINT_ENCODE3 (0x30C1u, 0x3099u, 0x30C2u), + HB_CODEPOINT_ENCODE3 (0x30C4u, 0x3099u, 0x30C5u), HB_CODEPOINT_ENCODE3 (0x30C6u, 0x3099u, 0x30C7u), + HB_CODEPOINT_ENCODE3 (0x30C8u, 0x3099u, 0x30C9u), HB_CODEPOINT_ENCODE3 (0x30CFu, 0x3099u, 0x30D0u), + HB_CODEPOINT_ENCODE3 (0x30CFu, 0x309Au, 0x30D1u), HB_CODEPOINT_ENCODE3 (0x30D2u, 0x3099u, 0x30D3u), + HB_CODEPOINT_ENCODE3 (0x30D2u, 0x309Au, 0x30D4u), HB_CODEPOINT_ENCODE3 (0x30D5u, 0x3099u, 0x30D6u), + HB_CODEPOINT_ENCODE3 (0x30D5u, 0x309Au, 0x30D7u), HB_CODEPOINT_ENCODE3 (0x30D8u, 0x3099u, 0x30D9u), + HB_CODEPOINT_ENCODE3 (0x30D8u, 0x309Au, 0x30DAu), HB_CODEPOINT_ENCODE3 (0x30DBu, 0x3099u, 0x30DCu), + HB_CODEPOINT_ENCODE3 (0x30DBu, 0x309Au, 0x30DDu), HB_CODEPOINT_ENCODE3 (0x30EFu, 0x3099u, 0x30F7u), + HB_CODEPOINT_ENCODE3 (0x30F0u, 0x3099u, 0x30F8u), HB_CODEPOINT_ENCODE3 (0x30F1u, 0x3099u, 0x30F9u), + HB_CODEPOINT_ENCODE3 (0x30F2u, 0x3099u, 0x30FAu), HB_CODEPOINT_ENCODE3 (0x30FDu, 0x3099u, 0x30FEu), + HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C1u, 0x0000u), HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C2u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x11099u, 0x110BAu, 0x1109Au),HB_CODEPOINT_ENCODE3 (0x1109Bu, 0x110BAu, 0x1109Cu), + HB_CODEPOINT_ENCODE3 (0x110A5u, 0x110BAu, 0x110ABu),HB_CODEPOINT_ENCODE3 (0x11131u, 0x11127u, 0x1112Eu), + HB_CODEPOINT_ENCODE3 (0x11132u, 0x11127u, 0x1112Fu),HB_CODEPOINT_ENCODE3 (0x11347u, 0x1133Eu, 0x1134Bu), + HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu), + HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu), + HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu), + HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D158u, 0x1D165u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Eu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Fu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D170u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D171u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D172u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1B9u, 0x1D165u, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x1D1BAu, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Eu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Eu, 0x0000u), + HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Fu, 0x0000u), +}; + +#ifndef HB_OPTIMIZE_SIZE + +static const uint8_t +_hb_ucd_u8[31814] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28, + 29, 26, 30, 31, 32, 33, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 34, 35, 35, 35, 35, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 26, 57, 58, 59, 59, 59, 59, 59, 26, 26, 60, 59, 59, 59, 59, 59, + 59, 59, 26, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 26, 62, 59, 63, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 64, 26, 65, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 66, 67, 59, 59, 59, 59, 68, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 69, 70, 71, 72, 73, 74, 59, 59, + 75, 76, 59, 59, 77, 59, 78, 79, 80, 81, 73, 82, 83, 84, 59, 59, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 85, 26, 26, 26, 26, 26, 26, 26, 86, 87, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 88, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 89, 59, 59, 59, 59, 59, 59, 26, 90, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 91, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 92, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 93, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21, + 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 21, 18, 24, 16, + 24, 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, 22, 25, 18, 25, 0, + 29, 21, 23, 23, 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, + 26, 25, 15, 15, 24, 5, 21, 21, 24, 15, 7, 19, 15, 15, 15, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 5, 5, + 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, + 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, + 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 9, 5, 5, + 5, 9, 9, 5, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 9, 9, + 9, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 5, 9, 9, 5, 9, + 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 5, 9, 5, 9, 9, + 5, 9, 9, 9, 5, 9, 5, 9, 9, 5, 5, 7, 9, 5, 5, 5, + 7, 7, 7, 7, 9, 8, 5, 9, 8, 5, 9, 8, 5, 9, 5, 9, + 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, + 5, 9, 8, 5, 9, 5, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, + 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 9, 9, 5, 9, 9, 5, + 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 5, 5, 5, 5, 7, 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, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 6, 6, 6, 6, 6, 24, 24, 24, 24, 24, 24, 24, 6, 24, 6, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 9, 5, 9, 5, 6, 24, 9, 5, 2, 2, 6, 5, 5, 5, 21, 9, + 2, 2, 2, 2, 24, 24, 9, 21, 9, 9, 9, 2, 9, 2, 9, 9, + 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, + 5, 5, 9, 9, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 5, 5, 5, 5, 9, 5, 25, 9, 5, 9, 9, 5, 5, 9, 9, 9, + 9, 5, 26, 12, 12, 12, 12, 12, 11, 11, 9, 5, 9, 5, 9, 5, + 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, + 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 2, 2, 6, 21, 21, 21, 21, 21, 21, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 17, 2, 2, 26, 26, 23, + 2, 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, 17, 12, + 21, 12, 12, 21, 12, 12, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 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, 2, 2, 2, 2, 7, + 7, 7, 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 1, 2, 21, 21, + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 7, 7, + 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 21, 7, 12, 12, 12, 12, 12, 12, 12, 1, 26, 12, + 12, 12, 12, 12, 12, 6, 6, 12, 12, 26, 12, 12, 12, 12, 7, 7, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 26, 26, 7, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 1, + 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 6, 6, 26, 21, 21, 21, 6, 2, 2, 12, 23, 23, + 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 6, 12, 12, 12, 6, 12, 12, 12, 12, 12, 2, 2, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 2, 2, 21, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, + 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 7, 10, 10, + 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10, + 7, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 21, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, + 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, + 7, 2, 7, 2, 2, 2, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10, + 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 7, 2, + 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 7, 7, 2, 7, + 7, 7, 12, 12, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 7, 7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23, 7, 21, 12, 2, + 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, + 7, 2, 7, 7, 2, 7, 7, 2, 7, 7, 2, 2, 12, 2, 10, 10, + 10, 12, 12, 2, 2, 2, 2, 12, 12, 2, 2, 12, 12, 12, 2, 2, + 2, 12, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 2, 7, 2, + 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 12, 12, 7, 7, 7, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, + 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10, + 10, 12, 12, 12, 12, 12, 2, 12, 12, 10, 2, 10, 10, 12, 2, 2, + 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 21, 23, 2, 2, 2, 2, 2, 2, 2, 7, 12, 12, 12, 12, 12, 12, + 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, + 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12, + 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 2, 2, + 2, 2, 2, 2, 2, 2, 12, 10, 2, 2, 2, 2, 7, 7, 2, 7, + 26, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 12, 7, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, + 7, 2, 7, 7, 7, 7, 2, 2, 2, 7, 7, 2, 7, 2, 7, 7, + 2, 2, 2, 7, 7, 2, 2, 2, 7, 7, 7, 2, 2, 2, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 10, 10, + 12, 10, 10, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 12, 2, 2, + 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, + 15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26, 2, 2, 2, 2, 2, + 12, 10, 10, 10, 12, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, + 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 12, 12, + 12, 10, 10, 10, 10, 2, 12, 12, 12, 2, 12, 12, 12, 12, 2, 2, + 2, 2, 2, 2, 2, 12, 12, 2, 7, 7, 7, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 21, 15, 15, 15, 15, 15, 15, 15, 26, + 7, 12, 10, 10, 21, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, + 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12, + 10, 10, 10, 10, 10, 2, 12, 10, 10, 2, 10, 10, 12, 12, 2, 2, + 2, 2, 2, 2, 2, 10, 10, 2, 2, 2, 2, 2, 2, 2, 7, 2, + 2, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 12, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 7, 10, 10, + 10, 12, 12, 12, 12, 2, 10, 10, 10, 2, 10, 10, 10, 12, 7, 26, + 2, 2, 2, 2, 7, 7, 7, 10, 15, 15, 15, 15, 15, 15, 15, 7, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 7, 7, 7, 7, 7, 7, + 2, 2, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, 7, 7, 7, 7, + 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 12, 2, 2, 2, 2, 10, + 10, 10, 12, 12, 12, 2, 12, 2, 10, 10, 10, 10, 10, 10, 10, 10, + 2, 2, 10, 10, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 23, + 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12, 12, 12, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 2, 2, 2, + 2, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, + 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 2, 2, + 7, 7, 7, 7, 7, 2, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 7, 7, 7, 7, + 7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, + 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, + 12, 12, 12, 12, 12, 21, 12, 12, 7, 7, 7, 7, 7, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 26, 26, + 26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 2, 26, 26, + 21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 12, + 12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12, 7, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21, + 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 7, 7, 7, 7, 12, 12, + 12, 7, 10, 10, 10, 7, 7, 10, 10, 10, 10, 10, 10, 10, 7, 7, + 7, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12, 7, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26, + 9, 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 2, 2, 9, 2, 2, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 6, 5, 5, 5, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 2, + 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 2, + 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, + 9, 9, 9, 9, 9, 9, 2, 2, 5, 5, 5, 5, 5, 5, 2, 2, + 17, 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, 26, 21, 7, + 29, 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, 22, 18, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 21, 21, 14, 14, + 14, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, + 7, 7, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 12, 12, 12, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 2, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10, + 10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 21, 21, 21, 6, 21, 21, 21, 23, 7, 12, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, + 21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12, 1, 2, + 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 7, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, + 12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10, 2, 2, 2, 2, + 10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12, 2, 2, 2, 2, + 26, 2, 2, 2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, + 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 2, 2, 2, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 7, 7, 7, 7, 7, 7, 7, 12, 12, 10, 10, 12, 2, 2, 21, 21, + 7, 7, 7, 7, 7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12, 2, + 12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, + 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, + 21, 21, 21, 21, 21, 21, 21, 6, 21, 21, 21, 21, 21, 21, 2, 2, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 2, + 12, 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, + 10, 10, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, + 21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, + 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12, 7, 7, + 7, 7, 7, 7, 7, 7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12, + 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, + 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, + 12, 12, 12, 12, 10, 10, 12, 12, 2, 2, 2, 21, 21, 21, 21, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 21, 21, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, + 12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 10, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 12, 7, 7, + 7, 7, 7, 7, 12, 7, 7, 10, 12, 12, 7, 2, 2, 2, 2, 2, + 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, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, + 9, 5, 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, + 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2, + 5, 5, 5, 5, 5, 5, 5, 5, 2, 9, 2, 9, 2, 9, 2, 9, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, + 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8, + 5, 5, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 5, 24, + 24, 24, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 24, + 5, 5, 5, 5, 2, 2, 5, 5, 9, 9, 9, 9, 2, 24, 24, 24, + 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 24, 24, 24, + 2, 2, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 2, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 27, 28, 1, 1, 1, 1, 1, 29, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16, + 16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 15, 6, 2, 2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 6, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 2, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, + 11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 9, 26, 26, 26, 26, 9, 26, 26, 5, 9, 9, 9, 5, 5, + 9, 9, 9, 5, 26, 9, 26, 26, 25, 9, 9, 9, 9, 9, 26, 26, + 26, 26, 26, 26, 9, 26, 9, 26, 9, 26, 9, 9, 9, 9, 26, 5, + 9, 9, 9, 9, 5, 7, 7, 7, 7, 5, 26, 26, 5, 5, 9, 9, + 25, 25, 25, 25, 25, 9, 5, 5, 5, 5, 26, 25, 26, 26, 5, 26, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 9, 5, 14, 14, 14, 14, 15, 26, 26, 2, 2, 2, 2, + 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26, + 25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, + 26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26, + 25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, + 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, + 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, + 22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, + 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, + 18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25, + 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26, + 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, + 9, 5, 9, 9, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, + 9, 5, 9, 5, 5, 9, 5, 5, 5, 5, 5, 5, 6, 6, 9, 9, + 9, 5, 9, 5, 5, 26, 26, 26, 26, 26, 26, 9, 5, 9, 5, 12, + 12, 12, 9, 5, 2, 2, 2, 2, 2, 21, 21, 21, 21, 15, 21, 21, + 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 6, + 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, + 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 2, + 21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21, + 20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21, 6, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21, + 17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, + 29, 21, 21, 21, 26, 6, 7, 14, 22, 18, 22, 18, 22, 18, 22, 18, + 22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18, + 26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10, + 17, 6, 6, 6, 6, 6, 26, 26, 14, 14, 14, 6, 7, 21, 26, 26, + 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 24, 24, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 6, 6, 6, 7, + 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 26, 26, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15, + 26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 21, 21, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 2, 2, 2, 2, + 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 7, 12, + 11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 6, + 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6, 6, 12, 12, + 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 12, 12, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, + 24, 24, 24, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 24, 24, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 6, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, 9, 5, 9, 9, 5, + 9, 5, 9, 5, 9, 5, 9, 5, 6, 24, 24, 9, 5, 9, 5, 7, + 9, 5, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, 9, 9, 5, + 9, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, + 2, 2, 9, 5, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 7, 6, 6, 5, 7, 7, 7, 7, 7, + 7, 7, 12, 7, 7, 7, 12, 7, 7, 7, 7, 12, 7, 7, 7, 7, + 7, 7, 7, 10, 10, 12, 12, 10, 26, 26, 26, 26, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 15, 26, 26, 23, 26, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, + 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, + 12, 12, 7, 7, 7, 7, 7, 7, 21, 21, 21, 7, 21, 7, 7, 12, + 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21, + 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, + 7, 7, 7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10, + 10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 6, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 21, 21, + 7, 7, 7, 7, 7, 12, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, + 10, 12, 12, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 21, 21, 21, 21, + 6, 7, 7, 7, 7, 7, 7, 26, 26, 26, 7, 10, 12, 10, 7, 7, + 12, 7, 12, 12, 12, 7, 7, 12, 12, 7, 7, 7, 7, 7, 12, 12, + 7, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 6, 21, 21, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 12, 12, 10, 10, + 21, 21, 7, 6, 6, 10, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 2, + 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12, 2, 2, + 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 7, 12, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 25, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 2, + 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 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, 18, 22, + 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 23, 26, 2, 2, + 21, 21, 21, 21, 21, 21, 21, 22, 18, 21, 2, 2, 2, 2, 2, 2, + 21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, + 18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16, + 21, 21, 21, 2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21, + 21, 21, 25, 17, 25, 25, 25, 2, 21, 23, 21, 21, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 1, + 2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 22, + 18, 21, 22, 18, 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 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, 6, 6, + 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, + 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 2, 2, 2, + 23, 23, 25, 24, 26, 23, 23, 2, 26, 25, 25, 25, 25, 26, 26, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 26, 26, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, + 21, 21, 21, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26, 2, + 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 2, 2, + 12, 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, 2, 2, 2, 2, + 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, + 7, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 21, + 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, + 21, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, + 9, 9, 9, 9, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, + 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, + 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 2, 2, 7, 2, 2, 7, + 7, 7, 7, 7, 7, 7, 2, 21, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 7, 7, 7, 7, 26, 26, 15, 15, 15, 15, 15, 15, 15, + 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 2, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, + 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 21, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 21, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 15, 15, 7, 7, + 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 12, 12, 12, 2, 12, 12, 2, 2, 2, 2, 2, 12, 12, 12, 12, + 7, 7, 7, 7, 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, 2, 2, 2, 2, 12, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 21, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, + 7, 7, 7, 7, 7, 7, 7, 7, 26, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 12, 12, 2, 2, 2, 2, 15, 15, 15, 15, 15, + 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 2, 2, 2, 21, 21, 21, 21, 21, 21, 21, + 7, 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, + 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 7, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, + 15, 15, 15, 15, 15, 15, 15, 7, 2, 2, 2, 2, 2, 2, 2, 2, + 12, 15, 15, 15, 15, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, + 10, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21, 2, 2, + 15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, + 10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21, 1, 21, 21, + 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, + 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 10, 12, 12, 12, + 12, 12, 12, 12, 12, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 21, 21, 21, 21, 7, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 12, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, + 10, 7, 7, 7, 7, 21, 21, 21, 21, 12, 12, 12, 12, 21, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 21, 7, 21, 21, 21, + 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 12, + 12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12, 2, + 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, + 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, + 12, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, + 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 12, 12, 7, 10, 10, + 12, 10, 10, 10, 10, 2, 2, 10, 10, 2, 2, 10, 10, 10, 2, 2, + 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 7, 7, 7, + 7, 7, 10, 10, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, + 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 12, 12, 12, 10, 12, 7, 7, 7, 7, 21, 21, 21, 21, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 21, 2, 21, 12, 7, + 10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12, + 12, 10, 12, 12, 7, 7, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, + 10, 10, 12, 12, 12, 12, 2, 2, 10, 10, 10, 10, 12, 12, 10, 12, + 12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 7, 7, 7, 7, 12, 12, 2, 2, + 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12, + 12, 21, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 10, 10, + 12, 12, 12, 12, 12, 12, 10, 12, 7, 2, 2, 2, 2, 2, 2, 2, + 10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 2, 2, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26, + 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 2, 2, 2, 2, + 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, + 7, 10, 10, 10, 12, 12, 12, 12, 2, 2, 12, 12, 10, 10, 10, 10, + 12, 7, 21, 7, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, + 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, 7, 12, 12, 12, 12, 21, + 21, 21, 21, 21, 21, 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21, 7, 21, 21, + 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 10, 12, + 7, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 2, 10, 12, 12, 12, 12, 12, 12, + 12, 10, 12, 12, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, + 7, 12, 12, 12, 12, 12, 12, 2, 2, 2, 12, 2, 12, 12, 2, 12, + 12, 12, 12, 12, 12, 12, 7, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10, 2, + 12, 12, 2, 10, 10, 12, 10, 12, 7, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 12, 12, 10, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23, + 23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, + 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 12, 12, 12, 12, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26, + 6, 6, 6, 6, 21, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 15, 15, 15, 15, 15, + 15, 15, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 7, 7, 7, + 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 12, + 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 12, + 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 21, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 26, 12, 12, 21, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10, + 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12, + 12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 12, 12, 12, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, + 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 9, 9, 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, 9, 2, 9, 9, + 2, 2, 9, 2, 2, 9, 9, 2, 2, 9, 9, 9, 9, 2, 9, 9, + 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 2, 5, 2, 5, 5, 5, + 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, 2, 9, 9, 9, + 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, + 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 9, 9, 9, 9, 9, 9, + 9, 2, 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, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 25, 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, 25, 5, 5, 5, 5, + 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 25, 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, 25, + 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 5, 2, 2, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, + 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, + 12, 12, 2, 12, 12, 2, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, + 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 2, 2, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 7, 26, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 23, + 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 5, 5, 5, 5, 12, 12, 12, 12, 12, 12, 12, 6, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15, + 23, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, + 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, 7, 2, 2, 2, 2, + 2, 2, 7, 2, 2, 2, 2, 7, 2, 7, 2, 7, 2, 7, 7, 7, + 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 2, 7, 2, 7, 2, 7, + 2, 7, 7, 2, 7, 2, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, + 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, + 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, + 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24, + 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, + 26, 26, 2, 26, 26, 26, 26, 2, 2, 2, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 2, 2, 2, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, + 26, 26, 26, 26, 2, 2, 2, 2, 26, 26, 26, 2, 2, 2, 2, 2, + 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 0, 0, 15, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 0, 0, + 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, 0, 0, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27, 0, 28, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 33, 0, + 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 37, 0, 0, 38, 0, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 51, 52, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 56, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 54, 59, 0, 0, 0, 0, 0, 60, 61, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, 14, 15, + 0, 16, 0, 0, 0, 0, 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, + 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, 0, 30, 31, 32, + 0, 0, 0, 0, 0, 30, 31, 0, 0, 33, 0, 0, 0, 30, 31, 0, + 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 31, 34, + 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 35, 31, 0, + 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 37, 38, 0, + 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 41, 0, 42, 0, 0, + 0, 43, 44, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 46, 0, 0, + 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, + 54, 55, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 57, 49, 0, + 58, 59, 0, 0, 60, 0, 0, 0, 61, 62, 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 64, 65, 66, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 67, 68, 1, 69, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 70, 71, 72, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 73, 74, 0, 0, 0, 0, 0, 0, + 0, 75, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 76, 0, 0, 0, + 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 73, 78, 0, 79, 0, 0, 0, 0, 0, 74, 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 49, 0, 1, 74, 0, 0, 81, 0, 0, 82, + 0, 0, 0, 0, 0, 83, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 84, 85, 0, 0, 80, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 86, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, + 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 91, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 88, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, + 0, 75, 0, 0, 0, 95, 0, 0, 0, 0, 96, 0, 0, 97, 0, 0, + 0, 83, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 99, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 0,101, 31, 0, + 102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 33, + 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 75,106, 0, 0, 0, 0, 0, 0, 75, 0, 0, + 0, 0, 0, 0, 0,107, 0, 0, 0, 0, 0, 0,108, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 49,109, 0, + 0, 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 0, + 0, 0, 0,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,112, 0, 0, 0,113, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 115,116,117, 0,118, 0, 0, 0, 0, 0, 0, 0, 0, 0,119, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,121,122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,123, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0,125, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230, + 230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,232, + 220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220, + 220,202,202,220,220,220,220,220,220,220,220,220,220,220, 1, 1, + 1, 1, 1,220,220,220,220,230,230,230,230,230,230,230,230,240, + 230,220,220,220,230,230,230,220,220, 0,230,230,230,220,220,220, + 220,230,232,220,220,230,233,234,234,233,234,234,233,230,230,230, + 230,230,230,230,230,230,230,230,230,230, 0, 0, 0,230,230,230, + 230,230, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,230,230,230,230, + 220,230,230,230,222,220,230,230,230,230,230,230,220,220,220,220, + 220,220,230,230,220,230,230,222,228,230, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0,230,220, + 0, 18, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230, + 230,230, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220, + 220,230,230,230,230,230,220,230,230,220, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230,230,230,230,230,230,230, 0, 0,230,230,230,230,220,230, 0, + 0,230,230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,220,230,230,220,230, + 230,220,220,220,230,220,220,230,220,230,230,230,220,230,220,230, + 220,230,220,230,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,230,230,230,230,230,230,230,220,230, 0, 0, + 0, 0, 0, 0, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 0, + 230,230,230,230, 0,230,230,230,230,230,230,230,230,230, 0,230, + 230,230, 0,230,230,230,230,230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,220,220,220, 0, 0, 0, 0, 0, 0, 0,220,230,230, + 230,230,230,230,230,230,230,230,230,230,230,230, 0,220,230,230, + 220,230,230,220,230,230,230,220,220,220, 27, 28, 29,230,230,230, + 220,230,230,220,220,230,230,230,230,230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 84, + 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,103,103, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,107,107,107,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,118,118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,122,122,122,122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,220,220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220, + 0,220, 0,216, 0, 0, 0, 0, 0, 0, 0,129,130, 0,132, 0, + 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0,230,230, 9, 0, + 230,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,222,230,220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,230,220, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230, + 230,230,230,230,230,230,230, 0, 0,220,230,230,230,230,230,220, + 220,220,220,220,220,230,230,220, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,230,220,230,230,230,230,230,230,230, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 1,220, + 220,220,220,220,230,230,220,220,220,220,230, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0,220, 0, 0, 0, 0, 0, 0,230, 0, + 0, 0,230,230, 0, 0, 0, 0, 0, 0,230,230,220,230,230,230, + 230,230,230,230,220,230,230,234,214,220,202,230,230,230,230,230, + 230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, + 232,228,228,220, 0,230,233,220,230,220,230,230, 1, 1,230,230, + 230,230, 1, 1, 1,230,230, 0, 0, 0, 0,230, 0, 0, 0, 1, + 1,230,220,230, 1, 1,220,220,220,220,230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,218,228,232,222,224,224, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230, + 230,230,230,230,230,230,230,230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,230,230, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,220,220,220, 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230, 0,230,230,220, 0, + 0,230,230, 0, 0, 0, 0, 0,230,230, 0,230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 26, 0,230,230,230,230,230,230, + 230,220,220,220,220,220,220,220,230,230,220, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230,230,230,230,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,220, 0,230, 0, 0, 0, 0, 0, 0, + 0, 0,230, 1,220, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,230, + 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230, + 230,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 220,220,230,230,230,220,230,220,220,220, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230,230,230,230,230,230,230, 0, 0, 0,230,230,230,230,230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,216, + 216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0, 0, 0, + 0, 0, 0, 0, 0,220,220,220,220,220,220,220,220, 0, 0,230, + 230,230,230,230,220,220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,230,230,230,230, 0, 0, 0, 0,230,230,230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230, + 230, 0,230,230,230,230,230,230,230,230,230,230,230,230,230,230, + 230,230,230, 0, 0,230,230,230,230,230,230,230, 0,230,230, 0, + 230,230,230,230,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,230,230,230,230,220,220,220,220,220,220, + 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230, + 230,230,230,230, 7, 0, 0, 0, 0, 0, 16, 17, 17, 17, 17, 17, + 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169, + 17, 27, 28, 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,237, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 0, 13, + 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, + 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, + 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, + 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21, 32, 4, 0, 10, + 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, + 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, + 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 21, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, + 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, + 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 1, 20, + 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 21, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, + 3, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 3, 4, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 17, 19, 20, + 21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 28, 28, 29, 30, 31, 32, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 35, 35, 35, + 35, 35, 59, 59, 60, 35, 35, 35, 35, 35, 35, 35, 61, 62, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 63, 64, + 35, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 66, 68, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 69, 70, 35, 35, 35, 35, 71, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 72, 73, 74, 75, 76, 77, 35, 35, 78, 79, 35, 35, 80, 35, + 81, 82, 83, 84, 17, 85, 86, 87, 35, 35, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 88, 25, 25, + 25, 25, 25, 25, 25, 89, 90, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 91, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 92, + 35, 35, 35, 35, 35, 35, 25, 93, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 94, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, + 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, + 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 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, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 0, 4, 2, 2, 4, 4, 4, 2, 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, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, + 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 0, 3, 2, 3, 0, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 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, 0, 3, 3, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, + 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, + 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, + 2, 2, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, + 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, + 2, 2, 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, 2, 2, 11, 11, 11, + 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, + 2, 11, 11, 2, 11, 11, 2, 2, 11, 2, 11, 11, 11, 11, 11, 2, + 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, + 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, + 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, + 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, + 2, 10, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, + 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, + 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, + 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, + 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, + 2, 2, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, + 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, + 2, 22, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, + 22, 22, 2, 2, 2, 22, 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, + 22, 2, 2, 2, 22, 22, 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, + 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 22, 2, 2, 2, + 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, + 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, + 2, 23, 23, 2, 23, 23, 23, 2, 2, 2, 2, 2, 23, 23, 23, 23, + 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 2, 2, 2, + 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 2, 16, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, + 2, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 2, 16, 16, 16, 16, + 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 20, 20, 20, 20, + 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 36, 36, + 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 36, 36, 36, 36, + 36, 36, 36, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, + 36, 2, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, + 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 36, 36, + 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18, 18, 2, + 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, + 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, + 25, 0, 0, 0, 0, 25, 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 2, 8, 2, 2, 2, 2, 2, 8, 2, 2, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, + 30, 30, 30, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 2, 30, 30, + 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 2, 30, 30, + 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 2, 2, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 2, 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 45, 45, 45, 45, 45, 45, + 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 2, 2, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, + 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, + 28, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, + 52, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 2, 2, 2, 2, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 2, 2, 2, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 2, 2, 8, 8, 8, 76, 76, 76, 76, + 76, 76, 76, 76, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, + 19, 19, 9, 9, 9, 9, 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, + 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 9, 9, 9, 9, + 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, + 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 2, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, + 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 19, 19, 0, 0, 0, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 30, 30, 30, 30, + 30, 30, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, + 30, 30, 30, 2, 30, 30, 30, 30, 30, 30, 30, 2, 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, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, + 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 13, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 13, 13, 13, 0, 0, 0, 0, 2, 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, 2, 2, 1, 1, 0, 0, 15, 15, 15, 0, 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, 0, 0, 17, 17, 17, 2, 2, 2, 2, + 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 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, 2, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, + 39, 39, 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 0, 0, 19, 19, 19, 19, 19, 2, 2, 19, 19, + 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 30, 30, 30, + 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 30, 30, 30, + 30, 30, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 9, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, + 12, 12, 12, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, + 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, + 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, + 14, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 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, 0, 0, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, + 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, + 12, 12, 12, 12, 2, 2, 12, 12, 12, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 2, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, + 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 2, 2, 2, 2, 2,118,118,118,118, + 118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118, + 118,118,118,118,118,118,118, 2, 2, 2, 2, 2, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 2, 2, 2, 2, 2, 2,135,135,135,135, + 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135,135,135, + 135,135,135,135,135,135,135,135, 2, 2, 2, 2,106,106,106,106, + 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106, + 106,106,106,106, 2, 2, 2, 2, 2, 2, 2, 2,104,104,104,104, + 104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,104,110,110,110,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, + 110,110,110, 2, 2, 2, 2, 2, 2, 2, 2, 2,110,110,110,110, + 110,110, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,110,110,110,110, + 110,110,110,110, 2, 2, 2, 2, 2, 2, 2, 2, 47, 47, 47, 47, + 47, 47, 2, 2, 47, 2, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 2, 81, 81, 81, 81, 81, 81, 81, 81, 81,120,120,120,120, + 120,120,120,120,120,120,120,120,120,120,120,120,116,116,116,116, + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116, + 116,116,116,116,116,116,116,116,116,116,116, 2, 2, 2, 2, 2, + 2, 2, 2,116,116,116,116,116,116,116,116,116,128,128,128,128, + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 2, + 128,128, 2, 2, 2, 2, 2,128,128,128,128,128, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, + 2, 57, 57, 2, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, + 2, 57, 57, 57, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 2, 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,117,117,117,117, + 117,117,117,117,117,117,117,117,117,117,117,117,112,112,112,112, + 112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112, + 112,112,112, 2, 2, 2, 2,112,112,112,112,112,112,112,112,112, + 112,112,112, 2, 2, 2, 2, 2, 2, 2, 2, 2, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 2, 2, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, + 2, 2, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82,122,122,122,122, + 122,122,122,122,122,122,122,122,122,122,122,122,122,122, 2, 2, + 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,122,122,122,122,122,122,122, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130,130,130, + 130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,130,130,130, 2, + 2, 2, 2, 2, 2, 2,130,130,130,130,130,130, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101,101,101, + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, + 101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101,101,101, + 101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 2, 2, 2, 2, 2, 2, 2, 2, 2,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 111,111,111, 2, 2, 2, 2, 2, 2, 2, 2, 2,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100, 2, 2, 2, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,108,108,108,108, + 108,108,108,108,108,108,108,108,108,108,108,108,108,108, 2,108, + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, + 108,108,108,108,108,108,108,108,108,108,108, 2,129,129,129,129, + 129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129, 2,129,129,129,129,129, + 129,129,129,129,129,129, 2, 2, 2, 2, 2, 2,109,109,109,109, + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109, + 109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109,109,109, + 109,109,109,109,109,109, 2, 2, 2, 2, 2, 2,107,107,107,107, + 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2, 2,107, + 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, + 107,107,107,107,107, 2,107,107,107,107,107,107,107, 2,107,107, + 2,107,107,107,107,107, 2, 1,107,107,107,107,107,107,107,107, + 107, 2, 2,107,107, 2, 2,107,107,107, 2, 2,107, 2, 2, 2, + 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107,107,107, + 2, 2,107,107,107,107,107,107,107, 2, 2, 2,107,107,107,107, + 107, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,137,137,137,137, + 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + 137,137,137,137,137,137, 2,137, 2,137,137,137,124,124,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, + 124,124,124,124, 2, 2, 2, 2, 2, 2, 2, 2,124,124,124,124, + 124,124,124,124,124,124, 2, 2, 2, 2, 2, 2,123,123,123,123, + 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, + 123,123, 2, 2,123,123,123,123,123,123,123,123,123,123,123,123, + 123,123,123,123,123,123,123,123,123,123, 2, 2,114,114,114,114, + 114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, + 114, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,114,114,114,114, + 114,114,114,114,114,114, 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 2,102,102,102,102, + 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, + 102,102,102,102,102, 2, 2, 2, 2, 2, 2, 2,102,102,102,102, + 102,102,102,102,102,102, 2, 2, 2, 2, 2, 2,126,126,126,126, + 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126, 2, 2,126,126,126,126,126,126,126, + 126,126,126,126,126,126,126,126, 2, 2, 2, 2, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2,125,125,125,125, + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125, 5, 5, 5, 5, + 5, 5, 5, 5, 2, 2, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, + 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,121,121,121,121, + 121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, + 121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2,133,133,133,133, + 133,133,133,133,133, 2,133,133,133,133,133,133,133,133,133,133, + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133, + 133,133,133, 2,133,133,133,133,133,133,133,133,133,133,133,133, + 133,133, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,133,133,133,133, + 133,133,133,133,133,133,133,133,133, 2, 2, 2,134,134,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134, 2, 2,134,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134,134, 2,134,134,134,134,134,134,134,134,134,134,134, + 134,134,134, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, + 8, 8, 8, 2, 8, 8, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 2, 2, 2, 8, 2, 8, 8, 2, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, + 9, 9, 2, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, + 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, + 63, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 2, 2, 2, 2, 2, 2, 2,127,127,127,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, + 127,127,127, 2, 2, 2, 2, 2, 2, 2, 2, 2, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 2, 2, 2, 2, 2, 2, 2,115,115,115,115, + 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 115,115,115,115,115,115,115,115,115,115,115, 2,115,115,115,115, + 115,115,115,115,115,115, 2, 2, 2, 2,115,115,103,103,103,103, + 103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103, + 103,103,103,103,103,103,103,103,103,103, 2, 2,103,103,103,103, + 103,103, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,119,119,119,119, + 119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, + 119,119, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,119,119,119,119, + 119,119,119,119,119,119, 2,119,119,119,119,119,119,119, 2,119, + 119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, + 119,119,119,119, 2, 2, 2, 2, 2,119,119,119, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 2, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 2, 2, 2, 2, 2, 2, 2, 99,136, 12, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,136,136,136,136, + 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, + 136,136,136,136, 2, 2, 2, 2, 2, 2, 2, 2,136,136,136, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 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, 2, 15, 15, 15, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 17, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, 2,105,105,105,105, + 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, + 105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105,105,105, + 105,105,105,105,105,105,105,105,105, 2, 2, 2,105,105,105,105, + 105,105,105,105,105, 2, 2, 2, 2, 2, 2, 2,105,105,105,105, + 105,105,105,105,105,105, 2, 2,105,105,105,105, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, + 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 2, + 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,131,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131, + 131,131,131,131,131,131,131,131, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131,131,131, + 131,131,131,131,131,131,131,131,131,131,131,131, 56, 56, 56, 56, + 56, 56, 56, 2, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, + 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 14,113,113,113,113, + 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, + 113, 2, 2,113,113,113,113,113,113,113,113,113,113,113,113,113, + 113,113,113, 2, 2, 2, 2, 2, 2, 2, 2, 2,132,132,132,132, + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, + 132,132,132,132,132,132,132,132, 2, 2, 2, 2,132,132,132,132, + 132,132,132,132,132,132, 2, 2, 2, 2,132,132, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 3, 3, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, + 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, 3, 2, + 3, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, + 3, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, + 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, + 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, + 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, + 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, + 2, 3, 4, 5, 6, 0, 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, + 0, 0, 0, 0, 13, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 16, 0, 17, 18, 19, 0, 0, 0, 20, 21, 22, 0, 23, 0, 24, + 0, 25, 0, 26, 0, 0, 0, 0, 0, 27, 28, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, + 41, 0, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, + 64, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 66, 0, + 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 68, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 0, +}; +static const uint16_t +_hb_ucd_u16[11168] = +{ + 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, + 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, + 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31, + 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39, + 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13, + 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50, + 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58, + 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66, + 48, 67, 68, 69, 48, 70, 71, 72, 72, 72, 48, 73, 72, 74, 75, 32, + 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101, + 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113, + 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124, + 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135, + 136, 48, 48, 137, 138, 139, 72, 72, 140, 48, 141, 142, 143, 144, 72, 72, + 145, 146, 147, 148, 149, 48, 150, 151, 152, 153, 32, 154, 155, 156, 72, 72, + 48, 48, 157, 158, 159, 160, 161, 162, 163, 164, 9, 9, 165, 11, 11, 166, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 167, 168, 48, 48, 167, 48, 48, 169, 170, 171, 48, 48, + 48, 170, 48, 48, 48, 172, 173, 174, 48, 175, 9, 9, 9, 9, 9, 176, + 177, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 178, 48, 179, 180, 48, 48, 48, 48, 181, 182, + 183, 184, 48, 185, 48, 186, 183, 187, 48, 48, 48, 188, 189, 190, 191, 192, + 193, 191, 48, 48, 194, 48, 48, 195, 196, 48, 197, 48, 48, 48, 48, 198, + 48, 199, 200, 201, 202, 48, 203, 204, 48, 48, 205, 48, 206, 207, 208, 208, + 48, 209, 48, 48, 48, 210, 211, 212, 191, 191, 213, 214, 72, 72, 72, 72, + 215, 48, 48, 216, 217, 159, 218, 219, 220, 48, 221, 64, 48, 48, 222, 223, + 48, 48, 224, 225, 226, 64, 48, 227, 228, 9, 9, 229, 230, 231, 232, 233, + 11, 11, 234, 27, 27, 27, 235, 236, 11, 237, 27, 27, 32, 32, 32, 238, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 239, 13, 13, 13, 13, 13, 13, + 240, 241, 240, 240, 241, 242, 240, 243, 244, 244, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260, 72, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 270, 271, 272, 273, 208, 274, 275, 208, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 278, 208, 279, 208, 208, 208, 208, 280, 208, 281, 277, 282, 208, 283, 284, 208, + 208, 208, 285, 72, 286, 72, 269, 269, 269, 287, 208, 208, 208, 208, 288, 269, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 289, 290, 208, 208, 291, + 208, 208, 208, 208, 208, 208, 292, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 293, 294, 269, 295, 208, 208, 296, 277, 297, 277, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 277, 277, 277, 277, 277, 277, 277, 277, 298, 299, 277, 277, 277, 300, 277, 301, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 208, 208, 208, 277, 302, 208, 208, 303, 208, 304, 208, 208, 208, 208, 208, 208, + 9, 9, 305, 11, 11, 306, 307, 308, 13, 13, 13, 13, 13, 13, 309, 310, + 11, 11, 311, 48, 48, 48, 312, 313, 48, 314, 315, 315, 315, 315, 32, 32, + 316, 317, 318, 319, 320, 72, 72, 72, 208, 321, 208, 208, 208, 208, 208, 322, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323, 72, 324, + 325, 326, 327, 328, 136, 48, 48, 48, 48, 329, 177, 48, 48, 48, 48, 330, + 331, 48, 48, 136, 48, 48, 48, 48, 199, 332, 48, 71, 208, 208, 322, 48, + 208, 333, 334, 208, 335, 336, 208, 208, 334, 208, 208, 336, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 198, 208, 208, 208, 208, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 72, + 48, 337, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 150, 208, 208, 208, 285, 48, 48, 227, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 338, 48, 339, 72, 13, 13, 340, 341, 13, 342, 48, 48, 48, 48, 343, 344, + 31, 345, 346, 347, 13, 13, 13, 348, 349, 350, 351, 352, 353, 72, 72, 354, + 355, 48, 356, 357, 48, 48, 48, 358, 359, 48, 48, 360, 361, 191, 32, 362, + 64, 48, 363, 48, 364, 365, 48, 150, 76, 48, 48, 366, 367, 368, 369, 370, + 48, 48, 371, 372, 373, 374, 48, 375, 48, 48, 48, 376, 377, 378, 379, 380, + 381, 382, 315, 11, 11, 383, 384, 11, 11, 11, 11, 11, 48, 48, 385, 191, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 386, 48, 387, 48, 48, 205, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 203, 48, 48, 48, 48, 48, 48, 206, 72, 72, + 390, 391, 392, 393, 394, 48, 48, 48, 48, 48, 48, 395, 396, 397, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 398, 72, 48, 48, 48, 48, 399, 48, 48, 400, 72, 72, 401, + 32, 402, 32, 403, 404, 405, 406, 407, 48, 48, 48, 48, 48, 48, 48, 408, + 409, 2, 3, 4, 5, 410, 411, 412, 48, 413, 48, 199, 414, 415, 416, 417, + 418, 48, 171, 419, 203, 203, 72, 72, 48, 48, 48, 48, 48, 48, 48, 71, + 420, 269, 269, 421, 270, 270, 270, 422, 423, 324, 424, 72, 72, 208, 208, 425, + 72, 72, 72, 72, 72, 72, 72, 72, 48, 150, 48, 48, 48, 100, 426, 427, + 48, 48, 428, 48, 429, 48, 48, 430, 48, 431, 48, 48, 432, 433, 72, 72, + 9, 9, 434, 11, 11, 48, 48, 48, 48, 203, 191, 9, 9, 435, 11, 436, + 48, 48, 400, 48, 48, 48, 437, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 314, 48, 198, 400, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 438, 48, 48, 439, 48, 440, 48, 441, 48, 199, 442, 72, 72, 72, 48, 443, + 48, 444, 48, 445, 72, 72, 72, 72, 48, 48, 48, 446, 269, 447, 269, 269, + 448, 449, 48, 450, 451, 452, 48, 453, 48, 454, 72, 72, 455, 48, 456, 457, + 48, 48, 48, 458, 48, 459, 48, 460, 48, 461, 462, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 195, 72, 72, 72, 9, 9, 9, 463, 11, 11, 11, 464, + 48, 48, 465, 191, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 269, 466, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 454, 467, 48, 62, 468, 72, 72, 72, 72, 72, 72, 72, 72, 48, 314, + 469, 48, 48, 470, 471, 447, 472, 473, 220, 48, 48, 474, 475, 48, 195, 191, + 476, 48, 477, 478, 479, 48, 48, 480, 220, 48, 48, 481, 482, 483, 484, 485, + 48, 97, 486, 487, 72, 72, 72, 72, 488, 489, 490, 48, 48, 491, 492, 191, + 493, 83, 84, 494, 495, 496, 497, 498, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 499, 500, 501, 72, 72, 48, 48, 48, 502, 503, 191, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 48, 48, 504, 505, 506, 507, 72, 72, + 48, 48, 48, 508, 509, 191, 510, 72, 48, 48, 511, 512, 191, 72, 72, 72, + 48, 172, 513, 514, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 486, 515, 72, 72, 72, 72, 72, 72, 9, 9, 11, 11, 147, 516, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 517, 48, 48, 518, 519, 72, + 520, 48, 48, 521, 522, 523, 48, 48, 524, 525, 526, 72, 48, 48, 48, 195, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 84, 48, 504, 527, 528, 147, 174, 529, 48, 530, 531, 532, 72, 72, 72, 72, + 533, 48, 48, 534, 535, 191, 536, 48, 537, 538, 191, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 48, 539, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 269, 540, 541, 542, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 206, 72, 72, 72, 72, 72, 72, + 270, 270, 270, 270, 270, 270, 543, 544, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 386, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 199, 545, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 314, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 195, 48, 199, 368, 72, 72, 72, 72, 72, 72, 48, 203, 546, + 48, 48, 48, 547, 548, 549, 550, 551, 48, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 9, 9, 11, 11, 269, 552, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 553, 554, 555, 555, 556, 557, 72, 72, 72, 72, 558, 72, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 400, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 559, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 199, 72, 72, 72, 559, 560, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 205, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 48, 48, 71, 150, 195, 561, 562, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323, + 208, 208, 563, 208, 208, 208, 564, 565, 566, 208, 567, 208, 208, 208, 568, 72, + 208, 208, 208, 208, 569, 72, 72, 72, 72, 72, 72, 72, 72, 72, 269, 570, + 208, 208, 208, 208, 208, 285, 269, 451, 72, 72, 72, 72, 72, 72, 72, 72, + 9, 571, 11, 572, 573, 574, 240, 9, 575, 576, 577, 578, 579, 9, 571, 11, + 580, 581, 11, 582, 583, 584, 585, 9, 586, 11, 9, 571, 11, 572, 573, 11, + 240, 9, 575, 585, 9, 586, 11, 9, 571, 11, 587, 9, 588, 589, 590, 591, + 11, 592, 9, 593, 594, 595, 596, 11, 597, 9, 598, 11, 599, 600, 600, 600, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 32, 32, 32, 601, 32, 32, 602, 603, 604, 605, 45, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 606, 607, 608, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 150, 609, 610, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 48, 48, 611, 612, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 613, 614, 72, 72, + 9, 9, 575, 11, 615, 368, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 484, 269, 269, 616, 617, 72, 72, 72, 72, + 484, 269, 618, 619, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 620, 48, 621, 622, 623, 624, 625, 626, 627, 205, 628, 205, 72, 72, 72, 629, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 208, 208, 324, 208, 208, 208, 208, 208, 208, 322, 333, 630, 630, 630, 208, 323, + 174, 208, 208, 208, 208, 208, 631, 208, 208, 208, 631, 72, 72, 72, 632, 208, + 633, 208, 208, 324, 568, 634, 323, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 635, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323, 631, 286, + 208, 208, 208, 208, 208, 208, 208, 322, 208, 208, 208, 208, 208, 568, 324, 72, + 324, 208, 208, 208, 636, 175, 208, 208, 636, 208, 637, 72, 72, 72, 72, 72, + 638, 208, 208, 208, 208, 208, 208, 639, 208, 208, 640, 208, 641, 208, 208, 208, + 208, 208, 208, 208, 208, 322, 637, 642, 633, 323, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 314, 72, 72, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 203, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 643, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 72, + 48, 203, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 644, 72, 645, 645, 645, 645, 645, 645, 72, 72, 72, 72, 72, 72, 72, 72, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 72, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 646, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 647, + 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5, + 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, 6, 0, 0, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 11, 11, 11, 13, 11, + 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 16, 17, 18, 17, 17, 19, 20, 21, 21, 22, 21, 23, 24, + 25, 26, 27, 27, 28, 29, 27, 30, 27, 27, 27, 27, 27, 31, 27, 27, + 32, 33, 33, 33, 34, 27, 27, 27, 35, 35, 35, 36, 37, 37, 37, 38, + 39, 39, 40, 41, 42, 43, 44, 45, 45, 45, 27, 46, 45, 47, 48, 27, + 49, 49, 49, 49, 49, 50, 51, 49, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 110, 111, 112, 113, 110, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 123, 124, 123, 125, 45, 45, 126, 127, 128, 129, 130, 131, 45, 45, + 132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 45, 45, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143, + 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170, + 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176, + 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168, + 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 195, 45, 45, 45, 45, + 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201, + 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211, + 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 217, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 11, 218, 11, 11, 218, 219, 11, 220, 11, 11, 11, 221, 221, 222, 11, 223, + 224, 0, 0, 0, 0, 0, 225, 226, 227, 228, 0, 0, 45, 8, 8, 229, + 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 234, 45, 235, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 237, 0, 238, 0, 0, 0, 0, 0, 0, + 239, 239, 240, 239, 239, 240, 4, 4, 241, 241, 241, 241, 241, 241, 241, 242, + 139, 139, 140, 243, 243, 243, 244, 245, 143, 246, 247, 247, 247, 247, 14, 14, + 0, 0, 0, 0, 0, 45, 45, 45, 248, 249, 248, 248, 248, 248, 248, 250, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 45, 252, + 253, 0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261, + 262, 263, 263, 264, 142, 142, 142, 142, 265, 0, 263, 266, 0, 0, 267, 260, + 142, 265, 0, 0, 0, 0, 142, 268, 0, 0, 0, 0, 0, 260, 260, 269, + 260, 260, 260, 260, 260, 270, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 0, 0, 0, 0, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 45, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 272, 271, 271, 271, 273, 274, 274, 274, + 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + 275, 275, 276, 45, 14, 14, 14, 14, 14, 14, 277, 277, 277, 277, 277, 278, + 0, 0, 279, 4, 4, 4, 4, 4, 280, 4, 4, 4, 281, 45, 45, 282, + 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 49, 49, + 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299, + 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308, + 309, 310, 247, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 45, 45, + 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 47, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 325, 45, 27, 27, 27, 27, 326, 27, 27, 327, 45, 45, 328, + 8, 285, 329, 0, 0, 330, 331, 332, 27, 27, 27, 27, 27, 27, 27, 333, + 334, 0, 1, 2, 1, 2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 345, 45, 45, 342, 342, 342, 342, 342, 342, 342, 346, + 347, 0, 0, 348, 11, 11, 11, 11, 349, 252, 350, 45, 45, 0, 0, 351, + 45, 45, 45, 45, 45, 45, 45, 45, 352, 353, 354, 354, 354, 355, 356, 252, + 357, 357, 358, 359, 360, 361, 361, 362, 363, 364, 365, 365, 366, 367, 45, 45, + 368, 368, 368, 368, 368, 369, 369, 369, 370, 371, 372, 373, 373, 374, 373, 375, + 376, 376, 377, 378, 378, 378, 379, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, + 380, 380, 380, 381, 380, 382, 383, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 384, 385, 385, 386, 387, 388, 389, 389, 390, 391, 392, 45, 45, 45, 393, 394, + 395, 396, 397, 398, 45, 45, 45, 45, 399, 399, 400, 401, 400, 402, 400, 400, + 403, 404, 405, 406, 407, 407, 408, 408, 409, 409, 45, 45, 410, 410, 411, 412, + 413, 413, 413, 414, 415, 416, 417, 418, 419, 420, 421, 45, 45, 45, 45, 45, + 422, 422, 422, 422, 423, 45, 45, 45, 424, 424, 424, 425, 424, 424, 424, 426, + 0, 0, 427, 285, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 27, 428, 45, 45, 45, 45, 45, 45, 45, 45, + 8, 8, 429, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 27, 430, + 431, 431, 431, 431, 432, 433, 431, 434, 435, 435, 435, 435, 436, 437, 438, 439, + 440, 440, 440, 441, 442, 443, 443, 444, 445, 445, 445, 445, 446, 445, 447, 448, + 449, 450, 449, 451, 45, 45, 45, 45, 452, 453, 454, 455, 455, 455, 456, 457, + 458, 459, 460, 461, 462, 463, 464, 465, 45, 45, 45, 45, 45, 45, 45, 45, + 466, 466, 466, 466, 466, 467, 45, 45, 468, 468, 468, 468, 469, 470, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 471, 471, 471, 472, 471, 473, 45, 45, + 474, 474, 474, 474, 475, 476, 477, 45, 478, 478, 478, 479, 480, 45, 45, 45, + 481, 482, 483, 481, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 17, 17, 17, 484, 45, 45, 45, 45, 45, 45, 485, 485, 485, 485, 485, 486, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 487, 488, 488, 487, 489, 45, + 14, 14, 14, 14, 490, 49, 49, 49, 49, 49, 491, 45, 492, 492, 492, 493, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 494, 495, 495, 496, 497, 495, 498, 499, 499, 500, 501, 502, 45, 45, 45, 45, + 503, 139, 139, 504, 505, 506, 507, 11, 349, 508, 509, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 510, 511, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 512, 512, 512, 513, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 515, 45, 45, 45, 45, 45, 45, + 514, 514, 514, 514, 514, 514, 516, 517, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 518, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 520, 521, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, + 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, + 522, 522, 522, 522, 523, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 524, 525, 526, 527, 45, 45, 45, 45, 45, 45, 528, 529, 530, + 531, 531, 531, 531, 532, 533, 534, 535, 531, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 536, 536, 536, 536, 536, 537, 45, 45, 45, 45, 45, 45, + 538, 538, 538, 538, 539, 538, 538, 538, 540, 538, 45, 45, 45, 45, 541, 45, + 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, + 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, + 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, + 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 543, + 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 544, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 545, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 546, 45, 45, 45, 547, 548, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 317, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 549, 549, 549, 549, 549, 549, 550, 551, 552, 553, 267, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 554, + 0, 0, 555, 0, 0, 0, 556, 557, 558, 0, 559, 0, 0, 0, 560, 45, + 11, 11, 11, 11, 561, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 267, + 0, 0, 0, 0, 0, 234, 0, 560, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 225, 0, 0, 0, 562, 563, 564, 565, 0, 0, 0, + 566, 567, 0, 568, 569, 570, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, 0, + 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, + 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, + 572, 572, 572, 572, 572, 572, 572, 572, 573, 574, 575, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 576, 577, 578, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 248, 248, 579, 318, 580, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 21, 21, 21, 581, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 584, 45, 45, + 585, 585, 585, 585, 586, 587, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 334, 0, 0, 0, 588, 45, 45, 45, 45, + 334, 0, 0, 589, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 590, 27, 591, 592, 593, 594, 595, 596, 597, 598, 599, 598, 45, 45, 45, 324, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 252, 0, 0, 0, 0, 0, 0, 267, 227, 334, 334, 334, 0, 554, + 600, 0, 0, 0, 0, 0, 600, 0, 0, 0, 600, 45, 45, 45, 601, 0, + 602, 0, 0, 252, 560, 603, 554, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 554, 600, 235, + 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 560, 252, 45, + 252, 0, 0, 0, 427, 285, 0, 0, 427, 0, 589, 45, 45, 45, 45, 45, + 604, 0, 0, 0, 0, 0, 0, 605, 0, 0, 606, 0, 607, 0, 0, 0, + 0, 0, 0, 0, 0, 267, 589, 608, 609, 554, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 610, 45, 45, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 611, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 612, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 613, 45, + 248, 318, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 614, 45, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, + 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0, + 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193, + 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303, + 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149, + 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, + 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199, + 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0, + 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231, + 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258, + 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275, + 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093, + 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010, + 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347, + 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424, + 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365, + 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238, + 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182, + 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232, + 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461, + 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486, + 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0, + 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553, + 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560, + 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0, + 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0, + 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0, + 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0, + 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0, + 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0, + 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, + 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, + 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356, + 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214, + 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363, + 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251, + 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266, + 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287, + 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302, + 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0, + 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375, + 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353, + 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234, + 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403, + 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412, + 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0, + 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721, + 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0, + 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757, + 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776, + 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0, + 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793, + 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814, + 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0, + 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728, + 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764, + 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821, + 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0, + 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828, + 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833, + 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3, + 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938, + 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0, + 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0, + 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0, + 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0, + 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0, + 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0, + 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0, + 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0, + 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, + 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, + 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, + 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, + 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, + 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, + 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, + 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, + 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, + 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, + 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, + 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, + 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, + 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, + 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, + 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, + 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0, + 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0, + 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773, + 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, + 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, + 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, + 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0, + 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, + 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, + 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, + 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, + 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, + 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, + 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575, + 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0, + 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1948,1949, + 1950,1951,1952,1953,1954, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1955,1956,1957,1959,1958, + 1960, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, + 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, + 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, + 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, + 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, + 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, + 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259, + 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276, + 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934, + 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312, + 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, + 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, + 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381, + 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399, + 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417, + 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, + 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460, + 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870, + 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505, + 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64, + 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538, + 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567, + 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592, + 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, + 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627, + 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, + 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83, + 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85, + 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696, + 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, + 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90, + 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787, + 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807, + 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +static const int16_t +_hb_ucd_i16[196] = +{ + 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2, + 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1, + 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3, + -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0, + 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0, + 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0, + 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0, + 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0, + 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1, + -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0, + 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106, + -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1, + -1, 0, 1, -1, +}; + +static inline uint_fast8_t +_hb_ucd_gc (unsigned u) +{ + return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2; +} +static inline uint_fast8_t +_hb_ucd_ccc (unsigned u) +{ + return u<125259u?_hb_ucd_u8[14026+(((_hb_ucd_u8[13034+(((_hb_ucd_u8[12544+(u>>4>>4)])<<4)+((u>>4)&15u))])<<4)+((u)&15u))]:0; +} +static inline unsigned +_hb_ucd_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline int_fast16_t +_hb_ucd_bmg (unsigned u) +{ + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16170+(((_hb_ucd_b4(16042+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0; +} +static inline uint_fast8_t +_hb_ucd_sc (unsigned u) +{ + return u<918000u?_hb_ucd_u8[18924+(((_hb_ucd_u16[3008+(((_hb_ucd_u8[17130+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2; +} +static inline uint_fast16_t +_hb_ucd_dm (unsigned u) +{ + return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[28764+(u>>6)])<<6)+((u)&63u))]:0; +} + + +#else + +static const uint8_t +_hb_ucd_u8[16998] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 9, 10, 11, 7, 7, 7, 7, 12, 13, 14, 14, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 21, 23, 21, 21, 21, 21, 24, 7, 7, + 25, 26, 21, 21, 21, 21, 27, 28, 21, 21, 29, 30, 31, 32, 33, 34, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 35, 7, 36, 37, 7, 38, 7, 7, 7, 39, 21, 40, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 41, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 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, 42, + 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, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73, + 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83, + 84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91, + 92, 34, 34, 34, 34, 34, 34, 34, 34, 93, 34, 34, 94, 95, 96, 97, + 98, 99,100,101,102,103,104,105, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,106, + 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108, + 108,108, 34, 34,109,110,111,112, 34, 34,113,114,115,116,117,118, + 119,120,121,122,123,124,125,126,127,128,129,123, 34, 34,130,123, + 131,132,133,134,135,136,137,138,139,140,141,123,142,123,143,144, + 145,146,147,148,149,150,151,123,152,153,123,154,155,156,157,123, + 158,159,123,160,161,162,123,123,163,164,165,166,123,167,123,168, + 34, 34, 34, 34, 34, 34, 34,169,170, 34,171,123,123,123,123,123, + 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, + 34, 34, 34, 34, 34, 34, 34, 34,172,123,123,123,123,123,123,123, + 123,123,123,123,123,123,123,123, 34, 34, 34, 34,173,123,123,123, + 34, 34, 34, 34,174,175,176,177,123,123,123,123,178,179,180,181, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,182, + 34, 34, 34, 34, 34,183,123,123,123,123,123,123,123,123,123,123, + 34, 34,184, 34, 34,185,123,123,123,123,123,123,123,123,123,123, + 123,123,123,123,123,123,123,123,186,187,123,123,123,123,123,123, + 69,188,189,190,191,192,193,123,194,195,196,197,198,199,200,201, + 69, 69, 69, 69,202,203,123,123,123,123,123,123,123,123,123,123, + 204,123,205,123,123,206,123,123,123,123,123,123,123,123,123,123, + 34,207,208,123,123,123,123,123,209,210,211,123,212,213,123,123, + 214,215,216,217,218,123, 69,219, 69, 69, 69, 69, 69,220,221,222, + 223,224,225,226,227,228,123,123,123,123,123,123,123,123,123,123, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,229, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,230, 34, + 231, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,232, 34, 34, + 34, 34, 34, 34, 34, 34, 34,233,123,123,123,123,123,123,123,123, + 34, 34, 34, 34,234,123,123,123,123,123,123,123,123,123,123,123, + 235,123,236,237,123,123,123,123,123,123,123,123,123,123,123,123, + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,238, + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,239, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2, + 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 18, 19, 1, 20, 20, 21, 22, 23, 24, 25, + 26, 27, 15, 2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32, + 32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11, + 11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11, + 34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34, + 34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32, + 32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32, + 16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, + 40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, + 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10, + 44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11, + 11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34, + 16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11, + 32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16, + 48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52, 2, 2, 2, + 16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62, + 36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65, 8, 9, 66, 2, 67, + 43, 43, 43, 43, 43, 60, 68, 2, 69, 36, 36, 36, 36, 70, 43, 43, + 7, 7, 7, 7, 7, 2, 2, 36, 71, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36, + 7, 7, 7, 7, 7, 36, 77, 78, 2, 2, 2, 2, 2, 2, 2, 79, + 70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36, + 36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44, + 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, + 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43, + 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64, + 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 61, 36, 36, 36, 36, 44, + 44, 57, 43, 43, 43, 43, 43, 43, 43, 82, 43, 43, 43, 43, 43, 43, + 43, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 83, 71, 84, + 85, 43, 43, 43, 83, 84, 85, 84, 70, 43, 43, 43, 36, 36, 36, 36, + 36, 43, 2, 7, 7, 7, 7, 7, 86, 36, 36, 36, 36, 36, 36, 36, + 70, 84, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 84, + 85, 43, 80, 87, 88, 87, 85, 61, 44, 44, 44, 87, 44, 44, 36, 62, + 36, 43, 44, 7, 7, 7, 7, 7, 36, 20, 27, 27, 27, 56, 63, 80, + 57, 83, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 84, + 85, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61, + 44, 44, 44, 7, 7, 7, 7, 7, 43, 36, 70, 64, 44, 44, 44, 44, + 57, 83, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36, + 61, 36, 62, 36, 36, 44, 71, 84, 85, 43, 43, 57, 83, 87, 85, 44, + 61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43, + 57, 84, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 85, + 85, 43, 80, 87, 88, 87, 85, 44, 44, 44, 44, 83, 44, 44, 36, 62, + 78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36, + 61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36, + 36, 36, 36, 36, 36, 44, 44, 84, 83, 88, 44, 84, 88, 84, 85, 44, + 61, 44, 44, 87, 44, 44, 44, 44, 27, 89, 67, 67, 56, 90, 44, 44, + 83, 84, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 44, 62, 43, 83, 84, 88, 43, 80, 43, 43, 44, + 44, 44, 57, 80, 36, 61, 44, 44, 44, 44, 44, 91, 27, 27, 27, 89, + 70, 84, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 85, + 84, 84, 88, 83, 88, 84, 43, 44, 44, 44, 87, 88, 44, 44, 44, 61, + 62, 61, 44, 44, 44, 44, 44, 44, 43, 84, 62, 36, 36, 36, 61, 36, + 36, 36, 36, 36, 36, 70, 71, 84, 85, 43, 80, 84, 88, 84, 85, 77, + 44, 44, 36, 92, 27, 27, 27, 93, 27, 27, 27, 27, 89, 36, 36, 36, + 44, 84, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36, + 36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 87, + 84, 43, 80, 80, 84, 84, 84, 84, 44, 84, 64, 44, 44, 44, 44, 44, + 62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 94, + 36, 36, 36, 75, 43, 43, 43, 60, 7, 7, 7, 7, 7, 2, 44, 44, + 62, 61, 61, 36, 36, 61, 36, 36, 36, 36, 62, 62, 36, 36, 36, 36, + 70, 36, 43, 43, 43, 43, 71, 44, 36, 36, 61, 81, 43, 43, 43, 44, + 7, 7, 7, 7, 7, 44, 36, 36, 77, 67, 2, 2, 2, 2, 2, 2, + 2, 95, 95, 67, 43, 67, 67, 67, 7, 7, 7, 7, 7, 27, 27, 27, + 27, 27, 50, 50, 50, 4, 4, 84, 36, 36, 36, 36, 62, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 61, 44, 57, 43, 43, 43, 43, 43, 43, 83, + 43, 43, 60, 43, 36, 36, 70, 43, 43, 43, 43, 43, 57, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 80, 67, 67, 67, 67, 76, 67, 67, 90, 67, + 2, 2, 95, 67, 21, 64, 44, 44, 36, 36, 36, 36, 36, 92, 85, 43, + 83, 43, 43, 43, 85, 83, 85, 71, 7, 7, 7, 7, 7, 2, 2, 2, + 36, 36, 36, 84, 43, 36, 36, 43, 71, 84, 96, 92, 84, 84, 84, 36, + 70, 43, 71, 36, 36, 36, 36, 36, 36, 83, 85, 83, 84, 84, 85, 92, + 7, 7, 7, 7, 7, 84, 85, 67, 11, 11, 11, 48, 44, 44, 48, 44, + 16, 16, 16, 16, 16, 53, 45, 16, 36, 36, 36, 36, 61, 36, 36, 44, + 36, 36, 36, 61, 61, 36, 36, 44, 61, 36, 36, 44, 36, 36, 36, 61, + 61, 36, 36, 44, 36, 36, 36, 36, 36, 36, 36, 61, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 61, 57, 43, 2, 2, 2, 2, 97, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 98, 44, 67, 67, 67, 67, 67, 44, 44, 44, + 11, 11, 11, 44, 16, 16, 16, 44, 99, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 77, 72,100, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36,101,102, 44, 36, 36, 36, 36, 36, 63, 2,103, + 104, 36, 36, 36, 61, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36, + 36, 43, 80, 44, 44, 44, 44, 44, 36, 43, 60, 64, 44, 44, 44, 44, + 36, 43, 44, 44, 44, 44, 44, 44, 61, 43, 44, 44, 44, 44, 44, 44, + 36, 36, 43, 85, 43, 43, 43, 84, 84, 84, 84, 83, 85, 43, 43, 43, + 43, 43, 2, 86, 2, 66, 70, 44, 7, 7, 7, 7, 7, 44, 44, 44, + 27, 27, 27, 27, 27, 44, 44, 44, 2, 2, 2,105, 2, 59, 43, 68, + 36,106, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 44, 44, + 36, 36, 70, 71, 36, 36, 36, 36, 36, 36, 36, 36, 70, 61, 44, 44, + 36, 36, 36, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 61, + 43, 83, 84, 85, 83, 84, 44, 44, 84, 83, 84, 84, 85, 43, 44, 44, + 90, 44, 2, 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 44, + 36, 36, 61, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 44, 44, + 36, 36, 36, 36, 36, 44, 44, 44, 7, 7, 7, 7, 7, 98, 44, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 36, 36, 36, 70, 83, 85, 44, 2, + 36, 36, 92, 83, 43, 43, 43, 80, 83, 83, 85, 43, 43, 43, 83, 84, + 84, 85, 43, 43, 43, 43, 80, 57, 2, 2, 2, 86, 2, 2, 2, 44, + 43, 43, 43, 43, 43, 43, 43,107, 43, 43, 96, 36, 36, 36, 36, 36, + 36, 36, 83, 43, 43, 83, 83, 84, 84, 83, 96, 36, 36, 36, 44, 44, + 95, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 90, 44, + 43, 96, 36, 36, 36, 36, 36, 36, 92, 43, 43, 84, 43, 85, 43, 36, + 36, 36, 36, 83, 43, 84, 85, 85, 43, 84, 44, 44, 44, 44, 2, 2, + 36, 36, 84, 84, 84, 84, 43, 43, 43, 43, 84, 43, 44, 91, 2, 2, + 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2, + 16, 16, 16, 16,108, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11, + 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43, + 83, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 92, 43, 61, 44, 44, + 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16, + 16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,109, 40, 40, + 43, 43, 43, 43, 43, 57, 43, 43, 32, 32, 32, 16, 16, 16, 16, 32, + 16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 44, 11, 11, 11, 44, + 16, 16, 16, 16, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 44, + 16, 16, 16, 16,110,110,110,110, 16, 16,108, 16, 11, 11,111,112, + 41, 16,108, 16, 11, 11,111, 41, 16, 16, 44, 16, 11, 11,113, 41, + 16, 16, 16, 16, 11, 11,114, 41, 44, 16,108, 16, 11, 11,111,115, + 116,116,116,116,116,117, 65, 65,118,118,118, 2,119,120,119,120, + 2, 2, 2, 2,121, 65, 65,122, 2, 2, 2, 2,123,124, 2,125, + 126, 2,127,128, 2, 2, 2, 2, 2, 9,126, 2, 2, 2, 2,129, + 65, 65, 68, 65, 65, 65, 65, 65,130, 44, 27, 27, 27, 8,127,131, + 27, 27, 27, 27, 27, 8,127,102, 40, 40, 40, 40, 40, 40, 81, 44, + 20, 20, 20, 20, 20, 20, 20, 20, 43, 43, 43, 43, 43, 43,132, 51, + 133, 51,133, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44, + 67,134, 67,135, 67, 34, 11, 16, 11, 32,135, 67, 49, 11, 11, 67, + 67, 67,134,134,134, 11, 11,136, 11, 11, 35, 36, 39, 67, 16, 11, + 8, 8, 49, 16, 16, 26, 67,137, 27, 27, 27, 27, 27, 27, 27, 27, + 103,103,103,103,103,103,103,103,103,138,139,103,140, 67, 44, 44, + 8, 8,141, 67, 67, 8, 67, 67,141, 26, 67,141, 67, 67, 67,141, + 67, 67, 67, 67, 67, 67, 67, 8, 67,141,141, 67, 67, 67, 67, 67, + 67, 67, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,142,143, 67, 67, + 67, 67, 67, 67, 67, 67,141, 67, 67, 67, 67, 67, 67, 26, 8, 8, + 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, + 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 90, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67, + 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67, + 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8, + 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4, + 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, + 8, 8,127,144, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, + 8,127,145,145,145,145,145,145,145,145,145,145,144, 8, 8, 8, + 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, + 8, 8,141, 26, 8, 8,141, 67, 67, 67, 44, 67, 67, 67, 67, 67, + 67, 67, 67, 44, 67, 67, 67, 67, 11, 11, 11, 11, 11, 11, 11, 47, + 16, 16, 16, 16, 16, 16, 16,108, 32, 11, 32, 34, 34, 34, 34, 11, + 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,137, 67, 67,135, 34,146, + 43, 32, 44, 44, 91, 2, 97, 2, 16, 16, 16,147, 44, 44,147, 44, + 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57, + 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61, + 2,119,119, 2,123,124,119, 2, 2, 2, 2, 6, 2,105,119, 2, + 119, 4, 4, 4, 4, 2, 2, 86, 2, 2, 2, 2, 2,118, 2, 2, + 105,148, 2, 2, 2, 2, 2, 2, 67, 67, 67, 67, 67, 55, 67, 67, + 67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44, + 67, 67, 67, 67, 67, 67, 44, 44, 1, 2,149,150, 4, 4, 4, 4, + 4, 67, 4, 4, 4, 4,151,152,153,103,103,103,103, 43, 43, 84, + 154, 40, 40, 67,103,155, 63, 67, 36, 36, 36, 61, 57,156,157, 69, + 36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36, + 67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, + 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, + 158, 27, 27, 27, 27, 27, 27, 27, 36, 36,106, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36,159, 2, 7, 7, 7, 7, 7, 36, 44, 44, + 32, 32, 32, 32, 32, 32, 32, 70, 51,160, 43, 43, 43, 43, 43, 86, + 32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36,103,103,103,103,103, + 43, 2, 2, 2, 44, 44, 44, 44, 41, 41, 41,157, 40, 40, 40, 40, + 41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, + 45, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,161, 34, 35, + 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32, + 11, 11, 32, 32, 32, 32, 32, 32, 44, 32, 11, 47, 44, 44, 44, 44, + 44, 44, 44, 62, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36, + 36, 92, 85, 83, 67, 67, 44, 44, 27, 27, 27, 67,162, 44, 44, 44, + 36, 36, 2, 2, 44, 44, 44, 44, 84, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 84, 84, 84, 84, 84, 84, 84, 84, 43, 44, 44, 44, 44, 2, + 43, 36, 36, 36, 2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43, 2, + 36, 36, 36, 70, 43, 43, 43, 43, 43, 84, 44, 44, 44, 44, 44, 91, + 36, 70, 84, 43, 43, 84, 43, 84,163, 2, 2, 2, 2, 2, 2, 52, + 7, 7, 7, 7, 7, 44, 44, 2, 36, 36, 70, 69, 36, 36, 36, 36, + 7, 7, 7, 7, 7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 83, + 85, 83, 85, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 83, 44, + 7, 7, 7, 7, 7, 44, 2, 2, 69, 36, 36, 77, 67, 92, 83, 36, + 71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 62,106, 2, 36, 36, 36, 36, 36, 92, 43, 84, + 2,106,164, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61, + 62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,112, 40, 40, + 16, 16, 16, 16, 44, 44, 44, 44, 36, 92, 85, 84, 83,163, 85, 44, + 36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36, + 165,165,165,165,165,165,165,165,166,166,166,166,166,166,166,166, + 16, 16, 16,108, 44, 44, 44, 44, 44,147, 16, 16, 44, 44, 62, 71, + 36, 36, 36, 36,167, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61, + 36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41, + 41, 44, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36,145, 44, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,162, 44, + 2, 2, 2,168,128, 44, 44, 44, 6,169,170,145,145,145,145,145, + 145,145,128,168,128, 2,125,171, 2, 64, 2, 2,151,145,145,128, + 2,172, 8,173, 66, 2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 61, 79, 91, 2, 3, 2, 4, 5, 6, 2, + 16, 16, 16, 16, 16, 17, 18,127,128, 4, 2, 36, 36, 36, 36, 36, + 69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40, + 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44, + 20,174, 56,175, 26, 8,141, 90, 44, 44, 44, 44, 79, 65, 67, 44, + 36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62, + 2, 64, 44,176, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67, + 103,103,140, 27, 89, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 90, + 90, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 50, 44, + 177, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 44, 44, + 27, 27, 44, 44, 44, 44, 62, 36,150, 36, 36, 36, 36,178, 44, 44, + 36, 36, 36, 43, 43, 80, 44, 44, 36, 36, 36, 36, 36, 36, 36, 91, + 36, 36, 44, 44, 36, 36, 36, 36,179,103,103, 44, 44, 44, 44, 44, + 11, 11, 11, 11, 16, 16, 16, 16, 11, 11, 44, 44, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 44, 44, 36, 36, 44, 44, 44, 44, 44, 91, + 36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62, + 36, 36, 36, 91, 27, 27, 27, 27, 36, 36, 36, 77,158, 27, 27, 27, + 44, 44, 44,176, 27, 27, 27, 27, 36, 61, 36, 44, 44,176, 27, 27, + 36, 36, 36, 27, 27, 27, 44, 91, 36, 36, 36, 36, 36, 44, 44, 91, + 36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27, + 70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36, + 36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27, 98, 44, 44, 44, + 2, 2, 2, 2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,180, 30, + 36, 36, 36, 36, 36, 36,180, 27, 36, 36, 36, 36, 78, 36, 36, 36, + 36, 36, 70, 80, 44,176, 27, 27, 2, 2, 2, 64, 44, 44, 44, 44, + 36, 36, 36, 44, 91, 2, 2, 2, 36, 36, 36, 44, 27, 27, 27, 27, + 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 91, 2, 64, 44, + 44, 44, 44, 44,176, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44, + 16,108, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44, + 27, 27, 27, 27, 27, 27, 27, 98, 27, 27, 27, 93, 44, 44, 44, 44, + 177, 27, 30, 2, 2, 44, 44, 44, 85, 96, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60, 2, 2, 2, 44, + 27, 27, 27, 7, 7, 7, 7, 7, 44, 44, 44, 44, 44, 44, 44, 57, + 84, 85, 43, 83, 85, 60,181, 2, 2, 44, 44, 44, 44, 44, 79, 44, + 43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 85, 43, + 43, 43, 80, 7, 7, 7, 7, 7, 2, 2, 92, 88, 44, 44, 44, 44, + 36, 70, 2, 61, 44, 44, 44, 44, 36, 92, 84, 43, 43, 43, 43, 83, + 96, 36, 63, 2, 59, 43, 60, 44, 7, 7, 7, 7, 7, 63, 63, 2, + 176, 27, 27, 27, 27, 27, 27, 27, 27, 27, 98, 44, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 84, 85, 43, 84, 83, 43, 2, 2, 2, 80, + 36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62, + 36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70, + 84, 85, 43, 43, 43, 80, 44, 44, 43, 84, 62, 36, 36, 36, 61, 62, + 61, 36, 62, 36, 36, 57, 71, 84, 83, 84, 88, 87, 88, 87, 84, 44, + 61, 44, 44, 87, 44, 44, 62, 36, 36, 84, 44, 43, 43, 43, 80, 44, + 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 92, 84, 43, 43, 43, 43, + 84, 43, 83, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 91, 91, 71, + 84, 85, 43, 43, 83, 83, 84, 85, 83, 43, 36, 72, 44, 44, 44, 44, + 36, 36, 36, 36, 36, 36, 36, 92, 84, 43, 43, 44, 84, 84, 43, 85, + 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44, + 84, 85, 43, 43, 43, 83, 85, 85, 60, 2, 61, 44, 44, 44, 44, 44, + 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 85, 84, + 43, 43, 43, 85, 61, 44, 44, 44, 84, 43, 43, 85, 43, 43, 44, 44, + 7, 7, 7, 7, 7, 27, 2, 95, 43, 43, 43, 43, 85, 60, 44, 44, + 27, 98, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 44, 36, 36, 36, + 92, 84, 43, 43, 44, 43, 84, 84, 71, 72, 88, 44, 44, 44, 44, 44, + 70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 83, 70, 43, 60, + 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 83, 85, 43, 36, 36, + 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 83, 43, 2, 72, 2, + 2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 85, + 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36, + 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 87, 43, 43, 43, + 83, 43, 85, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36, + 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44, + 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 84, 84, 88, + 43, 87, 85, 85, 61, 44, 44, 44, 36, 70, 83,163, 64, 44, 44, 44, + 27, 27, 89, 67, 67, 67, 56, 20,162, 67, 67, 67, 67, 67, 67, 67, + 67, 44, 44, 44, 44, 44, 44, 91,103,103,103,103,103,103,103,178, + 2, 2, 64, 44, 44, 44, 44, 44, 65, 65, 65, 65, 68, 44, 44, 44, + 43, 43, 60, 44, 44, 44, 44, 44, 43, 43, 43, 60, 2, 2, 67, 67, + 40, 40, 95, 44, 44, 44, 44, 44, 7, 7, 7, 7, 7,176, 27, 27, + 27, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 44, 44, 62, 36, + 27, 27, 27, 30, 2, 64, 44, 44, 36, 36, 36, 36, 36, 61, 44, 57, + 92, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 44, 44, 44, 57, 43, 74, 40, 40, 40, 40, 40, 40, + 40, 86, 44, 44, 44, 44, 44, 44, 36, 61, 44, 44, 44, 44, 44, 44, + 44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60, + 65, 65, 44, 44, 44, 44, 44, 44, 67, 67, 67, 90, 55, 67, 67, 67, + 67, 67,182, 85, 43, 67,182, 84, 84,183, 65, 65, 65, 82, 43, 43, + 43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67, + 67, 67, 67, 67, 90, 44, 44, 44, 67, 43, 76, 44, 44, 44, 44, 44, + 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16, + 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, + 16, 16,108, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11, + 11, 11, 11, 16, 16,147,147, 16, 16, 16,147, 16, 16, 16, 16, 16, + 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16, + 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11, + 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11, + 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11, + 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, + 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, + 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, + 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43, + 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67, + 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43, + 43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43, + 43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44, + 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 43, 43, + 7, 7, 7, 7, 7, 44, 44, 94, 36, 36, 61,176, 27, 27, 27, 27, + 43, 43, 43, 80, 44, 44, 44, 44, 16, 16, 43, 43, 43, 74, 44, 44, + 27, 27, 27, 27, 27, 27,158, 27,184, 27, 98, 44, 44, 44, 44, 44, + 27, 27, 27, 27, 27, 27, 27,158, 27, 27, 27, 27, 27, 27, 27, 44, + 36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36, + 36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36, + 62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36, + 36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36, + 62, 36, 62, 36, 36, 62, 36, 36, 8, 44, 44, 44, 44, 44, 44, 44, + 55, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, 44, + 44, 44, 44, 67, 67, 67, 67, 67, 67, 90, 44, 44, 44, 44, 44, 44, + 67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41, + 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 44, + 67, 67, 67, 67, 67, 67, 55, 67, 67, 55, 67, 90, 44, 67, 67, 67, + 67, 90, 55, 67, 67, 90, 44, 67, 67, 67, 67, 67, 67, 90, 55, 67, + 67, 67, 44, 44, 67, 90, 44, 44, 36, 44, 44, 44, 44, 44, 44, 44, + 79, 44, 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, 65, 65, 65, 65, + 166,166,166,166,166,166,166, 44,166,166,166,166,166,166,166, 0, + 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13, + 25, 25, 25, 21, 21, 9, 9, 9, 9, 22, 21, 18, 24, 16, 24, 5, + 5, 5, 5, 22, 25, 18, 25, 0, 23, 23, 26, 21, 24, 26, 7, 20, + 25, 1, 26, 24, 26, 25, 15, 15, 24, 15, 7, 19, 15, 21, 9, 25, + 9, 5, 5, 25, 5, 9, 5, 7, 7, 7, 9, 8, 8, 5, 7, 5, + 6, 6, 24, 24, 6, 24, 12, 12, 2, 2, 6, 5, 9, 21, 9, 2, + 2, 9, 25, 9, 26, 12, 11, 11, 2, 6, 5, 21, 17, 2, 2, 26, + 26, 23, 2, 12, 17, 12, 21, 12, 12, 21, 7, 2, 2, 7, 7, 21, + 21, 2, 1, 1, 21, 23, 26, 26, 1, 2, 6, 7, 7, 12, 12, 7, + 21, 7, 12, 1, 12, 6, 6, 12, 12, 26, 7, 26, 26, 7, 2, 1, + 12, 2, 6, 2, 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 2, 10, + 10, 2, 15, 26, 26, 2, 2, 21, 7, 10, 15, 7, 2, 23, 21, 26, + 10, 7, 21, 15, 15, 2, 17, 7, 29, 7, 7, 22, 18, 2, 14, 14, + 14, 7, 17, 21, 7, 6, 11, 2, 5, 2, 5, 6, 8, 8, 8, 24, + 5, 24, 2, 24, 9, 24, 24, 2, 29, 29, 29, 1, 17, 17, 20, 19, + 22, 20, 27, 28, 1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22, + 18, 21, 21, 29, 15, 6, 18, 6, 12, 11, 11, 12, 9, 26, 26, 9, + 26, 5, 5, 26, 14, 9, 5, 14, 14, 15, 25, 26, 26, 22, 18, 26, + 18, 25, 18, 22, 5, 12, 2, 5, 22, 21, 26, 6, 7, 14, 17, 22, + 18, 18, 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15, 6, 21, + 11, 21, 24, 9, 23, 26, 10, 21, 6, 10, 4, 4, 3, 3, 7, 25, + 21, 22, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 23, 2, + 2, 15, 12, 15, 14, 2, 21, 14, 7, 15, 21, 1, 26, 10, 10, 1, + 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, + 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 0, 0, 0, 0, + 0, 0, 38, 39, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 8, 0, 9, 0, 10, 11, 0, 0, 12, 13, + 14, 15, 16, 0, 0, 0, 0, 17, 18, 19, 20, 0, 0, 0, 21, 22, + 0, 23, 24, 0, 0, 23, 25, 26, 0, 23, 25, 0, 0, 23, 25, 0, + 0, 23, 25, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 23, 25, 0, + 0, 28, 25, 0, 0, 0, 29, 0, 0, 30, 31, 0, 0, 32, 33, 0, + 34, 35, 0, 36, 37, 0, 38, 0, 0, 39, 0, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 42, 42, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 44, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 46, 0, 0, 47, 0, 48, 0, 0, + 0, 49, 50, 51, 0, 52, 0, 53, 0, 54, 0, 0, 0, 0, 55, 56, + 0, 0, 0, 0, 0, 0, 57, 58, 0, 0, 0, 0, 0, 0, 59, 60, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, + 0, 0, 0, 62, 0, 0, 0, 63, 0, 64, 0, 0, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 0, 0, 68, + 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 50, 70, + 0, 71, 72, 0, 0, 73, 74, 0, 0, 0, 0, 0, 0, 75, 76, 77, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 81, + 0, 0, 0, 82, 0, 0, 0, 0, 83, 84, 0, 0, 0, 0, 0, 85, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 69, 62, 0, 88, 0, 0, + 89, 90, 0, 73, 0, 0, 91, 0, 0, 92, 0, 0, 0, 0, 0, 93, + 0, 94, 25, 95, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 97, 0, + 0, 0, 0, 0, 0, 62, 98, 0, 0, 62, 0, 0, 0, 99, 0, 0, + 0,100, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 74, 0, 42,101, 0,102, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 0,103, 0,104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, + 0,106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,108,109,110, 0, 0, 0, 0,111, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,112,113, 0, 0, 0, 0, 0, 0, + 0,106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 0, + 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, 4, 8, 9, 10, + 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 0, 0, 0, 0, + 19, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 1, + 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, + 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 39, + 14, 39, 40, 41, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 0, 0, + 0, 0, 19, 1, 21, 0, 0, 47, 0, 0, 0, 0, 0, 38, 48, 1, + 1, 49, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, + 0, 0, 0, 0, 52, 1, 1, 1, 53, 21, 43, 54, 55, 21, 35, 1, + 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 57, 58, 59, 0, 0, + 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, + 0, 0, 0, 57, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, + 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, + 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, + 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, + 0, 0, 0, 0, 0, 70, 71, 0, 0, 0, 0, 0, 72, 73, 74, 75, + 76, 77, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 79, 80, 0, 0, 0, 0, 47, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 64, 0, 0, 81, 0, 0, 82, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 19, 84, 0, + 63, 0, 0, 0, 0, 49, 1, 85, 0, 0, 0, 0, 1, 54, 15, 41, + 0, 0, 0, 0, 0, 56, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, + 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, + 0, 87, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, + 0, 0, 0, 0, 88, 9, 12, 4, 89, 8, 90, 47, 0, 59, 50, 0, + 21, 1, 21, 91, 92, 1, 1, 1, 1, 1, 1, 1, 1, 93, 94, 95, + 0, 0, 0, 0, 96, 1, 97, 59, 81, 98, 99, 4, 59, 0, 0, 0, + 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,100,101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0, 19, 0, 1, 1, 50, + 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 50, 0, 0, 0, + 0, 64, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 50, 0, 0, 0, + 0, 0, 52, 69, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, + 0, 0, 0, 0, 79, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,103,104, 59, 38, 81, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, + 1, 14, 4, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, + 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 88, 0, + 0, 0, 0,106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 62, + 0,108, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0,109, 14, 54, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0, + 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 0, 0, + 63, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0, 0, + 0, 0,111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 56, + 0, 38, 1, 59, 1, 59, 0, 0, 64, 87, 0, 0, 0, 0, 0, 60, + 112, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,112, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, + 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, + 87,113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, + 0, 0, 0, 0, 8, 90, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, + 0, 0, 0, 0, 0, 0, 0,114, 0,115,116,117,118, 0, 52, 4, + 119, 49, 23, 0, 0, 0, 0, 0, 0, 0, 38, 50, 0, 0, 0, 0, + 38, 59, 0, 0, 0, 0, 0, 0, 1, 88, 1, 1, 1, 1, 39, 1, + 48,103, 88, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 4,119, 0, 0, 0, 1,120, 0, 0, 0, 0, 0, + 0, 0, 0, 0,230,230,230,230,230,232,220,220,220,220,232,216, + 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220, + 1, 1, 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220, + 220,220,230,230,230,220,220, 0,230,230,230,220,220,220,220,230, + 232,220,220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, + 0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220, + 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, + 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, + 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230, + 220,230,230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230, + 230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230, + 220,220,230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0, + 230,230, 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220, + 0, 0, 0,220,230,230, 0,220,230,220,220,220, 27, 28, 29,230, + 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, + 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 9, 0,103,103, 9, 0,107,107,107,107,118,118, 9, 0, + 122,122,122,122,220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0, + 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0, + 130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7, + 0, 9, 9, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220, + 220, 0, 0, 0,230, 0, 0,220, 0, 0, 9, 9, 0, 0, 7, 0, + 230,230,230, 0,230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220, + 202,230,230,230,230,230,232,228,228,220, 0,230,233,220,230,220, + 230,230, 1, 1, 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, + 0, 0,218,228,232,222,224,224, 0, 8, 8, 0,230, 0,230,230, + 220, 0, 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, + 0,230,220, 0, 0, 0,220,220, 0, 9, 7, 0, 0, 7, 9, 0, + 0, 0, 9, 7, 9, 9, 0, 0, 0, 0, 1, 0, 0,216,216, 1, + 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,220,220,220, 0, + 230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19, + 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 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,237, 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26, 0, 27, 0, 28, + 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 0, 0, + 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, + 0, 0, 0, 0, 1, 2, 39, 40, 0, 1, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 11, 12, + 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19, + 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8, + 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27, + 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 20, 20, + 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20, + 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20, + 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0, + 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45, + 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1, + 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 20, 20, + 1, 20, 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 9, 10, 11, 12, 12, 12, 12, 13, 14, + 14, 14, 14, 15, 16, 17, 18, 19, 20, 14, 21, 14, 22, 14, 14, 14, + 14, 23, 24, 24, 25, 26, 14, 14, 14, 14, 27, 28, 14, 14, 29, 30, + 31, 32, 33, 34, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 35, 7, 36, 37, 7, 38, 7, 7, + 7, 39, 14, 40, 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, 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, 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, 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, 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, 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, 41, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, + 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 2, 2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59, + 59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 79, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 82, + 83, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 70, 70, 98, 99,100,101,102,102, + 103,104,105,106,107,108,109,110,111,112, 97,113,114,115,116,117, + 118, 97,119,119,120, 97,121,122,123,124,125,126,127,128,129,130, + 131, 97,132, 97,133,134,135,136,137,138,139,140,141, 97,142,143, + 97,144,145,146,147, 97,148,149, 97,150,151,152, 97, 97,153,154, + 155,156, 97,157, 97,158,159,159,159,159,159,159,159,160,161,159, + 162, 97, 97, 97, 97, 97,163,163,163,163,163,163,163,163,164, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,165,165, + 165,165,166, 97, 97, 97,167,167,167,167,168,169,170,171, 97, 97, + 97, 97,172,173,174,175,176,176,176,176,176,176,176,176,176,176, + 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, + 176,176,176,176,176,177,176,176,176,176,176,178, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,179,180,181, 32, 32,182, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,183,184, + 97, 97, 97, 97, 97, 97, 59,185,186,187,188,189,190, 97,191,192, + 193, 59, 59,194, 59,195,196,196,196,196,196,197, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,198, 97,199, 97, 97,200, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,201,202,203, 97, 97, 97, 97, 97,204,205, + 206, 97,207,208, 97, 97,209,210,211,212,213, 97, 59, 59, 59, 59, + 59, 59, 59,214,215,216,217,218,219,220,221,222, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70,223, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70,224, 70,225, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70,227, 97, 97, + 97, 97, 97, 97, 97, 97, 70, 70, 70, 70,228, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,229, 97,230,231, 0, 1, 2, 2, 0, 1, + 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, + 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, + 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 0, + 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, + 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 2, 3, 0, 0, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, + 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37, + 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, + 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5, + 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, + 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, + 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, + 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5, + 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11, + 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2, + 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, + 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11, + 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11, + 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2, + 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10, + 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, + 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, + 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10, + 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2, + 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, + 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21, + 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, + 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, + 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21, + 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2, + 2, 2, 2, 2, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21, + 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22, + 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22, + 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2, + 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, + 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, + 2, 2, 2, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2, + 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 2, 2, 2, 23, 23, + 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, + 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2, + 2, 2, 2, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 2, 16, 16, + 16, 16, 2, 2, 16, 16, 2, 16, 16, 2, 2, 2, 2, 2, 20, 20, + 20, 20, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, + 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 2, + 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, + 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2, + 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, + 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18, + 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18, + 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, + 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25, + 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, + 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2, + 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12, + 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, + 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30, + 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30, + 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2, + 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 2, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2, + 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32, + 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 32, 2, + 2, 2, 2, 2, 2, 2, 32, 32, 32, 2, 2, 2, 2, 2, 28, 28, + 28, 28, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 2, 2, 2, 2, 48, 2, + 2, 2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 58, 58, + 2, 2, 2, 2, 2, 2, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 91, 91, + 91, 91, 91, 2, 2, 91, 91, 91, 2, 2, 2, 2, 2, 2, 91, 91, + 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 2, 2, 2, 2, 62, 62, + 62, 62, 62, 2, 2, 2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2, + 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2, + 2, 70, 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 73, 73, + 73, 73, 73, 73, 73, 73, 6, 2, 2, 2, 2, 2, 2, 2, 8, 8, + 8, 2, 2, 8, 8, 8, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 19, 19, + 19, 19, 19, 19, 9, 9, 9, 9, 9, 6, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9, + 9, 19, 19, 19, 19, 19, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 9, 1, 1, 2, 1, 1, 1, 1, 1, 9, 9, + 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9, + 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, + 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19, + 19, 19, 19, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 19, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 19, 0, 19, 0, 0, 0, 2, 2, 2, 2, 0, 0, + 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2, 55, 55, + 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61, + 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2, + 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, + 13, 13, 13, 13, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 1, 1, 1, 12, 12, 13, 13, 13, 13, 0, 0, 0, 0, 2, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 2, 2, 1, 1, 0, 0, 15, 15, 15, 0, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 2, 26, 26, 26, 2, 2, 2, 2, 2, 12, 12, + 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39, + 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79, + 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0, + 0, 19, 19, 19, 19, 19, 2, 2, 19, 19, 19, 19, 19, 2, 2, 2, + 2, 2, 2, 2, 2, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65, + 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, + 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12, + 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33, + 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68, + 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30, + 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 9, 19, 19, 87, 87, 87, 87, 87, 87, 2, 2, 87, 87, + 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, + 2, 12, 12, 12, 12, 12, 13, 13, 2, 2, 2, 2, 2, 2, 19, 19, + 19, 19, 19, 19, 19, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14, + 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 3, 3, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2, + 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 6, 6, 0, 0, + 0, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2, + 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49, + 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0, + 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 9, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 2, 2, 2, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 2, 2, 2, 2, 2, 2, 2, 2, 2, 42, 42, 42, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 2, 2, 2, 2, 2,118,118, + 118,118,118,118,118,118,118,118,118, 2, 2, 2, 2, 2, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59, + 59, 59, 59, 59, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, + 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 2, 2, 50, 50, 2, 2, 2, 2, 2, 2,135,135, + 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,106,106, + 106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104, + 104,104, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,104,110,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110, + 110,110,110,110, 2, 2, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120, + 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116, + 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128, + 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2, + 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2, + 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2, + 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, + 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117, + 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112, + 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, + 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122, + 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122, + 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, + 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, + 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130, 3, 3, + 3, 3, 3, 3, 3, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, + 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101, + 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, + 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100, 2, 2, 2, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108, + 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, + 108,108,108,108,108, 2,129,129,129,129,129,129,129, 2,129, 2, + 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109, + 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109, + 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, + 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, + 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2, + 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2, + 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, + 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, + 107,107,107, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, + 2,137, 2,137,137,137,124,124,124,124,124,124,124,124,124,124, + 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123, + 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114, + 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32, + 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102, 2, + 2, 2, 2, 2, 2, 2,102,102, 2, 2, 2, 2, 2, 2,126,126, + 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126, + 126,126, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2,125,125, + 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2,125, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 2, 2, 2, 7, 7, 7, 2, 2, 2, 2, 2,121,121, + 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2,133,133, + 133,133,133,133,133,133,133, 2,133,133,133,133,133,133,133,133, + 133,133,133,133,133, 2,133,133,133,133,133,133, 2, 2,133,133, + 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134, 2, 2, + 134,134,134,134,134,134, 2,134,134,134,134,134,134,134,134,134, + 134,134,134,134,134, 2, 8, 8, 8, 8, 8, 8, 8, 2, 8, 8, + 2, 8, 8, 8, 8, 8, 2, 2, 8, 2, 8, 8, 2, 8, 8, 8, + 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 2, 9, 9, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 22, 22, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, 63, 63, + 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 63, 63, + 63, 63, 2, 2, 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 2, 80, 2, 2, 2, 2, 2, 2, 2,127,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 79, 2, + 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115, + 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,103,103, + 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119, + 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119, + 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119, 11, 11, + 11, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 2, 2, 2, 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136, 12, + 0, 0, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136,136, + 136, 2, 2, 2, 2, 2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,105,105, + 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, + 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, + 2, 2,105,105,105,105, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,131,131, + 131,131,131,131,131,131,131,131,131,131, 2, 2, 2, 2, 2, 2, + 2,131,131,131,131,131, 2,131,131,131,131,131,131,131, 56, 2, + 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56, + 56, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 2, 2, 2, 13, 13, + 2, 2, 2, 2, 13, 13, 14, 14, 2, 2, 2, 2, 2, 14,113,113, + 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113, + 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132, + 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 0, 0, + 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, + 3, 2, 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, + 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, + 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 13, 13, + 13, 13, 13, 13, 13, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 16, 50, 84,118, 88, 89, 90, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, + 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, + 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, + 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, + 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, + 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105, + 106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,111,112,113, 0, + 114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122, + 123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,134,135,136,137, + 138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153, + 154,155,156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162, + 163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,169, 0, 0, 0, + 0,170,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,172,173,174,175,176,177,178,179,180,181, + 182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, + 198,199,200,201,202,203,204,205, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, +}; +static const uint16_t +_hb_ucd_u16[8928] = +{ + 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, + 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, + 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31, + 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39, + 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13, + 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50, + 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58, + 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66, + 48, 67, 68, 69, 48, 70, 71, 72, 72, 72, 48, 73, 72, 74, 75, 32, + 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101, + 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113, + 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124, + 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135, + 136, 48, 48, 137, 138, 139, 72, 72, 140, 48, 141, 142, 143, 144, 72, 72, + 145, 146, 147, 148, 149, 48, 150, 151, 152, 153, 32, 154, 155, 156, 72, 72, + 48, 48, 157, 158, 159, 160, 161, 162, 163, 164, 9, 9, 165, 11, 11, 166, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 167, 168, 48, 48, + 167, 48, 48, 169, 170, 171, 48, 48, 48, 170, 48, 48, 48, 172, 173, 174, + 48, 175, 9, 9, 9, 9, 9, 176, 177, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 178, 48, 179, 180, 48, 48, 48, 48, 181, 182, + 183, 184, 48, 185, 48, 186, 183, 187, 48, 48, 48, 188, 189, 190, 191, 192, + 193, 191, 48, 48, 194, 48, 48, 195, 196, 48, 197, 48, 48, 48, 48, 198, + 48, 199, 200, 201, 202, 48, 203, 204, 48, 48, 205, 48, 206, 207, 208, 208, + 48, 209, 48, 48, 48, 210, 211, 212, 191, 191, 213, 214, 72, 72, 72, 72, + 215, 48, 48, 216, 217, 159, 218, 219, 220, 48, 221, 64, 48, 48, 222, 223, + 48, 48, 224, 225, 226, 64, 48, 227, 228, 9, 9, 229, 230, 231, 232, 233, + 11, 11, 234, 27, 27, 27, 235, 236, 11, 237, 27, 27, 32, 32, 32, 238, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 239, 13, 13, 13, 13, 13, 13, + 240, 241, 240, 240, 241, 242, 240, 243, 244, 244, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260, 72, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 270, 271, 272, 273, 208, 274, 275, 208, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 278, 208, 279, 208, 208, 208, 208, 280, + 208, 281, 277, 282, 208, 283, 284, 208, 208, 208, 285, 72, 286, 72, 269, 269, + 269, 287, 208, 208, 208, 208, 288, 269, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 289, 290, 208, 208, 291, 208, 208, 208, 208, 208, 208, 292, 208, + 208, 208, 208, 208, 208, 208, 293, 294, 269, 295, 208, 208, 296, 277, 297, 277, + 298, 299, 277, 277, 277, 300, 277, 301, 208, 208, 208, 277, 302, 208, 208, 303, + 208, 304, 208, 208, 208, 208, 208, 208, 9, 9, 305, 11, 11, 306, 307, 308, + 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313, + 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 72, 72, 72, + 208, 321, 208, 208, 208, 208, 208, 322, 208, 208, 208, 208, 208, 323, 72, 324, + 325, 326, 327, 328, 136, 48, 48, 48, 48, 329, 177, 48, 48, 48, 48, 330, + 331, 48, 48, 136, 48, 48, 48, 48, 199, 332, 48, 71, 208, 208, 322, 48, + 208, 333, 334, 208, 335, 336, 208, 208, 334, 208, 208, 336, 208, 208, 208, 208, + 48, 48, 48, 198, 208, 208, 208, 208, 48, 48, 48, 48, 48, 48, 48, 72, + 48, 337, 48, 48, 48, 48, 48, 48, 150, 208, 208, 208, 285, 48, 48, 227, + 338, 48, 339, 72, 13, 13, 340, 341, 13, 342, 48, 48, 48, 48, 343, 344, + 31, 345, 346, 347, 13, 13, 13, 348, 349, 350, 351, 352, 353, 72, 72, 354, + 355, 48, 356, 357, 48, 48, 48, 358, 359, 48, 48, 360, 361, 191, 32, 362, + 64, 48, 363, 48, 364, 365, 48, 150, 76, 48, 48, 366, 367, 368, 369, 370, + 48, 48, 371, 372, 373, 374, 48, 375, 48, 48, 48, 376, 377, 378, 379, 380, + 381, 382, 315, 11, 11, 383, 384, 11, 11, 11, 11, 11, 48, 48, 385, 191, + 48, 48, 386, 48, 387, 48, 48, 205, 388, 388, 388, 388, 388, 388, 388, 388, + 389, 389, 389, 389, 389, 389, 389, 389, 48, 48, 48, 48, 48, 48, 203, 48, + 48, 48, 48, 48, 48, 206, 72, 72, 390, 391, 392, 393, 394, 48, 48, 48, + 48, 48, 48, 395, 396, 397, 48, 48, 48, 48, 48, 398, 72, 48, 48, 48, + 48, 399, 48, 48, 400, 72, 72, 401, 32, 402, 32, 403, 404, 405, 406, 407, + 48, 48, 48, 48, 48, 48, 48, 408, 409, 2, 3, 4, 5, 410, 411, 412, + 48, 413, 48, 199, 414, 415, 416, 417, 418, 48, 171, 419, 203, 203, 72, 72, + 48, 48, 48, 48, 48, 48, 48, 71, 420, 269, 269, 421, 270, 270, 270, 422, + 423, 324, 424, 72, 72, 208, 208, 425, 72, 72, 72, 72, 72, 72, 72, 72, + 48, 150, 48, 48, 48, 100, 426, 427, 48, 48, 428, 48, 429, 48, 48, 430, + 48, 431, 48, 48, 432, 433, 72, 72, 9, 9, 434, 11, 11, 48, 48, 48, + 48, 203, 191, 9, 9, 435, 11, 436, 48, 48, 400, 48, 48, 48, 437, 72, + 48, 48, 48, 314, 48, 198, 400, 72, 438, 48, 48, 439, 48, 440, 48, 441, + 48, 199, 442, 72, 72, 72, 48, 443, 48, 444, 48, 445, 72, 72, 72, 72, + 48, 48, 48, 446, 269, 447, 269, 269, 448, 449, 48, 450, 451, 452, 48, 453, + 48, 454, 72, 72, 455, 48, 456, 457, 48, 48, 48, 458, 48, 459, 48, 460, + 48, 461, 462, 72, 72, 72, 72, 72, 48, 48, 48, 48, 195, 72, 72, 72, + 9, 9, 9, 463, 11, 11, 11, 464, 48, 48, 465, 191, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 269, 466, 48, 454, 467, 48, 62, 468, 72, 72, + 72, 72, 72, 72, 72, 72, 48, 314, 469, 48, 48, 470, 471, 447, 472, 473, + 220, 48, 48, 474, 475, 48, 195, 191, 476, 48, 477, 478, 479, 48, 48, 480, + 220, 48, 48, 481, 482, 483, 484, 485, 48, 97, 486, 487, 72, 72, 72, 72, + 488, 489, 490, 48, 48, 491, 492, 191, 493, 83, 84, 494, 495, 496, 497, 498, + 48, 48, 48, 499, 500, 501, 72, 72, 48, 48, 48, 502, 503, 191, 72, 72, + 48, 48, 504, 505, 506, 507, 72, 72, 48, 48, 48, 508, 509, 191, 510, 72, + 48, 48, 511, 512, 191, 72, 72, 72, 48, 172, 513, 514, 72, 72, 72, 72, + 48, 48, 486, 515, 72, 72, 72, 72, 72, 72, 9, 9, 11, 11, 147, 516, + 72, 72, 517, 48, 48, 518, 519, 72, 520, 48, 48, 521, 522, 523, 48, 48, + 524, 525, 526, 72, 48, 48, 48, 195, 84, 48, 504, 527, 528, 147, 174, 529, + 48, 530, 531, 532, 72, 72, 72, 72, 533, 48, 48, 534, 535, 191, 536, 48, + 537, 538, 191, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 48, 539, + 72, 72, 72, 72, 269, 540, 541, 542, 48, 206, 72, 72, 72, 72, 72, 72, + 270, 270, 270, 270, 270, 270, 543, 544, 48, 48, 48, 48, 386, 72, 72, 72, + 48, 48, 199, 545, 72, 72, 72, 72, 48, 48, 48, 48, 314, 72, 72, 72, + 48, 48, 48, 195, 48, 199, 368, 72, 72, 72, 72, 72, 72, 48, 203, 546, + 48, 48, 48, 547, 548, 549, 550, 551, 48, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 9, 9, 11, 11, 269, 552, 72, 72, 72, 72, 72, 72, + 48, 48, 48, 48, 553, 554, 555, 555, 556, 557, 72, 72, 72, 72, 558, 72, + 48, 48, 48, 48, 48, 48, 48, 400, 48, 48, 48, 48, 48, 48, 48, 559, + 48, 199, 72, 72, 72, 559, 560, 48, 48, 48, 48, 48, 48, 48, 48, 205, + 48, 48, 48, 48, 48, 48, 71, 150, 195, 561, 562, 72, 72, 72, 72, 72, + 208, 208, 208, 208, 208, 208, 208, 323, 208, 208, 563, 208, 208, 208, 564, 565, + 566, 208, 567, 208, 208, 208, 568, 72, 208, 208, 208, 208, 569, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 269, 570, 208, 208, 208, 208, 208, 285, 269, 451, + 9, 571, 11, 572, 573, 574, 240, 9, 575, 576, 577, 578, 579, 9, 571, 11, + 580, 581, 11, 582, 583, 584, 585, 9, 586, 11, 9, 571, 11, 572, 573, 11, + 240, 9, 575, 585, 9, 586, 11, 9, 571, 11, 587, 9, 588, 589, 590, 591, + 11, 592, 9, 593, 594, 595, 596, 11, 597, 9, 598, 11, 599, 600, 600, 600, + 32, 32, 32, 601, 32, 32, 602, 603, 604, 605, 45, 72, 72, 72, 72, 72, + 606, 607, 608, 72, 72, 72, 72, 72, 48, 48, 150, 609, 610, 72, 72, 72, + 72, 72, 72, 72, 48, 48, 611, 612, 48, 48, 48, 48, 613, 614, 72, 72, + 9, 9, 575, 11, 615, 368, 72, 72, 72, 72, 72, 72, 72, 72, 72, 484, + 269, 269, 616, 617, 72, 72, 72, 72, 484, 269, 618, 619, 72, 72, 72, 72, + 620, 48, 621, 622, 623, 624, 625, 626, 627, 205, 628, 205, 72, 72, 72, 629, + 208, 208, 324, 208, 208, 208, 208, 208, 208, 322, 333, 630, 630, 630, 208, 323, + 174, 208, 208, 208, 208, 208, 631, 208, 208, 208, 631, 72, 72, 72, 632, 208, + 633, 208, 208, 324, 568, 634, 323, 72, 208, 208, 208, 208, 208, 208, 208, 635, + 208, 208, 208, 208, 208, 323, 631, 286, 208, 208, 208, 208, 208, 208, 208, 322, + 208, 208, 208, 208, 208, 568, 324, 72, 324, 208, 208, 208, 636, 175, 208, 208, + 636, 208, 637, 72, 72, 72, 72, 72, 638, 208, 208, 208, 208, 208, 208, 639, + 208, 208, 640, 208, 641, 208, 208, 208, 208, 208, 208, 208, 208, 322, 637, 642, + 633, 323, 72, 72, 72, 72, 72, 72, 48, 48, 48, 48, 48, 314, 72, 72, + 48, 48, 48, 204, 48, 48, 48, 48, 48, 203, 48, 48, 48, 48, 48, 48, + 48, 48, 643, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 72, + 48, 203, 72, 72, 72, 72, 72, 72, 644, 72, 645, 645, 645, 645, 645, 645, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 72, + 389, 389, 389, 389, 389, 389, 389, 646, 389, 389, 389, 389, 389, 389, 389, 647, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, + 0, 0, 0, 0, 0, 4, 0, 4, 2, 2, 5, 2, 2, 2, 5, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 7, 8, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11, + 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 16, 17, 14, 14, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 20, 21, 21, 21, 22, 20, 21, 21, 21, 21, + 21, 23, 24, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 27, 28, 26, + 29, 30, 31, 32, 31, 31, 31, 31, 33, 34, 35, 31, 31, 31, 36, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 31, 31, 31, 31, + 37, 38, 37, 37, 37, 37, 37, 37, 37, 39, 31, 31, 31, 31, 31, 31, + 40, 40, 40, 40, 40, 40, 41, 26, 42, 42, 42, 42, 42, 42, 42, 43, + 44, 44, 44, 44, 44, 45, 44, 46, 47, 47, 47, 48, 37, 49, 26, 26, + 26, 26, 26, 26, 31, 31, 50, 51, 26, 26, 52, 31, 53, 31, 31, 31, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 54, 56, 54, 54, 54, + 57, 58, 59, 60, 60, 61, 62, 63, 58, 64, 65, 66, 67, 60, 60, 68, + 69, 70, 71, 72, 72, 73, 74, 75, 70, 76, 77, 78, 79, 72, 80, 26, + 81, 82, 83, 84, 84, 85, 86, 87, 82, 88, 89, 26, 90, 84, 91, 92, + 93, 94, 95, 96, 96, 97, 98, 99, 94, 100, 101, 102, 103, 96, 96, 26, + 104, 105, 106, 107, 108, 105, 109, 110, 105, 106, 111, 26, 112, 109, 109, 113, + 114, 115, 116, 114, 114, 116, 114, 117, 115, 118, 119, 120, 121, 114, 122, 114, + 123, 124, 125, 123, 123, 125, 126, 127, 124, 128, 129, 130, 131, 123, 132, 26, + 133, 134, 135, 136, 136, 136, 136, 136, 134, 135, 137, 136, 138, 136, 136, 136, + 139, 140, 141, 142, 140, 140, 143, 144, 141, 145, 146, 140, 147, 140, 148, 26, + 149, 150, 150, 150, 150, 150, 150, 151, 150, 150, 150, 152, 26, 26, 26, 26, + 153, 154, 155, 155, 156, 155, 155, 157, 158, 157, 155, 159, 26, 26, 26, 26, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 161, 160, 160, 160, 162, 161, 160, + 160, 160, 160, 161, 160, 160, 160, 163, 160, 163, 164, 165, 26, 26, 26, 26, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 167, 167, 167, 167, 168, 169, 167, 167, 167, 167, 167, 170, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 174, 173, 172, 172, 172, 172, + 172, 173, 172, 172, 172, 172, 173, 174, 173, 172, 174, 172, 172, 172, 172, 172, + 172, 172, 173, 172, 172, 172, 172, 172, 172, 172, 172, 175, 172, 172, 172, 176, + 172, 172, 172, 177, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 179, 179, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 181, 181, 181, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 184, 183, 185, + 186, 187, 188, 26, 189, 189, 190, 26, 191, 191, 192, 26, 193, 194, 195, 26, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 197, 196, 198, 196, 198, + 199, 200, 201, 202, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 203, + 201, 201, 201, 201, 201, 204, 180, 180, 180, 180, 180, 180, 180, 180, 205, 26, + 206, 206, 206, 207, 206, 208, 206, 208, 209, 206, 210, 210, 210, 211, 212, 26, + 213, 213, 213, 213, 213, 214, 213, 213, 213, 215, 213, 216, 196, 196, 196, 196, + 217, 217, 217, 218, 219, 219, 219, 219, 219, 219, 219, 220, 219, 219, 219, 221, + 219, 222, 219, 222, 219, 223, 9, 224, 26, 26, 26, 26, 26, 26, 26, 26, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 225, 225, 225, 225, 225, 227, + 228, 228, 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 230, 231, + 232, 232, 232, 232, 232, 232, 232, 233, 232, 234, 235, 235, 235, 235, 235, 235, + 18, 236, 167, 167, 167, 167, 167, 237, 228, 26, 238, 9, 239, 240, 241, 242, + 2, 2, 2, 2, 243, 244, 2, 2, 2, 2, 2, 245, 246, 247, 2, 248, + 2, 2, 2, 2, 2, 2, 2, 249, 9, 9, 9, 9, 9, 9, 9, 250, + 14, 14, 251, 251, 14, 14, 14, 14, 251, 251, 14, 252, 14, 14, 14, 251, + 14, 14, 14, 14, 14, 14, 253, 14, 253, 14, 254, 255, 14, 14, 256, 257, + 0, 258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 260, 261, + 0, 262, 2, 263, 0, 0, 0, 0, 26, 26, 9, 9, 9, 9, 264, 26, + 0, 0, 0, 0, 265, 266, 4, 0, 0, 267, 0, 0, 2, 2, 2, 2, + 2, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 262, 26, 26, 26, 0, 269, 26, 26, 0, 0, 0, 0, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 271, 0, + 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 273, 273, 273, 273, 273, 274, 273, 273, 273, 273, 273, 274, 2, 2, 2, 2, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 275, 276, + 167, 167, 167, 167, 168, 169, 277, 277, 277, 277, 277, 277, 277, 278, 279, 278, + 172, 172, 174, 26, 174, 174, 174, 174, 174, 174, 174, 174, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, + 280, 280, 280, 281, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 282, 26, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283, 26, 26, 26, 0, 284, + 285, 0, 0, 0, 286, 287, 0, 288, 289, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 291, 292, 293, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 295, + 296, 297, 297, 297, 297, 297, 298, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 299, 0, 0, 297, 297, 297, 300, 0, 0, 0, 0, 284, 26, 294, 294, + 171, 171, 171, 299, 0, 0, 0, 0, 0, 0, 0, 0, 171, 171, 171, 301, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, 294, 294, 294, 294, 302, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 0, 0, 0, 0, 0, + 280, 280, 280, 280, 280, 280, 283, 26, 0, 0, 0, 0, 0, 0, 0, 0, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 26, 26, + 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, + 303, 304, 303, 303, 303, 303, 303, 303, 305, 26, 306, 306, 306, 306, 306, 306, + 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 308, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 26, + 0, 0, 0, 0, 310, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 311, 2, 2, 2, 2, 2, 2, 312, 26, 26, 26, 26, 26, 313, 2, + 314, 314, 314, 314, 314, 315, 0, 316, 317, 317, 317, 317, 317, 317, 317, 26, + 318, 318, 318, 318, 318, 318, 318, 318, 319, 320, 318, 321, 54, 54, 54, 54, + 322, 322, 322, 322, 322, 323, 324, 324, 324, 324, 325, 326, 171, 171, 171, 327, + 328, 328, 328, 328, 328, 328, 328, 328, 328, 329, 328, 330, 166, 166, 166, 331, + 332, 332, 332, 332, 332, 332, 333, 26, 332, 334, 332, 335, 166, 166, 166, 166, + 336, 336, 336, 336, 336, 336, 336, 336, 337, 26, 26, 338, 339, 339, 340, 26, + 341, 341, 341, 26, 174, 174, 2, 2, 2, 2, 2, 342, 343, 26, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 339, 339, 339, 339, 339, 344, 339, 345, + 171, 171, 171, 171, 346, 26, 171, 171, 299, 347, 171, 171, 171, 171, 171, 346, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 348, 26, 26, 26, 26, + 349, 26, 350, 351, 25, 25, 352, 353, 354, 25, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 355, 26, 52, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 356, 26, 26, 31, 31, 31, 31, 31, 31, + 31, 31, 357, 31, 31, 31, 31, 31, 31, 26, 26, 26, 26, 26, 31, 51, + 9, 9, 0, 316, 9, 358, 0, 0, 0, 0, 359, 0, 262, 284, 50, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 360, + 361, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 362, 294, 293, 294, + 294, 294, 294, 363, 171, 171, 171, 299, 364, 364, 364, 365, 262, 262, 26, 366, + 367, 368, 367, 367, 369, 367, 367, 370, 367, 371, 367, 371, 26, 26, 26, 26, + 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 372, + 373, 0, 0, 0, 0, 0, 374, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 257, 0, 284, 375, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 376, + 377, 377, 377, 378, 379, 379, 379, 379, 379, 379, 380, 26, 381, 0, 0, 284, + 382, 382, 382, 382, 383, 384, 385, 385, 385, 386, 387, 387, 387, 387, 387, 388, + 389, 389, 389, 390, 391, 391, 391, 391, 392, 391, 393, 26, 26, 26, 26, 26, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 395, 395, 395, 395, 395, 395, + 396, 396, 396, 397, 396, 398, 399, 399, 399, 399, 400, 399, 399, 399, 399, 400, + 401, 401, 401, 401, 401, 26, 402, 402, 402, 402, 402, 402, 403, 404, 26, 26, + 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, + 405, 405, 405, 405, 405, 405, 406, 26, 405, 405, 407, 26, 405, 26, 26, 26, + 408, 409, 410, 410, 410, 410, 411, 412, 413, 413, 414, 413, 415, 415, 415, 415, + 416, 416, 416, 417, 418, 416, 26, 26, 26, 26, 26, 26, 419, 419, 420, 421, + 422, 422, 422, 423, 424, 424, 424, 425, 26, 26, 26, 26, 26, 26, 26, 26, + 426, 426, 426, 426, 427, 427, 427, 428, 427, 427, 429, 427, 427, 427, 427, 427, + 430, 431, 432, 433, 434, 434, 435, 436, 434, 437, 434, 437, 438, 438, 438, 438, + 439, 439, 439, 439, 26, 26, 26, 26, 440, 440, 440, 440, 441, 442, 441, 26, + 443, 443, 443, 443, 443, 443, 444, 445, 446, 446, 447, 446, 448, 448, 449, 448, + 450, 450, 451, 452, 26, 453, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 454, 454, 454, 454, 454, 454, 454, 454, 454, 455, 26, 26, 26, 26, 26, 26, + 456, 456, 456, 456, 456, 456, 457, 26, 456, 456, 456, 456, 456, 456, 457, 458, + 0, 0, 0, 0, 0, 26, 0, 316, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 459, + 9, 9, 9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 459, 26, + 460, 460, 460, 460, 460, 460, 460, 460, 460, 461, 462, 460, 460, 460, 26, 463, + 464, 464, 464, 464, 464, 464, 464, 464, 465, 466, 467, 467, 467, 468, 467, 469, + 470, 470, 470, 470, 470, 470, 471, 470, 472, 26, 473, 473, 473, 473, 474, 26, + 475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 475, 475, 477, 140, 478, 26, + 479, 479, 480, 479, 479, 479, 479, 481, 26, 26, 26, 26, 26, 26, 26, 26, + 482, 483, 484, 485, 484, 486, 487, 487, 487, 487, 487, 487, 487, 488, 487, 489, + 490, 491, 492, 493, 493, 494, 495, 496, 491, 497, 498, 499, 500, 501, 501, 26, + 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 503, 26, 26, 26, 26, + 504, 504, 504, 504, 504, 504, 504, 504, 504, 26, 504, 505, 26, 26, 26, 26, + 506, 506, 506, 506, 506, 506, 507, 506, 506, 506, 506, 507, 26, 26, 26, 26, + 508, 508, 508, 508, 508, 508, 508, 508, 509, 26, 508, 510, 201, 511, 26, 26, + 512, 512, 512, 512, 512, 512, 512, 513, 512, 514, 26, 26, 26, 26, 26, 26, + 515, 515, 515, 516, 515, 517, 515, 515, 26, 26, 26, 26, 26, 26, 26, 26, + 21, 21, 21, 21, 21, 21, 21, 518, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 520, 521, + 26, 26, 26, 26, 60, 522, 60, 60, 60, 60, 60, 522, 523, 26, 26, 26, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 26, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 524, 26, 26, 26, 525, 525, 525, 525, 525, 525, 525, 526, + 527, 528, 527, 527, 527, 527, 529, 527, 530, 26, 527, 527, 527, 531, 532, 532, + 532, 532, 533, 532, 532, 534, 535, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 536, 537, 167, 167, 167, 167, 536, 538, 167, 26, 167, 539, 540, 541, 14, 14, + 14, 257, 15, 375, 14, 542, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 84, 84, 84, 89, + 26, 26, 26, 26, 26, 26, 26, 26, 109, 109, 109, 109, 109, 109, 543, 544, + 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, + 545, 545, 545, 546, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 547, 548, 26, + 545, 545, 545, 545, 545, 545, 545, 545, 549, 26, 26, 26, 26, 26, 26, 26, + 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 550, 551, 550, 552, 26, 26, 26, 26, 26, 26, 26, 26, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 554, 26, 26, 26, 26, 26, 26, 26, + 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, + 309, 309, 309, 309, 309, 309, 309, 555, 556, 556, 556, 557, 556, 558, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 559, 559, 559, 560, 560, 26, + 561, 561, 561, 561, 561, 561, 561, 561, 562, 26, 561, 563, 563, 561, 561, 564, + 561, 561, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 565, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 566, 566, 566, 566, 566, 566, 566, 566, 566, 567, 566, 566, 566, 566, 566, 566, + 566, 568, 566, 566, 26, 26, 26, 26, 26, 26, 26, 26, 569, 26, 26, 26, + 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, + 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 26, + 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 571, 26, + 572, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 291, 26, 26, 26, 26, 26, 26, 573, 26, 574, 26, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 346, + 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 576, 575, 577, + 575, 578, 575, 579, 284, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 26, + 0, 0, 0, 0, 262, 361, 0, 0, 0, 0, 0, 0, 580, 581, 0, 582, + 583, 584, 0, 0, 0, 585, 0, 0, 0, 0, 0, 0, 0, 586, 26, 26, + 14, 14, 14, 14, 14, 14, 14, 14, 251, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 284, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 26, 0, 0, 0, 586, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 0, 0, 0, 0, + 0, 0, 0, 259, 587, 588, 0, 589, 590, 0, 0, 0, 0, 0, 0, 0, + 591, 592, 259, 259, 0, 0, 0, 593, 594, 595, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 271, 0, 0, 0, 0, 0, 0, + 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, + 597, 598, 26, 599, 600, 597, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 274, 273, 273, 601, 602, 603, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 280, 280, 280, 280, 280, 604, 280, 283, 280, 605, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 606, + 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, + 607, 607, 607, 607, 607, 607, 607, 607, 608, 607, 609, 26, 26, 26, 26, 26, + 610, 610, 610, 610, 610, 610, 610, 610, 610, 611, 610, 612, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 361, 0, + 0, 0, 0, 0, 0, 0, 613, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 361, 0, 0, 0, 0, 0, 0, 272, 26, 26, 26, 26, 26, 26, 26, 26, + 614, 31, 31, 31, 615, 616, 617, 618, 619, 620, 615, 621, 615, 617, 617, 622, + 31, 623, 31, 624, 625, 623, 31, 624, 26, 26, 26, 26, 26, 26, 355, 26, + 0, 0, 0, 0, 0, 284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 284, 26, 0, 262, 361, 0, 361, 0, 361, 0, 0, 0, 272, 26, + 0, 613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 613, 0, 0, + 0, 0, 0, 0, 0, 613, 26, 26, 26, 26, 26, 26, 626, 0, 0, 0, + 627, 26, 0, 0, 0, 0, 0, 284, 0, 586, 316, 26, 272, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 26, 0, 613, 0, 269, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 586, 0, 284, 26, 26, + 0, 284, 0, 0, 0, 0, 0, 0, 0, 26, 0, 316, 0, 0, 0, 0, + 0, 26, 0, 0, 0, 272, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 0, 590, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 593, 595, + 0, 0, 0, 0, 592, 628, 0, 0, 0, 592, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 26, 0, 272, 284, 269, + 269, 26, 272, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 629, 26, 26, 26, 26, 26, + 280, 280, 280, 280, 280, 280, 604, 26, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 283, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 348, 26, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 630, 26, 26, 26, + 280, 280, 280, 283, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 631, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, + 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0, + 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193, + 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303, + 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149, + 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, + 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199, + 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0, + 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231, + 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258, + 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275, + 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0, + 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093, + 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010, + 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347, + 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424, + 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365, + 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238, + 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182, + 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232, + 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461, + 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486, + 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0, + 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0, + 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0, + 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553, + 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560, + 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0, + 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0, + 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627, + 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0, + 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0, + 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0, + 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0, + 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0, + 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0, + 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0, + 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0, + 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, + 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, + 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356, + 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214, + 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363, + 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251, + 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266, + 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287, + 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302, + 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0, + 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375, + 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353, + 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234, + 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403, + 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412, + 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0, + 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721, + 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0, + 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757, + 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776, + 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0, + 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793, + 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814, + 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0, + 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728, + 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764, + 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821, + 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0, + 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828, + 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833, + 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3, + 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838, + 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0, + 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0, + 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938, + 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0, + 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870, + 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0, + 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0, + 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0, + 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0, + 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0, + 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0, + 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0, + 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0, + 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0, + 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, + 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, + 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, + 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, + 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, + 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, + 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, + 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, + 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, + 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, + 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, + 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, + 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, + 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, + 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, + 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, + 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0, + 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0, + 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773, + 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, + 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, + 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, + 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0, + 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, + 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, + 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, + 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, + 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, + 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, + 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575, + 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0, + 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1948,1949, + 1950,1951,1952,1953,1954, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1955,1956,1957,1959,1958, + 1960, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, + 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, + 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, + 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, + 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, + 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, + 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259, + 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276, + 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934, + 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312, + 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, + 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, + 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381, + 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399, + 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417, + 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, + 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460, + 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870, + 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505, + 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64, + 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538, + 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567, + 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592, + 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, + 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627, + 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, + 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83, + 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85, + 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696, + 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, + 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90, + 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787, + 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807, + 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0, +}; +static const int16_t +_hb_ucd_i16[196] = +{ + 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2, + 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1, + 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3, + -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0, + 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0, + 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0, + 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0, + 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0, + 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1, + -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0, + 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106, + -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1, + -1, 0, 1, -1, +}; + +static inline uint_fast8_t +_hb_ucd_gc (unsigned u) +{ + return u<1114110u?_hb_ucd_u8[6432+(((_hb_ucd_u8[1248+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; +} +static inline uint_fast8_t +_hb_ucd_ccc (unsigned u) +{ + return u<125259u?_hb_ucd_u8[8640+(((_hb_ucd_u8[7704+(((_hb_ucd_u8[7048+(((_hb_ucd_u8[6802+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0; +} +static inline unsigned +_hb_ucd_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline int_fast16_t +_hb_ucd_bmg (unsigned u) +{ + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9372+(((_hb_ucd_u8[9252+(((_hb_ucd_b4(9124+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0; +} +static inline uint_fast8_t +_hb_ucd_sc (unsigned u) +{ + return u<918000u?_hb_ucd_u8[10822+(((_hb_ucd_u16[1920+(((_hb_ucd_u8[10150+(((_hb_ucd_u8[9700+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2; +} +static inline uint_fast16_t +_hb_ucd_dm (unsigned u) +{ + return u<195102u?_hb_ucd_u16[5632+(((_hb_ucd_u8[15974+(((_hb_ucd_b4(15878+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; +} + +#endif + + +#endif /* HB_UCD_TABLE_HH */ + +/* == End of generated table == */ diff --git a/src/hb-ucd.cc b/src/hb-ucd.cc new file mode 100644 index 000000000..134e043d8 --- /dev/null +++ b/src/hb-ucd.cc @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2012 Grigori Goronzy + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hb.hh" +#include "hb-machinery.hh" + +#include "hb-ucd-table.hh" + +static hb_unicode_combining_class_t +hb_ucd_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED, + hb_codepoint_t unicode, + void *user_data HB_UNUSED) +{ + return (hb_unicode_combining_class_t) _hb_ucd_ccc (unicode); +} + +static hb_unicode_general_category_t +hb_ucd_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED, + hb_codepoint_t unicode, + void *user_data HB_UNUSED) +{ + return (hb_unicode_general_category_t) _hb_ucd_gc (unicode); +} + +static hb_codepoint_t +hb_ucd_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED, + hb_codepoint_t unicode, + void *user_data HB_UNUSED) +{ + return unicode + _hb_ucd_bmg (unicode); +} + +static hb_script_t +hb_ucd_script (hb_unicode_funcs_t *ufuncs HB_UNUSED, + hb_codepoint_t unicode, + void *user_data HB_UNUSED) +{ + return _hb_ucd_sc_map[_hb_ucd_sc (unicode)]; +} + + +#define SBASE 0xAC00u +#define LBASE 0x1100u +#define VBASE 0x1161u +#define TBASE 0x11A7u +#define SCOUNT 11172u +#define LCOUNT 19u +#define VCOUNT 21u +#define TCOUNT 28u +#define NCOUNT (VCOUNT * TCOUNT) + +static inline bool +_hb_ucd_decompose_hangul (hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b) +{ + unsigned si = ab - SBASE; + + if (si >= SCOUNT) + return false; + + if (si % TCOUNT) + { + /* LV,T */ + *a = SBASE + (si / TCOUNT) * TCOUNT; + *b = TBASE + (si % TCOUNT); + return true; + } else { + /* L,V */ + *a = LBASE + (si / NCOUNT); + *b = VBASE + (si % NCOUNT) / TCOUNT; + return true; + } +} + +static inline bool +_hb_ucd_compose_hangul (hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab) +{ + if (a >= SBASE && a < (SBASE + SCOUNT) && b > TBASE && b < (TBASE + TCOUNT) && + !((a - SBASE) % TCOUNT)) + { + /* LV,T */ + *ab = a + (b - TBASE); + return true; + } + else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT)) + { + /* L,V */ + int li = a - LBASE; + int vi = b - VBASE; + *ab = SBASE + li * NCOUNT + vi * TCOUNT; + return true; + } + else + return false; +} + +static int +_cmp_pair (const void *_key, const void *_item) +{ + uint64_t& a = * (uint64_t*) _key; + uint64_t b = (* (uint64_t*) _item) & HB_CODEPOINT_ENCODE3(0x1FFFFFu, 0x1FFFFFu, 0); + + return a < b ? -1 : a > b ? +1 : 0; +} + +static hb_bool_t +hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, + hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab, + void *user_data HB_UNUSED) +{ + if (_hb_ucd_compose_hangul (a, b, ab)) return true; + + uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0); + uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_map, + ARRAY_LENGTH (_hb_ucd_dm2_map), + sizeof (*_hb_ucd_dm2_map), + _cmp_pair); + if (likely (!v)) return false; + + hb_codepoint_t u = HB_CODEPOINT_DECODE3_3 (*v); + if (unlikely (!u)) return false; + + *ab = u; + return true; +} + +static hb_bool_t +hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, + hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b, + void *user_data HB_UNUSED) +{ + if (_hb_ucd_decompose_hangul (ab, a, b)) return true; + + unsigned i = _hb_ucd_dm (ab); + + if (likely (!i)) return false; + i--; + + if (i < ARRAY_LENGTH (_hb_ucd_dm1_map)) + { + *a = _hb_ucd_dm1_map[i]; + *b = 0; + return true; + } + i -= ARRAY_LENGTH (_hb_ucd_dm1_map); + + uint64_t v = _hb_ucd_dm2_map[i]; + *a = HB_CODEPOINT_DECODE3_1 (v); + *b = HB_CODEPOINT_DECODE3_2 (v); + return true; +} + + +#if HB_USE_ATEXIT +static void free_static_ucd_funcs (); +#endif + +static struct hb_ucd_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t +{ + static hb_unicode_funcs_t *create () + { + hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr); + + hb_unicode_funcs_set_combining_class_func (funcs, hb_ucd_combining_class, nullptr, nullptr); + hb_unicode_funcs_set_general_category_func (funcs, hb_ucd_general_category, nullptr, nullptr); + hb_unicode_funcs_set_mirroring_func (funcs, hb_ucd_mirroring, nullptr, nullptr); + hb_unicode_funcs_set_script_func (funcs, hb_ucd_script, nullptr, nullptr); + hb_unicode_funcs_set_compose_func (funcs, hb_ucd_compose, nullptr, nullptr); + hb_unicode_funcs_set_decompose_func (funcs, hb_ucd_decompose, nullptr, nullptr); + + hb_unicode_funcs_make_immutable (funcs); + +#if HB_USE_ATEXIT + atexit (free_static_ucd_funcs); +#endif + + return funcs; + } +} static_ucd_funcs; + +#if HB_USE_ATEXIT +static +void free_static_ucd_funcs () +{ + static_ucd_funcs.free_instance (); +} +#endif + +extern "C" HB_INTERNAL +hb_unicode_funcs_t * +hb_ucd_get_unicode_funcs (); + +hb_unicode_funcs_t * +hb_ucd_get_unicode_funcs () +{ +#ifdef HB_NO_UCD + return hb_unicode_funcs_get_empty (); +#endif + return static_ucd_funcs.get_unconst (); +} diff --git a/src/hb-ucdn.cc b/src/hb-ucdn.cc deleted file mode 100644 index 8230bf1e8..000000000 --- a/src/hb-ucdn.cc +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2012 Grigori Goronzy - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "hb.hh" - -#include "hb-machinery.hh" - -#include "ucdn.h" - -static const hb_script_t ucdn_script_translate[] = -{ - HB_SCRIPT_COMMON, - HB_SCRIPT_LATIN, - HB_SCRIPT_GREEK, - HB_SCRIPT_CYRILLIC, - HB_SCRIPT_ARMENIAN, - HB_SCRIPT_HEBREW, - HB_SCRIPT_ARABIC, - HB_SCRIPT_SYRIAC, - HB_SCRIPT_THAANA, - HB_SCRIPT_DEVANAGARI, - HB_SCRIPT_BENGALI, - HB_SCRIPT_GURMUKHI, - HB_SCRIPT_GUJARATI, - HB_SCRIPT_ORIYA, - HB_SCRIPT_TAMIL, - HB_SCRIPT_TELUGU, - HB_SCRIPT_KANNADA, - HB_SCRIPT_MALAYALAM, - HB_SCRIPT_SINHALA, - HB_SCRIPT_THAI, - HB_SCRIPT_LAO, - HB_SCRIPT_TIBETAN, - HB_SCRIPT_MYANMAR, - HB_SCRIPT_GEORGIAN, - HB_SCRIPT_HANGUL, - HB_SCRIPT_ETHIOPIC, - HB_SCRIPT_CHEROKEE, - HB_SCRIPT_CANADIAN_SYLLABICS, - HB_SCRIPT_OGHAM, - HB_SCRIPT_RUNIC, - HB_SCRIPT_KHMER, - HB_SCRIPT_MONGOLIAN, - HB_SCRIPT_HIRAGANA, - HB_SCRIPT_KATAKANA, - HB_SCRIPT_BOPOMOFO, - HB_SCRIPT_HAN, - HB_SCRIPT_YI, - HB_SCRIPT_OLD_ITALIC, - HB_SCRIPT_GOTHIC, - HB_SCRIPT_DESERET, - HB_SCRIPT_INHERITED, - HB_SCRIPT_TAGALOG, - HB_SCRIPT_HANUNOO, - HB_SCRIPT_BUHID, - HB_SCRIPT_TAGBANWA, - HB_SCRIPT_LIMBU, - HB_SCRIPT_TAI_LE, - HB_SCRIPT_LINEAR_B, - HB_SCRIPT_UGARITIC, - HB_SCRIPT_SHAVIAN, - HB_SCRIPT_OSMANYA, - HB_SCRIPT_CYPRIOT, - HB_SCRIPT_BRAILLE, - HB_SCRIPT_BUGINESE, - HB_SCRIPT_COPTIC, - HB_SCRIPT_NEW_TAI_LUE, - HB_SCRIPT_GLAGOLITIC, - HB_SCRIPT_TIFINAGH, - HB_SCRIPT_SYLOTI_NAGRI, - HB_SCRIPT_OLD_PERSIAN, - HB_SCRIPT_KHAROSHTHI, - HB_SCRIPT_BALINESE, - HB_SCRIPT_CUNEIFORM, - HB_SCRIPT_PHOENICIAN, - HB_SCRIPT_PHAGS_PA, - HB_SCRIPT_NKO, - HB_SCRIPT_SUNDANESE, - HB_SCRIPT_LEPCHA, - HB_SCRIPT_OL_CHIKI, - HB_SCRIPT_VAI, - HB_SCRIPT_SAURASHTRA, - HB_SCRIPT_KAYAH_LI, - HB_SCRIPT_REJANG, - HB_SCRIPT_LYCIAN, - HB_SCRIPT_CARIAN, - HB_SCRIPT_LYDIAN, - HB_SCRIPT_CHAM, - HB_SCRIPT_TAI_THAM, - HB_SCRIPT_TAI_VIET, - HB_SCRIPT_AVESTAN, - HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, - HB_SCRIPT_SAMARITAN, - HB_SCRIPT_LISU, - HB_SCRIPT_BAMUM, - HB_SCRIPT_JAVANESE, - HB_SCRIPT_MEETEI_MAYEK, - HB_SCRIPT_IMPERIAL_ARAMAIC, - HB_SCRIPT_OLD_SOUTH_ARABIAN, - HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, - HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, - HB_SCRIPT_OLD_TURKIC, - HB_SCRIPT_KAITHI, - HB_SCRIPT_BATAK, - HB_SCRIPT_BRAHMI, - HB_SCRIPT_MANDAIC, - HB_SCRIPT_CHAKMA, - HB_SCRIPT_MEROITIC_CURSIVE, - HB_SCRIPT_MEROITIC_HIEROGLYPHS, - HB_SCRIPT_MIAO, - HB_SCRIPT_SHARADA, - HB_SCRIPT_SORA_SOMPENG, - HB_SCRIPT_TAKRI, - HB_SCRIPT_UNKNOWN, - HB_SCRIPT_BASSA_VAH, - HB_SCRIPT_CAUCASIAN_ALBANIAN, - HB_SCRIPT_DUPLOYAN, - HB_SCRIPT_ELBASAN, - HB_SCRIPT_GRANTHA, - HB_SCRIPT_KHOJKI, - HB_SCRIPT_KHUDAWADI, - HB_SCRIPT_LINEAR_A, - HB_SCRIPT_MAHAJANI, - HB_SCRIPT_MANICHAEAN, - HB_SCRIPT_MENDE_KIKAKUI, - HB_SCRIPT_MODI, - HB_SCRIPT_MRO, - HB_SCRIPT_NABATAEAN, - HB_SCRIPT_OLD_NORTH_ARABIAN, - HB_SCRIPT_OLD_PERMIC, - HB_SCRIPT_PAHAWH_HMONG, - HB_SCRIPT_PALMYRENE, - HB_SCRIPT_PAU_CIN_HAU, - HB_SCRIPT_PSALTER_PAHLAVI, - HB_SCRIPT_SIDDHAM, - HB_SCRIPT_TIRHUTA, - HB_SCRIPT_WARANG_CITI, - HB_SCRIPT_AHOM, - HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, - HB_SCRIPT_HATRAN, - HB_SCRIPT_MULTANI, - HB_SCRIPT_OLD_HUNGARIAN, - HB_SCRIPT_SIGNWRITING, - HB_SCRIPT_ADLAM, - HB_SCRIPT_BHAIKSUKI, - HB_SCRIPT_MARCHEN, - HB_SCRIPT_NEWA, - HB_SCRIPT_OSAGE, - HB_SCRIPT_TANGUT, - HB_SCRIPT_MASARAM_GONDI, - HB_SCRIPT_NUSHU, - HB_SCRIPT_SOYOMBO, - HB_SCRIPT_ZANABAZAR_SQUARE, - HB_SCRIPT_DOGRA, - HB_SCRIPT_GUNJALA_GONDI, - HB_SCRIPT_HANIFI_ROHINGYA, - HB_SCRIPT_MAKASAR, - HB_SCRIPT_MEDEFAIDRIN, - HB_SCRIPT_OLD_SOGDIAN, - HB_SCRIPT_SOGDIAN, - HB_SCRIPT_ELYMAIC, - HB_SCRIPT_NANDINAGARI, - HB_SCRIPT_NYIAKENG_PUACHUE_HMONG, - HB_SCRIPT_WANCHO, -}; - -static hb_unicode_combining_class_t -hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t unicode, - void *user_data HB_UNUSED) -{ - return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode); -} - -static hb_unicode_general_category_t -hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t unicode, - void *user_data HB_UNUSED) -{ - return (hb_unicode_general_category_t)ucdn_get_general_category(unicode); -} - -static hb_codepoint_t -hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t unicode, - void *user_data HB_UNUSED) -{ - return ucdn_mirror(unicode); -} - -static hb_script_t -hb_ucdn_script(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t unicode, - void *user_data HB_UNUSED) -{ - return ucdn_script_translate[ucdn_get_script(unicode)]; -} - -static hb_bool_t -hb_ucdn_compose(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab, - void *user_data HB_UNUSED) -{ - return ucdn_compose(ab, a, b); -} - -static hb_bool_t -hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED, - hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b, - void *user_data HB_UNUSED) -{ - return ucdn_decompose(ab, a, b); -} - - -#if HB_USE_ATEXIT -static void free_static_ucdn_funcs (); -#endif - -static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t -{ - static hb_unicode_funcs_t *create () - { - hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr); - - hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr); - hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr); - hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr); - hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr); - hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr); - hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr); - - hb_unicode_funcs_make_immutable (funcs); - -#if HB_USE_ATEXIT - atexit (free_static_ucdn_funcs); -#endif - - return funcs; - } -} static_ucdn_funcs; - -#if HB_USE_ATEXIT -static -void free_static_ucdn_funcs () -{ - static_ucdn_funcs.free_instance (); -} -#endif - -extern "C" HB_INTERNAL -hb_unicode_funcs_t * -hb_ucdn_get_unicode_funcs (); - -hb_unicode_funcs_t * -hb_ucdn_get_unicode_funcs () -{ - return static_ucdn_funcs.get_unconst (); -} diff --git a/src/hb-ucdn/COPYING b/src/hb-ucdn/COPYING deleted file mode 100644 index be5205c65..000000000 --- a/src/hb-ucdn/COPYING +++ /dev/null @@ -1,13 +0,0 @@ -The contents of this directory are licensed under the following terms: - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/src/hb-ucdn/Makefile.am b/src/hb-ucdn/Makefile.am deleted file mode 100644 index 73b550254..000000000 --- a/src/hb-ucdn/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -## Process this file with automake to produce Makefile.in - -noinst_LTLIBRARIES = libhb-ucdn.la - -include Makefile.sources - -libhb_ucdn_la_SOURCES = $(LIBHB_UCDN_sources) -libhb_ucdn_la_CPPFLAGS = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src -libhb_ucdn_la_LIBADD = - -EXTRA_DIST = README COPYING - --include $(top_srcdir)/git.mk diff --git a/src/hb-ucdn/Makefile.sources b/src/hb-ucdn/Makefile.sources deleted file mode 100644 index cb823b605..000000000 --- a/src/hb-ucdn/Makefile.sources +++ /dev/null @@ -1,7 +0,0 @@ -NULL = - -LIBHB_UCDN_sources = \ - ucdn.h \ - ucdn.c \ - ucdn_db.h \ - $(NULL) diff --git a/src/hb-ucdn/README b/src/hb-ucdn/README deleted file mode 100644 index 2203ae69a..000000000 --- a/src/hb-ucdn/README +++ /dev/null @@ -1,40 +0,0 @@ -Contents of this directory are derived from UCDN: - - https://github.com/grigorig/ucdn - -The original README follows: - - -UCDN - Unicode Database and Normalization - -UCDN is a Unicode support library. Currently, it provides access -to basic character properties contained in the Unicode Character -Database and low-level normalization functions (pairwise canonical -composition/decomposition and compatibility decomposition). More -functionality might be provided in the future, such as additional -properties, string normalization and encoding conversion. - -UCDN uses standard C89 with no particular dependencies or requirements -except for stdint.h, and can be easily integrated into existing -projects. However, it can also be used as a standalone library, -and a CMake build script is provided for this. The first motivation -behind UCDN development was to provide a standalone set of Unicode -functions for the HarfBuzz OpenType shaping library. For this purpose, -a HarfBuzz-specific wrapper is shipped along with it (hb-ucdn.h). - -UCDN is published under the ISC license, please see the license header -in the C source code for more information. The makeunicodata.py script -required for parsing Unicode database files is licensed under the -PSF license, please see PYTHON-LICENSE for more information. - -UCDN was written by Grigori Goronzy . - -How to Use - -Include ucdn.c, ucdn.h and ucdn_db.h in your project. Now, just use the -functions as documented in ucdn.h. - -In some cases, it might be necessary to regenerate the Unicode -database file. The script makeunicodedata.py (Python 3.x required) -fetches the appropriate files and dumps the compressed database into -ucdn_db.h. diff --git a/src/hb-ucdn/ucdn.c b/src/hb-ucdn/ucdn.c deleted file mode 100644 index 30747fea2..000000000 --- a/src/hb-ucdn/ucdn.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2012 Grigori Goronzy - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include "ucdn.h" - -typedef struct { - unsigned char category; - unsigned char combining; - unsigned char bidi_class; - unsigned char east_asian_width; - unsigned char script; - unsigned char linebreak_class; -} UCDRecord; - -typedef struct { - unsigned short from, to; -} MirrorPair; - -typedef struct { - unsigned short from, to; - unsigned char type; -} BracketPair; - -typedef struct { - unsigned int start; - short count, index; -} Reindex; - -#include "ucdn_db.h" - -/* constants required for Hangul (de)composition */ -#define SBASE 0xAC00 -#define LBASE 0x1100 -#define VBASE 0x1161 -#define TBASE 0x11A7 -#define SCOUNT 11172 -#define LCOUNT 19 -#define VCOUNT 21 -#define TCOUNT 28 -#define NCOUNT (VCOUNT * TCOUNT) - -static const UCDRecord *get_ucd_record(uint32_t code) -{ - int index, offset; - - if (code >= 0x110000) - index = 0; - else { - index = index0[code >> (SHIFT1+SHIFT2)] << SHIFT1; - offset = (code >> SHIFT2) & ((1<= 0x110000) - index = 0; - else { - index = decomp_index0[code >> (DECOMP_SHIFT1+DECOMP_SHIFT2)] - << DECOMP_SHIFT1; - offset = (code >> DECOMP_SHIFT2) & ((1<start < rb->start) - return -1; - else if (ra->start > (rb->start + rb->count)) - return 1; - else - return 0; -} - -static int get_comp_index(uint32_t code, const Reindex *idx, size_t len) -{ - Reindex *res; - Reindex r = {0, 0, 0}; - r.start = code; - res = (Reindex *) bsearch(&r, idx, len, sizeof(Reindex), compare_reindex); - - if (res != NULL) - return res->index + (code - res->start); - else - return -1; -} - -static int compare_mp(const void *a, const void *b) -{ - MirrorPair *mpa = (MirrorPair *)a; - MirrorPair *mpb = (MirrorPair *)b; - return mpa->from - mpb->from; -} - -static int compare_bp(const void *a, const void *b) -{ - BracketPair *bpa = (BracketPair *)a; - BracketPair *bpb = (BracketPair *)b; - return bpa->from - bpb->from; -} - -static BracketPair *search_bp(uint32_t code) -{ - BracketPair bp = {0,0,2}; - BracketPair *res; - - bp.from = code; - res = (BracketPair *) bsearch(&bp, bracket_pairs, BIDI_BRACKET_LEN, - sizeof(BracketPair), compare_bp); - return res; -} - -static int hangul_pair_decompose(uint32_t code, uint32_t *a, uint32_t *b) -{ - int si = code - SBASE; - - if (si < 0 || si >= SCOUNT) - return 0; - - if (si % TCOUNT) { - /* LV,T */ - *a = SBASE + (si / TCOUNT) * TCOUNT; - *b = TBASE + (si % TCOUNT); - return 3; - } else { - /* L,V */ - *a = LBASE + (si / NCOUNT); - *b = VBASE + (si % NCOUNT) / TCOUNT; - return 2; - } -} - -static int hangul_pair_compose(uint32_t *code, uint32_t a, uint32_t b) -{ - if (a >= SBASE && a < (SBASE + SCOUNT) && b >= TBASE && b < (TBASE + TCOUNT)) { - /* LV,T */ - *code = a + (b - TBASE); - return 3; - } else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT)) { - /* L,V */ - int li = a - LBASE; - int vi = b - VBASE; - *code = SBASE + li * NCOUNT + vi * TCOUNT; - return 2; - } else { - return 0; - } -} - -static uint32_t decode_utf16(const unsigned short **code_ptr) -{ - const unsigned short *code = *code_ptr; - - if (code[0] < 0xd800 || code[0] > 0xdc00) { - *code_ptr += 1; - return (uint32_t)code[0]; - } else { - *code_ptr += 2; - return 0x10000 + ((uint32_t)code[1] - 0xdc00) + - (((uint32_t)code[0] - 0xd800) << 10); - } -} - -const char *ucdn_get_unicode_version(void) -{ - return UNIDATA_VERSION; -} - -int ucdn_get_combining_class(uint32_t code) -{ - return get_ucd_record(code)->combining; -} - -int ucdn_get_east_asian_width(uint32_t code) -{ - return get_ucd_record(code)->east_asian_width; -} - -int ucdn_get_general_category(uint32_t code) -{ - return get_ucd_record(code)->category; -} - -int ucdn_get_bidi_class(uint32_t code) -{ - return get_ucd_record(code)->bidi_class; -} - -int ucdn_get_mirrored(uint32_t code) -{ - return ucdn_mirror(code) != code; -} - -int ucdn_get_script(uint32_t code) -{ - return get_ucd_record(code)->script; -} - -int ucdn_get_linebreak_class(uint32_t code) -{ - return get_ucd_record(code)->linebreak_class; -} - -int ucdn_get_resolved_linebreak_class(uint32_t code) -{ - const UCDRecord *record = get_ucd_record(code); - - switch (record->linebreak_class) - { - case UCDN_LINEBREAK_CLASS_AI: - case UCDN_LINEBREAK_CLASS_SG: - case UCDN_LINEBREAK_CLASS_XX: - return UCDN_LINEBREAK_CLASS_AL; - - case UCDN_LINEBREAK_CLASS_SA: - if (record->category == UCDN_GENERAL_CATEGORY_MC || - record->category == UCDN_GENERAL_CATEGORY_MN) - return UCDN_LINEBREAK_CLASS_CM; - return UCDN_LINEBREAK_CLASS_AL; - - case UCDN_LINEBREAK_CLASS_CJ: - return UCDN_LINEBREAK_CLASS_NS; - - case UCDN_LINEBREAK_CLASS_CB: - return UCDN_LINEBREAK_CLASS_B2; - - case UCDN_LINEBREAK_CLASS_NL: - return UCDN_LINEBREAK_CLASS_BK; - - default: - return record->linebreak_class; - } -} - -uint32_t ucdn_mirror(uint32_t code) -{ - MirrorPair mp = {0}; - MirrorPair *res; - - mp.from = code; - res = (MirrorPair *) bsearch(&mp, mirror_pairs, BIDI_MIRROR_LEN, - sizeof(MirrorPair), compare_mp); - - if (res == NULL) - return code; - else - return res->to; -} - -uint32_t ucdn_paired_bracket(uint32_t code) -{ - BracketPair *res = search_bp(code); - if (res == NULL) - return code; - else - return res->to; -} - -int ucdn_paired_bracket_type(uint32_t code) -{ - BracketPair *res = search_bp(code); - if (res == NULL) - return UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE; - else - return res->type; -} - -int ucdn_decompose(uint32_t code, uint32_t *a, uint32_t *b) -{ - const unsigned short *rec; - int len; - - if (hangul_pair_decompose(code, a, b)) - return 1; - - rec = get_decomp_record(code); - len = rec[0] >> 8; - - if ((rec[0] & 0xff) != 0 || len == 0) - return 0; - - rec++; - *a = decode_utf16(&rec); - if (len > 1) - *b = decode_utf16(&rec); - else - *b = 0; - - return 1; -} - -int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b) -{ - int l, r, index, indexi, offset; - - if (hangul_pair_compose(code, a, b)) - return 1; - - l = get_comp_index(a, nfc_first, sizeof(nfc_first) / sizeof(Reindex)); - r = get_comp_index(b, nfc_last, sizeof(nfc_last) / sizeof(Reindex)); - - if (l < 0 || r < 0) - return 0; - - indexi = l * TOTAL_LAST + r; - index = comp_index0[indexi >> (COMP_SHIFT1+COMP_SHIFT2)] << COMP_SHIFT1; - offset = (indexi >> COMP_SHIFT2) & ((1<> 8; - - if (len == 0) - return 0; - - rec++; - for (i = 0; i < len; i++) - decomposed[i] = decode_utf16(&rec); - - return len; -} diff --git a/src/hb-ucdn/ucdn.h b/src/hb-ucdn/ucdn.h deleted file mode 100644 index 1317d4fe4..000000000 --- a/src/hb-ucdn/ucdn.h +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (C) 2012 Grigori Goronzy - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UCDN_H -#define UCDN_H - - - -#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) -# define HB_BEGIN_VISIBILITY _Pragma ("GCC visibility push(hidden)") -# define HB_END_VISIBILITY _Pragma ("GCC visibility pop") -#else -# define HB_BEGIN_VISIBILITY -# define HB_END_VISIBILITY -#endif -#ifdef __cplusplus -# define HB_BEGIN_HEADER extern "C" { HB_BEGIN_VISIBILITY -# define HB_END_HEADER HB_END_VISIBILITY } -#else -# define HB_BEGIN_HEADER HB_BEGIN_VISIBILITY -# define HB_END_HEADER HB_END_VISIBILITY -#endif - -HB_BEGIN_HEADER - -#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ - defined (_sgi) || defined (__sun) || defined (sun) || \ - defined (__digital__) || defined (__HP_cc) -# include -#elif defined (_AIX) -# include -#elif defined (_MSC_VER) && _MSC_VER < 1600 -/* VS 2010 (_MSC_VER 1600) has stdint.h */ -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -# include -#endif - - -#define UCDN_EAST_ASIAN_F 0 -#define UCDN_EAST_ASIAN_H 1 -#define UCDN_EAST_ASIAN_W 2 -#define UCDN_EAST_ASIAN_NA 3 -#define UCDN_EAST_ASIAN_A 4 -#define UCDN_EAST_ASIAN_N 5 - -#define UCDN_SCRIPT_COMMON 0 -#define UCDN_SCRIPT_LATIN 1 -#define UCDN_SCRIPT_GREEK 2 -#define UCDN_SCRIPT_CYRILLIC 3 -#define UCDN_SCRIPT_ARMENIAN 4 -#define UCDN_SCRIPT_HEBREW 5 -#define UCDN_SCRIPT_ARABIC 6 -#define UCDN_SCRIPT_SYRIAC 7 -#define UCDN_SCRIPT_THAANA 8 -#define UCDN_SCRIPT_DEVANAGARI 9 -#define UCDN_SCRIPT_BENGALI 10 -#define UCDN_SCRIPT_GURMUKHI 11 -#define UCDN_SCRIPT_GUJARATI 12 -#define UCDN_SCRIPT_ORIYA 13 -#define UCDN_SCRIPT_TAMIL 14 -#define UCDN_SCRIPT_TELUGU 15 -#define UCDN_SCRIPT_KANNADA 16 -#define UCDN_SCRIPT_MALAYALAM 17 -#define UCDN_SCRIPT_SINHALA 18 -#define UCDN_SCRIPT_THAI 19 -#define UCDN_SCRIPT_LAO 20 -#define UCDN_SCRIPT_TIBETAN 21 -#define UCDN_SCRIPT_MYANMAR 22 -#define UCDN_SCRIPT_GEORGIAN 23 -#define UCDN_SCRIPT_HANGUL 24 -#define UCDN_SCRIPT_ETHIOPIC 25 -#define UCDN_SCRIPT_CHEROKEE 26 -#define UCDN_SCRIPT_CANADIAN_ABORIGINAL 27 -#define UCDN_SCRIPT_OGHAM 28 -#define UCDN_SCRIPT_RUNIC 29 -#define UCDN_SCRIPT_KHMER 30 -#define UCDN_SCRIPT_MONGOLIAN 31 -#define UCDN_SCRIPT_HIRAGANA 32 -#define UCDN_SCRIPT_KATAKANA 33 -#define UCDN_SCRIPT_BOPOMOFO 34 -#define UCDN_SCRIPT_HAN 35 -#define UCDN_SCRIPT_YI 36 -#define UCDN_SCRIPT_OLD_ITALIC 37 -#define UCDN_SCRIPT_GOTHIC 38 -#define UCDN_SCRIPT_DESERET 39 -#define UCDN_SCRIPT_INHERITED 40 -#define UCDN_SCRIPT_TAGALOG 41 -#define UCDN_SCRIPT_HANUNOO 42 -#define UCDN_SCRIPT_BUHID 43 -#define UCDN_SCRIPT_TAGBANWA 44 -#define UCDN_SCRIPT_LIMBU 45 -#define UCDN_SCRIPT_TAI_LE 46 -#define UCDN_SCRIPT_LINEAR_B 47 -#define UCDN_SCRIPT_UGARITIC 48 -#define UCDN_SCRIPT_SHAVIAN 49 -#define UCDN_SCRIPT_OSMANYA 50 -#define UCDN_SCRIPT_CYPRIOT 51 -#define UCDN_SCRIPT_BRAILLE 52 -#define UCDN_SCRIPT_BUGINESE 53 -#define UCDN_SCRIPT_COPTIC 54 -#define UCDN_SCRIPT_NEW_TAI_LUE 55 -#define UCDN_SCRIPT_GLAGOLITIC 56 -#define UCDN_SCRIPT_TIFINAGH 57 -#define UCDN_SCRIPT_SYLOTI_NAGRI 58 -#define UCDN_SCRIPT_OLD_PERSIAN 59 -#define UCDN_SCRIPT_KHAROSHTHI 60 -#define UCDN_SCRIPT_BALINESE 61 -#define UCDN_SCRIPT_CUNEIFORM 62 -#define UCDN_SCRIPT_PHOENICIAN 63 -#define UCDN_SCRIPT_PHAGS_PA 64 -#define UCDN_SCRIPT_NKO 65 -#define UCDN_SCRIPT_SUNDANESE 66 -#define UCDN_SCRIPT_LEPCHA 67 -#define UCDN_SCRIPT_OL_CHIKI 68 -#define UCDN_SCRIPT_VAI 69 -#define UCDN_SCRIPT_SAURASHTRA 70 -#define UCDN_SCRIPT_KAYAH_LI 71 -#define UCDN_SCRIPT_REJANG 72 -#define UCDN_SCRIPT_LYCIAN 73 -#define UCDN_SCRIPT_CARIAN 74 -#define UCDN_SCRIPT_LYDIAN 75 -#define UCDN_SCRIPT_CHAM 76 -#define UCDN_SCRIPT_TAI_THAM 77 -#define UCDN_SCRIPT_TAI_VIET 78 -#define UCDN_SCRIPT_AVESTAN 79 -#define UCDN_SCRIPT_EGYPTIAN_HIEROGLYPHS 80 -#define UCDN_SCRIPT_SAMARITAN 81 -#define UCDN_SCRIPT_LISU 82 -#define UCDN_SCRIPT_BAMUM 83 -#define UCDN_SCRIPT_JAVANESE 84 -#define UCDN_SCRIPT_MEETEI_MAYEK 85 -#define UCDN_SCRIPT_IMPERIAL_ARAMAIC 86 -#define UCDN_SCRIPT_OLD_SOUTH_ARABIAN 87 -#define UCDN_SCRIPT_INSCRIPTIONAL_PARTHIAN 88 -#define UCDN_SCRIPT_INSCRIPTIONAL_PAHLAVI 89 -#define UCDN_SCRIPT_OLD_TURKIC 90 -#define UCDN_SCRIPT_KAITHI 91 -#define UCDN_SCRIPT_BATAK 92 -#define UCDN_SCRIPT_BRAHMI 93 -#define UCDN_SCRIPT_MANDAIC 94 -#define UCDN_SCRIPT_CHAKMA 95 -#define UCDN_SCRIPT_MEROITIC_CURSIVE 96 -#define UCDN_SCRIPT_MEROITIC_HIEROGLYPHS 97 -#define UCDN_SCRIPT_MIAO 98 -#define UCDN_SCRIPT_SHARADA 99 -#define UCDN_SCRIPT_SORA_SOMPENG 100 -#define UCDN_SCRIPT_TAKRI 101 -#define UCDN_SCRIPT_UNKNOWN 102 -#define UCDN_SCRIPT_BASSA_VAH 103 -#define UCDN_SCRIPT_CAUCASIAN_ALBANIAN 104 -#define UCDN_SCRIPT_DUPLOYAN 105 -#define UCDN_SCRIPT_ELBASAN 106 -#define UCDN_SCRIPT_GRANTHA 107 -#define UCDN_SCRIPT_KHOJKI 108 -#define UCDN_SCRIPT_KHUDAWADI 109 -#define UCDN_SCRIPT_LINEAR_A 110 -#define UCDN_SCRIPT_MAHAJANI 111 -#define UCDN_SCRIPT_MANICHAEAN 112 -#define UCDN_SCRIPT_MENDE_KIKAKUI 113 -#define UCDN_SCRIPT_MODI 114 -#define UCDN_SCRIPT_MRO 115 -#define UCDN_SCRIPT_NABATAEAN 116 -#define UCDN_SCRIPT_OLD_NORTH_ARABIAN 117 -#define UCDN_SCRIPT_OLD_PERMIC 118 -#define UCDN_SCRIPT_PAHAWH_HMONG 119 -#define UCDN_SCRIPT_PALMYRENE 120 -#define UCDN_SCRIPT_PAU_CIN_HAU 121 -#define UCDN_SCRIPT_PSALTER_PAHLAVI 122 -#define UCDN_SCRIPT_SIDDHAM 123 -#define UCDN_SCRIPT_TIRHUTA 124 -#define UCDN_SCRIPT_WARANG_CITI 125 -#define UCDN_SCRIPT_AHOM 126 -#define UCDN_SCRIPT_ANATOLIAN_HIEROGLYPHS 127 -#define UCDN_SCRIPT_HATRAN 128 -#define UCDN_SCRIPT_MULTANI 129 -#define UCDN_SCRIPT_OLD_HUNGARIAN 130 -#define UCDN_SCRIPT_SIGNWRITING 131 -#define UCDN_SCRIPT_ADLAM 132 -#define UCDN_SCRIPT_BHAIKSUKI 133 -#define UCDN_SCRIPT_MARCHEN 134 -#define UCDN_SCRIPT_NEWA 135 -#define UCDN_SCRIPT_OSAGE 136 -#define UCDN_SCRIPT_TANGUT 137 -#define UCDN_SCRIPT_MASARAM_GONDI 138 -#define UCDN_SCRIPT_NUSHU 139 -#define UCDN_SCRIPT_SOYOMBO 140 -#define UCDN_SCRIPT_ZANABAZAR_SQUARE 141 -#define UCDN_SCRIPT_DOGRA 142 -#define UCDN_SCRIPT_GUNJALA_GONDI 143 -#define UCDN_SCRIPT_HANIFI_ROHINGYA 144 -#define UCDN_SCRIPT_MAKASAR 145 -#define UCDN_SCRIPT_MEDEFAIDRIN 146 -#define UCDN_SCRIPT_OLD_SOGDIAN 147 -#define UCDN_SCRIPT_SOGDIAN 148 -#define UCDN_SCRIPT_ELYMAIC 149 -#define UCDN_SCRIPT_NANDINAGARI 150 -#define UCDN_SCRIPT_NYIAKENG_PUACHUE_HMONG 151 -#define UCDN_SCRIPT_WANCHO 152 - -#define UCDN_LINEBREAK_CLASS_OP 0 -#define UCDN_LINEBREAK_CLASS_CL 1 -#define UCDN_LINEBREAK_CLASS_CP 2 -#define UCDN_LINEBREAK_CLASS_QU 3 -#define UCDN_LINEBREAK_CLASS_GL 4 -#define UCDN_LINEBREAK_CLASS_NS 5 -#define UCDN_LINEBREAK_CLASS_EX 6 -#define UCDN_LINEBREAK_CLASS_SY 7 -#define UCDN_LINEBREAK_CLASS_IS 8 -#define UCDN_LINEBREAK_CLASS_PR 9 -#define UCDN_LINEBREAK_CLASS_PO 10 -#define UCDN_LINEBREAK_CLASS_NU 11 -#define UCDN_LINEBREAK_CLASS_AL 12 -#define UCDN_LINEBREAK_CLASS_HL 13 -#define UCDN_LINEBREAK_CLASS_ID 14 -#define UCDN_LINEBREAK_CLASS_IN 15 -#define UCDN_LINEBREAK_CLASS_HY 16 -#define UCDN_LINEBREAK_CLASS_BA 17 -#define UCDN_LINEBREAK_CLASS_BB 18 -#define UCDN_LINEBREAK_CLASS_B2 19 -#define UCDN_LINEBREAK_CLASS_ZW 20 -#define UCDN_LINEBREAK_CLASS_CM 21 -#define UCDN_LINEBREAK_CLASS_WJ 22 -#define UCDN_LINEBREAK_CLASS_H2 23 -#define UCDN_LINEBREAK_CLASS_H3 24 -#define UCDN_LINEBREAK_CLASS_JL 25 -#define UCDN_LINEBREAK_CLASS_JV 26 -#define UCDN_LINEBREAK_CLASS_JT 27 -#define UCDN_LINEBREAK_CLASS_RI 28 -#define UCDN_LINEBREAK_CLASS_AI 29 -#define UCDN_LINEBREAK_CLASS_BK 30 -#define UCDN_LINEBREAK_CLASS_CB 31 -#define UCDN_LINEBREAK_CLASS_CJ 32 -#define UCDN_LINEBREAK_CLASS_CR 33 -#define UCDN_LINEBREAK_CLASS_LF 34 -#define UCDN_LINEBREAK_CLASS_NL 35 -#define UCDN_LINEBREAK_CLASS_SA 36 -#define UCDN_LINEBREAK_CLASS_SG 37 -#define UCDN_LINEBREAK_CLASS_SP 38 -#define UCDN_LINEBREAK_CLASS_XX 39 -#define UCDN_LINEBREAK_CLASS_ZWJ 40 -#define UCDN_LINEBREAK_CLASS_EB 41 -#define UCDN_LINEBREAK_CLASS_EM 42 - -#define UCDN_GENERAL_CATEGORY_CC 0 -#define UCDN_GENERAL_CATEGORY_CF 1 -#define UCDN_GENERAL_CATEGORY_CN 2 -#define UCDN_GENERAL_CATEGORY_CO 3 -#define UCDN_GENERAL_CATEGORY_CS 4 -#define UCDN_GENERAL_CATEGORY_LL 5 -#define UCDN_GENERAL_CATEGORY_LM 6 -#define UCDN_GENERAL_CATEGORY_LO 7 -#define UCDN_GENERAL_CATEGORY_LT 8 -#define UCDN_GENERAL_CATEGORY_LU 9 -#define UCDN_GENERAL_CATEGORY_MC 10 -#define UCDN_GENERAL_CATEGORY_ME 11 -#define UCDN_GENERAL_CATEGORY_MN 12 -#define UCDN_GENERAL_CATEGORY_ND 13 -#define UCDN_GENERAL_CATEGORY_NL 14 -#define UCDN_GENERAL_CATEGORY_NO 15 -#define UCDN_GENERAL_CATEGORY_PC 16 -#define UCDN_GENERAL_CATEGORY_PD 17 -#define UCDN_GENERAL_CATEGORY_PE 18 -#define UCDN_GENERAL_CATEGORY_PF 19 -#define UCDN_GENERAL_CATEGORY_PI 20 -#define UCDN_GENERAL_CATEGORY_PO 21 -#define UCDN_GENERAL_CATEGORY_PS 22 -#define UCDN_GENERAL_CATEGORY_SC 23 -#define UCDN_GENERAL_CATEGORY_SK 24 -#define UCDN_GENERAL_CATEGORY_SM 25 -#define UCDN_GENERAL_CATEGORY_SO 26 -#define UCDN_GENERAL_CATEGORY_ZL 27 -#define UCDN_GENERAL_CATEGORY_ZP 28 -#define UCDN_GENERAL_CATEGORY_ZS 29 - -#define UCDN_BIDI_CLASS_L 0 -#define UCDN_BIDI_CLASS_LRE 1 -#define UCDN_BIDI_CLASS_LRO 2 -#define UCDN_BIDI_CLASS_R 3 -#define UCDN_BIDI_CLASS_AL 4 -#define UCDN_BIDI_CLASS_RLE 5 -#define UCDN_BIDI_CLASS_RLO 6 -#define UCDN_BIDI_CLASS_PDF 7 -#define UCDN_BIDI_CLASS_EN 8 -#define UCDN_BIDI_CLASS_ES 9 -#define UCDN_BIDI_CLASS_ET 10 -#define UCDN_BIDI_CLASS_AN 11 -#define UCDN_BIDI_CLASS_CS 12 -#define UCDN_BIDI_CLASS_NSM 13 -#define UCDN_BIDI_CLASS_BN 14 -#define UCDN_BIDI_CLASS_B 15 -#define UCDN_BIDI_CLASS_S 16 -#define UCDN_BIDI_CLASS_WS 17 -#define UCDN_BIDI_CLASS_ON 18 -#define UCDN_BIDI_CLASS_LRI 19 -#define UCDN_BIDI_CLASS_RLI 20 -#define UCDN_BIDI_CLASS_FSI 21 -#define UCDN_BIDI_CLASS_PDI 22 - -#define UCDN_BIDI_PAIRED_BRACKET_TYPE_OPEN 0 -#define UCDN_BIDI_PAIRED_BRACKET_TYPE_CLOSE 1 -#define UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE 2 - -/** - * Return version of the Unicode database. - * - * @return Unicode database version - */ -const char *ucdn_get_unicode_version(void); - -/** - * Get combining class of a codepoint. - * - * @param code Unicode codepoint - * @return combining class value, as defined in UAX#44 - */ -int ucdn_get_combining_class(uint32_t code); - -/** - * Get east-asian width of a codepoint. - * - * @param code Unicode codepoint - * @return value according to UCDN_EAST_ASIAN_* and as defined in UAX#11. - */ -int ucdn_get_east_asian_width(uint32_t code); - -/** - * Get general category of a codepoint. - * - * @param code Unicode codepoint - * @return value according to UCDN_GENERAL_CATEGORY_* and as defined in - * UAX#44. - */ -int ucdn_get_general_category(uint32_t code); - -/** - * Get bidirectional class of a codepoint. - * - * @param code Unicode codepoint - * @return value according to UCDN_BIDI_CLASS_* and as defined in UAX#44. - */ -int ucdn_get_bidi_class(uint32_t code); - -/** - * Get script of a codepoint. - * - * @param code Unicode codepoint - * @return value according to UCDN_SCRIPT_* and as defined in UAX#24. - */ -int ucdn_get_script(uint32_t code); - -/** - * Get unresolved linebreak class of a codepoint. This does not take - * rule LB1 of UAX#14 into account. See ucdn_get_resolved_linebreak_class() - * for resolved linebreak classes. - * - * @param code Unicode codepoint - * @return value according to UCDN_LINEBREAK_* and as defined in UAX#14. - */ -int ucdn_get_linebreak_class(uint32_t code); - -/** - * Get resolved linebreak class of a codepoint. This resolves characters - * in the AI, SG, XX, SA and CJ classes according to rule LB1 of UAX#14. - * In addition the CB class is resolved as the equivalent B2 class and - * the NL class is resolved as the equivalent BK class. - * - * @param code Unicode codepoint - * @return value according to UCDN_LINEBREAK_* and as defined in UAX#14. - */ -int ucdn_get_resolved_linebreak_class(uint32_t code); - -/** - * Check if codepoint can be mirrored. - * - * @param code Unicode codepoint - * @return 1 if mirrored character exists, otherwise 0 - */ -int ucdn_get_mirrored(uint32_t code); - -/** - * Mirror a codepoint. - * - * @param code Unicode codepoint - * @return mirrored codepoint or the original codepoint if no - * mirrored character exists - */ -uint32_t ucdn_mirror(uint32_t code); - -/** - * Get paired bracket for a codepoint. - * - * @param code Unicode codepoint - * @return paired bracket codepoint or the original codepoint if no - * paired bracket character exists - */ -uint32_t ucdn_paired_bracket(uint32_t code); - -/** - * Get paired bracket type for a codepoint. - * - * @param code Unicode codepoint - * @return value according to UCDN_BIDI_PAIRED_BRACKET_TYPE_* and as defined - * in UAX#9. - * - */ -int ucdn_paired_bracket_type(uint32_t code); - -/** - * Pairwise canonical decomposition of a codepoint. This includes - * Hangul Jamo decomposition (see chapter 3.12 of the Unicode core - * specification). - * - * Hangul is decomposed into L and V jamos for LV forms, and an - * LV precomposed syllable and a T jamo for LVT forms. - * - * @param code Unicode codepoint - * @param a filled with first codepoint of decomposition - * @param b filled with second codepoint of decomposition, or 0 - * @return success - */ -int ucdn_decompose(uint32_t code, uint32_t *a, uint32_t *b); - -/** - * Compatibility decomposition of a codepoint. - * - * @param code Unicode codepoint - * @param decomposed filled with decomposition, must be able to hold 18 - * characters - * @return length of decomposition or 0 in case none exists - */ -int ucdn_compat_decompose(uint32_t code, uint32_t *decomposed); - -/** - * Pairwise canonical composition of two codepoints. This includes - * Hangul Jamo composition (see chapter 3.12 of the Unicode core - * specification). - * - * Hangul composition expects either L and V jamos, or an LV - * precomposed syllable and a T jamo. This is exactly the inverse - * of pairwise Hangul decomposition. - * - * @param code filled with composition - * @param a first codepoint - * @param b second codepoint - * @return success - */ -int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b); - -HB_END_HEADER - -#endif diff --git a/src/hb-ucdn/ucdn_db.h b/src/hb-ucdn/ucdn_db.h deleted file mode 100644 index 8f1310f29..000000000 --- a/src/hb-ucdn/ucdn_db.h +++ /dev/null @@ -1,5790 +0,0 @@ -/* this file was generated by makeunicodedata.py 3.2 */ - -#define UNIDATA_VERSION "12.0.0" -/* a list of unique database records */ -static const UCDRecord ucd_records[] = { - {2, 0, 18, 5, 102, 39}, - {0, 0, 14, 5, 0, 21}, - {0, 0, 16, 5, 0, 17}, - {0, 0, 15, 5, 0, 34}, - {0, 0, 16, 5, 0, 30}, - {0, 0, 17, 5, 0, 30}, - {0, 0, 15, 5, 0, 33}, - {0, 0, 15, 5, 0, 21}, - {0, 0, 16, 5, 0, 21}, - {29, 0, 17, 3, 0, 38}, - {21, 0, 18, 3, 0, 6}, - {21, 0, 18, 3, 0, 3}, - {21, 0, 10, 3, 0, 12}, - {23, 0, 10, 3, 0, 9}, - {21, 0, 10, 3, 0, 10}, - {21, 0, 18, 3, 0, 12}, - {22, 0, 18, 3, 0, 0}, - {18, 0, 18, 3, 0, 2}, - {25, 0, 9, 3, 0, 9}, - {21, 0, 12, 3, 0, 8}, - {17, 0, 9, 3, 0, 16}, - {21, 0, 12, 3, 0, 7}, - {13, 0, 8, 3, 0, 11}, - {21, 0, 18, 3, 0, 8}, - {25, 0, 18, 3, 0, 12}, - {9, 0, 0, 3, 1, 12}, - {21, 0, 18, 3, 0, 9}, - {24, 0, 18, 3, 0, 12}, - {16, 0, 18, 3, 0, 12}, - {5, 0, 0, 3, 1, 12}, - {25, 0, 18, 3, 0, 17}, - {18, 0, 18, 3, 0, 1}, - {0, 0, 15, 5, 0, 35}, - {29, 0, 12, 5, 0, 4}, - {21, 0, 18, 4, 0, 0}, - {23, 0, 10, 3, 0, 10}, - {23, 0, 10, 4, 0, 9}, - {26, 0, 18, 3, 0, 12}, - {21, 0, 18, 4, 0, 29}, - {24, 0, 18, 4, 0, 29}, - {26, 0, 18, 5, 0, 12}, - {7, 0, 0, 4, 1, 29}, - {20, 0, 18, 5, 0, 3}, - {1, 0, 14, 4, 0, 17}, - {26, 0, 18, 4, 0, 12}, - {26, 0, 10, 4, 0, 10}, - {25, 0, 10, 4, 0, 9}, - {15, 0, 8, 4, 0, 29}, - {24, 0, 18, 4, 0, 18}, - {5, 0, 0, 5, 0, 12}, - {19, 0, 18, 5, 0, 3}, - {15, 0, 18, 4, 0, 29}, - {9, 0, 0, 5, 1, 12}, - {9, 0, 0, 4, 1, 12}, - {25, 0, 18, 4, 0, 29}, - {5, 0, 0, 4, 1, 12}, - {5, 0, 0, 5, 1, 12}, - {7, 0, 0, 5, 1, 12}, - {8, 0, 0, 5, 1, 12}, - {6, 0, 0, 5, 1, 12}, - {6, 0, 18, 5, 0, 12}, - {6, 0, 0, 5, 0, 12}, - {24, 0, 18, 5, 0, 12}, - {24, 0, 18, 4, 0, 12}, - {6, 0, 18, 4, 0, 29}, - {6, 0, 18, 5, 0, 18}, - {6, 0, 0, 4, 0, 29}, - {24, 0, 18, 5, 34, 12}, - {12, 230, 13, 4, 40, 21}, - {12, 232, 13, 4, 40, 21}, - {12, 220, 13, 4, 40, 21}, - {12, 216, 13, 4, 40, 21}, - {12, 202, 13, 4, 40, 21}, - {12, 1, 13, 4, 40, 21}, - {12, 240, 13, 4, 40, 21}, - {12, 0, 13, 4, 40, 4}, - {12, 233, 13, 4, 40, 4}, - {12, 234, 13, 4, 40, 4}, - {9, 0, 0, 5, 2, 12}, - {5, 0, 0, 5, 2, 12}, - {24, 0, 18, 5, 2, 12}, - {2, 0, 18, 5, 102, 39}, - {6, 0, 0, 5, 2, 12}, - {21, 0, 18, 5, 0, 8}, - {21, 0, 18, 5, 0, 12}, - {9, 0, 0, 4, 2, 12}, - {5, 0, 0, 4, 2, 12}, - {9, 0, 0, 5, 54, 12}, - {5, 0, 0, 5, 54, 12}, - {25, 0, 18, 5, 2, 12}, - {9, 0, 0, 5, 3, 12}, - {9, 0, 0, 4, 3, 12}, - {5, 0, 0, 4, 3, 12}, - {5, 0, 0, 5, 3, 12}, - {26, 0, 0, 5, 3, 12}, - {12, 230, 13, 5, 3, 21}, - {12, 230, 13, 5, 40, 21}, - {11, 0, 13, 5, 3, 21}, - {9, 0, 0, 5, 4, 12}, - {6, 0, 0, 5, 4, 12}, - {21, 0, 0, 5, 4, 12}, - {5, 0, 0, 5, 4, 12}, - {21, 0, 0, 5, 0, 8}, - {17, 0, 18, 5, 4, 17}, - {26, 0, 18, 5, 4, 12}, - {23, 0, 10, 5, 4, 9}, - {12, 220, 13, 5, 5, 21}, - {12, 230, 13, 5, 5, 21}, - {12, 222, 13, 5, 5, 21}, - {12, 228, 13, 5, 5, 21}, - {12, 10, 13, 5, 5, 21}, - {12, 11, 13, 5, 5, 21}, - {12, 12, 13, 5, 5, 21}, - {12, 13, 13, 5, 5, 21}, - {12, 14, 13, 5, 5, 21}, - {12, 15, 13, 5, 5, 21}, - {12, 16, 13, 5, 5, 21}, - {12, 17, 13, 5, 5, 21}, - {12, 18, 13, 5, 5, 21}, - {12, 19, 13, 5, 5, 21}, - {12, 20, 13, 5, 5, 21}, - {12, 21, 13, 5, 5, 21}, - {12, 22, 13, 5, 5, 21}, - {17, 0, 3, 5, 5, 17}, - {12, 23, 13, 5, 5, 21}, - {21, 0, 3, 5, 5, 12}, - {12, 24, 13, 5, 5, 21}, - {12, 25, 13, 5, 5, 21}, - {21, 0, 3, 5, 5, 6}, - {7, 0, 3, 5, 5, 13}, - {1, 0, 11, 5, 6, 12}, - {1, 0, 11, 5, 0, 12}, - {25, 0, 18, 5, 6, 12}, - {25, 0, 4, 5, 6, 12}, - {21, 0, 10, 5, 6, 10}, - {23, 0, 4, 5, 6, 10}, - {21, 0, 12, 5, 0, 8}, - {21, 0, 4, 5, 6, 8}, - {26, 0, 18, 5, 6, 12}, - {12, 230, 13, 5, 6, 21}, - {12, 30, 13, 5, 6, 21}, - {12, 31, 13, 5, 6, 21}, - {12, 32, 13, 5, 6, 21}, - {21, 0, 4, 5, 0, 6}, - {1, 0, 4, 5, 6, 21}, - {21, 0, 4, 5, 6, 6}, - {7, 0, 4, 5, 6, 12}, - {6, 0, 4, 5, 0, 12}, - {12, 27, 13, 5, 40, 21}, - {12, 28, 13, 5, 40, 21}, - {12, 29, 13, 5, 40, 21}, - {12, 30, 13, 5, 40, 21}, - {12, 31, 13, 5, 40, 21}, - {12, 32, 13, 5, 40, 21}, - {12, 33, 13, 5, 40, 21}, - {12, 34, 13, 5, 40, 21}, - {12, 220, 13, 5, 40, 21}, - {12, 220, 13, 5, 6, 21}, - {13, 0, 11, 5, 6, 11}, - {21, 0, 11, 5, 6, 11}, - {21, 0, 4, 5, 6, 12}, - {12, 35, 13, 5, 40, 21}, - {6, 0, 4, 5, 6, 12}, - {13, 0, 8, 5, 6, 11}, - {26, 0, 4, 5, 6, 12}, - {21, 0, 4, 5, 7, 12}, - {1, 0, 4, 5, 7, 12}, - {7, 0, 4, 5, 7, 12}, - {12, 36, 13, 5, 7, 21}, - {12, 230, 13, 5, 7, 21}, - {12, 220, 13, 5, 7, 21}, - {7, 0, 4, 5, 8, 12}, - {12, 0, 13, 5, 8, 21}, - {13, 0, 3, 5, 65, 11}, - {7, 0, 3, 5, 65, 12}, - {12, 230, 13, 5, 65, 21}, - {12, 220, 13, 5, 65, 21}, - {6, 0, 3, 5, 65, 12}, - {26, 0, 18, 5, 65, 12}, - {21, 0, 18, 5, 65, 12}, - {21, 0, 18, 5, 65, 8}, - {21, 0, 18, 5, 65, 6}, - {23, 0, 3, 5, 65, 9}, - {7, 0, 3, 5, 81, 12}, - {12, 230, 13, 5, 81, 21}, - {6, 0, 3, 5, 81, 12}, - {21, 0, 3, 5, 81, 12}, - {7, 0, 3, 5, 94, 12}, - {12, 220, 13, 5, 94, 21}, - {21, 0, 3, 5, 94, 12}, - {12, 27, 13, 5, 6, 21}, - {12, 28, 13, 5, 6, 21}, - {12, 29, 13, 5, 6, 21}, - {12, 0, 13, 5, 9, 21}, - {10, 0, 0, 5, 9, 21}, - {7, 0, 0, 5, 9, 12}, - {12, 7, 13, 5, 9, 21}, - {12, 9, 13, 5, 9, 21}, - {21, 0, 0, 5, 0, 17}, - {13, 0, 0, 5, 9, 11}, - {21, 0, 0, 5, 9, 12}, - {6, 0, 0, 5, 9, 12}, - {7, 0, 0, 5, 10, 12}, - {12, 0, 13, 5, 10, 21}, - {10, 0, 0, 5, 10, 21}, - {12, 7, 13, 5, 10, 21}, - {12, 9, 13, 5, 10, 21}, - {13, 0, 0, 5, 10, 11}, - {23, 0, 10, 5, 10, 10}, - {15, 0, 0, 5, 10, 12}, - {15, 0, 0, 5, 10, 10}, - {26, 0, 0, 5, 10, 12}, - {23, 0, 10, 5, 10, 9}, - {21, 0, 0, 5, 10, 12}, - {12, 230, 13, 5, 10, 21}, - {12, 0, 13, 5, 11, 21}, - {10, 0, 0, 5, 11, 21}, - {7, 0, 0, 5, 11, 12}, - {12, 7, 13, 5, 11, 21}, - {12, 9, 13, 5, 11, 21}, - {13, 0, 0, 5, 11, 11}, - {21, 0, 0, 5, 11, 12}, - {12, 0, 13, 5, 12, 21}, - {10, 0, 0, 5, 12, 21}, - {7, 0, 0, 5, 12, 12}, - {12, 7, 13, 5, 12, 21}, - {12, 9, 13, 5, 12, 21}, - {13, 0, 0, 5, 12, 11}, - {21, 0, 0, 5, 12, 12}, - {23, 0, 10, 5, 12, 9}, - {12, 0, 13, 5, 13, 21}, - {10, 0, 0, 5, 13, 21}, - {7, 0, 0, 5, 13, 12}, - {12, 7, 13, 5, 13, 21}, - {12, 9, 13, 5, 13, 21}, - {13, 0, 0, 5, 13, 11}, - {26, 0, 0, 5, 13, 12}, - {15, 0, 0, 5, 13, 12}, - {12, 0, 13, 5, 14, 21}, - {7, 0, 0, 5, 14, 12}, - {10, 0, 0, 5, 14, 21}, - {12, 9, 13, 5, 14, 21}, - {13, 0, 0, 5, 14, 11}, - {15, 0, 0, 5, 14, 12}, - {26, 0, 18, 5, 14, 12}, - {23, 0, 10, 5, 14, 9}, - {12, 0, 13, 5, 15, 21}, - {10, 0, 0, 5, 15, 21}, - {7, 0, 0, 5, 15, 12}, - {12, 9, 13, 5, 15, 21}, - {12, 84, 13, 5, 15, 21}, - {12, 91, 13, 5, 15, 21}, - {13, 0, 0, 5, 15, 11}, - {21, 0, 0, 5, 15, 18}, - {15, 0, 18, 5, 15, 12}, - {26, 0, 0, 5, 15, 12}, - {7, 0, 0, 5, 16, 12}, - {12, 0, 13, 5, 16, 21}, - {10, 0, 0, 5, 16, 21}, - {21, 0, 0, 5, 16, 18}, - {12, 7, 13, 5, 16, 21}, - {12, 0, 0, 5, 16, 21}, - {12, 9, 13, 5, 16, 21}, - {13, 0, 0, 5, 16, 11}, - {12, 0, 13, 5, 17, 21}, - {10, 0, 0, 5, 17, 21}, - {7, 0, 0, 5, 17, 12}, - {12, 9, 13, 5, 17, 21}, - {26, 0, 0, 5, 17, 12}, - {15, 0, 0, 5, 17, 12}, - {13, 0, 0, 5, 17, 11}, - {26, 0, 0, 5, 17, 10}, - {10, 0, 0, 5, 18, 21}, - {7, 0, 0, 5, 18, 12}, - {12, 9, 13, 5, 18, 21}, - {12, 0, 13, 5, 18, 21}, - {13, 0, 0, 5, 18, 11}, - {21, 0, 0, 5, 18, 12}, - {7, 0, 0, 5, 19, 36}, - {12, 0, 13, 5, 19, 36}, - {12, 103, 13, 5, 19, 36}, - {12, 9, 13, 5, 19, 36}, - {23, 0, 10, 5, 0, 9}, - {6, 0, 0, 5, 19, 36}, - {12, 107, 13, 5, 19, 36}, - {21, 0, 0, 5, 19, 12}, - {13, 0, 0, 5, 19, 11}, - {21, 0, 0, 5, 19, 17}, - {7, 0, 0, 5, 20, 36}, - {12, 0, 13, 5, 20, 36}, - {12, 118, 13, 5, 20, 36}, - {12, 9, 13, 5, 20, 36}, - {6, 0, 0, 5, 20, 36}, - {12, 122, 13, 5, 20, 36}, - {13, 0, 0, 5, 20, 11}, - {7, 0, 0, 5, 21, 12}, - {26, 0, 0, 5, 21, 18}, - {21, 0, 0, 5, 21, 18}, - {21, 0, 0, 5, 21, 12}, - {21, 0, 0, 5, 21, 4}, - {21, 0, 0, 5, 21, 17}, - {21, 0, 0, 5, 21, 6}, - {26, 0, 0, 5, 21, 12}, - {12, 220, 13, 5, 21, 21}, - {13, 0, 0, 5, 21, 11}, - {15, 0, 0, 5, 21, 12}, - {26, 0, 0, 5, 21, 17}, - {12, 216, 13, 5, 21, 21}, - {22, 0, 18, 5, 21, 0}, - {18, 0, 18, 5, 21, 1}, - {10, 0, 0, 5, 21, 21}, - {12, 129, 13, 5, 21, 21}, - {12, 130, 13, 5, 21, 21}, - {12, 0, 13, 5, 21, 21}, - {12, 132, 13, 5, 21, 21}, - {10, 0, 0, 5, 21, 17}, - {12, 230, 13, 5, 21, 21}, - {12, 9, 13, 5, 21, 21}, - {26, 0, 0, 5, 0, 12}, - {7, 0, 0, 5, 22, 36}, - {10, 0, 0, 5, 22, 36}, - {12, 0, 13, 5, 22, 36}, - {12, 7, 13, 5, 22, 36}, - {12, 9, 13, 5, 22, 36}, - {13, 0, 0, 5, 22, 11}, - {21, 0, 0, 5, 22, 17}, - {21, 0, 0, 5, 22, 12}, - {12, 220, 13, 5, 22, 36}, - {26, 0, 0, 5, 22, 36}, - {9, 0, 0, 5, 23, 12}, - {5, 0, 0, 5, 23, 12}, - {21, 0, 0, 5, 0, 12}, - {6, 0, 0, 5, 23, 12}, - {7, 0, 0, 2, 24, 25}, - {7, 0, 0, 5, 24, 26}, - {7, 0, 0, 5, 24, 27}, - {7, 0, 0, 5, 25, 12}, - {12, 230, 13, 5, 25, 21}, - {21, 0, 0, 5, 25, 12}, - {21, 0, 0, 5, 25, 17}, - {15, 0, 0, 5, 25, 12}, - {26, 0, 18, 5, 25, 12}, - {9, 0, 0, 5, 26, 12}, - {5, 0, 0, 5, 26, 12}, - {17, 0, 18, 5, 27, 17}, - {7, 0, 0, 5, 27, 12}, - {26, 0, 0, 5, 27, 12}, - {21, 0, 0, 5, 27, 12}, - {29, 0, 17, 5, 28, 17}, - {7, 0, 0, 5, 28, 12}, - {22, 0, 18, 5, 28, 0}, - {18, 0, 18, 5, 28, 1}, - {7, 0, 0, 5, 29, 12}, - {14, 0, 0, 5, 29, 12}, - {7, 0, 0, 5, 41, 12}, - {12, 0, 13, 5, 41, 21}, - {12, 9, 13, 5, 41, 21}, - {7, 0, 0, 5, 42, 12}, - {12, 0, 13, 5, 42, 21}, - {12, 9, 13, 5, 42, 21}, - {7, 0, 0, 5, 43, 12}, - {12, 0, 13, 5, 43, 21}, - {7, 0, 0, 5, 44, 12}, - {12, 0, 13, 5, 44, 21}, - {7, 0, 0, 5, 30, 36}, - {12, 0, 13, 5, 30, 36}, - {10, 0, 0, 5, 30, 36}, - {12, 9, 13, 5, 30, 36}, - {21, 0, 0, 5, 30, 17}, - {21, 0, 0, 5, 30, 5}, - {6, 0, 0, 5, 30, 36}, - {21, 0, 0, 5, 30, 12}, - {23, 0, 10, 5, 30, 9}, - {12, 230, 13, 5, 30, 36}, - {13, 0, 0, 5, 30, 11}, - {15, 0, 18, 5, 30, 12}, - {21, 0, 18, 5, 31, 12}, - {21, 0, 18, 5, 0, 6}, - {21, 0, 18, 5, 31, 17}, - {21, 0, 18, 5, 0, 17}, - {17, 0, 18, 5, 31, 18}, - {21, 0, 18, 5, 31, 6}, - {12, 0, 13, 5, 31, 21}, - {1, 0, 14, 5, 31, 4}, - {13, 0, 0, 5, 31, 11}, - {7, 0, 0, 5, 31, 12}, - {6, 0, 0, 5, 31, 12}, - {12, 228, 13, 5, 31, 21}, - {7, 0, 0, 5, 45, 12}, - {12, 0, 13, 5, 45, 21}, - {10, 0, 0, 5, 45, 21}, - {12, 222, 13, 5, 45, 21}, - {12, 230, 13, 5, 45, 21}, - {12, 220, 13, 5, 45, 21}, - {26, 0, 18, 5, 45, 12}, - {21, 0, 18, 5, 45, 6}, - {13, 0, 0, 5, 45, 11}, - {7, 0, 0, 5, 46, 36}, - {7, 0, 0, 5, 55, 36}, - {13, 0, 0, 5, 55, 11}, - {15, 0, 0, 5, 55, 36}, - {26, 0, 18, 5, 55, 36}, - {26, 0, 18, 5, 30, 12}, - {7, 0, 0, 5, 53, 12}, - {12, 230, 13, 5, 53, 21}, - {12, 220, 13, 5, 53, 21}, - {10, 0, 0, 5, 53, 21}, - {12, 0, 13, 5, 53, 21}, - {21, 0, 0, 5, 53, 12}, - {7, 0, 0, 5, 77, 36}, - {10, 0, 0, 5, 77, 36}, - {12, 0, 13, 5, 77, 36}, - {12, 9, 13, 5, 77, 36}, - {12, 230, 13, 5, 77, 36}, - {12, 220, 13, 5, 77, 21}, - {13, 0, 0, 5, 77, 11}, - {21, 0, 0, 5, 77, 36}, - {6, 0, 0, 5, 77, 36}, - {11, 0, 13, 5, 40, 21}, - {12, 0, 13, 5, 61, 21}, - {10, 0, 0, 5, 61, 21}, - {7, 0, 0, 5, 61, 12}, - {12, 7, 13, 5, 61, 21}, - {10, 9, 0, 5, 61, 21}, - {13, 0, 0, 5, 61, 11}, - {21, 0, 0, 5, 61, 17}, - {21, 0, 0, 5, 61, 12}, - {26, 0, 0, 5, 61, 12}, - {12, 230, 13, 5, 61, 21}, - {12, 220, 13, 5, 61, 21}, - {12, 0, 13, 5, 66, 21}, - {10, 0, 0, 5, 66, 21}, - {7, 0, 0, 5, 66, 12}, - {10, 9, 0, 5, 66, 21}, - {12, 9, 13, 5, 66, 21}, - {13, 0, 0, 5, 66, 11}, - {7, 0, 0, 5, 92, 12}, - {12, 7, 13, 5, 92, 21}, - {10, 0, 0, 5, 92, 21}, - {12, 0, 13, 5, 92, 21}, - {10, 9, 0, 5, 92, 21}, - {21, 0, 0, 5, 92, 12}, - {7, 0, 0, 5, 67, 12}, - {10, 0, 0, 5, 67, 21}, - {12, 0, 13, 5, 67, 21}, - {12, 7, 13, 5, 67, 21}, - {21, 0, 0, 5, 67, 17}, - {13, 0, 0, 5, 67, 11}, - {13, 0, 0, 5, 68, 11}, - {7, 0, 0, 5, 68, 12}, - {6, 0, 0, 5, 68, 12}, - {21, 0, 0, 5, 68, 17}, - {21, 0, 0, 5, 66, 12}, - {12, 1, 13, 5, 40, 21}, - {10, 0, 0, 5, 0, 21}, - {7, 0, 0, 5, 0, 12}, - {6, 0, 0, 5, 3, 12}, - {12, 234, 13, 5, 40, 21}, - {12, 214, 13, 5, 40, 21}, - {12, 202, 13, 5, 40, 21}, - {12, 232, 13, 5, 40, 21}, - {12, 228, 13, 5, 40, 21}, - {12, 233, 13, 5, 40, 21}, - {8, 0, 0, 5, 2, 12}, - {24, 0, 18, 5, 2, 18}, - {29, 0, 17, 5, 0, 17}, - {29, 0, 17, 5, 0, 4}, - {1, 0, 14, 5, 0, 20}, - {1, 0, 14, 5, 40, 21}, - {1, 0, 14, 5, 40, 40}, - {1, 0, 0, 5, 0, 21}, - {1, 0, 3, 5, 0, 21}, - {17, 0, 18, 4, 0, 17}, - {17, 0, 18, 5, 0, 4}, - {17, 0, 18, 5, 0, 17}, - {17, 0, 18, 4, 0, 19}, - {17, 0, 18, 4, 0, 29}, - {20, 0, 18, 4, 0, 3}, - {19, 0, 18, 4, 0, 3}, - {22, 0, 18, 5, 0, 0}, - {21, 0, 18, 4, 0, 12}, - {21, 0, 18, 4, 0, 15}, - {21, 0, 18, 4, 0, 17}, - {27, 0, 17, 5, 0, 30}, - {28, 0, 15, 5, 0, 30}, - {1, 0, 1, 5, 0, 21}, - {1, 0, 5, 5, 0, 21}, - {1, 0, 7, 5, 0, 21}, - {1, 0, 2, 5, 0, 21}, - {1, 0, 6, 5, 0, 21}, - {21, 0, 10, 4, 0, 10}, - {21, 0, 10, 5, 0, 10}, - {21, 0, 18, 4, 0, 10}, - {21, 0, 18, 5, 0, 10}, - {21, 0, 18, 5, 0, 5}, - {16, 0, 18, 5, 0, 12}, - {25, 0, 12, 5, 0, 8}, - {18, 0, 18, 5, 0, 1}, - {25, 0, 18, 5, 0, 12}, - {1, 0, 14, 5, 0, 22}, - {1, 0, 14, 5, 0, 12}, - {1, 0, 19, 5, 0, 21}, - {1, 0, 20, 5, 0, 21}, - {1, 0, 21, 5, 0, 21}, - {1, 0, 22, 5, 0, 21}, - {1, 0, 14, 5, 0, 21}, - {15, 0, 8, 5, 0, 12}, - {25, 0, 9, 5, 0, 12}, - {6, 0, 0, 4, 1, 29}, - {23, 0, 10, 5, 0, 10}, - {23, 0, 10, 1, 0, 9}, - {2, 0, 18, 5, 102, 9}, - {9, 0, 0, 5, 0, 12}, - {26, 0, 18, 4, 0, 10}, - {26, 0, 18, 4, 0, 29}, - {5, 0, 0, 4, 0, 29}, - {26, 0, 18, 4, 0, 9}, - {9, 0, 0, 4, 1, 29}, - {26, 0, 10, 5, 0, 12}, - {15, 0, 18, 5, 0, 12}, - {15, 0, 18, 4, 0, 12}, - {15, 0, 18, 5, 0, 29}, - {14, 0, 0, 4, 1, 29}, - {14, 0, 0, 5, 1, 12}, - {25, 0, 9, 5, 0, 9}, - {25, 0, 10, 5, 0, 9}, - {25, 0, 18, 5, 0, 15}, - {26, 0, 18, 2, 0, 14}, - {22, 0, 18, 2, 0, 0}, - {18, 0, 18, 2, 0, 1}, - {26, 0, 18, 2, 0, 12}, - {26, 0, 18, 5, 0, 14}, - {26, 0, 0, 4, 0, 29}, - {26, 0, 18, 5, 0, 29}, - {25, 0, 18, 2, 0, 12}, - {26, 0, 18, 4, 0, 14}, - {26, 0, 18, 5, 0, 41}, - {26, 0, 18, 4, 0, 41}, - {26, 0, 18, 2, 0, 41}, - {26, 0, 18, 2, 0, 29}, - {26, 0, 18, 5, 0, 3}, - {26, 0, 18, 5, 0, 6}, - {26, 0, 0, 5, 52, 12}, - {9, 0, 0, 5, 56, 12}, - {5, 0, 0, 5, 56, 12}, - {26, 0, 18, 5, 54, 12}, - {12, 230, 13, 5, 54, 21}, - {21, 0, 18, 5, 54, 6}, - {21, 0, 18, 5, 54, 17}, - {15, 0, 18, 5, 54, 12}, - {7, 0, 0, 5, 57, 12}, - {6, 0, 0, 5, 57, 12}, - {21, 0, 0, 5, 57, 17}, - {12, 9, 13, 5, 57, 21}, - {21, 0, 18, 5, 0, 3}, - {21, 0, 18, 5, 0, 0}, - {17, 0, 18, 5, 0, 12}, - {17, 0, 18, 5, 0, 19}, - {26, 0, 18, 2, 35, 14}, - {29, 0, 17, 0, 0, 17}, - {21, 0, 18, 2, 0, 1}, - {21, 0, 18, 2, 0, 14}, - {6, 0, 0, 2, 35, 5}, - {7, 0, 0, 2, 0, 14}, - {14, 0, 0, 2, 35, 14}, - {17, 0, 18, 2, 0, 5}, - {12, 218, 13, 2, 40, 21}, - {12, 228, 13, 2, 40, 21}, - {12, 232, 13, 2, 40, 21}, - {12, 222, 13, 2, 40, 21}, - {10, 224, 0, 2, 24, 21}, - {17, 0, 18, 2, 0, 14}, - {6, 0, 0, 2, 0, 14}, - {6, 0, 0, 2, 0, 21}, - {7, 0, 0, 2, 0, 5}, - {7, 0, 0, 2, 32, 32}, - {7, 0, 0, 2, 32, 14}, - {12, 8, 13, 2, 40, 21}, - {24, 0, 18, 2, 0, 5}, - {6, 0, 0, 2, 32, 5}, - {7, 0, 0, 2, 33, 32}, - {7, 0, 0, 2, 33, 14}, - {21, 0, 18, 2, 0, 5}, - {6, 0, 0, 2, 0, 32}, - {6, 0, 0, 2, 33, 5}, - {7, 0, 0, 2, 34, 14}, - {7, 0, 0, 2, 24, 14}, - {26, 0, 0, 2, 0, 14}, - {15, 0, 0, 2, 0, 14}, - {26, 0, 0, 2, 24, 14}, - {26, 0, 18, 2, 24, 14}, - {15, 0, 0, 4, 0, 29}, - {15, 0, 18, 2, 0, 14}, - {26, 0, 0, 2, 33, 14}, - {7, 0, 0, 2, 35, 14}, - {2, 0, 18, 2, 102, 14}, - {7, 0, 0, 2, 36, 14}, - {6, 0, 0, 2, 36, 5}, - {26, 0, 18, 2, 36, 14}, - {7, 0, 0, 5, 82, 12}, - {6, 0, 0, 5, 82, 12}, - {21, 0, 0, 5, 82, 17}, - {7, 0, 0, 5, 69, 12}, - {6, 0, 0, 5, 69, 12}, - {21, 0, 18, 5, 69, 17}, - {21, 0, 18, 5, 69, 6}, - {13, 0, 0, 5, 69, 11}, - {7, 0, 0, 5, 3, 12}, - {21, 0, 18, 5, 3, 12}, - {6, 0, 18, 5, 3, 12}, - {7, 0, 0, 5, 83, 12}, - {14, 0, 0, 5, 83, 12}, - {12, 230, 13, 5, 83, 21}, - {21, 0, 0, 5, 83, 12}, - {21, 0, 0, 5, 83, 17}, - {24, 0, 0, 5, 0, 12}, - {7, 0, 0, 5, 58, 12}, - {12, 0, 13, 5, 58, 21}, - {12, 9, 13, 5, 58, 21}, - {10, 0, 0, 5, 58, 21}, - {26, 0, 18, 5, 58, 12}, - {15, 0, 0, 5, 0, 12}, - {7, 0, 0, 5, 64, 12}, - {21, 0, 18, 5, 64, 18}, - {21, 0, 18, 5, 64, 6}, - {10, 0, 0, 5, 70, 21}, - {7, 0, 0, 5, 70, 12}, - {12, 9, 13, 5, 70, 21}, - {12, 0, 13, 5, 70, 21}, - {21, 0, 0, 5, 70, 17}, - {13, 0, 0, 5, 70, 11}, - {12, 230, 13, 5, 9, 21}, - {21, 0, 0, 5, 9, 18}, - {13, 0, 0, 5, 71, 11}, - {7, 0, 0, 5, 71, 12}, - {12, 0, 13, 5, 71, 21}, - {12, 220, 13, 5, 71, 21}, - {21, 0, 0, 5, 71, 17}, - {7, 0, 0, 5, 72, 12}, - {12, 0, 13, 5, 72, 21}, - {10, 0, 0, 5, 72, 21}, - {10, 9, 0, 5, 72, 21}, - {21, 0, 0, 5, 72, 12}, - {12, 0, 13, 5, 84, 21}, - {10, 0, 0, 5, 84, 21}, - {7, 0, 0, 5, 84, 12}, - {12, 7, 13, 5, 84, 21}, - {10, 9, 0, 5, 84, 21}, - {21, 0, 0, 5, 84, 12}, - {21, 0, 0, 5, 84, 17}, - {13, 0, 0, 5, 84, 11}, - {6, 0, 0, 5, 22, 36}, - {7, 0, 0, 5, 76, 12}, - {12, 0, 13, 5, 76, 21}, - {10, 0, 0, 5, 76, 21}, - {13, 0, 0, 5, 76, 11}, - {21, 0, 0, 5, 76, 12}, - {21, 0, 0, 5, 76, 17}, - {7, 0, 0, 5, 78, 36}, - {12, 230, 13, 5, 78, 36}, - {12, 220, 13, 5, 78, 36}, - {6, 0, 0, 5, 78, 36}, - {21, 0, 0, 5, 78, 36}, - {7, 0, 0, 5, 85, 12}, - {10, 0, 0, 5, 85, 21}, - {12, 0, 13, 5, 85, 21}, - {21, 0, 0, 5, 85, 17}, - {6, 0, 0, 5, 85, 12}, - {12, 9, 13, 5, 85, 21}, - {13, 0, 0, 5, 85, 11}, - {7, 0, 0, 2, 24, 23}, - {7, 0, 0, 2, 24, 24}, - {4, 0, 0, 5, 102, 37}, - {3, 0, 0, 4, 102, 39}, - {12, 26, 13, 5, 5, 21}, - {25, 0, 9, 5, 5, 12}, - {24, 0, 4, 5, 6, 12}, - {12, 0, 13, 4, 40, 21}, - {21, 0, 18, 2, 0, 8}, - {21, 0, 18, 2, 0, 6}, - {21, 0, 18, 2, 0, 15}, - {16, 0, 18, 2, 0, 14}, - {21, 0, 12, 2, 0, 1}, - {21, 0, 12, 2, 0, 5}, - {21, 0, 10, 2, 0, 14}, - {25, 0, 9, 2, 0, 14}, - {17, 0, 9, 2, 0, 14}, - {25, 0, 18, 2, 0, 14}, - {23, 0, 10, 2, 0, 9}, - {21, 0, 10, 2, 0, 10}, - {21, 0, 18, 0, 0, 6}, - {21, 0, 18, 0, 0, 14}, - {21, 0, 10, 0, 0, 14}, - {23, 0, 10, 0, 0, 9}, - {21, 0, 10, 0, 0, 10}, - {22, 0, 18, 0, 0, 0}, - {18, 0, 18, 0, 0, 1}, - {25, 0, 9, 0, 0, 14}, - {21, 0, 12, 0, 0, 1}, - {17, 0, 9, 0, 0, 14}, - {21, 0, 12, 0, 0, 14}, - {13, 0, 8, 0, 0, 14}, - {21, 0, 12, 0, 0, 5}, - {21, 0, 18, 0, 0, 5}, - {25, 0, 18, 0, 0, 14}, - {9, 0, 0, 0, 1, 14}, - {24, 0, 18, 0, 0, 14}, - {16, 0, 18, 0, 0, 14}, - {5, 0, 0, 0, 1, 14}, - {21, 0, 18, 1, 0, 1}, - {22, 0, 18, 1, 0, 0}, - {18, 0, 18, 1, 0, 1}, - {21, 0, 18, 1, 0, 5}, - {7, 0, 0, 1, 33, 14}, - {7, 0, 0, 1, 33, 32}, - {6, 0, 0, 1, 0, 32}, - {6, 0, 0, 1, 0, 5}, - {7, 0, 0, 1, 24, 14}, - {23, 0, 10, 0, 0, 10}, - {26, 0, 18, 0, 0, 14}, - {26, 0, 18, 1, 0, 12}, - {25, 0, 18, 1, 0, 12}, - {1, 0, 18, 5, 0, 21}, - {26, 0, 18, 5, 0, 31}, - {7, 0, 0, 5, 47, 12}, - {14, 0, 18, 5, 2, 12}, - {15, 0, 18, 5, 2, 12}, - {26, 0, 18, 5, 2, 12}, - {26, 0, 0, 5, 2, 12}, - {7, 0, 0, 5, 73, 12}, - {7, 0, 0, 5, 74, 12}, - {7, 0, 0, 5, 37, 12}, - {15, 0, 0, 5, 37, 12}, - {7, 0, 0, 5, 38, 12}, - {14, 0, 0, 5, 38, 12}, - {7, 0, 0, 5, 118, 12}, - {12, 230, 13, 5, 118, 21}, - {7, 0, 0, 5, 48, 12}, - {21, 0, 0, 5, 48, 17}, - {7, 0, 0, 5, 59, 12}, - {21, 0, 0, 5, 59, 17}, - {14, 0, 0, 5, 59, 12}, - {9, 0, 0, 5, 39, 12}, - {5, 0, 0, 5, 39, 12}, - {7, 0, 0, 5, 49, 12}, - {7, 0, 0, 5, 50, 12}, - {13, 0, 0, 5, 50, 11}, - {9, 0, 0, 5, 136, 12}, - {5, 0, 0, 5, 136, 12}, - {7, 0, 0, 5, 106, 12}, - {7, 0, 0, 5, 104, 12}, - {21, 0, 0, 5, 104, 12}, - {7, 0, 0, 5, 110, 12}, - {7, 0, 3, 5, 51, 12}, - {7, 0, 3, 5, 86, 12}, - {21, 0, 3, 5, 86, 17}, - {15, 0, 3, 5, 86, 12}, - {7, 0, 3, 5, 120, 12}, - {26, 0, 3, 5, 120, 12}, - {15, 0, 3, 5, 120, 12}, - {7, 0, 3, 5, 116, 12}, - {15, 0, 3, 5, 116, 12}, - {7, 0, 3, 5, 128, 12}, - {15, 0, 3, 5, 128, 12}, - {7, 0, 3, 5, 63, 12}, - {15, 0, 3, 5, 63, 12}, - {21, 0, 18, 5, 63, 17}, - {7, 0, 3, 5, 75, 12}, - {21, 0, 3, 5, 75, 12}, - {7, 0, 3, 5, 97, 12}, - {7, 0, 3, 5, 96, 12}, - {15, 0, 3, 5, 96, 12}, - {7, 0, 3, 5, 60, 12}, - {12, 0, 13, 5, 60, 21}, - {12, 220, 13, 5, 60, 21}, - {12, 230, 13, 5, 60, 21}, - {12, 1, 13, 5, 60, 21}, - {12, 9, 13, 5, 60, 21}, - {15, 0, 3, 5, 60, 12}, - {21, 0, 3, 5, 60, 17}, - {21, 0, 3, 5, 60, 12}, - {7, 0, 3, 5, 87, 12}, - {15, 0, 3, 5, 87, 12}, - {21, 0, 3, 5, 87, 12}, - {7, 0, 3, 5, 117, 12}, - {15, 0, 3, 5, 117, 12}, - {7, 0, 3, 5, 112, 12}, - {26, 0, 3, 5, 112, 12}, - {12, 230, 13, 5, 112, 21}, - {12, 220, 13, 5, 112, 21}, - {15, 0, 3, 5, 112, 12}, - {21, 0, 3, 5, 112, 17}, - {21, 0, 3, 5, 112, 15}, - {7, 0, 3, 5, 79, 12}, - {21, 0, 18, 5, 79, 17}, - {7, 0, 3, 5, 88, 12}, - {15, 0, 3, 5, 88, 12}, - {7, 0, 3, 5, 89, 12}, - {15, 0, 3, 5, 89, 12}, - {7, 0, 3, 5, 122, 12}, - {21, 0, 3, 5, 122, 12}, - {15, 0, 3, 5, 122, 12}, - {7, 0, 3, 5, 90, 12}, - {9, 0, 3, 5, 130, 12}, - {5, 0, 3, 5, 130, 12}, - {15, 0, 3, 5, 130, 12}, - {7, 0, 4, 5, 144, 12}, - {12, 230, 13, 5, 144, 21}, - {13, 0, 11, 5, 144, 11}, - {15, 0, 11, 5, 6, 12}, - {7, 0, 3, 5, 147, 12}, - {15, 0, 3, 5, 147, 12}, - {7, 0, 4, 5, 148, 12}, - {12, 220, 13, 5, 148, 21}, - {12, 230, 13, 5, 148, 21}, - {15, 0, 4, 5, 148, 12}, - {21, 0, 4, 5, 148, 12}, - {7, 0, 3, 5, 149, 12}, - {10, 0, 0, 5, 93, 21}, - {12, 0, 13, 5, 93, 21}, - {7, 0, 0, 5, 93, 12}, - {12, 9, 13, 5, 93, 21}, - {21, 0, 0, 5, 93, 17}, - {21, 0, 0, 5, 93, 12}, - {15, 0, 18, 5, 93, 12}, - {13, 0, 0, 5, 93, 11}, - {12, 0, 13, 5, 91, 21}, - {10, 0, 0, 5, 91, 21}, - {7, 0, 0, 5, 91, 12}, - {12, 9, 13, 5, 91, 21}, - {12, 7, 13, 5, 91, 21}, - {21, 0, 0, 5, 91, 12}, - {1, 0, 0, 5, 91, 12}, - {21, 0, 0, 5, 91, 17}, - {7, 0, 0, 5, 100, 12}, - {13, 0, 0, 5, 100, 11}, - {12, 230, 13, 5, 95, 21}, - {7, 0, 0, 5, 95, 12}, - {12, 0, 13, 5, 95, 21}, - {10, 0, 0, 5, 95, 21}, - {12, 9, 13, 5, 95, 21}, - {13, 0, 0, 5, 95, 11}, - {21, 0, 0, 5, 95, 17}, - {7, 0, 0, 5, 111, 12}, - {12, 7, 13, 5, 111, 21}, - {21, 0, 0, 5, 111, 12}, - {21, 0, 0, 5, 111, 18}, - {12, 0, 13, 5, 99, 21}, - {10, 0, 0, 5, 99, 21}, - {7, 0, 0, 5, 99, 12}, - {10, 9, 0, 5, 99, 21}, - {21, 0, 0, 5, 99, 17}, - {21, 0, 0, 5, 99, 12}, - {12, 7, 13, 5, 99, 21}, - {13, 0, 0, 5, 99, 11}, - {21, 0, 0, 5, 99, 18}, - {15, 0, 0, 5, 18, 12}, - {7, 0, 0, 5, 108, 12}, - {10, 0, 0, 5, 108, 21}, - {12, 0, 13, 5, 108, 21}, - {10, 9, 0, 5, 108, 21}, - {12, 7, 13, 5, 108, 21}, - {21, 0, 0, 5, 108, 17}, - {21, 0, 0, 5, 108, 12}, - {7, 0, 0, 5, 129, 12}, - {21, 0, 0, 5, 129, 17}, - {7, 0, 0, 5, 109, 12}, - {12, 0, 13, 5, 109, 21}, - {10, 0, 0, 5, 109, 21}, - {12, 7, 13, 5, 109, 21}, - {12, 9, 13, 5, 109, 21}, - {13, 0, 0, 5, 109, 11}, - {12, 0, 13, 5, 107, 21}, - {10, 0, 0, 5, 107, 21}, - {7, 0, 0, 5, 107, 12}, - {12, 7, 13, 5, 40, 21}, - {12, 7, 13, 5, 107, 21}, - {10, 9, 0, 5, 107, 21}, - {12, 230, 13, 5, 107, 21}, - {7, 0, 0, 5, 135, 12}, - {10, 0, 0, 5, 135, 21}, - {12, 0, 13, 5, 135, 21}, - {12, 9, 13, 5, 135, 21}, - {12, 7, 13, 5, 135, 21}, - {21, 0, 0, 5, 135, 17}, - {21, 0, 0, 5, 135, 12}, - {13, 0, 0, 5, 135, 11}, - {12, 230, 13, 5, 135, 21}, - {7, 0, 0, 5, 124, 12}, - {10, 0, 0, 5, 124, 21}, - {12, 0, 13, 5, 124, 21}, - {12, 9, 13, 5, 124, 21}, - {12, 7, 13, 5, 124, 21}, - {21, 0, 0, 5, 124, 12}, - {13, 0, 0, 5, 124, 11}, - {7, 0, 0, 5, 123, 12}, - {10, 0, 0, 5, 123, 21}, - {12, 0, 13, 5, 123, 21}, - {12, 9, 13, 5, 123, 21}, - {12, 7, 13, 5, 123, 21}, - {21, 0, 0, 5, 123, 18}, - {21, 0, 0, 5, 123, 17}, - {21, 0, 0, 5, 123, 6}, - {21, 0, 0, 5, 123, 12}, - {7, 0, 0, 5, 114, 12}, - {10, 0, 0, 5, 114, 21}, - {12, 0, 13, 5, 114, 21}, - {12, 9, 13, 5, 114, 21}, - {21, 0, 0, 5, 114, 17}, - {21, 0, 0, 5, 114, 12}, - {13, 0, 0, 5, 114, 11}, - {21, 0, 18, 5, 31, 18}, - {7, 0, 0, 5, 101, 12}, - {12, 0, 13, 5, 101, 21}, - {10, 0, 0, 5, 101, 21}, - {10, 9, 0, 5, 101, 21}, - {12, 7, 13, 5, 101, 21}, - {13, 0, 0, 5, 101, 11}, - {7, 0, 0, 5, 126, 36}, - {12, 0, 13, 5, 126, 36}, - {10, 0, 0, 5, 126, 36}, - {12, 9, 13, 5, 126, 36}, - {13, 0, 0, 5, 126, 11}, - {15, 0, 0, 5, 126, 36}, - {21, 0, 0, 5, 126, 17}, - {26, 0, 0, 5, 126, 36}, - {7, 0, 0, 5, 142, 12}, - {10, 0, 0, 5, 142, 21}, - {12, 0, 13, 5, 142, 21}, - {12, 9, 13, 5, 142, 21}, - {12, 7, 13, 5, 142, 21}, - {21, 0, 0, 5, 142, 12}, - {9, 0, 0, 5, 125, 12}, - {5, 0, 0, 5, 125, 12}, - {13, 0, 0, 5, 125, 11}, - {15, 0, 0, 5, 125, 12}, - {7, 0, 0, 5, 125, 12}, - {7, 0, 0, 5, 150, 12}, - {10, 0, 0, 5, 150, 21}, - {12, 0, 13, 5, 150, 21}, - {12, 9, 13, 5, 150, 21}, - {21, 0, 0, 5, 150, 18}, - {7, 0, 0, 5, 141, 12}, - {12, 0, 13, 5, 141, 21}, - {12, 0, 0, 5, 141, 21}, - {12, 9, 13, 5, 141, 21}, - {10, 0, 0, 5, 141, 21}, - {21, 0, 0, 5, 141, 18}, - {21, 0, 0, 5, 141, 12}, - {21, 0, 0, 5, 141, 17}, - {7, 0, 0, 5, 140, 12}, - {12, 0, 13, 5, 140, 21}, - {10, 0, 0, 5, 140, 21}, - {12, 9, 13, 5, 140, 21}, - {21, 0, 0, 5, 140, 17}, - {21, 0, 0, 5, 140, 18}, - {7, 0, 0, 5, 121, 12}, - {7, 0, 0, 5, 133, 12}, - {10, 0, 0, 5, 133, 21}, - {12, 0, 13, 5, 133, 21}, - {12, 9, 0, 5, 133, 21}, - {21, 0, 0, 5, 133, 17}, - {13, 0, 0, 5, 133, 11}, - {15, 0, 0, 5, 133, 12}, - {21, 0, 0, 5, 134, 18}, - {21, 0, 0, 5, 134, 6}, - {7, 0, 0, 5, 134, 12}, - {12, 0, 13, 5, 134, 21}, - {10, 0, 0, 5, 134, 21}, - {7, 0, 0, 5, 138, 12}, - {12, 0, 13, 5, 138, 21}, - {12, 7, 13, 5, 138, 21}, - {12, 9, 13, 5, 138, 21}, - {13, 0, 0, 5, 138, 11}, - {7, 0, 0, 5, 143, 12}, - {10, 0, 0, 5, 143, 21}, - {12, 0, 13, 5, 143, 21}, - {12, 9, 13, 5, 143, 21}, - {13, 0, 0, 5, 143, 11}, - {7, 0, 0, 5, 145, 12}, - {12, 0, 13, 5, 145, 21}, - {10, 0, 0, 5, 145, 21}, - {21, 0, 0, 5, 145, 12}, - {23, 0, 10, 5, 14, 10}, - {21, 0, 0, 5, 14, 17}, - {7, 0, 0, 5, 62, 12}, - {14, 0, 0, 5, 62, 12}, - {21, 0, 0, 5, 62, 17}, - {7, 0, 0, 5, 80, 12}, - {7, 0, 0, 5, 80, 0}, - {7, 0, 0, 5, 80, 1}, - {1, 0, 0, 5, 80, 4}, - {1, 0, 0, 5, 80, 0}, - {1, 0, 0, 5, 80, 1}, - {7, 0, 0, 5, 127, 12}, - {7, 0, 0, 5, 127, 0}, - {7, 0, 0, 5, 127, 1}, - {7, 0, 0, 5, 115, 12}, - {13, 0, 0, 5, 115, 11}, - {21, 0, 0, 5, 115, 17}, - {7, 0, 0, 5, 103, 12}, - {12, 1, 13, 5, 103, 21}, - {21, 0, 0, 5, 103, 17}, - {7, 0, 0, 5, 119, 12}, - {12, 230, 13, 5, 119, 21}, - {21, 0, 0, 5, 119, 17}, - {21, 0, 0, 5, 119, 12}, - {26, 0, 0, 5, 119, 12}, - {6, 0, 0, 5, 119, 12}, - {13, 0, 0, 5, 119, 11}, - {15, 0, 0, 5, 119, 12}, - {9, 0, 0, 5, 146, 12}, - {5, 0, 0, 5, 146, 12}, - {15, 0, 0, 5, 146, 12}, - {21, 0, 0, 5, 146, 17}, - {21, 0, 0, 5, 146, 12}, - {7, 0, 0, 5, 98, 12}, - {12, 0, 13, 5, 98, 21}, - {10, 0, 0, 5, 98, 21}, - {6, 0, 0, 5, 98, 12}, - {6, 0, 0, 2, 137, 5}, - {6, 0, 0, 2, 139, 5}, - {6, 0, 0, 2, 0, 5}, - {7, 0, 0, 2, 137, 14}, - {7, 0, 0, 2, 139, 14}, - {7, 0, 0, 5, 105, 12}, - {26, 0, 0, 5, 105, 12}, - {12, 0, 13, 5, 105, 21}, - {12, 1, 13, 5, 105, 21}, - {21, 0, 0, 5, 105, 17}, - {10, 216, 0, 5, 0, 21}, - {10, 226, 0, 5, 0, 21}, - {12, 230, 13, 5, 2, 21}, - {25, 0, 0, 5, 0, 12}, - {13, 0, 8, 5, 0, 11}, - {26, 0, 0, 5, 131, 12}, - {12, 0, 13, 5, 131, 21}, - {21, 0, 0, 5, 131, 17}, - {21, 0, 0, 5, 131, 12}, - {12, 230, 13, 5, 56, 21}, - {7, 0, 0, 5, 151, 12}, - {12, 230, 13, 5, 151, 21}, - {6, 0, 0, 5, 151, 12}, - {13, 0, 0, 5, 151, 11}, - {26, 0, 0, 5, 151, 12}, - {7, 0, 0, 5, 152, 12}, - {12, 230, 13, 5, 152, 21}, - {13, 0, 0, 5, 152, 11}, - {23, 0, 10, 5, 152, 9}, - {7, 0, 3, 5, 113, 12}, - {15, 0, 3, 5, 113, 12}, - {12, 220, 13, 5, 113, 21}, - {9, 0, 3, 5, 132, 12}, - {5, 0, 3, 5, 132, 12}, - {12, 230, 13, 5, 132, 21}, - {12, 7, 13, 5, 132, 21}, - {6, 0, 3, 5, 132, 12}, - {13, 0, 3, 5, 132, 11}, - {21, 0, 3, 5, 132, 0}, - {15, 0, 4, 5, 0, 12}, - {26, 0, 4, 5, 0, 10}, - {23, 0, 4, 5, 0, 10}, - {26, 0, 4, 5, 0, 12}, - {2, 0, 18, 5, 102, 14}, - {26, 0, 0, 2, 0, 29}, - {26, 0, 0, 5, 0, 28}, - {26, 0, 0, 2, 32, 14}, - {24, 0, 18, 2, 0, 42}, - {26, 0, 18, 5, 0, 5}, -}; - -#define BIDI_MIRROR_LEN 420 -static const MirrorPair mirror_pairs[] = { - {40, 41}, - {41, 40}, - {60, 62}, - {62, 60}, - {91, 93}, - {93, 91}, - {123, 125}, - {125, 123}, - {171, 187}, - {187, 171}, - {3898, 3899}, - {3899, 3898}, - {3900, 3901}, - {3901, 3900}, - {5787, 5788}, - {5788, 5787}, - {8249, 8250}, - {8250, 8249}, - {8261, 8262}, - {8262, 8261}, - {8317, 8318}, - {8318, 8317}, - {8333, 8334}, - {8334, 8333}, - {8712, 8715}, - {8713, 8716}, - {8714, 8717}, - {8715, 8712}, - {8716, 8713}, - {8717, 8714}, - {8725, 10741}, - {8735, 11262}, - {8736, 10659}, - {8737, 10651}, - {8738, 10656}, - {8740, 10990}, - {8764, 8765}, - {8765, 8764}, - {8771, 8909}, - {8773, 8780}, - {8780, 8773}, - {8786, 8787}, - {8787, 8786}, - {8788, 8789}, - {8789, 8788}, - {8804, 8805}, - {8805, 8804}, - {8806, 8807}, - {8807, 8806}, - {8808, 8809}, - {8809, 8808}, - {8810, 8811}, - {8811, 8810}, - {8814, 8815}, - {8815, 8814}, - {8816, 8817}, - {8817, 8816}, - {8818, 8819}, - {8819, 8818}, - {8820, 8821}, - {8821, 8820}, - {8822, 8823}, - {8823, 8822}, - {8824, 8825}, - {8825, 8824}, - {8826, 8827}, - {8827, 8826}, - {8828, 8829}, - {8829, 8828}, - {8830, 8831}, - {8831, 8830}, - {8832, 8833}, - {8833, 8832}, - {8834, 8835}, - {8835, 8834}, - {8836, 8837}, - {8837, 8836}, - {8838, 8839}, - {8839, 8838}, - {8840, 8841}, - {8841, 8840}, - {8842, 8843}, - {8843, 8842}, - {8847, 8848}, - {8848, 8847}, - {8849, 8850}, - {8850, 8849}, - {8856, 10680}, - {8866, 8867}, - {8867, 8866}, - {8870, 10974}, - {8872, 10980}, - {8873, 10979}, - {8875, 10981}, - {8880, 8881}, - {8881, 8880}, - {8882, 8883}, - {8883, 8882}, - {8884, 8885}, - {8885, 8884}, - {8886, 8887}, - {8887, 8886}, - {8888, 10204}, - {8905, 8906}, - {8906, 8905}, - {8907, 8908}, - {8908, 8907}, - {8909, 8771}, - {8912, 8913}, - {8913, 8912}, - {8918, 8919}, - {8919, 8918}, - {8920, 8921}, - {8921, 8920}, - {8922, 8923}, - {8923, 8922}, - {8924, 8925}, - {8925, 8924}, - {8926, 8927}, - {8927, 8926}, - {8928, 8929}, - {8929, 8928}, - {8930, 8931}, - {8931, 8930}, - {8932, 8933}, - {8933, 8932}, - {8934, 8935}, - {8935, 8934}, - {8936, 8937}, - {8937, 8936}, - {8938, 8939}, - {8939, 8938}, - {8940, 8941}, - {8941, 8940}, - {8944, 8945}, - {8945, 8944}, - {8946, 8954}, - {8947, 8955}, - {8948, 8956}, - {8950, 8957}, - {8951, 8958}, - {8954, 8946}, - {8955, 8947}, - {8956, 8948}, - {8957, 8950}, - {8958, 8951}, - {8968, 8969}, - {8969, 8968}, - {8970, 8971}, - {8971, 8970}, - {9001, 9002}, - {9002, 9001}, - {10088, 10089}, - {10089, 10088}, - {10090, 10091}, - {10091, 10090}, - {10092, 10093}, - {10093, 10092}, - {10094, 10095}, - {10095, 10094}, - {10096, 10097}, - {10097, 10096}, - {10098, 10099}, - {10099, 10098}, - {10100, 10101}, - {10101, 10100}, - {10179, 10180}, - {10180, 10179}, - {10181, 10182}, - {10182, 10181}, - {10184, 10185}, - {10185, 10184}, - {10187, 10189}, - {10189, 10187}, - {10197, 10198}, - {10198, 10197}, - {10204, 8888}, - {10205, 10206}, - {10206, 10205}, - {10210, 10211}, - {10211, 10210}, - {10212, 10213}, - {10213, 10212}, - {10214, 10215}, - {10215, 10214}, - {10216, 10217}, - {10217, 10216}, - {10218, 10219}, - {10219, 10218}, - {10220, 10221}, - {10221, 10220}, - {10222, 10223}, - {10223, 10222}, - {10627, 10628}, - {10628, 10627}, - {10629, 10630}, - {10630, 10629}, - {10631, 10632}, - {10632, 10631}, - {10633, 10634}, - {10634, 10633}, - {10635, 10636}, - {10636, 10635}, - {10637, 10640}, - {10638, 10639}, - {10639, 10638}, - {10640, 10637}, - {10641, 10642}, - {10642, 10641}, - {10643, 10644}, - {10644, 10643}, - {10645, 10646}, - {10646, 10645}, - {10647, 10648}, - {10648, 10647}, - {10651, 8737}, - {10656, 8738}, - {10659, 8736}, - {10660, 10661}, - {10661, 10660}, - {10664, 10665}, - {10665, 10664}, - {10666, 10667}, - {10667, 10666}, - {10668, 10669}, - {10669, 10668}, - {10670, 10671}, - {10671, 10670}, - {10680, 8856}, - {10688, 10689}, - {10689, 10688}, - {10692, 10693}, - {10693, 10692}, - {10703, 10704}, - {10704, 10703}, - {10705, 10706}, - {10706, 10705}, - {10708, 10709}, - {10709, 10708}, - {10712, 10713}, - {10713, 10712}, - {10714, 10715}, - {10715, 10714}, - {10728, 10729}, - {10729, 10728}, - {10741, 8725}, - {10744, 10745}, - {10745, 10744}, - {10748, 10749}, - {10749, 10748}, - {10795, 10796}, - {10796, 10795}, - {10797, 10798}, - {10798, 10797}, - {10804, 10805}, - {10805, 10804}, - {10812, 10813}, - {10813, 10812}, - {10852, 10853}, - {10853, 10852}, - {10873, 10874}, - {10874, 10873}, - {10875, 10876}, - {10876, 10875}, - {10877, 10878}, - {10878, 10877}, - {10879, 10880}, - {10880, 10879}, - {10881, 10882}, - {10882, 10881}, - {10883, 10884}, - {10884, 10883}, - {10885, 10886}, - {10886, 10885}, - {10887, 10888}, - {10888, 10887}, - {10889, 10890}, - {10890, 10889}, - {10891, 10892}, - {10892, 10891}, - {10893, 10894}, - {10894, 10893}, - {10895, 10896}, - {10896, 10895}, - {10897, 10898}, - {10898, 10897}, - {10899, 10900}, - {10900, 10899}, - {10901, 10902}, - {10902, 10901}, - {10903, 10904}, - {10904, 10903}, - {10905, 10906}, - {10906, 10905}, - {10907, 10908}, - {10908, 10907}, - {10909, 10910}, - {10910, 10909}, - {10911, 10912}, - {10912, 10911}, - {10913, 10914}, - {10914, 10913}, - {10918, 10919}, - {10919, 10918}, - {10920, 10921}, - {10921, 10920}, - {10922, 10923}, - {10923, 10922}, - {10924, 10925}, - {10925, 10924}, - {10927, 10928}, - {10928, 10927}, - {10929, 10930}, - {10930, 10929}, - {10931, 10932}, - {10932, 10931}, - {10933, 10934}, - {10934, 10933}, - {10935, 10936}, - {10936, 10935}, - {10937, 10938}, - {10938, 10937}, - {10939, 10940}, - {10940, 10939}, - {10941, 10942}, - {10942, 10941}, - {10943, 10944}, - {10944, 10943}, - {10945, 10946}, - {10946, 10945}, - {10947, 10948}, - {10948, 10947}, - {10949, 10950}, - {10950, 10949}, - {10951, 10952}, - {10952, 10951}, - {10953, 10954}, - {10954, 10953}, - {10955, 10956}, - {10956, 10955}, - {10957, 10958}, - {10958, 10957}, - {10959, 10960}, - {10960, 10959}, - {10961, 10962}, - {10962, 10961}, - {10963, 10964}, - {10964, 10963}, - {10965, 10966}, - {10966, 10965}, - {10974, 8870}, - {10979, 8873}, - {10980, 8872}, - {10981, 8875}, - {10988, 10989}, - {10989, 10988}, - {10990, 8740}, - {10999, 11000}, - {11000, 10999}, - {11001, 11002}, - {11002, 11001}, - {11262, 8735}, - {11778, 11779}, - {11779, 11778}, - {11780, 11781}, - {11781, 11780}, - {11785, 11786}, - {11786, 11785}, - {11788, 11789}, - {11789, 11788}, - {11804, 11805}, - {11805, 11804}, - {11808, 11809}, - {11809, 11808}, - {11810, 11811}, - {11811, 11810}, - {11812, 11813}, - {11813, 11812}, - {11814, 11815}, - {11815, 11814}, - {11816, 11817}, - {11817, 11816}, - {12296, 12297}, - {12297, 12296}, - {12298, 12299}, - {12299, 12298}, - {12300, 12301}, - {12301, 12300}, - {12302, 12303}, - {12303, 12302}, - {12304, 12305}, - {12305, 12304}, - {12308, 12309}, - {12309, 12308}, - {12310, 12311}, - {12311, 12310}, - {12312, 12313}, - {12313, 12312}, - {12314, 12315}, - {12315, 12314}, - {65113, 65114}, - {65114, 65113}, - {65115, 65116}, - {65116, 65115}, - {65117, 65118}, - {65118, 65117}, - {65124, 65125}, - {65125, 65124}, - {65288, 65289}, - {65289, 65288}, - {65308, 65310}, - {65310, 65308}, - {65339, 65341}, - {65341, 65339}, - {65371, 65373}, - {65373, 65371}, - {65375, 65376}, - {65376, 65375}, - {65378, 65379}, - {65379, 65378}, -}; - -#define BIDI_BRACKET_LEN 120 -static const BracketPair bracket_pairs[] = { - {40, 41, 0}, - {41, 40, 1}, - {91, 93, 0}, - {93, 91, 1}, - {123, 125, 0}, - {125, 123, 1}, - {3898, 3899, 0}, - {3899, 3898, 1}, - {3900, 3901, 0}, - {3901, 3900, 1}, - {5787, 5788, 0}, - {5788, 5787, 1}, - {8261, 8262, 0}, - {8262, 8261, 1}, - {8317, 8318, 0}, - {8318, 8317, 1}, - {8333, 8334, 0}, - {8334, 8333, 1}, - {8968, 8969, 0}, - {8969, 8968, 1}, - {8970, 8971, 0}, - {8971, 8970, 1}, - {9001, 9002, 0}, - {9002, 9001, 1}, - {10088, 10089, 0}, - {10089, 10088, 1}, - {10090, 10091, 0}, - {10091, 10090, 1}, - {10092, 10093, 0}, - {10093, 10092, 1}, - {10094, 10095, 0}, - {10095, 10094, 1}, - {10096, 10097, 0}, - {10097, 10096, 1}, - {10098, 10099, 0}, - {10099, 10098, 1}, - {10100, 10101, 0}, - {10101, 10100, 1}, - {10181, 10182, 0}, - {10182, 10181, 1}, - {10214, 10215, 0}, - {10215, 10214, 1}, - {10216, 10217, 0}, - {10217, 10216, 1}, - {10218, 10219, 0}, - {10219, 10218, 1}, - {10220, 10221, 0}, - {10221, 10220, 1}, - {10222, 10223, 0}, - {10223, 10222, 1}, - {10627, 10628, 0}, - {10628, 10627, 1}, - {10629, 10630, 0}, - {10630, 10629, 1}, - {10631, 10632, 0}, - {10632, 10631, 1}, - {10633, 10634, 0}, - {10634, 10633, 1}, - {10635, 10636, 0}, - {10636, 10635, 1}, - {10637, 10640, 0}, - {10638, 10639, 1}, - {10639, 10638, 0}, - {10640, 10637, 1}, - {10641, 10642, 0}, - {10642, 10641, 1}, - {10643, 10644, 0}, - {10644, 10643, 1}, - {10645, 10646, 0}, - {10646, 10645, 1}, - {10647, 10648, 0}, - {10648, 10647, 1}, - {10712, 10713, 0}, - {10713, 10712, 1}, - {10714, 10715, 0}, - {10715, 10714, 1}, - {10748, 10749, 0}, - {10749, 10748, 1}, - {11810, 11811, 0}, - {11811, 11810, 1}, - {11812, 11813, 0}, - {11813, 11812, 1}, - {11814, 11815, 0}, - {11815, 11814, 1}, - {11816, 11817, 0}, - {11817, 11816, 1}, - {12296, 12297, 0}, - {12297, 12296, 1}, - {12298, 12299, 0}, - {12299, 12298, 1}, - {12300, 12301, 0}, - {12301, 12300, 1}, - {12302, 12303, 0}, - {12303, 12302, 1}, - {12304, 12305, 0}, - {12305, 12304, 1}, - {12308, 12309, 0}, - {12309, 12308, 1}, - {12310, 12311, 0}, - {12311, 12310, 1}, - {12312, 12313, 0}, - {12313, 12312, 1}, - {12314, 12315, 0}, - {12315, 12314, 1}, - {65113, 65114, 0}, - {65114, 65113, 1}, - {65115, 65116, 0}, - {65116, 65115, 1}, - {65117, 65118, 0}, - {65118, 65117, 1}, - {65288, 65289, 0}, - {65289, 65288, 1}, - {65339, 65341, 0}, - {65341, 65339, 1}, - {65371, 65373, 0}, - {65373, 65371, 1}, - {65375, 65376, 0}, - {65376, 65375, 1}, - {65378, 65379, 0}, - {65379, 65378, 1}, -}; - -/* Reindexing of NFC first characters. */ -#define TOTAL_FIRST 376 -#define TOTAL_LAST 62 -static const Reindex nfc_first[] = { - { 60, 2, 0}, - { 65, 15, 3}, - { 82, 8, 19}, - { 97, 15, 28}, - { 114, 8, 44}, - { 168, 0, 53}, - { 194, 0, 54}, - { 196, 3, 55}, - { 202, 0, 59}, - { 207, 0, 60}, - { 212, 2, 61}, - { 216, 0, 64}, - { 220, 0, 65}, - { 226, 0, 66}, - { 228, 3, 67}, - { 234, 0, 71}, - { 239, 0, 72}, - { 244, 2, 73}, - { 248, 0, 76}, - { 252, 0, 77}, - { 258, 1, 78}, - { 274, 1, 80}, - { 332, 1, 82}, - { 346, 1, 84}, - { 352, 1, 86}, - { 360, 3, 88}, - { 383, 0, 92}, - { 416, 1, 93}, - { 431, 1, 95}, - { 439, 0, 97}, - { 490, 1, 98}, - { 550, 3, 100}, - { 558, 1, 104}, - { 658, 0, 106}, - { 913, 0, 107}, - { 917, 0, 108}, - { 919, 0, 109}, - { 921, 0, 110}, - { 927, 0, 111}, - { 929, 0, 112}, - { 933, 0, 113}, - { 937, 0, 114}, - { 940, 0, 115}, - { 942, 0, 116}, - { 945, 0, 117}, - { 949, 0, 118}, - { 951, 0, 119}, - { 953, 0, 120}, - { 959, 0, 121}, - { 961, 0, 122}, - { 965, 0, 123}, - { 969, 2, 124}, - { 974, 0, 127}, - { 978, 0, 128}, - { 1030, 0, 129}, - { 1040, 0, 130}, - { 1043, 0, 131}, - { 1045, 3, 132}, - { 1050, 0, 136}, - { 1054, 0, 137}, - { 1059, 0, 138}, - { 1063, 0, 139}, - { 1067, 0, 140}, - { 1069, 0, 141}, - { 1072, 0, 142}, - { 1075, 0, 143}, - { 1077, 3, 144}, - { 1082, 0, 148}, - { 1086, 0, 149}, - { 1091, 0, 150}, - { 1095, 0, 151}, - { 1099, 0, 152}, - { 1101, 0, 153}, - { 1110, 0, 154}, - { 1140, 1, 155}, - { 1240, 1, 157}, - { 1256, 1, 159}, - { 1575, 0, 161}, - { 1608, 0, 162}, - { 1610, 0, 163}, - { 1729, 0, 164}, - { 1746, 0, 165}, - { 1749, 0, 166}, - { 2344, 0, 167}, - { 2352, 0, 168}, - { 2355, 0, 169}, - { 2503, 0, 170}, - { 2887, 0, 171}, - { 2962, 0, 172}, - { 3014, 1, 173}, - { 3142, 0, 175}, - { 3263, 0, 176}, - { 3270, 0, 177}, - { 3274, 0, 178}, - { 3398, 1, 179}, - { 3545, 0, 181}, - { 3548, 0, 182}, - { 4133, 0, 183}, - { 6917, 0, 184}, - { 6919, 0, 185}, - { 6921, 0, 186}, - { 6923, 0, 187}, - { 6925, 0, 188}, - { 6929, 0, 189}, - { 6970, 0, 190}, - { 6972, 0, 191}, - { 6974, 1, 192}, - { 6978, 0, 194}, - { 7734, 1, 195}, - { 7770, 1, 197}, - { 7778, 1, 199}, - { 7840, 1, 201}, - { 7864, 1, 203}, - { 7884, 1, 205}, - { 7936, 17, 207}, - { 7960, 1, 225}, - { 7968, 17, 227}, - { 7992, 1, 245}, - { 8000, 1, 247}, - { 8008, 1, 249}, - { 8016, 1, 251}, - { 8025, 0, 253}, - { 8032, 16, 254}, - { 8052, 0, 271}, - { 8060, 0, 272}, - { 8118, 0, 273}, - { 8127, 0, 274}, - { 8134, 0, 275}, - { 8182, 0, 276}, - { 8190, 0, 277}, - { 8592, 0, 278}, - { 8594, 0, 279}, - { 8596, 0, 280}, - { 8656, 0, 281}, - { 8658, 0, 282}, - { 8660, 0, 283}, - { 8707, 0, 284}, - { 8712, 0, 285}, - { 8715, 0, 286}, - { 8739, 0, 287}, - { 8741, 0, 288}, - { 8764, 0, 289}, - { 8771, 0, 290}, - { 8773, 0, 291}, - { 8776, 0, 292}, - { 8781, 0, 293}, - { 8801, 0, 294}, - { 8804, 1, 295}, - { 8818, 1, 297}, - { 8822, 1, 299}, - { 8826, 3, 301}, - { 8834, 1, 305}, - { 8838, 1, 307}, - { 8849, 1, 309}, - { 8866, 0, 311}, - { 8872, 1, 312}, - { 8875, 0, 314}, - { 8882, 3, 315}, - { 12358, 0, 319}, - { 12363, 0, 320}, - { 12365, 0, 321}, - { 12367, 0, 322}, - { 12369, 0, 323}, - { 12371, 0, 324}, - { 12373, 0, 325}, - { 12375, 0, 326}, - { 12377, 0, 327}, - { 12379, 0, 328}, - { 12381, 0, 329}, - { 12383, 0, 330}, - { 12385, 0, 331}, - { 12388, 0, 332}, - { 12390, 0, 333}, - { 12392, 0, 334}, - { 12399, 0, 335}, - { 12402, 0, 336}, - { 12405, 0, 337}, - { 12408, 0, 338}, - { 12411, 0, 339}, - { 12445, 0, 340}, - { 12454, 0, 341}, - { 12459, 0, 342}, - { 12461, 0, 343}, - { 12463, 0, 344}, - { 12465, 0, 345}, - { 12467, 0, 346}, - { 12469, 0, 347}, - { 12471, 0, 348}, - { 12473, 0, 349}, - { 12475, 0, 350}, - { 12477, 0, 351}, - { 12479, 0, 352}, - { 12481, 0, 353}, - { 12484, 0, 354}, - { 12486, 0, 355}, - { 12488, 0, 356}, - { 12495, 0, 357}, - { 12498, 0, 358}, - { 12501, 0, 359}, - { 12504, 0, 360}, - { 12507, 0, 361}, - { 12527, 3, 362}, - { 12541, 0, 366}, - { 69785, 0, 367}, - { 69787, 0, 368}, - { 69797, 0, 369}, - { 69937, 1, 370}, - { 70471, 0, 372}, - { 70841, 0, 373}, - { 71096, 1, 374}, - {0,0,0} -}; - -static const Reindex nfc_last[] = { - { 768, 4, 0}, - { 774, 6, 5}, - { 783, 0, 12}, - { 785, 0, 13}, - { 787, 1, 14}, - { 795, 0, 16}, - { 803, 5, 17}, - { 813, 1, 23}, - { 816, 1, 25}, - { 824, 0, 27}, - { 834, 0, 28}, - { 837, 0, 29}, - { 1619, 2, 30}, - { 2364, 0, 33}, - { 2494, 0, 34}, - { 2519, 0, 35}, - { 2878, 0, 36}, - { 2902, 1, 37}, - { 3006, 0, 39}, - { 3031, 0, 40}, - { 3158, 0, 41}, - { 3266, 0, 42}, - { 3285, 1, 43}, - { 3390, 0, 45}, - { 3415, 0, 46}, - { 3530, 0, 47}, - { 3535, 0, 48}, - { 3551, 0, 49}, - { 4142, 0, 50}, - { 6965, 0, 51}, - { 12441, 1, 52}, - { 69818, 0, 54}, - { 69927, 0, 55}, - { 70462, 0, 56}, - { 70487, 0, 57}, - { 70832, 0, 58}, - { 70842, 0, 59}, - { 70845, 0, 60}, - { 71087, 0, 61}, - {0,0,0} -}; - -#define UCDN_EAST_ASIAN_F 0 -#define UCDN_EAST_ASIAN_H 1 -#define UCDN_EAST_ASIAN_W 2 -#define UCDN_EAST_ASIAN_NA 3 -#define UCDN_EAST_ASIAN_A 4 -#define UCDN_EAST_ASIAN_N 5 - -#define UCDN_SCRIPT_COMMON 0 -#define UCDN_SCRIPT_LATIN 1 -#define UCDN_SCRIPT_GREEK 2 -#define UCDN_SCRIPT_CYRILLIC 3 -#define UCDN_SCRIPT_ARMENIAN 4 -#define UCDN_SCRIPT_HEBREW 5 -#define UCDN_SCRIPT_ARABIC 6 -#define UCDN_SCRIPT_SYRIAC 7 -#define UCDN_SCRIPT_THAANA 8 -#define UCDN_SCRIPT_DEVANAGARI 9 -#define UCDN_SCRIPT_BENGALI 10 -#define UCDN_SCRIPT_GURMUKHI 11 -#define UCDN_SCRIPT_GUJARATI 12 -#define UCDN_SCRIPT_ORIYA 13 -#define UCDN_SCRIPT_TAMIL 14 -#define UCDN_SCRIPT_TELUGU 15 -#define UCDN_SCRIPT_KANNADA 16 -#define UCDN_SCRIPT_MALAYALAM 17 -#define UCDN_SCRIPT_SINHALA 18 -#define UCDN_SCRIPT_THAI 19 -#define UCDN_SCRIPT_LAO 20 -#define UCDN_SCRIPT_TIBETAN 21 -#define UCDN_SCRIPT_MYANMAR 22 -#define UCDN_SCRIPT_GEORGIAN 23 -#define UCDN_SCRIPT_HANGUL 24 -#define UCDN_SCRIPT_ETHIOPIC 25 -#define UCDN_SCRIPT_CHEROKEE 26 -#define UCDN_SCRIPT_CANADIAN_ABORIGINAL 27 -#define UCDN_SCRIPT_OGHAM 28 -#define UCDN_SCRIPT_RUNIC 29 -#define UCDN_SCRIPT_KHMER 30 -#define UCDN_SCRIPT_MONGOLIAN 31 -#define UCDN_SCRIPT_HIRAGANA 32 -#define UCDN_SCRIPT_KATAKANA 33 -#define UCDN_SCRIPT_BOPOMOFO 34 -#define UCDN_SCRIPT_HAN 35 -#define UCDN_SCRIPT_YI 36 -#define UCDN_SCRIPT_OLD_ITALIC 37 -#define UCDN_SCRIPT_GOTHIC 38 -#define UCDN_SCRIPT_DESERET 39 -#define UCDN_SCRIPT_INHERITED 40 -#define UCDN_SCRIPT_TAGALOG 41 -#define UCDN_SCRIPT_HANUNOO 42 -#define UCDN_SCRIPT_BUHID 43 -#define UCDN_SCRIPT_TAGBANWA 44 -#define UCDN_SCRIPT_LIMBU 45 -#define UCDN_SCRIPT_TAI_LE 46 -#define UCDN_SCRIPT_LINEAR_B 47 -#define UCDN_SCRIPT_UGARITIC 48 -#define UCDN_SCRIPT_SHAVIAN 49 -#define UCDN_SCRIPT_OSMANYA 50 -#define UCDN_SCRIPT_CYPRIOT 51 -#define UCDN_SCRIPT_BRAILLE 52 -#define UCDN_SCRIPT_BUGINESE 53 -#define UCDN_SCRIPT_COPTIC 54 -#define UCDN_SCRIPT_NEW_TAI_LUE 55 -#define UCDN_SCRIPT_GLAGOLITIC 56 -#define UCDN_SCRIPT_TIFINAGH 57 -#define UCDN_SCRIPT_SYLOTI_NAGRI 58 -#define UCDN_SCRIPT_OLD_PERSIAN 59 -#define UCDN_SCRIPT_KHAROSHTHI 60 -#define UCDN_SCRIPT_BALINESE 61 -#define UCDN_SCRIPT_CUNEIFORM 62 -#define UCDN_SCRIPT_PHOENICIAN 63 -#define UCDN_SCRIPT_PHAGS_PA 64 -#define UCDN_SCRIPT_NKO 65 -#define UCDN_SCRIPT_SUNDANESE 66 -#define UCDN_SCRIPT_LEPCHA 67 -#define UCDN_SCRIPT_OL_CHIKI 68 -#define UCDN_SCRIPT_VAI 69 -#define UCDN_SCRIPT_SAURASHTRA 70 -#define UCDN_SCRIPT_KAYAH_LI 71 -#define UCDN_SCRIPT_REJANG 72 -#define UCDN_SCRIPT_LYCIAN 73 -#define UCDN_SCRIPT_CARIAN 74 -#define UCDN_SCRIPT_LYDIAN 75 -#define UCDN_SCRIPT_CHAM 76 -#define UCDN_SCRIPT_TAI_THAM 77 -#define UCDN_SCRIPT_TAI_VIET 78 -#define UCDN_SCRIPT_AVESTAN 79 -#define UCDN_SCRIPT_EGYPTIAN_HIEROGLYPHS 80 -#define UCDN_SCRIPT_SAMARITAN 81 -#define UCDN_SCRIPT_LISU 82 -#define UCDN_SCRIPT_BAMUM 83 -#define UCDN_SCRIPT_JAVANESE 84 -#define UCDN_SCRIPT_MEETEI_MAYEK 85 -#define UCDN_SCRIPT_IMPERIAL_ARAMAIC 86 -#define UCDN_SCRIPT_OLD_SOUTH_ARABIAN 87 -#define UCDN_SCRIPT_INSCRIPTIONAL_PARTHIAN 88 -#define UCDN_SCRIPT_INSCRIPTIONAL_PAHLAVI 89 -#define UCDN_SCRIPT_OLD_TURKIC 90 -#define UCDN_SCRIPT_KAITHI 91 -#define UCDN_SCRIPT_BATAK 92 -#define UCDN_SCRIPT_BRAHMI 93 -#define UCDN_SCRIPT_MANDAIC 94 -#define UCDN_SCRIPT_CHAKMA 95 -#define UCDN_SCRIPT_MEROITIC_CURSIVE 96 -#define UCDN_SCRIPT_MEROITIC_HIEROGLYPHS 97 -#define UCDN_SCRIPT_MIAO 98 -#define UCDN_SCRIPT_SHARADA 99 -#define UCDN_SCRIPT_SORA_SOMPENG 100 -#define UCDN_SCRIPT_TAKRI 101 -#define UCDN_SCRIPT_UNKNOWN 102 -#define UCDN_SCRIPT_BASSA_VAH 103 -#define UCDN_SCRIPT_CAUCASIAN_ALBANIAN 104 -#define UCDN_SCRIPT_DUPLOYAN 105 -#define UCDN_SCRIPT_ELBASAN 106 -#define UCDN_SCRIPT_GRANTHA 107 -#define UCDN_SCRIPT_KHOJKI 108 -#define UCDN_SCRIPT_KHUDAWADI 109 -#define UCDN_SCRIPT_LINEAR_A 110 -#define UCDN_SCRIPT_MAHAJANI 111 -#define UCDN_SCRIPT_MANICHAEAN 112 -#define UCDN_SCRIPT_MENDE_KIKAKUI 113 -#define UCDN_SCRIPT_MODI 114 -#define UCDN_SCRIPT_MRO 115 -#define UCDN_SCRIPT_NABATAEAN 116 -#define UCDN_SCRIPT_OLD_NORTH_ARABIAN 117 -#define UCDN_SCRIPT_OLD_PERMIC 118 -#define UCDN_SCRIPT_PAHAWH_HMONG 119 -#define UCDN_SCRIPT_PALMYRENE 120 -#define UCDN_SCRIPT_PAU_CIN_HAU 121 -#define UCDN_SCRIPT_PSALTER_PAHLAVI 122 -#define UCDN_SCRIPT_SIDDHAM 123 -#define UCDN_SCRIPT_TIRHUTA 124 -#define UCDN_SCRIPT_WARANG_CITI 125 -#define UCDN_SCRIPT_AHOM 126 -#define UCDN_SCRIPT_ANATOLIAN_HIEROGLYPHS 127 -#define UCDN_SCRIPT_HATRAN 128 -#define UCDN_SCRIPT_MULTANI 129 -#define UCDN_SCRIPT_OLD_HUNGARIAN 130 -#define UCDN_SCRIPT_SIGNWRITING 131 -#define UCDN_SCRIPT_ADLAM 132 -#define UCDN_SCRIPT_BHAIKSUKI 133 -#define UCDN_SCRIPT_MARCHEN 134 -#define UCDN_SCRIPT_NEWA 135 -#define UCDN_SCRIPT_OSAGE 136 -#define UCDN_SCRIPT_TANGUT 137 -#define UCDN_SCRIPT_MASARAM_GONDI 138 -#define UCDN_SCRIPT_NUSHU 139 -#define UCDN_SCRIPT_SOYOMBO 140 -#define UCDN_SCRIPT_ZANABAZAR_SQUARE 141 -#define UCDN_SCRIPT_DOGRA 142 -#define UCDN_SCRIPT_GUNJALA_GONDI 143 -#define UCDN_SCRIPT_HANIFI_ROHINGYA 144 -#define UCDN_SCRIPT_MAKASAR 145 -#define UCDN_SCRIPT_MEDEFAIDRIN 146 -#define UCDN_SCRIPT_OLD_SOGDIAN 147 -#define UCDN_SCRIPT_SOGDIAN 148 -#define UCDN_SCRIPT_ELYMAIC 149 -#define UCDN_SCRIPT_NANDINAGARI 150 -#define UCDN_SCRIPT_NYIAKENG_PUACHUE_HMONG 151 -#define UCDN_SCRIPT_WANCHO 152 - -#define UCDN_GENERAL_CATEGORY_CC 0 -#define UCDN_GENERAL_CATEGORY_CF 1 -#define UCDN_GENERAL_CATEGORY_CN 2 -#define UCDN_GENERAL_CATEGORY_CO 3 -#define UCDN_GENERAL_CATEGORY_CS 4 -#define UCDN_GENERAL_CATEGORY_LL 5 -#define UCDN_GENERAL_CATEGORY_LM 6 -#define UCDN_GENERAL_CATEGORY_LO 7 -#define UCDN_GENERAL_CATEGORY_LT 8 -#define UCDN_GENERAL_CATEGORY_LU 9 -#define UCDN_GENERAL_CATEGORY_MC 10 -#define UCDN_GENERAL_CATEGORY_ME 11 -#define UCDN_GENERAL_CATEGORY_MN 12 -#define UCDN_GENERAL_CATEGORY_ND 13 -#define UCDN_GENERAL_CATEGORY_NL 14 -#define UCDN_GENERAL_CATEGORY_NO 15 -#define UCDN_GENERAL_CATEGORY_PC 16 -#define UCDN_GENERAL_CATEGORY_PD 17 -#define UCDN_GENERAL_CATEGORY_PE 18 -#define UCDN_GENERAL_CATEGORY_PF 19 -#define UCDN_GENERAL_CATEGORY_PI 20 -#define UCDN_GENERAL_CATEGORY_PO 21 -#define UCDN_GENERAL_CATEGORY_PS 22 -#define UCDN_GENERAL_CATEGORY_SC 23 -#define UCDN_GENERAL_CATEGORY_SK 24 -#define UCDN_GENERAL_CATEGORY_SM 25 -#define UCDN_GENERAL_CATEGORY_SO 26 -#define UCDN_GENERAL_CATEGORY_ZL 27 -#define UCDN_GENERAL_CATEGORY_ZP 28 -#define UCDN_GENERAL_CATEGORY_ZS 29 - -#define UCDN_BIDI_CLASS_L 0 -#define UCDN_BIDI_CLASS_LRE 1 -#define UCDN_BIDI_CLASS_LRO 2 -#define UCDN_BIDI_CLASS_R 3 -#define UCDN_BIDI_CLASS_AL 4 -#define UCDN_BIDI_CLASS_RLE 5 -#define UCDN_BIDI_CLASS_RLO 6 -#define UCDN_BIDI_CLASS_PDF 7 -#define UCDN_BIDI_CLASS_EN 8 -#define UCDN_BIDI_CLASS_ES 9 -#define UCDN_BIDI_CLASS_ET 10 -#define UCDN_BIDI_CLASS_AN 11 -#define UCDN_BIDI_CLASS_CS 12 -#define UCDN_BIDI_CLASS_NSM 13 -#define UCDN_BIDI_CLASS_BN 14 -#define UCDN_BIDI_CLASS_B 15 -#define UCDN_BIDI_CLASS_S 16 -#define UCDN_BIDI_CLASS_WS 17 -#define UCDN_BIDI_CLASS_ON 18 -#define UCDN_BIDI_CLASS_LRI 19 -#define UCDN_BIDI_CLASS_RLI 20 -#define UCDN_BIDI_CLASS_FSI 21 -#define UCDN_BIDI_CLASS_PDI 22 - -/* index tables for the database records */ -#define SHIFT1 5 -#define SHIFT2 3 -static const unsigned char index0[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 54, 55, 56, 56, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, - 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, - 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 72, 73, 73, 73, - 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 52, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 113, 113, 114, 115, 116, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 117, 117, 118, 119, 120, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 121, 122, 123, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 124, 124, 125, 126, 108, 108, 127, 128, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 130, 129, 129, 131, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 132, 133, 134, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 135, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 144, 145, 108, 108, 108, 108, 108, 146, 147, 148, 108, - 108, 108, 108, 108, 149, 150, 108, 108, 151, 152, 153, 108, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 165, 165, 165, 166, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 167, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 168, 169, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 170, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 52, 52, - 173, 172, 172, 172, 172, 174, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 174, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 175, 176, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 177, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 177, -}; - -static const unsigned short index1[] = { - 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13, 0, 0, 0, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 29, 31, 32, - 33, 34, 35, 27, 30, 29, 27, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 27, 27, 49, 27, 27, 27, 27, 27, 27, 27, 50, 51, 52, 27, 53, 54, - 53, 54, 54, 54, 54, 54, 55, 54, 54, 54, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 64, 65, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 65, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 97, 97, 97, 98, 98, 98, 98, 99, 100, 101, 101, 101, 101, 102, 103, - 101, 101, 101, 101, 101, 101, 104, 105, 101, 101, 101, 101, 101, 101, - 101, 101, 101, 101, 101, 101, 106, 107, 107, 107, 108, 109, 110, 110, - 110, 110, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, - 120, 121, 122, 119, 123, 124, 125, 126, 127, 127, 127, 127, 128, 129, - 130, 131, 132, 133, 134, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 144, - 145, 146, 147, 148, 127, 127, 127, 127, 127, 127, 149, 149, 149, 149, - 150, 151, 152, 119, 153, 154, 155, 155, 155, 156, 157, 158, 159, 159, - 160, 161, 162, 163, 164, 165, 166, 166, 166, 167, 144, 168, 119, 119, - 119, 119, 119, 119, 127, 127, 169, 170, 119, 119, 171, 125, 172, 173, - 174, 175, 176, 177, 177, 177, 177, 177, 177, 178, 179, 180, 181, 177, - 182, 183, 184, 177, 185, 186, 187, 188, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 119, 214, 215, 216, 217, 217, 218, - 219, 220, 221, 222, 223, 119, 224, 225, 226, 227, 228, 229, 230, 231, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 119, 242, 243, - 244, 245, 246, 243, 247, 248, 249, 250, 251, 119, 252, 253, 254, 255, - 256, 257, 258, 259, 259, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 272, 271, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 119, 282, 283, 284, 285, 285, 285, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 296, 296, 299, 300, - 297, 301, 302, 303, 304, 305, 306, 119, 307, 308, 308, 308, 308, 308, - 309, 310, 311, 312, 313, 314, 119, 119, 119, 119, 315, 316, 317, 317, - 318, 317, 319, 320, 321, 322, 323, 324, 119, 119, 119, 119, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 333, 333, 333, 335, 336, 337, - 338, 339, 340, 341, 340, 340, 340, 342, 343, 344, 345, 346, 119, 119, - 119, 119, 347, 347, 347, 347, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 347, 358, 359, 351, 360, 361, 361, 361, 361, 362, 363, - 364, 364, 364, 364, 364, 365, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 367, 367, 367, 367, 367, 367, 367, 367, 367, 368, - 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 370, 371, 370, 369, 369, 369, 369, 369, 370, - 369, 369, 369, 369, 370, 371, 370, 369, 371, 369, 369, 369, 369, 369, - 369, 369, 370, 369, 369, 369, 369, 369, 369, 369, 369, 372, 373, 374, - 375, 376, 369, 369, 377, 378, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 380, 381, 382, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 384, 383, 383, - 385, 386, 386, 387, 388, 388, 388, 388, 388, 388, 388, 388, 388, 389, - 390, 391, 392, 393, 394, 119, 395, 395, 396, 119, 397, 397, 398, 119, - 399, 400, 401, 119, 402, 402, 402, 402, 402, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 417, 417, 417, - 418, 417, 417, 417, 417, 417, 417, 419, 420, 417, 417, 417, 417, 421, - 383, 383, 383, 383, 383, 383, 383, 383, 422, 119, 423, 423, 423, 424, - 425, 426, 427, 428, 429, 430, 431, 431, 431, 432, 433, 119, 434, 434, - 434, 434, 434, 435, 434, 434, 434, 436, 437, 438, 439, 439, 439, 439, - 440, 440, 441, 442, 443, 443, 443, 443, 443, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 450, 451, 452, 453, 454, 455, 119, 119, 119, 119, - 119, 119, 119, 119, 456, 457, 457, 457, 457, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 469, 469, 470, 471, 472, 473, - 474, 474, 474, 474, 475, 476, 477, 478, 479, 479, 479, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 488, 488, 489, 100, 490, 361, 361, - 361, 361, 361, 491, 492, 119, 493, 494, 495, 496, 497, 498, 54, 54, 54, - 54, 499, 500, 56, 56, 56, 56, 56, 501, 502, 503, 54, 504, 54, 54, 54, - 505, 56, 56, 56, 506, 507, 508, 509, 510, 510, 510, 511, 512, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 513, 514, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 515, 516, 517, 518, 515, 516, - 515, 516, 517, 518, 515, 519, 515, 516, 515, 517, 515, 520, 515, 520, - 515, 520, 521, 522, 523, 524, 525, 526, 515, 527, 528, 529, 530, 531, - 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, - 546, 547, 56, 548, 549, 550, 551, 552, 553, 553, 554, 555, 556, 557, 558, - 119, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, - 572, 571, 573, 574, 575, 576, 577, 578, 579, 580, 581, 580, 582, 583, - 580, 584, 580, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 586, - 595, 596, 586, 597, 598, 586, 586, 598, 586, 599, 600, 599, 586, 586, - 601, 586, 586, 586, 586, 586, 602, 586, 586, 580, 603, 604, 605, 606, - 607, 608, 609, 609, 609, 609, 609, 609, 609, 609, 610, 580, 580, 611, - 612, 586, 586, 613, 580, 580, 580, 580, 585, 606, 614, 615, 580, 580, - 580, 580, 580, 616, 119, 119, 119, 580, 617, 119, 119, 618, 618, 618, - 618, 618, 619, 619, 620, 621, 621, 621, 621, 621, 621, 621, 621, 621, - 622, 618, 623, 624, 624, 624, 624, 624, 624, 624, 624, 624, 625, 624, - 624, 624, 624, 626, 580, 624, 624, 627, 580, 628, 629, 630, 631, 632, - 633, 629, 580, 627, 634, 580, 635, 636, 637, 638, 639, 580, 580, 580, - 640, 641, 642, 643, 580, 644, 645, 580, 646, 580, 580, 647, 648, 649, - 650, 580, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 580, - 580, 580, 662, 580, 663, 580, 664, 665, 666, 667, 668, 669, 618, 670, - 670, 671, 580, 580, 580, 662, 672, 673, 586, 586, 586, 674, 675, 586, - 586, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, - 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, - 676, 676, 676, 676, 676, 586, 586, 586, 586, 586, 586, 586, 586, 586, - 586, 586, 586, 586, 586, 586, 586, 677, 678, 678, 679, 586, 586, 586, - 586, 586, 586, 586, 680, 586, 586, 586, 681, 586, 586, 586, 586, 586, - 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, - 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 580, - 580, 580, 682, 580, 580, 586, 586, 683, 684, 685, 629, 580, 580, 686, - 580, 580, 580, 687, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 580, 688, 688, 688, 688, 688, 689, 690, 690, 690, 690, 690, - 691, 692, 693, 694, 695, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 696, 697, 698, 699, 364, 364, 364, 364, 700, 701, 702, 702, 702, 702, - 702, 702, 702, 703, 704, 705, 369, 369, 371, 119, 371, 371, 371, 371, - 371, 371, 371, 371, 706, 706, 706, 706, 707, 708, 709, 710, 711, 712, - 713, 714, 715, 716, 119, 119, 119, 119, 119, 119, 717, 717, 717, 718, - 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 719, 119, 717, 717, - 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, - 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 720, 119, 119, 119, - 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 733, - 734, 733, 733, 733, 735, 736, 737, 738, 739, 740, 741, 741, 742, 741, - 741, 741, 743, 744, 745, 746, 747, 748, 748, 748, 748, 748, 749, 750, - 750, 750, 750, 750, 750, 750, 750, 750, 750, 751, 752, 753, 748, 748, - 748, 754, 721, 721, 721, 721, 722, 119, 755, 755, 756, 756, 756, 757, - 758, 759, 753, 753, 753, 760, 761, 762, 756, 756, 756, 763, 758, 759, - 753, 753, 753, 753, 764, 762, 753, 765, 766, 766, 766, 766, 766, 767, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 753, 753, 753, - 768, 769, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 770, - 753, 753, 753, 768, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 772, 773, 580, 580, 580, 580, 580, 580, 580, 580, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 773, 773, 774, 774, 775, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 776, - 777, 777, 777, 777, 777, 777, 778, 119, 779, 779, 779, 779, 779, 780, - 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, - 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, - 781, 781, 781, 781, 781, 782, 781, 781, 783, 784, 119, 119, 101, 101, - 101, 101, 101, 785, 786, 787, 101, 101, 101, 788, 789, 789, 789, 789, - 789, 789, 789, 789, 790, 791, 792, 119, 64, 64, 793, 794, 795, 27, 796, - 27, 27, 27, 27, 27, 27, 27, 797, 798, 27, 799, 800, 27, 27, 801, 802, 27, - 803, 119, 119, 119, 119, 119, 804, 805, 806, 807, 808, 808, 809, 810, - 811, 812, 813, 813, 813, 813, 813, 813, 814, 119, 815, 816, 816, 816, - 816, 816, 817, 818, 819, 820, 821, 822, 823, 823, 824, 825, 826, 827, - 828, 828, 829, 830, 831, 831, 832, 833, 834, 835, 366, 366, 366, 836, - 837, 838, 838, 838, 838, 838, 839, 840, 841, 842, 843, 844, 845, 347, - 351, 846, 847, 847, 847, 847, 847, 848, 849, 119, 850, 851, 852, 853, - 347, 347, 854, 855, 856, 856, 856, 856, 856, 856, 857, 858, 859, 119, - 119, 860, 861, 862, 863, 119, 864, 864, 864, 119, 371, 371, 54, 54, 54, - 54, 54, 865, 866, 119, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, - 861, 861, 861, 861, 868, 869, 870, 871, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, - 873, 872, 873, 873, 874, 873, 873, 873, 873, 873, 873, 872, 873, 873, - 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, - 875, 119, 367, 367, 876, 877, 368, 368, 368, 368, 368, 878, 879, 879, - 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, - 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, - 879, 879, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, - 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, - 880, 880, 880, 880, 880, 880, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 772, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 881, 773, 773, 773, 773, 882, 119, 883, 884, - 120, 885, 886, 887, 888, 120, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 889, 890, 891, 119, 892, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 893, 119, 119, - 127, 127, 127, 127, 127, 127, 127, 127, 894, 127, 127, 127, 127, 127, - 127, 119, 119, 119, 119, 119, 127, 895, 896, 896, 897, 898, 899, 900, - 901, 902, 903, 904, 905, 906, 907, 908, 169, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 909, 910, 911, - 912, 913, 914, 915, 915, 916, 917, 918, 918, 919, 920, 921, 922, 923, - 923, 923, 923, 924, 925, 925, 925, 926, 927, 927, 927, 928, 929, 930, - 119, 931, 932, 933, 932, 932, 934, 932, 932, 935, 932, 936, 932, 936, - 119, 119, 119, 119, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, - 932, 932, 932, 932, 932, 937, 938, 939, 939, 939, 939, 939, 940, 609, - 941, 941, 941, 941, 941, 941, 942, 943, 944, 945, 580, 946, 947, 119, - 119, 119, 119, 119, 609, 609, 609, 609, 609, 948, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 949, 949, - 949, 950, 951, 951, 951, 951, 951, 951, 952, 119, 953, 954, 954, 955, - 956, 956, 956, 956, 957, 958, 959, 959, 960, 961, 962, 962, 962, 962, - 963, 964, 965, 965, 965, 966, 967, 967, 967, 967, 968, 967, 969, 119, - 119, 119, 119, 119, 970, 970, 970, 970, 970, 971, 971, 971, 971, 971, - 972, 972, 972, 972, 972, 972, 973, 973, 973, 974, 975, 976, 977, 977, - 977, 977, 978, 979, 979, 979, 979, 980, 981, 981, 981, 981, 981, 119, - 982, 982, 982, 982, 982, 982, 983, 984, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 985, 985, - 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, - 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, - 985, 985, 985, 985, 985, 985, 985, 985, 986, 119, 985, 985, 987, 119, - 985, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 988, 989, 990, 990, 990, 990, 991, 992, - 993, 993, 994, 995, 996, 996, 997, 998, 999, 999, 999, 1000, 1001, 1002, - 119, 119, 119, 119, 119, 119, 1003, 1003, 1004, 1005, 1006, 1006, 1007, - 1008, 1009, 1009, 1009, 1010, 119, 119, 119, 119, 119, 119, 119, 119, - 1011, 1011, 1011, 1011, 1012, 1012, 1012, 1013, 1014, 1014, 1015, 1014, - 1014, 1014, 1014, 1014, 1016, 1017, 1018, 1019, 1020, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1027, 1027, 1028, 1029, 1029, 1029, 1030, - 119, 119, 119, 119, 1031, 1032, 1031, 1031, 1033, 1034, 1035, 119, 1036, - 1036, 1036, 1036, 1036, 1036, 1037, 1038, 1039, 1039, 1040, 1041, 1042, - 1042, 1043, 1044, 1045, 1045, 1046, 1047, 119, 1048, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 1049, 1049, 1049, 1049, 1049, 1049, 1049, - 1049, 1049, 1050, 119, 119, 119, 119, 119, 119, 1051, 1051, 1051, 1051, - 1051, 1051, 1052, 119, 1053, 1053, 1053, 1053, 1053, 1053, 1054, 1055, - 1056, 1056, 1056, 1056, 1057, 119, 1058, 1059, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 1060, 1060, 1060, 1061, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 1062, 1062, 1062, 1063, - 1064, 119, 1065, 1065, 1066, 1067, 1068, 1069, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1070, 1070, 1071, - 119, 1072, 1073, 1073, 1073, 1073, 1073, 1073, 1074, 1075, 1076, 1077, - 1078, 1079, 1080, 119, 1081, 1082, 1083, 1083, 1083, 1083, 1083, 1084, - 1085, 1086, 1087, 1088, 1088, 1088, 1089, 1090, 1091, 1092, 1093, 1093, - 1093, 1094, 1095, 1096, 1097, 1098, 119, 1099, 1099, 1099, 1099, 1100, - 119, 1101, 1102, 1102, 1102, 1102, 1102, 1103, 1104, 1105, 1106, 1107, - 1108, 1109, 1110, 1111, 119, 1112, 1112, 1113, 1112, 1112, 1114, 1115, - 1116, 119, 119, 119, 119, 119, 119, 119, 119, 1117, 1118, 1119, 1120, - 1119, 1121, 1122, 1122, 1122, 1122, 1122, 1123, 1124, 1125, 1126, 1127, - 1128, 1129, 1130, 1131, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, - 1139, 1140, 1140, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 1141, 1141, 1141, 1141, 1141, 1141, 1142, - 1143, 1144, 1145, 1146, 1147, 119, 119, 119, 119, 1148, 1148, 1148, 1148, - 1148, 1148, 1149, 1150, 1151, 119, 1152, 1153, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 1154, 1154, 1154, 1154, 1154, 1155, 1156, 1157, 1158, 1159, 1160, - 1161, 119, 119, 119, 119, 1162, 1162, 1162, 1162, 1162, 1162, 1163, 1164, - 1165, 119, 1166, 1167, 1168, 1169, 119, 119, 1170, 1170, 1170, 1170, - 1170, 1171, 1172, 1173, 1174, 1175, 119, 119, 119, 119, 119, 119, 1176, - 1176, 1176, 1177, 1178, 1179, 1180, 1181, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 1182, 1182, 1182, 1182, 1182, 1183, 1184, 1185, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1186, 1186, 1186, - 1186, 1187, 1187, 1187, 1187, 1188, 1189, 1190, 1191, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 1192, 1193, 1192, 1192, 1192, 1192, 1194, 1195, 1196, 119, 119, - 119, 1197, 1198, 1199, 1199, 1199, 1199, 1200, 1201, 1202, 119, 1203, - 1204, 1205, 1205, 1205, 1205, 1205, 1206, 1207, 1208, 1209, 119, 119, - 119, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1211, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 1212, 1213, 1212, 1212, 1212, 1214, 1215, 1216, 1217, 119, 1218, 1219, - 1220, 1221, 1222, 1223, 1223, 1223, 1224, 1225, 1225, 1226, 1227, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 1228, 1229, 1230, 1230, 1230, - 1230, 1231, 1232, 1233, 119, 1234, 1235, 1236, 1237, 1238, 1238, 1238, - 1239, 1240, 1241, 1242, 1243, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 1244, 1244, 1245, 1246, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 1247, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1254, - 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - 1254, 1255, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, - 1256, 1257, 1258, 119, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - 1254, 1254, 1254, 1254, 1259, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1261, 1260, 1260, 1260, - 1260, 1262, 1263, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1264, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, - 1260, 1260, 1260, 1260, 1260, 1260, 1265, 1266, 1267, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 1268, 1268, 1268, 1268, 1268, 1268, 1268, - 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, - 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, - 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, - 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, - 1268, 1268, 1269, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, - 1268, 1268, 1268, 1268, 1268, 1270, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, - 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, - 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 1271, - 1272, 1272, 1272, 1273, 1274, 1275, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 1276, 1276, 1276, 1277, 1278, 119, 1279, 1279, - 1279, 1279, 1279, 1279, 1280, 1281, 1282, 119, 1283, 1284, 1285, 1279, - 1279, 1286, 1279, 1279, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1287, 1287, - 1287, 1287, 1288, 1288, 1288, 1288, 1289, 1289, 1290, 1291, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1292, 1292, 1292, 1292, - 1292, 1292, 1292, 1292, 1292, 1293, 1294, 1295, 1295, 1295, 1295, 1295, - 1295, 1296, 1297, 1298, 119, 119, 119, 119, 119, 119, 119, 119, 1299, - 119, 119, 119, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 119, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, - 1300, 1301, 119, 1302, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, - 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, - 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 1303, 119, 119, 119, - 119, 119, 119, 1304, 119, 1305, 119, 1306, 1306, 1306, 1306, 1306, 1306, - 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, - 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, - 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, - 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1307, 1308, 1308, 1308, 1308, - 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1309, 1308, 1310, - 1308, 1311, 1308, 1312, 1313, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 1314, 119, 609, 609, 609, 609, 1315, 1316, 609, - 609, 609, 609, 609, 609, 1317, 1318, 1319, 1320, 1321, 1322, 609, 609, - 609, 1323, 609, 609, 609, 609, 609, 609, 609, 1324, 119, 119, 944, 944, - 944, 944, 944, 944, 944, 944, 1325, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 939, 939, - 1326, 119, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 616, 119, - 939, 939, 939, 1327, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 1328, 1328, 1328, 1329, 1330, 1330, 1331, - 1328, 1328, 1332, 1333, 1330, 1330, 1328, 1328, 1328, 1329, 1330, 1330, - 1334, 1335, 1336, 1332, 1337, 1338, 1330, 1328, 1328, 1328, 1329, 1330, - 1330, 1339, 1340, 1341, 1342, 1330, 1330, 1330, 1343, 1344, 1345, 1346, - 1330, 1330, 1331, 1328, 1328, 1332, 1330, 1330, 1330, 1328, 1328, 1328, - 1329, 1330, 1330, 1331, 1328, 1328, 1332, 1330, 1330, 1330, 1328, 1328, - 1328, 1329, 1330, 1330, 1331, 1328, 1328, 1332, 1330, 1330, 1330, 1328, - 1328, 1328, 1329, 1330, 1330, 1347, 1328, 1328, 1328, 1348, 1330, 1330, - 1349, 1350, 1328, 1328, 1351, 1330, 1330, 1352, 1331, 1328, 1328, 1353, - 1330, 1330, 1354, 1355, 1328, 1328, 1356, 1330, 1330, 1330, 1357, 1328, - 1328, 1328, 1348, 1330, 1330, 1349, 1358, 1359, 1359, 1359, 1359, 1359, - 1359, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, - 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, - 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1361, 1361, 1361, - 1361, 1361, 1361, 1362, 1363, 1361, 1361, 1361, 1361, 1361, 1364, 1365, - 1360, 1366, 1367, 119, 1368, 1369, 1361, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 1370, 1371, 1371, 1372, 1373, 1374, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 1375, 1375, 1375, 1375, - 1375, 1376, 1377, 1378, 1379, 1380, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1381, 1381, 1381, - 1381, 1381, 1382, 1383, 1384, 1385, 1385, 1385, 1385, 1385, 1385, 1385, - 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, - 1385, 1385, 1385, 1385, 1385, 1386, 1387, 1388, 119, 119, 119, 119, 119, - 1389, 1389, 1389, 1389, 1390, 1391, 1391, 1391, 1392, 1393, 1394, 1395, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 1396, 1397, 1397, 1397, 1397, 1397, 1397, - 1398, 1399, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1396, 1397, - 1397, 1397, 1397, 1400, 1397, 1401, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 1402, 127, 127, 127, 1403, 1404, 1405, 1406, 1407, 1408, - 1403, 1409, 1403, 1405, 1405, 1410, 127, 1411, 127, 1412, 1413, 1411, - 127, 1412, 119, 119, 119, 119, 119, 119, 1414, 119, 1415, 1416, 1416, - 1416, 1416, 1417, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, - 1416, 1416, 1416, 1417, 1418, 1416, 1419, 1420, 1416, 1420, 1421, 1420, - 1416, 1416, 1416, 1422, 1418, 619, 1423, 621, 621, 621, 1424, 621, 621, - 621, 621, 621, 621, 621, 1425, 621, 621, 621, 1426, 1427, 1428, 621, - 1429, 1418, 1418, 1418, 1418, 1418, 1418, 1430, 1431, 1431, 1431, 1432, - 1418, 753, 753, 753, 753, 753, 1433, 753, 1434, 1435, 1418, 1436, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 721, 721, 721, 721, 1437, 1438, 1439, - 721, 721, 721, 721, 721, 721, 721, 721, 1440, 1441, 721, 1442, 1443, 721, - 721, 1444, 1445, 1446, 1447, 1442, 1416, 721, 721, 1448, 1449, 721, 721, - 721, 721, 721, 721, 721, 1450, 1451, 1452, 1453, 721, 1454, 1452, 1452, - 1455, 1456, 1457, 1458, 721, 1459, 1460, 1461, 721, 721, 721, 721, 721, - 721, 721, 721, 1462, 1463, 721, 1464, 642, 1465, 721, 1466, 1467, 580, - 1468, 721, 721, 721, 1416, 1469, 1470, 1416, 1416, 1471, 1416, 1415, - 1416, 1416, 1416, 1416, 1416, 1472, 1473, 1416, 1416, 1472, 1474, 721, - 721, 721, 721, 721, 721, 721, 721, 1475, 1476, 580, 580, 580, 580, 1477, - 1478, 721, 721, 721, 721, 1479, 721, 1480, 721, 1481, 1482, 1483, 1418, - 1416, 1484, 1485, 1486, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 580, 580, 1487, 1418, 580, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 1488, 1489, 721, 1490, 1418, 1418, 580, 1487, 580, 580, 580, - 580, 580, 580, 580, 1418, 580, 1491, 580, 580, 580, 580, 580, 1418, 580, - 580, 580, 1492, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 580, 1493, 721, 1452, 1494, 721, 1452, 1495, 721, 721, 721, 721, - 721, 721, 1496, 1497, 721, 721, 721, 721, 1498, 1499, 1500, 1501, 721, - 1502, 1503, 1504, 721, 721, 721, 721, 580, 580, 580, 580, 580, 580, 580, - 580, 580, 580, 1487, 1418, 1416, 1422, 1490, 1486, 1486, 1418, 1436, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, - 1418, 1418, 1418, 1418, 1505, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 1506, 773, 773, 773, 773, 773, 771, 771, 771, 771, - 771, 771, 1507, 773, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 772, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 881, 773, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, - 771, 771, 771, 771, 771, 771, 771, 771, 1508, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 771, 771, 771, 772, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 773, 773, 773, 1509, 1510, 119, 119, 119, - 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, - 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, - 896, 896, 896, 896, 119, 119, 880, 880, 880, 880, 880, 880, 880, 880, - 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, - 880, 880, 880, 880, 880, 880, 880, 880, 880, 1512, -}; - -static const unsigned short index2[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 7, 7, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 11, 16, 17, 15, 18, 19, 20, 19, 21, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 19, 23, 24, 24, 24, 10, 15, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 16, 26, 17, - 27, 28, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 16, 30, 31, 24, 1, 1, 1, 1, 1, 1, 32, 1, 1, 33, 34, 35, 13, - 36, 13, 37, 38, 39, 40, 41, 42, 24, 43, 44, 27, 45, 46, 47, 47, 48, 49, - 38, 38, 39, 47, 41, 50, 51, 51, 51, 34, 52, 52, 52, 52, 52, 52, 53, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 52, 54, 53, 52, - 52, 52, 52, 52, 53, 55, 55, 55, 56, 56, 56, 56, 55, 56, 55, 55, 55, 56, - 55, 55, 56, 56, 55, 56, 55, 55, 56, 56, 56, 54, 55, 55, 55, 56, 55, 56, - 55, 56, 52, 55, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, - 52, 55, 52, 55, 52, 56, 52, 56, 52, 56, 52, 55, 52, 56, 52, 56, 52, 56, - 52, 56, 52, 56, 53, 55, 52, 55, 53, 55, 52, 56, 52, 56, 55, 52, 56, 52, - 56, 52, 56, 53, 55, 53, 55, 52, 55, 52, 56, 52, 55, 55, 53, 55, 52, 55, - 52, 56, 52, 56, 53, 55, 52, 56, 52, 56, 52, 52, 56, 52, 56, 52, 56, 56, - 56, 52, 52, 56, 52, 56, 52, 52, 56, 52, 52, 52, 56, 56, 52, 52, 52, 52, - 56, 52, 52, 56, 52, 52, 52, 56, 56, 56, 52, 52, 56, 52, 52, 56, 52, 56, - 52, 56, 52, 52, 56, 52, 56, 56, 52, 56, 52, 52, 56, 52, 52, 52, 56, 52, - 56, 52, 52, 56, 56, 57, 52, 56, 56, 56, 57, 57, 57, 57, 52, 58, 56, 52, - 58, 56, 52, 58, 56, 52, 55, 52, 55, 52, 55, 52, 55, 52, 55, 52, 55, 52, - 55, 52, 55, 56, 52, 56, 56, 52, 58, 56, 52, 56, 52, 52, 52, 56, 52, 56, - 56, 56, 56, 56, 56, 56, 52, 52, 56, 52, 52, 56, 56, 52, 56, 52, 52, 52, - 52, 56, 56, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 57, 56, 56, 56, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, - 60, 61, 61, 61, 61, 61, 61, 61, 62, 62, 63, 62, 60, 64, 65, 64, 64, 64, - 65, 64, 60, 60, 66, 61, 62, 62, 62, 62, 62, 62, 39, 39, 39, 39, 62, 39, - 62, 48, 59, 59, 59, 59, 59, 62, 62, 62, 62, 62, 67, 67, 60, 62, 61, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 69, 70, 70, 70, 70, 69, 71, 70, 70, 70, 70, 70, 72, 72, 70, - 70, 70, 70, 72, 72, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 73, 73, - 73, 73, 73, 70, 70, 70, 70, 68, 68, 68, 68, 68, 68, 68, 68, 74, 68, 70, - 70, 70, 68, 68, 68, 70, 70, 75, 68, 68, 68, 70, 70, 70, 70, 68, 69, 70, - 70, 68, 76, 77, 77, 76, 77, 77, 76, 68, 68, 68, 68, 68, 78, 79, 78, 79, - 60, 80, 78, 79, 81, 81, 82, 79, 79, 79, 83, 78, 81, 81, 81, 81, 80, 62, - 78, 84, 78, 78, 78, 81, 78, 81, 78, 78, 79, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 81, 85, 85, 85, 85, 85, 85, 85, - 78, 78, 79, 79, 79, 79, 79, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 79, 86, 86, 86, 86, 86, 86, 86, 79, 79, 79, 79, - 79, 78, 79, 79, 78, 78, 78, 79, 79, 79, 78, 79, 78, 79, 78, 79, 78, 79, - 78, 79, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 79, 79, - 79, 79, 78, 79, 89, 78, 79, 78, 78, 79, 79, 78, 78, 78, 90, 91, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, - 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 93, 92, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 90, 93, 90, 93, 90, 93, 90, 93, 90, 93, - 94, 95, 95, 96, 96, 95, 97, 97, 90, 93, 90, 93, 90, 93, 90, 90, 93, 90, - 93, 90, 93, 90, 93, 90, 93, 90, 93, 90, 93, 93, 81, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 81, - 81, 99, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, - 101, 101, 102, 103, 81, 81, 104, 104, 105, 81, 106, 107, 107, 107, 107, - 106, 107, 107, 107, 108, 106, 107, 107, 107, 107, 107, 107, 106, 106, - 106, 106, 106, 106, 107, 107, 106, 107, 107, 108, 109, 107, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 125, 107, 106, 128, 118, 81, 81, 81, 81, 81, 81, 81, 81, - 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 81, 81, 81, 81, - 129, 129, 129, 129, 125, 125, 81, 81, 81, 130, 130, 130, 130, 130, 131, - 132, 132, 133, 134, 134, 135, 136, 137, 138, 138, 139, 139, 139, 139, - 139, 139, 139, 139, 140, 141, 142, 143, 144, 81, 145, 143, 146, 146, 146, - 146, 146, 146, 146, 146, 147, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 148, 149, 150, 151, 152, 153, 154, 155, 96, 96, 156, 157, 139, - 139, 139, 139, 139, 157, 139, 139, 157, 158, 158, 158, 158, 158, 158, - 158, 158, 158, 158, 134, 159, 159, 160, 146, 146, 161, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 145, 146, 139, 139, 139, 139, - 139, 139, 139, 131, 138, 139, 139, 139, 139, 157, 139, 162, 162, 139, - 139, 138, 157, 139, 139, 157, 146, 146, 163, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 146, 146, 146, 164, 164, 146, 165, 165, 165, 165, - 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 81, 166, 167, 168, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 169, - 170, 169, 169, 170, 169, 169, 170, 170, 170, 169, 170, 170, 169, 170, - 169, 169, 169, 170, 169, 170, 169, 170, 169, 170, 169, 169, 81, 81, 167, - 167, 167, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 171, 81, - 81, 81, 81, 81, 81, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 176, 175, 177, 177, - 178, 179, 180, 181, 177, 81, 81, 176, 182, 182, 183, 183, 183, 183, 183, - 183, 183, 183, 183, 183, 183, 183, 183, 183, 184, 184, 184, 184, 185, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 185, 184, 184, 184, 185, - 184, 184, 184, 184, 184, 81, 81, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 81, 187, 187, 187, 187, 187, 187, 187, - 187, 187, 188, 188, 188, 81, 81, 189, 81, 167, 167, 167, 81, 81, 81, 81, - 81, 146, 146, 146, 146, 146, 81, 146, 146, 146, 146, 146, 146, 146, 146, - 81, 81, 81, 81, 81, 157, 139, 139, 139, 139, 139, 139, 131, 157, 139, - 139, 157, 139, 139, 157, 139, 139, 139, 157, 157, 157, 190, 191, 192, - 139, 139, 139, 157, 139, 139, 157, 157, 139, 139, 139, 139, 139, 193, - 193, 193, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 193, 194, 196, 195, 194, 194, 194, 193, 193, 193, 193, - 193, 193, 193, 193, 194, 194, 194, 194, 197, 194, 194, 195, 96, 156, 96, - 96, 193, 193, 193, 195, 195, 193, 193, 198, 198, 199, 199, 199, 199, 199, - 199, 199, 199, 199, 199, 200, 201, 195, 195, 195, 195, 195, 195, 202, - 203, 204, 204, 81, 202, 202, 202, 202, 202, 202, 202, 202, 81, 81, 202, - 202, 81, 81, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 81, 202, 202, 202, 202, 202, 202, 202, 81, 202, 81, 81, 81, - 202, 202, 202, 202, 81, 81, 205, 202, 204, 204, 204, 203, 203, 203, 203, - 81, 81, 204, 204, 81, 81, 204, 204, 206, 202, 81, 81, 81, 81, 81, 81, 81, - 81, 204, 81, 81, 81, 81, 202, 202, 81, 202, 202, 202, 203, 203, 81, 81, - 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 202, 202, 208, 208, - 209, 209, 209, 209, 209, 210, 211, 212, 202, 213, 214, 81, 81, 215, 215, - 216, 81, 217, 217, 217, 217, 217, 217, 81, 81, 81, 81, 217, 217, 81, 81, - 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 81, - 217, 217, 217, 217, 217, 217, 217, 81, 217, 217, 81, 217, 217, 81, 217, - 217, 81, 81, 218, 81, 216, 216, 216, 215, 215, 81, 81, 81, 81, 215, 215, - 81, 81, 215, 215, 219, 81, 81, 81, 215, 81, 81, 81, 81, 81, 81, 81, 217, - 217, 217, 217, 81, 217, 81, 81, 81, 81, 81, 81, 81, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 215, 215, 217, 217, 217, 215, 221, 81, 81, - 222, 222, 223, 81, 224, 224, 224, 224, 224, 224, 224, 224, 224, 81, 224, - 224, 224, 81, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 81, 224, 224, 224, 224, 224, 224, 224, 81, 224, 224, 81, 224, - 224, 224, 224, 224, 81, 81, 225, 224, 223, 223, 223, 222, 222, 222, 222, - 222, 81, 222, 222, 223, 81, 223, 223, 226, 81, 81, 224, 81, 81, 81, 81, - 81, 81, 81, 224, 224, 222, 222, 81, 81, 227, 227, 227, 227, 227, 227, - 227, 227, 227, 227, 228, 229, 81, 81, 81, 81, 81, 81, 81, 224, 222, 222, - 222, 222, 222, 222, 81, 230, 231, 231, 81, 232, 232, 232, 232, 232, 232, - 232, 232, 81, 81, 232, 232, 81, 81, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 81, 232, 232, 232, 232, 232, 232, 232, - 81, 232, 232, 81, 232, 232, 232, 232, 232, 81, 81, 233, 232, 231, 230, - 231, 230, 230, 230, 230, 81, 81, 231, 231, 81, 81, 231, 231, 234, 81, 81, - 81, 81, 81, 81, 81, 81, 230, 231, 81, 81, 81, 81, 232, 232, 81, 232, 232, - 232, 230, 230, 81, 81, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, - 236, 232, 237, 237, 237, 237, 237, 237, 81, 81, 238, 239, 81, 239, 239, - 239, 239, 239, 239, 81, 81, 81, 239, 239, 239, 81, 239, 239, 239, 239, - 81, 81, 81, 239, 239, 81, 239, 81, 239, 239, 81, 81, 81, 239, 239, 81, - 81, 81, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 81, 81, 81, 81, - 240, 240, 238, 240, 240, 81, 81, 81, 240, 240, 240, 81, 240, 240, 240, - 241, 81, 81, 239, 81, 81, 81, 81, 81, 81, 240, 81, 81, 81, 81, 81, 81, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 244, - 244, 244, 244, 244, 244, 245, 244, 81, 81, 81, 81, 81, 246, 247, 247, - 247, 246, 248, 248, 248, 248, 248, 248, 248, 248, 81, 248, 248, 248, 81, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 81, 81, 81, 248, 246, 246, 246, 247, 247, 247, 247, 81, 246, - 246, 246, 81, 246, 246, 246, 249, 81, 81, 81, 81, 81, 81, 81, 250, 251, - 81, 248, 248, 248, 81, 81, 81, 81, 81, 248, 248, 246, 246, 81, 81, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 81, 81, 81, 81, 81, 81, 81, - 253, 254, 254, 254, 254, 254, 254, 254, 255, 256, 257, 258, 258, 259, - 256, 256, 256, 256, 256, 256, 256, 256, 81, 256, 256, 256, 81, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 81, 256, 256, 256, 256, 256, 81, 81, 260, 256, 258, 261, 258, - 258, 258, 258, 258, 81, 261, 258, 258, 81, 258, 258, 257, 262, 81, 81, - 81, 81, 81, 81, 81, 258, 258, 81, 81, 81, 81, 81, 81, 81, 256, 81, 256, - 256, 257, 257, 81, 81, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, - 81, 256, 256, 81, 81, 81, 81, 81, 264, 264, 265, 265, 81, 266, 266, 266, - 266, 266, 266, 266, 266, 81, 266, 266, 266, 81, 266, 266, 266, 266, 266, - 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 267, 267, - 266, 265, 265, 265, 264, 264, 264, 264, 81, 265, 265, 265, 81, 265, 265, - 265, 267, 266, 268, 81, 81, 81, 81, 266, 266, 266, 265, 269, 269, 269, - 269, 269, 269, 269, 266, 266, 266, 264, 264, 81, 81, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 269, 269, 269, 269, 269, 269, 269, 269, - 269, 271, 266, 266, 266, 266, 266, 266, 81, 81, 272, 272, 81, 273, 273, - 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, - 273, 273, 81, 81, 81, 273, 273, 273, 273, 273, 273, 273, 273, 81, 273, - 273, 273, 273, 273, 273, 273, 273, 273, 81, 273, 81, 81, 81, 81, 274, 81, - 81, 81, 81, 272, 272, 272, 275, 275, 275, 81, 275, 81, 272, 272, 272, - 272, 272, 272, 272, 272, 81, 81, 81, 81, 81, 81, 276, 276, 276, 276, 276, - 276, 276, 276, 276, 276, 81, 81, 272, 272, 277, 81, 81, 81, 81, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 279, 278, 278, 279, 279, 279, 279, 280, 280, 281, 81, 81, 81, 81, 282, - 278, 278, 278, 278, 278, 278, 283, 279, 284, 284, 284, 284, 279, 279, - 279, 285, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 287, 287, 81, - 81, 81, 81, 81, 288, 288, 81, 288, 81, 288, 288, 288, 288, 288, 81, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 81, 288, 81, 288, 288, 289, 288, 288, 289, 289, 289, 289, 290, 290, - 291, 289, 289, 288, 81, 81, 288, 288, 288, 288, 288, 81, 292, 81, 293, - 293, 293, 293, 289, 289, 81, 81, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 81, 81, 288, 288, 288, 288, 295, 296, 296, 296, 297, 298, 297, - 297, 299, 297, 297, 300, 299, 301, 301, 301, 301, 301, 299, 302, 301, - 302, 302, 302, 303, 303, 302, 302, 302, 302, 302, 302, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 305, 305, 305, 305, 305, 305, 305, - 305, 305, 305, 306, 303, 302, 303, 302, 307, 308, 309, 308, 309, 310, - 310, 295, 295, 295, 295, 295, 295, 295, 295, 81, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 81, 81, 81, 81, 311, 312, 313, 314, - 313, 313, 313, 313, 313, 312, 312, 312, 312, 313, 315, 312, 313, 316, - 316, 317, 300, 316, 316, 295, 295, 295, 295, 295, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 81, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 81, 306, 306, 302, 302, 302, 302, 302, 302, 303, - 302, 302, 302, 302, 302, 302, 81, 302, 302, 297, 297, 300, 297, 298, 318, - 318, 318, 318, 299, 299, 81, 81, 81, 81, 81, 319, 319, 319, 319, 319, - 319, 319, 319, 319, 319, 319, 320, 320, 321, 321, 321, 321, 320, 321, - 321, 321, 321, 321, 322, 320, 323, 323, 320, 320, 321, 321, 319, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 324, 325, 325, 326, 326, 326, - 326, 319, 319, 319, 319, 319, 319, 320, 320, 321, 321, 319, 319, 319, - 319, 321, 321, 321, 319, 320, 320, 320, 319, 319, 320, 320, 320, 320, - 320, 320, 320, 319, 319, 319, 321, 321, 321, 321, 319, 319, 319, 319, - 319, 321, 320, 320, 321, 321, 320, 320, 320, 320, 320, 320, 327, 319, - 320, 324, 324, 320, 320, 320, 321, 328, 328, 329, 329, 329, 329, 329, - 329, 329, 329, 329, 329, 329, 329, 329, 329, 81, 329, 81, 81, 81, 81, 81, - 329, 81, 81, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 331, - 332, 330, 330, 330, 333, 333, 333, 333, 333, 333, 333, 333, 334, 334, - 334, 334, 334, 334, 334, 334, 335, 335, 335, 335, 335, 335, 335, 335, - 336, 336, 336, 336, 336, 336, 336, 336, 336, 81, 336, 336, 336, 336, 81, - 81, 336, 336, 336, 336, 336, 336, 336, 81, 336, 336, 336, 81, 81, 337, - 337, 337, 338, 339, 338, 338, 338, 338, 338, 338, 338, 340, 340, 340, - 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, - 340, 340, 340, 81, 81, 81, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 81, 81, 81, 81, 81, 81, 342, 342, 342, 342, 342, 342, 342, 342, 342, - 342, 342, 342, 342, 342, 81, 81, 343, 343, 343, 343, 343, 343, 81, 81, - 344, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, - 345, 345, 345, 345, 345, 345, 345, 346, 347, 345, 348, 349, 349, 349, - 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, - 349, 350, 351, 81, 81, 81, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 198, 198, 198, 353, 353, 353, 352, 352, 352, 352, 352, 352, - 352, 352, 81, 81, 81, 81, 81, 81, 81, 354, 354, 354, 354, 354, 354, 354, - 354, 354, 354, 354, 354, 354, 81, 354, 354, 354, 354, 355, 355, 356, 81, - 81, 81, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 358, 358, 359, - 198, 198, 81, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 361, 361, - 81, 81, 81, 81, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - 362, 362, 81, 362, 362, 362, 81, 363, 363, 81, 81, 81, 81, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 364, 364, 365, 365, 366, 365, 365, - 365, 365, 365, 365, 365, 366, 366, 366, 366, 366, 366, 366, 366, 365, - 366, 366, 365, 365, 365, 365, 365, 365, 365, 365, 365, 367, 365, 368, - 368, 369, 370, 368, 371, 368, 372, 364, 373, 81, 81, 374, 374, 374, 374, - 374, 374, 374, 374, 374, 374, 81, 81, 81, 81, 81, 81, 375, 375, 375, 375, - 375, 375, 375, 375, 375, 375, 81, 81, 81, 81, 81, 81, 376, 376, 377, 377, - 378, 379, 380, 376, 381, 381, 376, 382, 382, 382, 383, 81, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 81, 81, 81, 81, 81, 81, 385, 385, 385, - 385, 385, 385, 385, 385, 385, 385, 385, 386, 385, 385, 385, 385, 385, 81, - 81, 81, 81, 81, 81, 81, 385, 385, 385, 385, 385, 382, 382, 385, 385, 387, - 385, 81, 81, 81, 81, 81, 345, 345, 345, 345, 345, 345, 81, 81, 388, 388, - 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 81, 389, - 389, 389, 390, 390, 390, 390, 389, 389, 390, 390, 390, 81, 81, 81, 81, - 390, 390, 389, 390, 390, 390, 390, 390, 390, 391, 392, 393, 81, 81, 81, - 81, 394, 81, 81, 81, 395, 395, 396, 396, 396, 396, 396, 396, 396, 396, - 396, 396, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, - 397, 397, 81, 81, 397, 397, 397, 397, 397, 81, 81, 81, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 81, 81, 81, 81, 398, 398, - 81, 81, 81, 81, 81, 81, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, - 400, 81, 81, 81, 401, 401, 402, 402, 402, 402, 402, 402, 402, 402, 403, - 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, - 404, 405, 406, 406, 407, 81, 81, 408, 408, 409, 409, 409, 409, 409, 409, - 409, 409, 409, 409, 409, 409, 409, 410, 411, 410, 411, 411, 411, 411, - 411, 411, 411, 81, 412, 410, 411, 410, 410, 411, 411, 411, 411, 411, 411, - 411, 411, 410, 410, 410, 410, 410, 410, 411, 411, 413, 413, 413, 413, - 413, 413, 413, 413, 81, 81, 414, 415, 415, 415, 415, 415, 415, 415, 415, - 415, 415, 81, 81, 81, 81, 81, 81, 416, 416, 416, 416, 416, 416, 416, 417, - 416, 416, 416, 416, 416, 416, 81, 81, 96, 96, 96, 96, 96, 156, 156, 156, - 156, 156, 156, 96, 96, 156, 418, 81, 419, 419, 419, 419, 420, 421, 421, - 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 422, - 420, 419, 419, 419, 419, 419, 420, 419, 420, 420, 420, 420, 420, 419, - 420, 423, 421, 421, 421, 421, 421, 421, 421, 81, 81, 81, 81, 424, 424, - 424, 424, 424, 424, 424, 424, 424, 424, 425, 425, 426, 425, 425, 425, - 425, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 428, 429, 428, - 428, 428, 428, 428, 428, 428, 427, 427, 427, 427, 427, 427, 427, 427, - 427, 81, 81, 81, 430, 430, 431, 432, 432, 432, 432, 432, 432, 432, 432, - 432, 432, 432, 432, 432, 432, 431, 430, 430, 430, 430, 431, 431, 430, - 430, 433, 434, 430, 430, 432, 432, 435, 435, 435, 435, 435, 435, 435, - 435, 435, 435, 432, 432, 432, 432, 432, 432, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, 436, 437, 438, 439, 439, 438, - 438, 438, 439, 438, 439, 439, 439, 440, 440, 81, 81, 81, 81, 81, 81, 81, - 81, 441, 441, 441, 441, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, - 442, 442, 443, 443, 443, 443, 443, 443, 443, 443, 444, 444, 444, 444, - 444, 444, 444, 444, 443, 443, 444, 445, 81, 81, 81, 446, 446, 446, 446, - 446, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 81, 81, 81, 442, - 442, 442, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 449, 449, - 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 450, 450, - 450, 450, 450, 450, 451, 451, 93, 81, 81, 81, 81, 81, 81, 81, 329, 329, - 329, 81, 81, 329, 329, 329, 452, 452, 452, 452, 452, 452, 452, 452, 96, - 96, 96, 331, 453, 156, 156, 156, 156, 156, 96, 96, 156, 156, 156, 156, - 96, 454, 453, 453, 453, 453, 453, 453, 453, 455, 455, 455, 455, 156, 455, - 455, 455, 455, 455, 455, 96, 455, 455, 454, 96, 96, 455, 81, 81, 81, 81, - 81, 56, 56, 56, 56, 56, 56, 79, 79, 79, 79, 79, 93, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 82, 82, 82, 82, 82, 59, 59, 59, 59, 82, 82, 82, 82, 82, - 56, 56, 56, 56, 56, 456, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 82, 96, 96, 156, 96, 96, 96, 96, - 96, 96, 96, 156, 96, 96, 457, 458, 156, 459, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 460, 461, 461, - 156, 81, 96, 462, 156, 96, 156, 52, 56, 52, 56, 52, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 52, 56, 79, 79, 79, 79, 79, 79, 79, 79, 78, 78, 78, 78, - 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 81, 81, 78, 78, 78, 78, 78, 78, - 81, 81, 81, 78, 81, 78, 81, 78, 81, 78, 463, 463, 463, 463, 463, 463, - 463, 463, 79, 79, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 463, 80, 79, - 80, 80, 80, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 463, 80, 80, 80, 79, - 79, 79, 79, 81, 81, 79, 79, 78, 78, 78, 78, 81, 80, 80, 80, 78, 78, 78, - 78, 78, 80, 80, 80, 81, 81, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 463, - 464, 80, 81, 465, 465, 465, 465, 465, 465, 465, 466, 465, 465, 465, 467, - 468, 469, 470, 471, 472, 473, 474, 472, 475, 476, 38, 84, 477, 478, 479, - 42, 477, 478, 479, 42, 38, 38, 480, 84, 481, 481, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 33, 490, 491, 490, 490, 491, 492, 493, 493, 84, - 42, 50, 38, 494, 494, 480, 495, 495, 84, 84, 84, 496, 479, 497, 494, 494, - 494, 84, 84, 84, 84, 84, 84, 84, 84, 498, 84, 495, 84, 379, 84, 379, 379, - 379, 379, 84, 379, 379, 465, 499, 500, 500, 500, 500, 81, 501, 502, 503, - 504, 505, 505, 505, 505, 505, 505, 506, 59, 81, 81, 47, 506, 506, 506, - 506, 506, 507, 507, 498, 479, 497, 508, 506, 47, 47, 47, 47, 506, 506, - 506, 506, 506, 507, 507, 498, 479, 497, 81, 59, 59, 59, 59, 59, 81, 81, - 81, 282, 282, 282, 282, 282, 282, 282, 509, 282, 510, 282, 282, 36, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 509, 282, 282, 282, 282, 509, - 282, 282, 509, 282, 511, 511, 511, 511, 511, 511, 511, 511, 96, 96, 453, - 453, 96, 96, 96, 96, 453, 453, 453, 96, 96, 418, 418, 418, 418, 96, 418, - 418, 418, 453, 453, 96, 156, 96, 453, 453, 156, 156, 156, 156, 96, 81, - 81, 81, 81, 81, 81, 81, 40, 40, 512, 513, 40, 514, 40, 512, 40, 513, 49, - 512, 512, 512, 49, 49, 512, 512, 512, 515, 40, 512, 516, 40, 498, 512, - 512, 512, 512, 512, 40, 40, 40, 514, 514, 40, 512, 40, 85, 40, 512, 40, - 52, 517, 512, 512, 518, 49, 512, 512, 52, 512, 49, 455, 455, 455, 455, - 49, 40, 40, 49, 49, 512, 512, 498, 498, 498, 498, 498, 512, 49, 49, 49, - 49, 40, 498, 40, 40, 56, 318, 519, 519, 519, 520, 51, 521, 519, 519, 519, - 519, 519, 51, 520, 520, 51, 519, 522, 522, 522, 522, 522, 522, 522, 522, - 522, 522, 522, 522, 523, 523, 523, 523, 522, 522, 523, 523, 523, 523, - 523, 523, 523, 523, 523, 52, 56, 523, 523, 523, 523, 51, 40, 40, 81, 81, - 81, 81, 54, 54, 54, 54, 54, 514, 514, 514, 514, 514, 498, 498, 40, 40, - 40, 40, 498, 40, 40, 498, 40, 40, 498, 40, 40, 40, 40, 40, 40, 40, 498, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 44, 44, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 498, 498, 40, 40, 54, 40, 54, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 44, 40, 40, 40, 40, 498, 498, 498, 498, 498, 498, 498, - 498, 498, 498, 498, 498, 54, 498, 54, 54, 498, 498, 498, 54, 54, 498, - 498, 54, 498, 498, 498, 54, 498, 54, 524, 525, 498, 54, 498, 498, 498, - 498, 54, 498, 498, 54, 54, 54, 54, 498, 498, 54, 498, 54, 498, 54, 54, - 54, 54, 54, 54, 498, 54, 498, 498, 498, 498, 498, 54, 54, 54, 54, 498, - 498, 498, 498, 54, 54, 498, 498, 54, 498, 498, 498, 54, 498, 498, 498, - 498, 498, 54, 498, 498, 498, 498, 498, 54, 54, 498, 498, 54, 54, 54, 54, - 498, 498, 54, 54, 498, 498, 54, 54, 498, 498, 498, 498, 498, 54, 498, - 498, 498, 54, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, - 498, 54, 498, 498, 498, 498, 498, 498, 498, 526, 479, 497, 479, 497, 40, - 40, 40, 40, 40, 40, 514, 40, 40, 40, 40, 40, 40, 40, 527, 527, 40, 40, - 40, 40, 498, 498, 40, 40, 40, 40, 40, 40, 40, 528, 529, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 40, 498, 40, 40, 40, 40, 40, 40, 40, 40, 318, 40, 40, - 40, 40, 40, 498, 498, 498, 498, 498, 498, 498, 498, 498, 40, 40, 40, 40, - 40, 530, 530, 530, 530, 40, 40, 40, 527, 531, 531, 527, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 81, 40, 40, 40, 81, 81, 81, 81, 81, 51, 51, - 51, 51, 51, 51, 51, 51, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, - 521, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 520, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 40, 40, 40, 40, 514, 514, - 514, 514, 533, 40, 40, 40, 40, 40, 514, 514, 514, 514, 40, 40, 514, 514, - 40, 514, 514, 514, 514, 514, 514, 514, 40, 40, 40, 40, 40, 40, 40, 40, - 514, 514, 40, 40, 514, 54, 40, 40, 40, 40, 514, 514, 40, 40, 514, 54, 40, - 40, 40, 40, 514, 514, 514, 40, 40, 514, 40, 40, 514, 514, 40, 40, 40, 40, - 40, 40, 40, 514, 498, 498, 498, 498, 498, 534, 534, 498, 531, 531, 531, - 531, 40, 514, 514, 40, 40, 514, 40, 40, 40, 40, 514, 514, 40, 40, 40, 40, - 527, 527, 533, 533, 531, 40, 531, 531, 535, 536, 535, 531, 40, 531, 531, - 531, 40, 40, 40, 40, 514, 40, 514, 40, 40, 40, 40, 40, 530, 530, 530, - 530, 530, 530, 530, 530, 530, 530, 530, 530, 40, 40, 40, 40, 514, 514, - 40, 514, 514, 514, 40, 514, 535, 514, 514, 40, 514, 514, 40, 54, 40, 40, - 40, 40, 40, 40, 40, 527, 40, 40, 40, 530, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 514, 514, 40, 530, 40, 40, 40, 40, 40, 40, 40, 40, 530, 530, 318, - 40, 40, 40, 40, 40, 40, 40, 40, 527, 527, 535, 531, 531, 531, 531, 527, - 527, 535, 535, 535, 514, 514, 514, 514, 535, 530, 535, 535, 535, 514, - 535, 527, 514, 514, 514, 535, 535, 514, 514, 535, 514, 514, 535, 535, - 535, 40, 514, 40, 40, 40, 40, 514, 514, 527, 514, 514, 514, 514, 514, - 514, 535, 527, 527, 535, 527, 514, 535, 535, 537, 527, 514, 514, 527, - 535, 535, 531, 531, 531, 531, 531, 530, 40, 40, 531, 531, 538, 538, 536, - 536, 40, 40, 530, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 44, 40, - 40, 40, 40, 40, 40, 530, 40, 530, 40, 40, 40, 40, 530, 530, 530, 40, 539, - 40, 40, 40, 540, 540, 540, 540, 540, 540, 40, 541, 541, 531, 40, 40, 40, - 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 51, - 51, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 40, 530, - 530, 530, 40, 40, 40, 40, 40, 40, 40, 530, 498, 498, 498, 498, 498, 479, - 497, 498, 498, 498, 498, 498, 498, 498, 16, 31, 16, 31, 16, 31, 16, 31, - 479, 497, 542, 542, 542, 542, 542, 542, 542, 542, 498, 498, 498, 479, - 497, 16, 31, 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 498, 498, - 498, 498, 498, 498, 498, 479, 497, 479, 497, 498, 498, 498, 498, 498, - 498, 498, 498, 479, 497, 498, 498, 40, 40, 40, 530, 530, 40, 40, 40, 498, - 498, 498, 498, 498, 40, 40, 498, 498, 498, 498, 498, 498, 40, 40, 40, - 530, 40, 40, 40, 40, 539, 514, 514, 40, 40, 40, 40, 81, 81, 40, 40, 40, - 40, 40, 40, 40, 40, 81, 81, 543, 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 81, 544, 544, 544, 544, 544, 544, 544, 544, - 544, 544, 544, 544, 544, 544, 544, 81, 52, 56, 52, 52, 52, 56, 56, 52, - 56, 52, 56, 52, 56, 52, 52, 52, 52, 56, 52, 56, 56, 52, 56, 56, 56, 56, - 56, 56, 59, 59, 52, 52, 87, 88, 87, 88, 88, 545, 545, 545, 545, 545, 545, - 87, 88, 87, 88, 546, 546, 546, 87, 88, 81, 81, 81, 81, 81, 547, 548, 548, - 548, 549, 547, 548, 330, 330, 330, 330, 330, 330, 81, 330, 81, 81, 81, - 81, 81, 330, 81, 81, 550, 550, 550, 550, 550, 550, 550, 550, 81, 81, 81, - 81, 81, 81, 81, 551, 552, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 553, 95, 95, 95, 95, 95, 95, 95, 95, 554, 554, 42, 50, 42, 50, - 554, 554, 554, 42, 50, 554, 42, 50, 379, 379, 379, 379, 379, 379, 379, - 379, 84, 474, 555, 379, 556, 84, 42, 50, 84, 84, 42, 50, 479, 497, 479, - 497, 479, 497, 479, 497, 379, 379, 379, 379, 377, 60, 379, 379, 84, 379, - 379, 84, 84, 84, 84, 84, 557, 557, 379, 379, 379, 84, 474, 379, 479, 379, - 379, 379, 379, 379, 379, 379, 379, 84, 379, 84, 379, 379, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 81, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 81, 81, 81, 81, 558, 558, 558, 558, 558, 558, 81, 81, 527, 527, - 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 81, 81, 81, 81, 559, - 560, 560, 561, 527, 562, 563, 564, 528, 529, 528, 529, 528, 529, 528, - 529, 528, 529, 527, 527, 528, 529, 528, 529, 528, 529, 528, 529, 565, - 528, 529, 529, 527, 564, 564, 564, 564, 564, 564, 564, 564, 564, 566, - 567, 568, 569, 570, 570, 571, 572, 572, 572, 572, 573, 527, 527, 564, - 564, 564, 562, 574, 561, 527, 531, 81, 575, 576, 575, 576, 575, 576, 575, - 576, 575, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, - 576, 576, 576, 576, 576, 575, 576, 576, 576, 576, 576, 576, 576, 575, - 576, 575, 576, 575, 576, 576, 576, 576, 576, 576, 575, 576, 576, 576, - 576, 576, 576, 575, 575, 81, 81, 577, 577, 578, 578, 579, 579, 576, 565, - 580, 581, 580, 581, 580, 581, 580, 581, 580, 581, 581, 581, 581, 581, - 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 580, 581, - 581, 581, 581, 581, 581, 581, 580, 581, 580, 581, 580, 581, 581, 581, - 581, 581, 581, 580, 581, 581, 581, 581, 581, 581, 580, 580, 581, 581, - 581, 581, 582, 583, 584, 584, 581, 81, 81, 81, 81, 81, 585, 585, 585, - 585, 585, 585, 585, 585, 585, 585, 585, 81, 586, 586, 586, 586, 586, 586, - 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, - 586, 586, 81, 587, 587, 588, 588, 588, 588, 587, 587, 587, 587, 587, 587, - 587, 587, 587, 587, 585, 585, 585, 81, 81, 81, 81, 81, 580, 580, 580, - 580, 580, 580, 580, 580, 589, 589, 589, 589, 589, 589, 589, 589, 589, - 589, 589, 589, 589, 590, 590, 81, 588, 588, 588, 588, 588, 588, 588, 588, - 588, 588, 587, 587, 587, 587, 587, 587, 591, 591, 591, 591, 591, 591, - 591, 591, 527, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, - 592, 592, 592, 592, 589, 589, 589, 589, 590, 590, 590, 587, 587, 592, - 592, 592, 592, 592, 592, 592, 587, 587, 587, 587, 527, 527, 527, 527, - 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, - 593, 81, 587, 587, 587, 587, 587, 587, 587, 527, 527, 527, 527, 587, 587, - 587, 587, 587, 587, 587, 587, 587, 587, 587, 527, 527, 594, 594, 594, - 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 595, 595, 595, - 595, 595, 595, 595, 595, 595, 595, 596, 596, 596, 596, 596, 596, 596, - 596, 596, 596, 596, 596, 596, 597, 596, 596, 596, 596, 596, 596, 596, 81, - 81, 81, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 81, 599, 599, 599, 599, 599, 599, 599, 599, 600, 600, 600, 600, - 600, 600, 601, 601, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 602, 603, 604, 605, 604, 606, 606, 606, 606, 606, 606, 606, 606, - 606, 606, 602, 602, 81, 81, 81, 81, 90, 93, 90, 93, 90, 93, 607, 95, 97, - 97, 97, 608, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 608, 609, 90, 93, - 90, 93, 456, 456, 95, 95, 610, 610, 610, 610, 610, 610, 610, 610, 610, - 610, 610, 610, 610, 610, 611, 611, 611, 611, 611, 611, 611, 611, 611, - 611, 612, 612, 613, 614, 614, 614, 614, 614, 62, 62, 62, 62, 62, 62, 62, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 62, 62, 52, 56, 52, 56, 52, 56, 56, - 56, 52, 56, 52, 56, 52, 56, 59, 56, 56, 56, 56, 56, 56, 56, 56, 52, 56, - 52, 56, 52, 52, 56, 60, 615, 615, 52, 56, 52, 56, 57, 52, 56, 52, 56, 56, - 56, 52, 56, 52, 56, 52, 52, 52, 52, 52, 56, 52, 52, 52, 52, 52, 56, 52, - 56, 81, 81, 52, 56, 52, 52, 52, 81, 81, 81, 81, 81, 81, 81, 81, 57, 59, - 59, 56, 57, 57, 57, 57, 57, 616, 616, 617, 616, 616, 616, 618, 616, 616, - 616, 616, 617, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, - 616, 616, 616, 616, 619, 619, 617, 617, 619, 620, 620, 620, 620, 81, 81, - 81, 81, 621, 621, 621, 621, 621, 621, 318, 318, 509, 518, 81, 81, 81, 81, - 81, 81, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 623, - 623, 624, 624, 625, 625, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 625, 625, 625, 625, 625, - 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 627, 628, 81, 81, - 81, 81, 81, 81, 81, 81, 629, 629, 630, 630, 630, 630, 630, 630, 630, 630, - 630, 630, 81, 81, 81, 81, 81, 81, 631, 631, 631, 631, 631, 631, 631, 631, - 631, 631, 195, 195, 195, 195, 195, 195, 200, 200, 200, 195, 632, 195, - 195, 193, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 634, 634, - 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, - 634, 634, 634, 634, 635, 635, 635, 635, 635, 636, 636, 636, 198, 637, - 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, - 638, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 640, 641, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 642, 333, 333, 333, 333, 333, 81, - 81, 81, 643, 643, 643, 644, 645, 645, 645, 645, 645, 645, 645, 645, 645, - 645, 645, 645, 645, 645, 645, 646, 644, 644, 643, 643, 643, 643, 644, - 644, 643, 643, 644, 644, 647, 648, 648, 648, 648, 648, 648, 649, 649, - 649, 648, 648, 648, 648, 81, 61, 650, 650, 650, 650, 650, 650, 650, 650, - 650, 650, 81, 81, 81, 81, 648, 648, 319, 319, 319, 319, 319, 321, 651, - 319, 324, 324, 319, 319, 319, 319, 319, 81, 652, 652, 652, 652, 652, 652, - 652, 652, 652, 653, 653, 653, 653, 653, 653, 654, 654, 653, 653, 654, - 654, 653, 653, 81, 652, 652, 652, 653, 652, 652, 652, 652, 652, 652, 652, - 652, 653, 654, 81, 81, 655, 655, 655, 655, 655, 655, 655, 655, 655, 655, - 81, 81, 656, 657, 657, 657, 651, 319, 319, 319, 319, 319, 319, 328, 328, - 328, 319, 320, 321, 320, 319, 319, 658, 658, 658, 658, 658, 658, 658, - 658, 659, 658, 659, 659, 660, 658, 658, 659, 659, 658, 658, 658, 658, - 658, 659, 659, 658, 659, 658, 81, 81, 81, 81, 81, 81, 81, 81, 658, 658, - 661, 662, 662, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, - 664, 665, 665, 664, 664, 666, 666, 663, 667, 667, 664, 668, 81, 81, 336, - 336, 336, 336, 336, 336, 81, 56, 56, 56, 615, 59, 59, 59, 59, 56, 56, 56, - 56, 56, 79, 56, 56, 343, 343, 343, 343, 343, 343, 343, 343, 663, 663, - 663, 664, 664, 665, 664, 664, 665, 664, 664, 666, 664, 668, 81, 81, 669, - 669, 669, 669, 669, 669, 669, 669, 669, 669, 81, 81, 81, 81, 81, 81, 670, - 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, - 671, 671, 671, 671, 671, 670, 671, 671, 671, 671, 671, 671, 671, 81, 81, - 81, 81, 334, 334, 334, 334, 334, 334, 334, 81, 81, 81, 81, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 81, 81, 81, 81, 672, 672, 672, 672, 672, - 672, 672, 672, 673, 673, 673, 673, 673, 673, 673, 673, 594, 594, 595, - 595, 595, 595, 595, 595, 56, 56, 56, 56, 56, 56, 56, 81, 81, 81, 81, 101, - 101, 101, 101, 101, 81, 81, 81, 81, 81, 129, 674, 129, 129, 675, 129, - 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 81, 129, 129, - 129, 129, 129, 81, 129, 81, 129, 129, 81, 129, 129, 81, 129, 129, 146, - 146, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, - 676, 676, 676, 81, 81, 81, 81, 81, 81, 81, 81, 81, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 497, 479, 81, 81, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 135, 138, 81, 81, 677, 677, 677, 677, 677, - 677, 677, 677, 678, 560, 560, 678, 678, 679, 679, 528, 529, 680, 81, 81, - 81, 81, 81, 81, 96, 96, 96, 96, 96, 96, 96, 156, 156, 156, 156, 156, 156, - 156, 95, 95, 561, 571, 571, 681, 681, 528, 529, 528, 529, 528, 529, 528, - 529, 528, 529, 528, 529, 528, 529, 528, 529, 561, 561, 528, 529, 561, - 561, 561, 561, 681, 681, 681, 682, 561, 682, 81, 582, 683, 679, 679, 571, - 528, 529, 528, 529, 528, 529, 684, 561, 561, 685, 686, 687, 687, 687, 81, - 561, 688, 689, 561, 81, 81, 81, 81, 146, 146, 146, 146, 146, 81, 81, 499, - 81, 690, 691, 692, 693, 694, 691, 691, 695, 696, 691, 697, 698, 699, 698, - 700, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 702, 703, 704, - 704, 704, 690, 691, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, - 705, 705, 705, 705, 705, 705, 705, 705, 695, 691, 696, 706, 707, 706, - 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, - 708, 708, 708, 708, 695, 704, 696, 704, 695, 696, 709, 710, 711, 709, - 712, 713, 714, 714, 714, 714, 714, 714, 714, 714, 714, 715, 713, 713, - 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, - 713, 713, 713, 713, 713, 716, 716, 717, 717, 717, 717, 717, 717, 717, - 717, 717, 717, 717, 717, 717, 717, 717, 81, 81, 81, 717, 717, 717, 717, - 717, 717, 81, 81, 717, 717, 717, 81, 81, 81, 718, 693, 704, 706, 719, - 693, 693, 81, 720, 721, 721, 721, 721, 720, 720, 81, 81, 722, 722, 722, - 723, 514, 81, 81, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, - 724, 81, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 81, 724, 724, - 724, 81, 724, 724, 81, 724, 724, 724, 724, 724, 724, 724, 81, 81, 724, - 724, 724, 81, 81, 81, 81, 81, 198, 379, 198, 81, 81, 81, 81, 621, 621, - 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 81, 81, 81, 318, - 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 726, - 726, 726, 726, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, - 727, 727, 727, 727, 727, 727, 726, 726, 727, 728, 728, 81, 40, 40, 40, - 40, 81, 81, 81, 81, 727, 81, 81, 81, 81, 81, 81, 81, 318, 318, 318, 318, - 318, 156, 81, 81, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, - 729, 729, 81, 81, 81, 730, 730, 730, 730, 730, 730, 730, 730, 730, 81, - 81, 81, 81, 81, 81, 81, 156, 506, 506, 506, 506, 506, 506, 506, 506, 506, - 506, 506, 506, 506, 506, 506, 506, 506, 506, 506, 81, 81, 81, 81, 731, - 731, 731, 731, 731, 731, 731, 731, 732, 732, 732, 732, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 731, 731, 731, 733, 733, 733, 733, 733, 733, 733, - 733, 733, 734, 733, 733, 733, 733, 733, 733, 733, 733, 734, 81, 81, 81, - 81, 81, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, - 735, 736, 736, 736, 736, 736, 81, 81, 81, 81, 81, 737, 737, 737, 737, - 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 81, 738, 739, 739, 739, - 739, 739, 739, 739, 739, 739, 739, 739, 739, 81, 81, 81, 81, 740, 741, - 741, 741, 741, 741, 81, 81, 742, 742, 742, 742, 742, 742, 742, 742, 743, - 743, 743, 743, 743, 743, 743, 743, 744, 744, 744, 744, 744, 744, 744, - 744, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, - 745, 81, 81, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 81, 81, - 81, 81, 81, 81, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, - 747, 81, 81, 81, 81, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, - 748, 748, 81, 81, 81, 81, 749, 749, 749, 749, 749, 749, 749, 749, 750, - 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 751, 752, 752, 752, 752, 752, 752, 752, 752, - 752, 752, 752, 752, 752, 752, 752, 81, 752, 752, 752, 752, 752, 752, 81, - 81, 753, 753, 753, 753, 753, 753, 81, 81, 753, 81, 753, 753, 753, 753, - 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, - 753, 753, 81, 753, 753, 81, 81, 81, 753, 81, 81, 753, 754, 754, 754, 754, - 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 81, 755, 756, 756, 756, - 756, 756, 756, 756, 756, 757, 757, 757, 757, 757, 757, 757, 757, 757, - 757, 757, 757, 757, 757, 757, 758, 758, 759, 759, 759, 759, 759, 759, - 759, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 81, 81, 81, 81, 81, 81, 81, 81, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 81, - 762, 762, 81, 81, 81, 81, 81, 763, 763, 763, 763, 763, 764, 764, 764, - 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 765, 765, 765, - 765, 765, 765, 81, 81, 81, 766, 767, 767, 767, 767, 767, 767, 767, 767, - 767, 767, 81, 81, 81, 81, 81, 768, 769, 769, 769, 769, 769, 769, 769, - 769, 770, 770, 770, 770, 770, 770, 770, 770, 81, 81, 81, 81, 771, 771, - 770, 770, 771, 771, 771, 771, 771, 771, 771, 771, 81, 81, 771, 771, 771, - 771, 771, 771, 772, 773, 773, 773, 81, 773, 773, 81, 81, 81, 81, 81, 773, - 774, 773, 775, 772, 772, 772, 772, 81, 772, 772, 772, 81, 772, 772, 772, - 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, - 772, 772, 772, 772, 81, 81, 775, 776, 774, 81, 81, 81, 81, 777, 778, 778, - 778, 778, 778, 778, 778, 778, 778, 81, 81, 81, 81, 81, 81, 81, 779, 779, - 779, 779, 779, 779, 779, 779, 780, 81, 81, 81, 81, 81, 81, 81, 781, 781, - 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 782, 782, 783, - 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 785, - 785, 785, 786, 786, 786, 786, 786, 786, 786, 786, 787, 786, 786, 786, - 786, 786, 786, 786, 786, 786, 786, 786, 786, 788, 789, 81, 81, 81, 81, - 790, 790, 790, 790, 790, 791, 791, 791, 791, 791, 791, 792, 81, 793, 793, - 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 81, 81, 81, - 794, 794, 794, 794, 794, 794, 794, 795, 795, 795, 795, 795, 795, 795, - 795, 795, 795, 795, 795, 795, 795, 81, 81, 796, 796, 796, 796, 796, 796, - 796, 796, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 81, 81, - 81, 81, 81, 798, 798, 798, 798, 798, 798, 798, 798, 799, 799, 799, 799, - 799, 799, 799, 799, 799, 799, 81, 81, 81, 81, 81, 81, 81, 800, 800, 800, - 800, 81, 81, 81, 81, 801, 801, 801, 801, 801, 801, 801, 802, 802, 802, - 802, 802, 802, 802, 802, 802, 81, 81, 81, 81, 81, 81, 81, 803, 803, 803, - 803, 803, 803, 803, 803, 803, 803, 803, 81, 81, 81, 81, 81, 804, 804, - 804, 804, 804, 804, 804, 804, 804, 804, 804, 81, 81, 81, 81, 81, 81, 81, - 805, 805, 805, 805, 805, 805, 806, 806, 806, 806, 806, 806, 806, 806, - 806, 806, 806, 806, 807, 807, 807, 807, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 81, 81, 81, 81, 81, 81, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 81, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 811, 811, 811, 811, 811, 811, - 811, 811, 811, 811, 810, 812, 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 813, 813, 814, 814, 814, 813, 814, 813, 813, - 813, 813, 815, 815, 815, 815, 816, 816, 816, 816, 816, 81, 81, 81, 81, - 81, 81, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, - 817, 817, 81, 818, 819, 818, 820, 820, 820, 820, 820, 820, 820, 820, 820, - 820, 820, 820, 820, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, - 819, 819, 819, 819, 821, 822, 822, 823, 823, 823, 823, 823, 81, 81, 81, - 81, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, - 824, 824, 824, 824, 824, 824, 825, 825, 825, 825, 825, 825, 825, 825, - 825, 825, 81, 81, 81, 81, 81, 81, 81, 821, 826, 826, 827, 828, 828, 828, - 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 827, 827, 827, 826, - 826, 826, 826, 827, 827, 829, 830, 831, 831, 832, 833, 833, 833, 833, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 832, 81, 81, 834, 834, 834, 834, - 834, 834, 834, 834, 834, 81, 81, 81, 81, 81, 81, 81, 835, 835, 835, 835, - 835, 835, 835, 835, 835, 835, 81, 81, 81, 81, 81, 81, 836, 836, 836, 837, - 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, - 837, 837, 837, 837, 837, 838, 838, 838, 838, 838, 839, 838, 838, 838, - 838, 838, 838, 840, 840, 81, 841, 841, 841, 841, 841, 841, 841, 841, 841, - 841, 842, 842, 842, 842, 837, 839, 839, 81, 843, 843, 843, 843, 843, 843, - 843, 843, 843, 843, 843, 844, 845, 846, 843, 81, 847, 847, 848, 849, 849, - 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, - 848, 848, 848, 847, 847, 847, 847, 847, 847, 847, 847, 847, 848, 850, - 849, 849, 849, 849, 851, 851, 852, 851, 847, 853, 847, 847, 852, 81, 81, - 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 849, 855, 849, 851, - 851, 851, 81, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - 856, 856, 856, 856, 856, 856, 856, 856, 81, 81, 81, 857, 857, 857, 857, - 857, 857, 857, 857, 857, 857, 81, 857, 857, 857, 857, 857, 857, 857, 857, - 857, 858, 858, 858, 859, 859, 859, 858, 858, 859, 860, 861, 859, 862, - 862, 863, 862, 862, 863, 859, 81, 864, 864, 864, 864, 864, 864, 864, 81, - 864, 81, 864, 864, 864, 864, 81, 864, 864, 864, 864, 864, 864, 864, 864, - 864, 864, 864, 864, 864, 864, 864, 81, 864, 864, 865, 81, 81, 81, 81, 81, - 81, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, - 866, 867, 868, 868, 868, 867, 867, 867, 867, 867, 867, 869, 870, 81, 81, - 81, 81, 81, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 81, 81, 81, - 81, 81, 81, 872, 872, 873, 873, 81, 874, 874, 874, 874, 874, 874, 874, - 874, 81, 81, 874, 874, 81, 81, 874, 874, 874, 874, 874, 874, 874, 874, - 874, 874, 874, 874, 874, 874, 81, 874, 874, 874, 874, 874, 874, 874, 81, - 874, 874, 81, 874, 874, 874, 874, 874, 81, 875, 876, 874, 873, 873, 872, - 873, 873, 873, 873, 81, 81, 873, 873, 81, 81, 873, 873, 877, 81, 81, 874, - 81, 81, 81, 81, 81, 81, 873, 81, 81, 81, 81, 81, 874, 874, 874, 874, 874, - 873, 873, 81, 81, 878, 878, 878, 878, 878, 878, 878, 81, 81, 81, 879, - 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 880, 880, - 880, 881, 881, 881, 881, 881, 881, 881, 881, 880, 880, 882, 881, 881, - 880, 883, 879, 879, 879, 879, 884, 884, 884, 884, 885, 886, 886, 886, - 886, 886, 886, 886, 886, 886, 886, 81, 884, 81, 885, 887, 879, 888, 888, - 888, 888, 888, 888, 888, 888, 889, 889, 889, 890, 890, 890, 890, 890, - 890, 889, 890, 889, 889, 889, 889, 890, 890, 889, 891, 892, 888, 888, - 893, 888, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 81, 81, 81, - 81, 81, 81, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, - 895, 895, 895, 896, 896, 896, 897, 897, 897, 897, 81, 81, 896, 896, 896, - 896, 897, 897, 896, 898, 899, 900, 901, 901, 902, 902, 903, 903, 903, - 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, - 901, 895, 895, 895, 895, 897, 897, 81, 81, 904, 904, 904, 904, 904, 904, - 904, 904, 905, 905, 905, 906, 906, 906, 906, 906, 906, 906, 906, 905, - 905, 906, 905, 907, 906, 908, 908, 909, 904, 81, 81, 81, 910, 910, 910, - 910, 910, 910, 910, 910, 910, 910, 81, 81, 81, 81, 81, 81, 911, 911, 911, - 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 81, 81, 81, 912, 912, - 912, 912, 912, 912, 912, 912, 912, 912, 912, 913, 914, 913, 914, 914, - 913, 913, 913, 913, 913, 913, 915, 916, 912, 81, 81, 81, 81, 81, 81, 81, - 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 81, 81, 81, 81, 81, 81, - 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 81, 81, 919, 919, - 919, 920, 920, 919, 919, 919, 919, 920, 919, 919, 919, 919, 921, 81, 81, - 81, 81, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 923, 923, 924, - 924, 924, 925, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, - 926, 927, 927, 927, 928, 928, 928, 928, 928, 928, 928, 928, 928, 927, - 929, 930, 931, 81, 81, 81, 81, 932, 932, 932, 932, 932, 932, 932, 932, - 933, 933, 933, 933, 933, 933, 933, 933, 934, 934, 934, 934, 934, 934, - 934, 934, 934, 934, 935, 935, 935, 935, 935, 935, 935, 935, 935, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 936, 937, 937, 937, 937, 937, - 937, 937, 937, 81, 81, 937, 937, 937, 937, 937, 937, 937, 938, 938, 938, - 939, 939, 939, 939, 81, 81, 939, 939, 938, 938, 938, 938, 940, 937, 941, - 937, 938, 81, 81, 81, 942, 943, 943, 943, 943, 943, 943, 944, 944, 943, - 943, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, - 942, 942, 942, 943, 945, 943, 943, 943, 943, 946, 942, 943, 943, 943, - 943, 947, 948, 949, 949, 949, 949, 947, 948, 945, 950, 951, 951, 951, - 951, 951, 951, 952, 952, 951, 951, 951, 950, 950, 950, 950, 950, 950, - 950, 950, 950, 950, 950, 950, 950, 950, 951, 951, 951, 951, 951, 951, - 951, 951, 951, 951, 951, 951, 951, 952, 951, 953, 954, 954, 954, 950, - 955, 955, 955, 954, 954, 81, 81, 81, 81, 81, 956, 956, 956, 956, 956, - 956, 956, 956, 956, 81, 81, 81, 81, 81, 81, 81, 957, 957, 957, 957, 957, - 957, 957, 957, 957, 81, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, - 957, 957, 957, 958, 959, 959, 959, 959, 959, 959, 959, 81, 959, 959, 959, - 959, 959, 959, 958, 960, 957, 961, 961, 961, 961, 961, 81, 81, 962, 962, - 962, 962, 962, 962, 962, 962, 962, 962, 963, 963, 963, 963, 963, 963, - 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 81, 81, - 81, 964, 965, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, - 966, 966, 81, 81, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, - 967, 967, 967, 81, 968, 967, 967, 967, 967, 967, 967, 967, 968, 967, 967, - 968, 967, 967, 81, 969, 969, 969, 969, 969, 969, 969, 81, 969, 969, 81, - 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, - 970, 970, 970, 970, 970, 970, 81, 81, 81, 970, 81, 970, 970, 81, 970, - 970, 970, 971, 970, 972, 972, 969, 970, 973, 973, 973, 973, 973, 973, - 973, 973, 973, 973, 81, 81, 81, 81, 81, 81, 974, 974, 974, 974, 974, 974, - 81, 974, 974, 81, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, - 974, 974, 974, 974, 974, 975, 975, 975, 975, 975, 81, 976, 976, 81, 975, - 975, 976, 975, 977, 974, 81, 81, 81, 81, 81, 81, 81, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 81, 81, 81, 81, 81, 81, 979, 979, 979, 979, - 979, 979, 979, 979, 979, 979, 979, 980, 980, 981, 981, 982, 982, 81, 81, - 81, 81, 81, 81, 81, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, - 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 983, 983, 983, - 983, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, - 244, 244, 244, 244, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 984, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 81, 81, 81, 81, - 81, 81, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, - 986, 986, 81, 987, 987, 987, 987, 987, 81, 81, 81, 985, 985, 985, 985, - 81, 81, 81, 81, 988, 988, 988, 988, 988, 988, 988, 988, 989, 989, 989, - 990, 990, 990, 988, 988, 988, 988, 990, 988, 988, 988, 989, 990, 989, - 990, 988, 988, 988, 988, 988, 988, 988, 989, 990, 990, 988, 988, 988, - 988, 988, 988, 988, 988, 988, 988, 988, 81, 991, 991, 991, 991, 991, 991, - 991, 992, 993, 81, 81, 81, 81, 81, 81, 81, 994, 994, 994, 994, 994, 994, - 994, 994, 994, 994, 994, 994, 994, 994, 995, 996, 994, 994, 994, 994, - 994, 994, 994, 81, 610, 81, 81, 81, 81, 81, 81, 81, 997, 997, 997, 997, - 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 81, 998, 998, 998, - 998, 998, 998, 998, 998, 998, 998, 81, 81, 81, 81, 999, 999, 1000, 1000, - 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, - 81, 81, 1001, 1001, 1001, 1001, 1001, 1002, 81, 81, 1003, 1003, 1003, - 1003, 1003, 1003, 1003, 1003, 1004, 1004, 1004, 1004, 1004, 1004, 1004, - 1005, 1005, 1005, 1006, 1006, 1007, 1007, 1007, 1007, 1008, 1008, 1008, - 1008, 1005, 1007, 81, 81, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, - 1009, 1009, 81, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 81, 1003, 1003, - 1003, 1003, 1003, 81, 81, 81, 81, 81, 1003, 1003, 1003, 1011, 1011, 1011, - 1011, 1011, 1011, 1011, 1011, 1012, 1012, 1012, 1012, 1012, 1012, 1012, - 1012, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, - 1013, 1013, 1013, 1013, 1014, 1014, 1015, 1015, 81, 81, 81, 81, 81, 1016, - 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 81, 81, 81, - 81, 1017, 1016, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, - 1018, 1018, 1018, 1018, 1018, 1018, 81, 81, 81, 81, 81, 81, 81, 1017, - 1017, 1017, 1017, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, - 1019, 1019, 1019, 1019, 1020, 1021, 582, 1022, 81, 81, 81, 81, 1023, - 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 81, 81, 81, - 81, 81, 581, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, - 576, 576, 81, 575, 575, 575, 81, 81, 81, 81, 81, 81, 81, 81, 81, 580, - 580, 580, 580, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, - 1024, 1024, 1024, 81, 81, 81, 81, 1025, 1025, 1025, 1025, 1025, 1025, - 1025, 1025, 1025, 1025, 1025, 81, 81, 81, 81, 81, 1025, 1025, 1025, 1025, - 1025, 81, 81, 81, 1025, 81, 81, 81, 81, 81, 81, 81, 1025, 1025, 81, 81, - 1026, 1027, 1028, 1029, 505, 505, 505, 505, 81, 81, 81, 81, 318, 318, - 318, 318, 318, 318, 81, 81, 318, 318, 318, 318, 318, 318, 318, 81, 81, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 1030, 1030, - 453, 453, 453, 318, 318, 318, 1031, 1030, 1030, 1030, 1030, 1030, 505, - 505, 505, 505, 505, 505, 505, 505, 156, 156, 156, 156, 156, 156, 156, - 156, 318, 318, 96, 96, 96, 96, 96, 156, 156, 318, 318, 318, 318, 318, - 318, 96, 96, 96, 96, 318, 318, 318, 81, 81, 81, 81, 81, 81, 81, 727, 727, - 1032, 1032, 1032, 727, 81, 81, 621, 621, 621, 621, 81, 81, 81, 81, 621, - 81, 81, 81, 81, 81, 81, 81, 512, 512, 512, 512, 512, 512, 512, 512, 512, - 512, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 49, 49, 49, 49, 49, - 49, 49, 81, 49, 49, 49, 49, 49, 49, 512, 81, 512, 512, 81, 81, 512, 81, - 81, 512, 512, 81, 81, 512, 512, 512, 512, 81, 512, 512, 49, 49, 81, 49, - 81, 49, 49, 49, 49, 49, 49, 49, 81, 49, 49, 49, 49, 49, 49, 49, 512, 512, - 81, 512, 512, 512, 512, 81, 81, 512, 512, 512, 512, 512, 512, 512, 512, - 81, 512, 512, 512, 512, 512, 512, 512, 81, 49, 49, 512, 512, 81, 512, - 512, 512, 512, 81, 512, 512, 512, 512, 512, 81, 512, 81, 81, 81, 512, - 512, 512, 512, 512, 512, 512, 81, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 81, 81, 512, 1033, 49, 49, 49, 49, 49, 49, 49, 49, 49, 498, 49, - 49, 49, 49, 49, 49, 512, 512, 512, 512, 512, 512, 512, 512, 512, 1033, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 498, 49, 49, 512, 512, 512, 512, 512, - 1033, 49, 49, 49, 49, 49, 49, 49, 49, 49, 498, 49, 49, 49, 49, 49, 49, - 512, 512, 512, 512, 512, 512, 512, 512, 512, 1033, 49, 498, 49, 49, 49, - 49, 49, 49, 49, 49, 512, 49, 81, 81, 1034, 1034, 1034, 1034, 1034, 1034, - 1034, 1034, 1034, 1034, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, - 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, - 1036, 1036, 1036, 1035, 1035, 1035, 1035, 1036, 1036, 1036, 1036, 1036, - 1036, 1036, 1036, 1036, 1036, 1035, 1035, 1035, 1035, 1035, 1035, 1035, - 1035, 1036, 1035, 1035, 1035, 1035, 1035, 1035, 1036, 1035, 1035, 1037, - 1037, 1037, 1037, 1038, 81, 81, 81, 81, 81, 81, 81, 1036, 1036, 1036, - 1036, 1036, 81, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1039, 1039, - 1039, 1039, 1039, 1039, 1039, 81, 1039, 1039, 1039, 1039, 1039, 1039, - 1039, 1039, 1039, 81, 81, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 81, - 1039, 1039, 81, 1039, 1039, 1039, 1039, 1039, 81, 81, 81, 81, 81, 1040, - 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, - 81, 81, 81, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1042, 1042, 1042, - 1042, 1042, 1042, 1042, 81, 81, 1043, 1043, 1043, 1043, 1043, 1043, 1043, - 1043, 1043, 1043, 81, 81, 81, 81, 1040, 1044, 1045, 1045, 1045, 1045, - 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1046, 1046, 1046, 1046, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 81, 81, 81, - 81, 81, 1048, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, - 1049, 1049, 1049, 81, 81, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 81, 1052, 1052, 1052, - 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1053, 1053, 1053, 1053, 1053, - 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, - 1053, 1054, 1054, 1054, 1054, 1054, 1054, 1055, 1056, 81, 81, 81, 81, - 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 81, 81, 81, - 81, 1058, 1058, 81, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, - 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1060, 1059, - 1059, 1059, 1061, 1059, 1059, 1059, 1059, 81, 81, 81, 1059, 1059, 1059, - 1059, 1059, 1059, 1062, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 81, 81, - 146, 146, 146, 146, 81, 146, 146, 146, 81, 146, 146, 81, 146, 81, 81, - 146, 81, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 81, 146, 146, - 146, 146, 81, 146, 81, 146, 81, 81, 81, 81, 81, 81, 146, 81, 81, 81, 81, - 146, 81, 146, 81, 146, 81, 146, 146, 146, 81, 146, 81, 146, 81, 146, 81, - 146, 81, 146, 146, 146, 146, 81, 146, 81, 146, 146, 81, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 81, 81, 81, 81, 81, 146, 146, 146, 81, 146, - 146, 146, 132, 132, 81, 81, 81, 81, 81, 81, 531, 531, 531, 531, 527, 531, - 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, - 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - 531, 531, 531, 531, 531, 531, 531, 1063, 1063, 531, 531, 531, 531, 531, - 531, 531, 531, 531, 531, 531, 531, 531, 531, 527, 531, 531, 531, 531, - 531, 531, 1063, 1063, 47, 47, 47, 521, 521, 1063, 1063, 1063, 532, 532, - 532, 532, 532, 532, 318, 40, 532, 532, 40, 40, 40, 1063, 1063, 1063, 532, - 532, 532, 532, 532, 532, 1064, 532, 532, 1064, 1064, 1064, 1064, 1064, - 1064, 1064, 1064, 1064, 1064, 532, 532, 532, 532, 532, 532, 532, 532, - 532, 532, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1065, - 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1066, 587, 587, - 1063, 1063, 1063, 1063, 1063, 587, 587, 587, 587, 1063, 1063, 1063, 1063, - 587, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 587, 587, 1063, 1063, - 1063, 1063, 1063, 1063, 527, 527, 527, 527, 527, 527, 1063, 1063, 527, - 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 527, 527, - 527, 527, 527, 527, 527, 527, 527, 531, 527, 527, 527, 527, 527, 527, - 531, 527, 527, 527, 527, 527, 527, 527, 538, 527, 527, 527, 527, 527, - 527, 531, 531, 531, 531, 531, 531, 531, 531, 40, 40, 531, 531, 527, 527, - 527, 527, 527, 530, 530, 527, 527, 527, 527, 527, 530, 527, 527, 527, - 527, 527, 538, 538, 538, 527, 527, 538, 527, 527, 538, 536, 536, 531, - 531, 527, 527, 531, 531, 531, 527, 531, 531, 531, 527, 527, 527, 1067, - 1067, 1067, 1067, 1067, 527, 527, 527, 527, 527, 527, 527, 531, 527, 531, - 538, 538, 527, 527, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, - 538, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, - 538, 538, 538, 527, 527, 527, 538, 527, 527, 527, 527, 538, 538, 538, - 527, 538, 538, 538, 527, 527, 527, 527, 527, 527, 527, 538, 527, 538, - 527, 527, 527, 527, 527, 527, 530, 527, 530, 527, 530, 527, 527, 527, - 527, 527, 538, 527, 527, 527, 527, 530, 527, 530, 530, 527, 527, 527, - 527, 527, 527, 527, 527, 527, 527, 531, 531, 527, 530, 530, 530, 530, - 530, 530, 530, 527, 527, 527, 527, 527, 527, 527, 527, 530, 530, 530, - 530, 530, 530, 527, 527, 527, 527, 527, 530, 530, 530, 530, 530, 530, - 530, 530, 530, 530, 530, 530, 40, 40, 40, 40, 531, 527, 527, 527, 527, - 531, 531, 531, 531, 531, 536, 536, 531, 531, 531, 531, 538, 531, 531, - 531, 531, 531, 536, 531, 531, 531, 531, 538, 538, 531, 531, 531, 531, - 531, 40, 40, 40, 40, 40, 40, 40, 40, 531, 531, 531, 531, 40, 40, 531, - 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 538, 538, 538, 527, - 527, 527, 538, 538, 538, 538, 538, 40, 40, 40, 40, 40, 40, 540, 540, 540, - 1068, 1068, 1068, 40, 40, 40, 40, 527, 527, 527, 538, 527, 527, 527, 527, - 527, 527, 527, 527, 538, 538, 538, 527, 538, 527, 527, 527, 527, 527, - 531, 531, 531, 531, 531, 531, 538, 531, 531, 531, 527, 527, 527, 531, - 531, 527, 1063, 1063, 531, 531, 531, 527, 527, 1063, 1063, 1063, 531, - 531, 531, 531, 527, 527, 527, 527, 527, 527, 527, 1063, 1063, 1063, 1063, - 1063, 40, 40, 40, 40, 1063, 1063, 1063, 1063, 40, 40, 40, 40, 40, 531, - 531, 531, 531, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 527, 527, 527, - 527, 1063, 1063, 1063, 1063, 40, 40, 1063, 1063, 1063, 1063, 1063, 1063, - 40, 40, 40, 40, 40, 40, 1063, 1063, 40, 40, 40, 40, 1063, 527, 527, 538, - 527, 527, 527, 527, 527, 527, 538, 527, 538, 538, 527, 527, 538, 538, - 538, 527, 527, 527, 1063, 527, 527, 527, 527, 1063, 1063, 1063, 527, 527, - 527, 527, 527, 527, 527, 527, 527, 1063, 1063, 527, 527, 527, 527, 527, - 527, 1063, 1063, 1063, 527, 527, 527, 527, 527, 527, 527, 538, 538, 527, - 538, 538, 527, 538, 527, 527, 527, 527, 527, 527, 527, 1063, 1063, 538, - 538, 538, 527, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, - 538, 538, 527, 527, 1063, 1063, 1063, 1063, 1063, 1063, 81, 81, 594, 594, - 594, 594, 594, 594, 594, 595, 594, 594, 594, 594, 594, 595, 595, 595, - 594, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 81, - 81, 81, 505, 81, 81, 81, 81, 81, 81, 505, 505, 505, 505, 505, 505, 505, - 505, 673, 673, 673, 673, 673, 673, 81, 81, -}; - -/* decomposition data */ -static const unsigned short decomp_data[] = { - 0, 257, 32, 514, 32, 776, 259, 97, 514, 32, 772, 259, 50, 259, 51, 514, - 32, 769, 258, 956, 514, 32, 807, 259, 49, 259, 111, 772, 49, 8260, 52, - 772, 49, 8260, 50, 772, 51, 8260, 52, 512, 65, 768, 512, 65, 769, 512, - 65, 770, 512, 65, 771, 512, 65, 776, 512, 65, 778, 512, 67, 807, 512, 69, - 768, 512, 69, 769, 512, 69, 770, 512, 69, 776, 512, 73, 768, 512, 73, - 769, 512, 73, 770, 512, 73, 776, 512, 78, 771, 512, 79, 768, 512, 79, - 769, 512, 79, 770, 512, 79, 771, 512, 79, 776, 512, 85, 768, 512, 85, - 769, 512, 85, 770, 512, 85, 776, 512, 89, 769, 512, 97, 768, 512, 97, - 769, 512, 97, 770, 512, 97, 771, 512, 97, 776, 512, 97, 778, 512, 99, - 807, 512, 101, 768, 512, 101, 769, 512, 101, 770, 512, 101, 776, 512, - 105, 768, 512, 105, 769, 512, 105, 770, 512, 105, 776, 512, 110, 771, - 512, 111, 768, 512, 111, 769, 512, 111, 770, 512, 111, 771, 512, 111, - 776, 512, 117, 768, 512, 117, 769, 512, 117, 770, 512, 117, 776, 512, - 121, 769, 512, 121, 776, 512, 65, 772, 512, 97, 772, 512, 65, 774, 512, - 97, 774, 512, 65, 808, 512, 97, 808, 512, 67, 769, 512, 99, 769, 512, 67, - 770, 512, 99, 770, 512, 67, 775, 512, 99, 775, 512, 67, 780, 512, 99, - 780, 512, 68, 780, 512, 100, 780, 512, 69, 772, 512, 101, 772, 512, 69, - 774, 512, 101, 774, 512, 69, 775, 512, 101, 775, 512, 69, 808, 512, 101, - 808, 512, 69, 780, 512, 101, 780, 512, 71, 770, 512, 103, 770, 512, 71, - 774, 512, 103, 774, 512, 71, 775, 512, 103, 775, 512, 71, 807, 512, 103, - 807, 512, 72, 770, 512, 104, 770, 512, 73, 771, 512, 105, 771, 512, 73, - 772, 512, 105, 772, 512, 73, 774, 512, 105, 774, 512, 73, 808, 512, 105, - 808, 512, 73, 775, 514, 73, 74, 514, 105, 106, 512, 74, 770, 512, 106, - 770, 512, 75, 807, 512, 107, 807, 512, 76, 769, 512, 108, 769, 512, 76, - 807, 512, 108, 807, 512, 76, 780, 512, 108, 780, 514, 76, 183, 514, 108, - 183, 512, 78, 769, 512, 110, 769, 512, 78, 807, 512, 110, 807, 512, 78, - 780, 512, 110, 780, 514, 700, 110, 512, 79, 772, 512, 111, 772, 512, 79, - 774, 512, 111, 774, 512, 79, 779, 512, 111, 779, 512, 82, 769, 512, 114, - 769, 512, 82, 807, 512, 114, 807, 512, 82, 780, 512, 114, 780, 512, 83, - 769, 512, 115, 769, 512, 83, 770, 512, 115, 770, 512, 83, 807, 512, 115, - 807, 512, 83, 780, 512, 115, 780, 512, 84, 807, 512, 116, 807, 512, 84, - 780, 512, 116, 780, 512, 85, 771, 512, 117, 771, 512, 85, 772, 512, 117, - 772, 512, 85, 774, 512, 117, 774, 512, 85, 778, 512, 117, 778, 512, 85, - 779, 512, 117, 779, 512, 85, 808, 512, 117, 808, 512, 87, 770, 512, 119, - 770, 512, 89, 770, 512, 121, 770, 512, 89, 776, 512, 90, 769, 512, 122, - 769, 512, 90, 775, 512, 122, 775, 512, 90, 780, 512, 122, 780, 258, 115, - 512, 79, 795, 512, 111, 795, 512, 85, 795, 512, 117, 795, 514, 68, 381, - 514, 68, 382, 514, 100, 382, 514, 76, 74, 514, 76, 106, 514, 108, 106, - 514, 78, 74, 514, 78, 106, 514, 110, 106, 512, 65, 780, 512, 97, 780, - 512, 73, 780, 512, 105, 780, 512, 79, 780, 512, 111, 780, 512, 85, 780, - 512, 117, 780, 512, 220, 772, 512, 252, 772, 512, 220, 769, 512, 252, - 769, 512, 220, 780, 512, 252, 780, 512, 220, 768, 512, 252, 768, 512, - 196, 772, 512, 228, 772, 512, 550, 772, 512, 551, 772, 512, 198, 772, - 512, 230, 772, 512, 71, 780, 512, 103, 780, 512, 75, 780, 512, 107, 780, - 512, 79, 808, 512, 111, 808, 512, 490, 772, 512, 491, 772, 512, 439, 780, - 512, 658, 780, 512, 106, 780, 514, 68, 90, 514, 68, 122, 514, 100, 122, - 512, 71, 769, 512, 103, 769, 512, 78, 768, 512, 110, 768, 512, 197, 769, - 512, 229, 769, 512, 198, 769, 512, 230, 769, 512, 216, 769, 512, 248, - 769, 512, 65, 783, 512, 97, 783, 512, 65, 785, 512, 97, 785, 512, 69, - 783, 512, 101, 783, 512, 69, 785, 512, 101, 785, 512, 73, 783, 512, 105, - 783, 512, 73, 785, 512, 105, 785, 512, 79, 783, 512, 111, 783, 512, 79, - 785, 512, 111, 785, 512, 82, 783, 512, 114, 783, 512, 82, 785, 512, 114, - 785, 512, 85, 783, 512, 117, 783, 512, 85, 785, 512, 117, 785, 512, 83, - 806, 512, 115, 806, 512, 84, 806, 512, 116, 806, 512, 72, 780, 512, 104, - 780, 512, 65, 775, 512, 97, 775, 512, 69, 807, 512, 101, 807, 512, 214, - 772, 512, 246, 772, 512, 213, 772, 512, 245, 772, 512, 79, 775, 512, 111, - 775, 512, 558, 772, 512, 559, 772, 512, 89, 772, 512, 121, 772, 259, 104, - 259, 614, 259, 106, 259, 114, 259, 633, 259, 635, 259, 641, 259, 119, - 259, 121, 514, 32, 774, 514, 32, 775, 514, 32, 778, 514, 32, 808, 514, - 32, 771, 514, 32, 779, 259, 611, 259, 108, 259, 115, 259, 120, 259, 661, - 256, 768, 256, 769, 256, 787, 512, 776, 769, 256, 697, 514, 32, 837, 256, - 59, 514, 32, 769, 512, 168, 769, 512, 913, 769, 256, 183, 512, 917, 769, - 512, 919, 769, 512, 921, 769, 512, 927, 769, 512, 933, 769, 512, 937, - 769, 512, 970, 769, 512, 921, 776, 512, 933, 776, 512, 945, 769, 512, - 949, 769, 512, 951, 769, 512, 953, 769, 512, 971, 769, 512, 953, 776, - 512, 965, 776, 512, 959, 769, 512, 965, 769, 512, 969, 769, 258, 946, - 258, 952, 258, 933, 512, 978, 769, 512, 978, 776, 258, 966, 258, 960, - 258, 954, 258, 961, 258, 962, 258, 920, 258, 949, 258, 931, 512, 1045, - 768, 512, 1045, 776, 512, 1043, 769, 512, 1030, 776, 512, 1050, 769, 512, - 1048, 768, 512, 1059, 774, 512, 1048, 774, 512, 1080, 774, 512, 1077, - 768, 512, 1077, 776, 512, 1075, 769, 512, 1110, 776, 512, 1082, 769, 512, - 1080, 768, 512, 1091, 774, 512, 1140, 783, 512, 1141, 783, 512, 1046, - 774, 512, 1078, 774, 512, 1040, 774, 512, 1072, 774, 512, 1040, 776, 512, - 1072, 776, 512, 1045, 774, 512, 1077, 774, 512, 1240, 776, 512, 1241, - 776, 512, 1046, 776, 512, 1078, 776, 512, 1047, 776, 512, 1079, 776, 512, - 1048, 772, 512, 1080, 772, 512, 1048, 776, 512, 1080, 776, 512, 1054, - 776, 512, 1086, 776, 512, 1256, 776, 512, 1257, 776, 512, 1069, 776, 512, - 1101, 776, 512, 1059, 772, 512, 1091, 772, 512, 1059, 776, 512, 1091, - 776, 512, 1059, 779, 512, 1091, 779, 512, 1063, 776, 512, 1095, 776, 512, - 1067, 776, 512, 1099, 776, 514, 1381, 1410, 512, 1575, 1619, 512, 1575, - 1620, 512, 1608, 1620, 512, 1575, 1621, 512, 1610, 1620, 514, 1575, 1652, - 514, 1608, 1652, 514, 1735, 1652, 514, 1610, 1652, 512, 1749, 1620, 512, - 1729, 1620, 512, 1746, 1620, 512, 2344, 2364, 512, 2352, 2364, 512, 2355, - 2364, 512, 2325, 2364, 512, 2326, 2364, 512, 2327, 2364, 512, 2332, 2364, - 512, 2337, 2364, 512, 2338, 2364, 512, 2347, 2364, 512, 2351, 2364, 512, - 2503, 2494, 512, 2503, 2519, 512, 2465, 2492, 512, 2466, 2492, 512, 2479, - 2492, 512, 2610, 2620, 512, 2616, 2620, 512, 2582, 2620, 512, 2583, 2620, - 512, 2588, 2620, 512, 2603, 2620, 512, 2887, 2902, 512, 2887, 2878, 512, - 2887, 2903, 512, 2849, 2876, 512, 2850, 2876, 512, 2962, 3031, 512, 3014, - 3006, 512, 3015, 3006, 512, 3014, 3031, 512, 3142, 3158, 512, 3263, 3285, - 512, 3270, 3285, 512, 3270, 3286, 512, 3270, 3266, 512, 3274, 3285, 512, - 3398, 3390, 512, 3399, 3390, 512, 3398, 3415, 512, 3545, 3530, 512, 3545, - 3535, 512, 3548, 3530, 512, 3545, 3551, 514, 3661, 3634, 514, 3789, 3762, - 514, 3755, 3737, 514, 3755, 3745, 257, 3851, 512, 3906, 4023, 512, 3916, - 4023, 512, 3921, 4023, 512, 3926, 4023, 512, 3931, 4023, 512, 3904, 4021, - 512, 3953, 3954, 512, 3953, 3956, 512, 4018, 3968, 514, 4018, 3969, 512, - 4019, 3968, 514, 4019, 3969, 512, 3953, 3968, 512, 3986, 4023, 512, 3996, - 4023, 512, 4001, 4023, 512, 4006, 4023, 512, 4011, 4023, 512, 3984, 4021, - 512, 4133, 4142, 259, 4316, 512, 6917, 6965, 512, 6919, 6965, 512, 6921, - 6965, 512, 6923, 6965, 512, 6925, 6965, 512, 6929, 6965, 512, 6970, 6965, - 512, 6972, 6965, 512, 6974, 6965, 512, 6975, 6965, 512, 6978, 6965, 259, - 65, 259, 198, 259, 66, 259, 68, 259, 69, 259, 398, 259, 71, 259, 72, 259, - 73, 259, 74, 259, 75, 259, 76, 259, 77, 259, 78, 259, 79, 259, 546, 259, - 80, 259, 82, 259, 84, 259, 85, 259, 87, 259, 97, 259, 592, 259, 593, 259, - 7426, 259, 98, 259, 100, 259, 101, 259, 601, 259, 603, 259, 604, 259, - 103, 259, 107, 259, 109, 259, 331, 259, 111, 259, 596, 259, 7446, 259, - 7447, 259, 112, 259, 116, 259, 117, 259, 7453, 259, 623, 259, 118, 259, - 7461, 259, 946, 259, 947, 259, 948, 259, 966, 259, 967, 261, 105, 261, - 114, 261, 117, 261, 118, 261, 946, 261, 947, 261, 961, 261, 966, 261, - 967, 259, 1085, 259, 594, 259, 99, 259, 597, 259, 240, 259, 604, 259, - 102, 259, 607, 259, 609, 259, 613, 259, 616, 259, 617, 259, 618, 259, - 7547, 259, 669, 259, 621, 259, 7557, 259, 671, 259, 625, 259, 624, 259, - 626, 259, 627, 259, 628, 259, 629, 259, 632, 259, 642, 259, 643, 259, - 427, 259, 649, 259, 650, 259, 7452, 259, 651, 259, 652, 259, 122, 259, - 656, 259, 657, 259, 658, 259, 952, 512, 65, 805, 512, 97, 805, 512, 66, - 775, 512, 98, 775, 512, 66, 803, 512, 98, 803, 512, 66, 817, 512, 98, - 817, 512, 199, 769, 512, 231, 769, 512, 68, 775, 512, 100, 775, 512, 68, - 803, 512, 100, 803, 512, 68, 817, 512, 100, 817, 512, 68, 807, 512, 100, - 807, 512, 68, 813, 512, 100, 813, 512, 274, 768, 512, 275, 768, 512, 274, - 769, 512, 275, 769, 512, 69, 813, 512, 101, 813, 512, 69, 816, 512, 101, - 816, 512, 552, 774, 512, 553, 774, 512, 70, 775, 512, 102, 775, 512, 71, - 772, 512, 103, 772, 512, 72, 775, 512, 104, 775, 512, 72, 803, 512, 104, - 803, 512, 72, 776, 512, 104, 776, 512, 72, 807, 512, 104, 807, 512, 72, - 814, 512, 104, 814, 512, 73, 816, 512, 105, 816, 512, 207, 769, 512, 239, - 769, 512, 75, 769, 512, 107, 769, 512, 75, 803, 512, 107, 803, 512, 75, - 817, 512, 107, 817, 512, 76, 803, 512, 108, 803, 512, 7734, 772, 512, - 7735, 772, 512, 76, 817, 512, 108, 817, 512, 76, 813, 512, 108, 813, 512, - 77, 769, 512, 109, 769, 512, 77, 775, 512, 109, 775, 512, 77, 803, 512, - 109, 803, 512, 78, 775, 512, 110, 775, 512, 78, 803, 512, 110, 803, 512, - 78, 817, 512, 110, 817, 512, 78, 813, 512, 110, 813, 512, 213, 769, 512, - 245, 769, 512, 213, 776, 512, 245, 776, 512, 332, 768, 512, 333, 768, - 512, 332, 769, 512, 333, 769, 512, 80, 769, 512, 112, 769, 512, 80, 775, - 512, 112, 775, 512, 82, 775, 512, 114, 775, 512, 82, 803, 512, 114, 803, - 512, 7770, 772, 512, 7771, 772, 512, 82, 817, 512, 114, 817, 512, 83, - 775, 512, 115, 775, 512, 83, 803, 512, 115, 803, 512, 346, 775, 512, 347, - 775, 512, 352, 775, 512, 353, 775, 512, 7778, 775, 512, 7779, 775, 512, - 84, 775, 512, 116, 775, 512, 84, 803, 512, 116, 803, 512, 84, 817, 512, - 116, 817, 512, 84, 813, 512, 116, 813, 512, 85, 804, 512, 117, 804, 512, - 85, 816, 512, 117, 816, 512, 85, 813, 512, 117, 813, 512, 360, 769, 512, - 361, 769, 512, 362, 776, 512, 363, 776, 512, 86, 771, 512, 118, 771, 512, - 86, 803, 512, 118, 803, 512, 87, 768, 512, 119, 768, 512, 87, 769, 512, - 119, 769, 512, 87, 776, 512, 119, 776, 512, 87, 775, 512, 119, 775, 512, - 87, 803, 512, 119, 803, 512, 88, 775, 512, 120, 775, 512, 88, 776, 512, - 120, 776, 512, 89, 775, 512, 121, 775, 512, 90, 770, 512, 122, 770, 512, - 90, 803, 512, 122, 803, 512, 90, 817, 512, 122, 817, 512, 104, 817, 512, - 116, 776, 512, 119, 778, 512, 121, 778, 514, 97, 702, 512, 383, 775, 512, - 65, 803, 512, 97, 803, 512, 65, 777, 512, 97, 777, 512, 194, 769, 512, - 226, 769, 512, 194, 768, 512, 226, 768, 512, 194, 777, 512, 226, 777, - 512, 194, 771, 512, 226, 771, 512, 7840, 770, 512, 7841, 770, 512, 258, - 769, 512, 259, 769, 512, 258, 768, 512, 259, 768, 512, 258, 777, 512, - 259, 777, 512, 258, 771, 512, 259, 771, 512, 7840, 774, 512, 7841, 774, - 512, 69, 803, 512, 101, 803, 512, 69, 777, 512, 101, 777, 512, 69, 771, - 512, 101, 771, 512, 202, 769, 512, 234, 769, 512, 202, 768, 512, 234, - 768, 512, 202, 777, 512, 234, 777, 512, 202, 771, 512, 234, 771, 512, - 7864, 770, 512, 7865, 770, 512, 73, 777, 512, 105, 777, 512, 73, 803, - 512, 105, 803, 512, 79, 803, 512, 111, 803, 512, 79, 777, 512, 111, 777, - 512, 212, 769, 512, 244, 769, 512, 212, 768, 512, 244, 768, 512, 212, - 777, 512, 244, 777, 512, 212, 771, 512, 244, 771, 512, 7884, 770, 512, - 7885, 770, 512, 416, 769, 512, 417, 769, 512, 416, 768, 512, 417, 768, - 512, 416, 777, 512, 417, 777, 512, 416, 771, 512, 417, 771, 512, 416, - 803, 512, 417, 803, 512, 85, 803, 512, 117, 803, 512, 85, 777, 512, 117, - 777, 512, 431, 769, 512, 432, 769, 512, 431, 768, 512, 432, 768, 512, - 431, 777, 512, 432, 777, 512, 431, 771, 512, 432, 771, 512, 431, 803, - 512, 432, 803, 512, 89, 768, 512, 121, 768, 512, 89, 803, 512, 121, 803, - 512, 89, 777, 512, 121, 777, 512, 89, 771, 512, 121, 771, 512, 945, 787, - 512, 945, 788, 512, 7936, 768, 512, 7937, 768, 512, 7936, 769, 512, 7937, - 769, 512, 7936, 834, 512, 7937, 834, 512, 913, 787, 512, 913, 788, 512, - 7944, 768, 512, 7945, 768, 512, 7944, 769, 512, 7945, 769, 512, 7944, - 834, 512, 7945, 834, 512, 949, 787, 512, 949, 788, 512, 7952, 768, 512, - 7953, 768, 512, 7952, 769, 512, 7953, 769, 512, 917, 787, 512, 917, 788, - 512, 7960, 768, 512, 7961, 768, 512, 7960, 769, 512, 7961, 769, 512, 951, - 787, 512, 951, 788, 512, 7968, 768, 512, 7969, 768, 512, 7968, 769, 512, - 7969, 769, 512, 7968, 834, 512, 7969, 834, 512, 919, 787, 512, 919, 788, - 512, 7976, 768, 512, 7977, 768, 512, 7976, 769, 512, 7977, 769, 512, - 7976, 834, 512, 7977, 834, 512, 953, 787, 512, 953, 788, 512, 7984, 768, - 512, 7985, 768, 512, 7984, 769, 512, 7985, 769, 512, 7984, 834, 512, - 7985, 834, 512, 921, 787, 512, 921, 788, 512, 7992, 768, 512, 7993, 768, - 512, 7992, 769, 512, 7993, 769, 512, 7992, 834, 512, 7993, 834, 512, 959, - 787, 512, 959, 788, 512, 8000, 768, 512, 8001, 768, 512, 8000, 769, 512, - 8001, 769, 512, 927, 787, 512, 927, 788, 512, 8008, 768, 512, 8009, 768, - 512, 8008, 769, 512, 8009, 769, 512, 965, 787, 512, 965, 788, 512, 8016, - 768, 512, 8017, 768, 512, 8016, 769, 512, 8017, 769, 512, 8016, 834, 512, - 8017, 834, 512, 933, 788, 512, 8025, 768, 512, 8025, 769, 512, 8025, 834, - 512, 969, 787, 512, 969, 788, 512, 8032, 768, 512, 8033, 768, 512, 8032, - 769, 512, 8033, 769, 512, 8032, 834, 512, 8033, 834, 512, 937, 787, 512, - 937, 788, 512, 8040, 768, 512, 8041, 768, 512, 8040, 769, 512, 8041, 769, - 512, 8040, 834, 512, 8041, 834, 512, 945, 768, 256, 940, 512, 949, 768, - 256, 941, 512, 951, 768, 256, 942, 512, 953, 768, 256, 943, 512, 959, - 768, 256, 972, 512, 965, 768, 256, 973, 512, 969, 768, 256, 974, 512, - 7936, 837, 512, 7937, 837, 512, 7938, 837, 512, 7939, 837, 512, 7940, - 837, 512, 7941, 837, 512, 7942, 837, 512, 7943, 837, 512, 7944, 837, 512, - 7945, 837, 512, 7946, 837, 512, 7947, 837, 512, 7948, 837, 512, 7949, - 837, 512, 7950, 837, 512, 7951, 837, 512, 7968, 837, 512, 7969, 837, 512, - 7970, 837, 512, 7971, 837, 512, 7972, 837, 512, 7973, 837, 512, 7974, - 837, 512, 7975, 837, 512, 7976, 837, 512, 7977, 837, 512, 7978, 837, 512, - 7979, 837, 512, 7980, 837, 512, 7981, 837, 512, 7982, 837, 512, 7983, - 837, 512, 8032, 837, 512, 8033, 837, 512, 8034, 837, 512, 8035, 837, 512, - 8036, 837, 512, 8037, 837, 512, 8038, 837, 512, 8039, 837, 512, 8040, - 837, 512, 8041, 837, 512, 8042, 837, 512, 8043, 837, 512, 8044, 837, 512, - 8045, 837, 512, 8046, 837, 512, 8047, 837, 512, 945, 774, 512, 945, 772, - 512, 8048, 837, 512, 945, 837, 512, 940, 837, 512, 945, 834, 512, 8118, - 837, 512, 913, 774, 512, 913, 772, 512, 913, 768, 256, 902, 512, 913, - 837, 514, 32, 787, 256, 953, 514, 32, 787, 514, 32, 834, 512, 168, 834, - 512, 8052, 837, 512, 951, 837, 512, 942, 837, 512, 951, 834, 512, 8134, - 837, 512, 917, 768, 256, 904, 512, 919, 768, 256, 905, 512, 919, 837, - 512, 8127, 768, 512, 8127, 769, 512, 8127, 834, 512, 953, 774, 512, 953, - 772, 512, 970, 768, 256, 912, 512, 953, 834, 512, 970, 834, 512, 921, - 774, 512, 921, 772, 512, 921, 768, 256, 906, 512, 8190, 768, 512, 8190, - 769, 512, 8190, 834, 512, 965, 774, 512, 965, 772, 512, 971, 768, 256, - 944, 512, 961, 787, 512, 961, 788, 512, 965, 834, 512, 971, 834, 512, - 933, 774, 512, 933, 772, 512, 933, 768, 256, 910, 512, 929, 788, 512, - 168, 768, 256, 901, 256, 96, 512, 8060, 837, 512, 969, 837, 512, 974, - 837, 512, 969, 834, 512, 8182, 837, 512, 927, 768, 256, 908, 512, 937, - 768, 256, 911, 512, 937, 837, 256, 180, 514, 32, 788, 256, 8194, 256, - 8195, 258, 32, 258, 32, 258, 32, 258, 32, 258, 32, 257, 32, 258, 32, 258, - 32, 258, 32, 257, 8208, 514, 32, 819, 258, 46, 514, 46, 46, 770, 46, 46, - 46, 257, 32, 514, 8242, 8242, 770, 8242, 8242, 8242, 514, 8245, 8245, - 770, 8245, 8245, 8245, 514, 33, 33, 514, 32, 773, 514, 63, 63, 514, 63, - 33, 514, 33, 63, 1026, 8242, 8242, 8242, 8242, 258, 32, 259, 48, 259, - 105, 259, 52, 259, 53, 259, 54, 259, 55, 259, 56, 259, 57, 259, 43, 259, - 8722, 259, 61, 259, 40, 259, 41, 259, 110, 261, 48, 261, 49, 261, 50, - 261, 51, 261, 52, 261, 53, 261, 54, 261, 55, 261, 56, 261, 57, 261, 43, - 261, 8722, 261, 61, 261, 40, 261, 41, 261, 97, 261, 101, 261, 111, 261, - 120, 261, 601, 261, 104, 261, 107, 261, 108, 261, 109, 261, 110, 261, - 112, 261, 115, 261, 116, 514, 82, 115, 770, 97, 47, 99, 770, 97, 47, 115, - 262, 67, 514, 176, 67, 770, 99, 47, 111, 770, 99, 47, 117, 258, 400, 514, - 176, 70, 262, 103, 262, 72, 262, 72, 262, 72, 262, 104, 262, 295, 262, - 73, 262, 73, 262, 76, 262, 108, 262, 78, 514, 78, 111, 262, 80, 262, 81, - 262, 82, 262, 82, 262, 82, 515, 83, 77, 770, 84, 69, 76, 515, 84, 77, - 262, 90, 256, 937, 262, 90, 256, 75, 256, 197, 262, 66, 262, 67, 262, - 101, 262, 69, 262, 70, 262, 77, 262, 111, 258, 1488, 258, 1489, 258, - 1490, 258, 1491, 262, 105, 770, 70, 65, 88, 262, 960, 262, 947, 262, 915, - 262, 928, 262, 8721, 262, 68, 262, 100, 262, 101, 262, 105, 262, 106, - 772, 49, 8260, 55, 772, 49, 8260, 57, 1028, 49, 8260, 49, 48, 772, 49, - 8260, 51, 772, 50, 8260, 51, 772, 49, 8260, 53, 772, 50, 8260, 53, 772, - 51, 8260, 53, 772, 52, 8260, 53, 772, 49, 8260, 54, 772, 53, 8260, 54, - 772, 49, 8260, 56, 772, 51, 8260, 56, 772, 53, 8260, 56, 772, 55, 8260, - 56, 516, 49, 8260, 258, 73, 514, 73, 73, 770, 73, 73, 73, 514, 73, 86, - 258, 86, 514, 86, 73, 770, 86, 73, 73, 1026, 86, 73, 73, 73, 514, 73, 88, - 258, 88, 514, 88, 73, 770, 88, 73, 73, 258, 76, 258, 67, 258, 68, 258, - 77, 258, 105, 514, 105, 105, 770, 105, 105, 105, 514, 105, 118, 258, 118, - 514, 118, 105, 770, 118, 105, 105, 1026, 118, 105, 105, 105, 514, 105, - 120, 258, 120, 514, 120, 105, 770, 120, 105, 105, 258, 108, 258, 99, 258, - 100, 258, 109, 772, 48, 8260, 51, 512, 8592, 824, 512, 8594, 824, 512, - 8596, 824, 512, 8656, 824, 512, 8660, 824, 512, 8658, 824, 512, 8707, - 824, 512, 8712, 824, 512, 8715, 824, 512, 8739, 824, 512, 8741, 824, 514, - 8747, 8747, 770, 8747, 8747, 8747, 514, 8750, 8750, 770, 8750, 8750, - 8750, 512, 8764, 824, 512, 8771, 824, 512, 8773, 824, 512, 8776, 824, - 512, 61, 824, 512, 8801, 824, 512, 8781, 824, 512, 60, 824, 512, 62, 824, - 512, 8804, 824, 512, 8805, 824, 512, 8818, 824, 512, 8819, 824, 512, - 8822, 824, 512, 8823, 824, 512, 8826, 824, 512, 8827, 824, 512, 8834, - 824, 512, 8835, 824, 512, 8838, 824, 512, 8839, 824, 512, 8866, 824, 512, - 8872, 824, 512, 8873, 824, 512, 8875, 824, 512, 8828, 824, 512, 8829, - 824, 512, 8849, 824, 512, 8850, 824, 512, 8882, 824, 512, 8883, 824, 512, - 8884, 824, 512, 8885, 824, 256, 12296, 256, 12297, 263, 49, 263, 50, 263, - 51, 263, 52, 263, 53, 263, 54, 263, 55, 263, 56, 263, 57, 519, 49, 48, - 519, 49, 49, 519, 49, 50, 519, 49, 51, 519, 49, 52, 519, 49, 53, 519, 49, - 54, 519, 49, 55, 519, 49, 56, 519, 49, 57, 519, 50, 48, 770, 40, 49, 41, - 770, 40, 50, 41, 770, 40, 51, 41, 770, 40, 52, 41, 770, 40, 53, 41, 770, - 40, 54, 41, 770, 40, 55, 41, 770, 40, 56, 41, 770, 40, 57, 41, 1026, 40, - 49, 48, 41, 1026, 40, 49, 49, 41, 1026, 40, 49, 50, 41, 1026, 40, 49, 51, - 41, 1026, 40, 49, 52, 41, 1026, 40, 49, 53, 41, 1026, 40, 49, 54, 41, - 1026, 40, 49, 55, 41, 1026, 40, 49, 56, 41, 1026, 40, 49, 57, 41, 1026, - 40, 50, 48, 41, 514, 49, 46, 514, 50, 46, 514, 51, 46, 514, 52, 46, 514, - 53, 46, 514, 54, 46, 514, 55, 46, 514, 56, 46, 514, 57, 46, 770, 49, 48, - 46, 770, 49, 49, 46, 770, 49, 50, 46, 770, 49, 51, 46, 770, 49, 52, 46, - 770, 49, 53, 46, 770, 49, 54, 46, 770, 49, 55, 46, 770, 49, 56, 46, 770, - 49, 57, 46, 770, 50, 48, 46, 770, 40, 97, 41, 770, 40, 98, 41, 770, 40, - 99, 41, 770, 40, 100, 41, 770, 40, 101, 41, 770, 40, 102, 41, 770, 40, - 103, 41, 770, 40, 104, 41, 770, 40, 105, 41, 770, 40, 106, 41, 770, 40, - 107, 41, 770, 40, 108, 41, 770, 40, 109, 41, 770, 40, 110, 41, 770, 40, - 111, 41, 770, 40, 112, 41, 770, 40, 113, 41, 770, 40, 114, 41, 770, 40, - 115, 41, 770, 40, 116, 41, 770, 40, 117, 41, 770, 40, 118, 41, 770, 40, - 119, 41, 770, 40, 120, 41, 770, 40, 121, 41, 770, 40, 122, 41, 263, 65, - 263, 66, 263, 67, 263, 68, 263, 69, 263, 70, 263, 71, 263, 72, 263, 73, - 263, 74, 263, 75, 263, 76, 263, 77, 263, 78, 263, 79, 263, 80, 263, 81, - 263, 82, 263, 83, 263, 84, 263, 85, 263, 86, 263, 87, 263, 88, 263, 89, - 263, 90, 263, 97, 263, 98, 263, 99, 263, 100, 263, 101, 263, 102, 263, - 103, 263, 104, 263, 105, 263, 106, 263, 107, 263, 108, 263, 109, 263, - 110, 263, 111, 263, 112, 263, 113, 263, 114, 263, 115, 263, 116, 263, - 117, 263, 118, 263, 119, 263, 120, 263, 121, 263, 122, 263, 48, 1026, - 8747, 8747, 8747, 8747, 770, 58, 58, 61, 514, 61, 61, 770, 61, 61, 61, - 512, 10973, 824, 261, 106, 259, 86, 259, 11617, 258, 27597, 258, 40863, - 258, 19968, 258, 20008, 258, 20022, 258, 20031, 258, 20057, 258, 20101, - 258, 20108, 258, 20128, 258, 20154, 258, 20799, 258, 20837, 258, 20843, - 258, 20866, 258, 20886, 258, 20907, 258, 20960, 258, 20981, 258, 20992, - 258, 21147, 258, 21241, 258, 21269, 258, 21274, 258, 21304, 258, 21313, - 258, 21340, 258, 21353, 258, 21378, 258, 21430, 258, 21448, 258, 21475, - 258, 22231, 258, 22303, 258, 22763, 258, 22786, 258, 22794, 258, 22805, - 258, 22823, 258, 22899, 258, 23376, 258, 23424, 258, 23544, 258, 23567, - 258, 23586, 258, 23608, 258, 23662, 258, 23665, 258, 24027, 258, 24037, - 258, 24049, 258, 24062, 258, 24178, 258, 24186, 258, 24191, 258, 24308, - 258, 24318, 258, 24331, 258, 24339, 258, 24400, 258, 24417, 258, 24435, - 258, 24515, 258, 25096, 258, 25142, 258, 25163, 258, 25903, 258, 25908, - 258, 25991, 258, 26007, 258, 26020, 258, 26041, 258, 26080, 258, 26085, - 258, 26352, 258, 26376, 258, 26408, 258, 27424, 258, 27490, 258, 27513, - 258, 27571, 258, 27595, 258, 27604, 258, 27611, 258, 27663, 258, 27668, - 258, 27700, 258, 28779, 258, 29226, 258, 29238, 258, 29243, 258, 29247, - 258, 29255, 258, 29273, 258, 29275, 258, 29356, 258, 29572, 258, 29577, - 258, 29916, 258, 29926, 258, 29976, 258, 29983, 258, 29992, 258, 30000, - 258, 30091, 258, 30098, 258, 30326, 258, 30333, 258, 30382, 258, 30399, - 258, 30446, 258, 30683, 258, 30690, 258, 30707, 258, 31034, 258, 31160, - 258, 31166, 258, 31348, 258, 31435, 258, 31481, 258, 31859, 258, 31992, - 258, 32566, 258, 32593, 258, 32650, 258, 32701, 258, 32769, 258, 32780, - 258, 32786, 258, 32819, 258, 32895, 258, 32905, 258, 33251, 258, 33258, - 258, 33267, 258, 33276, 258, 33292, 258, 33307, 258, 33311, 258, 33390, - 258, 33394, 258, 33400, 258, 34381, 258, 34411, 258, 34880, 258, 34892, - 258, 34915, 258, 35198, 258, 35211, 258, 35282, 258, 35328, 258, 35895, - 258, 35910, 258, 35925, 258, 35960, 258, 35997, 258, 36196, 258, 36208, - 258, 36275, 258, 36523, 258, 36554, 258, 36763, 258, 36784, 258, 36789, - 258, 37009, 258, 37193, 258, 37318, 258, 37324, 258, 37329, 258, 38263, - 258, 38272, 258, 38428, 258, 38582, 258, 38585, 258, 38632, 258, 38737, - 258, 38750, 258, 38754, 258, 38761, 258, 38859, 258, 38893, 258, 38899, - 258, 38913, 258, 39080, 258, 39131, 258, 39135, 258, 39318, 258, 39321, - 258, 39340, 258, 39592, 258, 39640, 258, 39647, 258, 39717, 258, 39727, - 258, 39730, 258, 39740, 258, 39770, 258, 40165, 258, 40565, 258, 40575, - 258, 40613, 258, 40635, 258, 40643, 258, 40653, 258, 40657, 258, 40697, - 258, 40701, 258, 40718, 258, 40723, 258, 40736, 258, 40763, 258, 40778, - 258, 40786, 258, 40845, 258, 40860, 258, 40864, 264, 32, 258, 12306, 258, - 21313, 258, 21316, 258, 21317, 512, 12363, 12441, 512, 12365, 12441, 512, - 12367, 12441, 512, 12369, 12441, 512, 12371, 12441, 512, 12373, 12441, - 512, 12375, 12441, 512, 12377, 12441, 512, 12379, 12441, 512, 12381, - 12441, 512, 12383, 12441, 512, 12385, 12441, 512, 12388, 12441, 512, - 12390, 12441, 512, 12392, 12441, 512, 12399, 12441, 512, 12399, 12442, - 512, 12402, 12441, 512, 12402, 12442, 512, 12405, 12441, 512, 12405, - 12442, 512, 12408, 12441, 512, 12408, 12442, 512, 12411, 12441, 512, - 12411, 12442, 512, 12358, 12441, 514, 32, 12441, 514, 32, 12442, 512, - 12445, 12441, 521, 12424, 12426, 512, 12459, 12441, 512, 12461, 12441, - 512, 12463, 12441, 512, 12465, 12441, 512, 12467, 12441, 512, 12469, - 12441, 512, 12471, 12441, 512, 12473, 12441, 512, 12475, 12441, 512, - 12477, 12441, 512, 12479, 12441, 512, 12481, 12441, 512, 12484, 12441, - 512, 12486, 12441, 512, 12488, 12441, 512, 12495, 12441, 512, 12495, - 12442, 512, 12498, 12441, 512, 12498, 12442, 512, 12501, 12441, 512, - 12501, 12442, 512, 12504, 12441, 512, 12504, 12442, 512, 12507, 12441, - 512, 12507, 12442, 512, 12454, 12441, 512, 12527, 12441, 512, 12528, - 12441, 512, 12529, 12441, 512, 12530, 12441, 512, 12541, 12441, 521, - 12467, 12488, 258, 4352, 258, 4353, 258, 4522, 258, 4354, 258, 4524, 258, - 4525, 258, 4355, 258, 4356, 258, 4357, 258, 4528, 258, 4529, 258, 4530, - 258, 4531, 258, 4532, 258, 4533, 258, 4378, 258, 4358, 258, 4359, 258, - 4360, 258, 4385, 258, 4361, 258, 4362, 258, 4363, 258, 4364, 258, 4365, - 258, 4366, 258, 4367, 258, 4368, 258, 4369, 258, 4370, 258, 4449, 258, - 4450, 258, 4451, 258, 4452, 258, 4453, 258, 4454, 258, 4455, 258, 4456, - 258, 4457, 258, 4458, 258, 4459, 258, 4460, 258, 4461, 258, 4462, 258, - 4463, 258, 4464, 258, 4465, 258, 4466, 258, 4467, 258, 4468, 258, 4469, - 258, 4448, 258, 4372, 258, 4373, 258, 4551, 258, 4552, 258, 4556, 258, - 4558, 258, 4563, 258, 4567, 258, 4569, 258, 4380, 258, 4573, 258, 4575, - 258, 4381, 258, 4382, 258, 4384, 258, 4386, 258, 4387, 258, 4391, 258, - 4393, 258, 4395, 258, 4396, 258, 4397, 258, 4398, 258, 4399, 258, 4402, - 258, 4406, 258, 4416, 258, 4423, 258, 4428, 258, 4593, 258, 4594, 258, - 4439, 258, 4440, 258, 4441, 258, 4484, 258, 4485, 258, 4488, 258, 4497, - 258, 4498, 258, 4500, 258, 4510, 258, 4513, 259, 19968, 259, 20108, 259, - 19977, 259, 22235, 259, 19978, 259, 20013, 259, 19979, 259, 30002, 259, - 20057, 259, 19993, 259, 19969, 259, 22825, 259, 22320, 259, 20154, 770, - 40, 4352, 41, 770, 40, 4354, 41, 770, 40, 4355, 41, 770, 40, 4357, 41, - 770, 40, 4358, 41, 770, 40, 4359, 41, 770, 40, 4361, 41, 770, 40, 4363, - 41, 770, 40, 4364, 41, 770, 40, 4366, 41, 770, 40, 4367, 41, 770, 40, - 4368, 41, 770, 40, 4369, 41, 770, 40, 4370, 41, 1026, 40, 4352, 4449, 41, - 1026, 40, 4354, 4449, 41, 1026, 40, 4355, 4449, 41, 1026, 40, 4357, 4449, - 41, 1026, 40, 4358, 4449, 41, 1026, 40, 4359, 4449, 41, 1026, 40, 4361, - 4449, 41, 1026, 40, 4363, 4449, 41, 1026, 40, 4364, 4449, 41, 1026, 40, - 4366, 4449, 41, 1026, 40, 4367, 4449, 41, 1026, 40, 4368, 4449, 41, 1026, - 40, 4369, 4449, 41, 1026, 40, 4370, 4449, 41, 1026, 40, 4364, 4462, 41, - 1794, 40, 4363, 4457, 4364, 4453, 4523, 41, 1538, 40, 4363, 4457, 4370, - 4462, 41, 770, 40, 19968, 41, 770, 40, 20108, 41, 770, 40, 19977, 41, - 770, 40, 22235, 41, 770, 40, 20116, 41, 770, 40, 20845, 41, 770, 40, - 19971, 41, 770, 40, 20843, 41, 770, 40, 20061, 41, 770, 40, 21313, 41, - 770, 40, 26376, 41, 770, 40, 28779, 41, 770, 40, 27700, 41, 770, 40, - 26408, 41, 770, 40, 37329, 41, 770, 40, 22303, 41, 770, 40, 26085, 41, - 770, 40, 26666, 41, 770, 40, 26377, 41, 770, 40, 31038, 41, 770, 40, - 21517, 41, 770, 40, 29305, 41, 770, 40, 36001, 41, 770, 40, 31069, 41, - 770, 40, 21172, 41, 770, 40, 20195, 41, 770, 40, 21628, 41, 770, 40, - 23398, 41, 770, 40, 30435, 41, 770, 40, 20225, 41, 770, 40, 36039, 41, - 770, 40, 21332, 41, 770, 40, 31085, 41, 770, 40, 20241, 41, 770, 40, - 33258, 41, 770, 40, 33267, 41, 263, 21839, 263, 24188, 263, 25991, 263, - 31631, 778, 80, 84, 69, 519, 50, 49, 519, 50, 50, 519, 50, 51, 519, 50, - 52, 519, 50, 53, 519, 50, 54, 519, 50, 55, 519, 50, 56, 519, 50, 57, 519, - 51, 48, 519, 51, 49, 519, 51, 50, 519, 51, 51, 519, 51, 52, 519, 51, 53, - 263, 4352, 263, 4354, 263, 4355, 263, 4357, 263, 4358, 263, 4359, 263, - 4361, 263, 4363, 263, 4364, 263, 4366, 263, 4367, 263, 4368, 263, 4369, - 263, 4370, 519, 4352, 4449, 519, 4354, 4449, 519, 4355, 4449, 519, 4357, - 4449, 519, 4358, 4449, 519, 4359, 4449, 519, 4361, 4449, 519, 4363, 4449, - 519, 4364, 4449, 519, 4366, 4449, 519, 4367, 4449, 519, 4368, 4449, 519, - 4369, 4449, 519, 4370, 4449, 1287, 4366, 4449, 4535, 4352, 4457, 1031, - 4364, 4462, 4363, 4468, 519, 4363, 4462, 263, 19968, 263, 20108, 263, - 19977, 263, 22235, 263, 20116, 263, 20845, 263, 19971, 263, 20843, 263, - 20061, 263, 21313, 263, 26376, 263, 28779, 263, 27700, 263, 26408, 263, - 37329, 263, 22303, 263, 26085, 263, 26666, 263, 26377, 263, 31038, 263, - 21517, 263, 29305, 263, 36001, 263, 31069, 263, 21172, 263, 31192, 263, - 30007, 263, 22899, 263, 36969, 263, 20778, 263, 21360, 263, 27880, 263, - 38917, 263, 20241, 263, 20889, 263, 27491, 263, 19978, 263, 20013, 263, - 19979, 263, 24038, 263, 21491, 263, 21307, 263, 23447, 263, 23398, 263, - 30435, 263, 20225, 263, 36039, 263, 21332, 263, 22812, 519, 51, 54, 519, - 51, 55, 519, 51, 56, 519, 51, 57, 519, 52, 48, 519, 52, 49, 519, 52, 50, - 519, 52, 51, 519, 52, 52, 519, 52, 53, 519, 52, 54, 519, 52, 55, 519, 52, - 56, 519, 52, 57, 519, 53, 48, 514, 49, 26376, 514, 50, 26376, 514, 51, - 26376, 514, 52, 26376, 514, 53, 26376, 514, 54, 26376, 514, 55, 26376, - 514, 56, 26376, 514, 57, 26376, 770, 49, 48, 26376, 770, 49, 49, 26376, - 770, 49, 50, 26376, 522, 72, 103, 778, 101, 114, 103, 522, 101, 86, 778, - 76, 84, 68, 263, 12450, 263, 12452, 263, 12454, 263, 12456, 263, 12458, - 263, 12459, 263, 12461, 263, 12463, 263, 12465, 263, 12467, 263, 12469, - 263, 12471, 263, 12473, 263, 12475, 263, 12477, 263, 12479, 263, 12481, - 263, 12484, 263, 12486, 263, 12488, 263, 12490, 263, 12491, 263, 12492, - 263, 12493, 263, 12494, 263, 12495, 263, 12498, 263, 12501, 263, 12504, - 263, 12507, 263, 12510, 263, 12511, 263, 12512, 263, 12513, 263, 12514, - 263, 12516, 263, 12518, 263, 12520, 263, 12521, 263, 12522, 263, 12523, - 263, 12524, 263, 12525, 263, 12527, 263, 12528, 263, 12529, 263, 12530, - 1034, 12450, 12497, 12540, 12488, 1034, 12450, 12523, 12501, 12449, 1034, - 12450, 12531, 12506, 12450, 778, 12450, 12540, 12523, 1034, 12452, 12491, - 12531, 12464, 778, 12452, 12531, 12481, 778, 12454, 12457, 12531, 1290, - 12456, 12473, 12463, 12540, 12489, 1034, 12456, 12540, 12459, 12540, 778, - 12458, 12531, 12473, 778, 12458, 12540, 12512, 778, 12459, 12452, 12522, - 1034, 12459, 12521, 12483, 12488, 1034, 12459, 12525, 12522, 12540, 778, - 12460, 12525, 12531, 778, 12460, 12531, 12510, 522, 12462, 12460, 778, - 12462, 12491, 12540, 1034, 12461, 12517, 12522, 12540, 1034, 12462, - 12523, 12480, 12540, 522, 12461, 12525, 1290, 12461, 12525, 12464, 12521, - 12512, 1546, 12461, 12525, 12513, 12540, 12488, 12523, 1290, 12461, - 12525, 12527, 12483, 12488, 778, 12464, 12521, 12512, 1290, 12464, 12521, - 12512, 12488, 12531, 1290, 12463, 12523, 12476, 12452, 12525, 1034, - 12463, 12525, 12540, 12493, 778, 12465, 12540, 12473, 778, 12467, 12523, - 12490, 778, 12467, 12540, 12509, 1034, 12469, 12452, 12463, 12523, 1290, - 12469, 12531, 12481, 12540, 12512, 1034, 12471, 12522, 12531, 12464, 778, - 12475, 12531, 12481, 778, 12475, 12531, 12488, 778, 12480, 12540, 12473, - 522, 12487, 12471, 522, 12489, 12523, 522, 12488, 12531, 522, 12490, - 12494, 778, 12494, 12483, 12488, 778, 12495, 12452, 12484, 1290, 12497, - 12540, 12475, 12531, 12488, 778, 12497, 12540, 12484, 1034, 12496, 12540, - 12524, 12523, 1290, 12500, 12450, 12473, 12488, 12523, 778, 12500, 12463, - 12523, 522, 12500, 12467, 522, 12499, 12523, 1290, 12501, 12449, 12521, - 12483, 12489, 1034, 12501, 12451, 12540, 12488, 1290, 12502, 12483, - 12471, 12455, 12523, 778, 12501, 12521, 12531, 1290, 12504, 12463, 12479, - 12540, 12523, 522, 12506, 12477, 778, 12506, 12491, 12498, 778, 12504, - 12523, 12484, 778, 12506, 12531, 12473, 778, 12506, 12540, 12472, 778, - 12505, 12540, 12479, 1034, 12509, 12452, 12531, 12488, 778, 12508, 12523, - 12488, 522, 12507, 12531, 778, 12509, 12531, 12489, 778, 12507, 12540, - 12523, 778, 12507, 12540, 12531, 1034, 12510, 12452, 12463, 12525, 778, - 12510, 12452, 12523, 778, 12510, 12483, 12495, 778, 12510, 12523, 12463, - 1290, 12510, 12531, 12471, 12519, 12531, 1034, 12511, 12463, 12525, - 12531, 522, 12511, 12522, 1290, 12511, 12522, 12496, 12540, 12523, 522, - 12513, 12460, 1034, 12513, 12460, 12488, 12531, 1034, 12513, 12540, - 12488, 12523, 778, 12516, 12540, 12489, 778, 12516, 12540, 12523, 778, - 12518, 12450, 12531, 1034, 12522, 12483, 12488, 12523, 522, 12522, 12521, - 778, 12523, 12500, 12540, 1034, 12523, 12540, 12502, 12523, 522, 12524, - 12512, 1290, 12524, 12531, 12488, 12466, 12531, 778, 12527, 12483, 12488, - 514, 48, 28857, 514, 49, 28857, 514, 50, 28857, 514, 51, 28857, 514, 52, - 28857, 514, 53, 28857, 514, 54, 28857, 514, 55, 28857, 514, 56, 28857, - 514, 57, 28857, 770, 49, 48, 28857, 770, 49, 49, 28857, 770, 49, 50, - 28857, 770, 49, 51, 28857, 770, 49, 52, 28857, 770, 49, 53, 28857, 770, - 49, 54, 28857, 770, 49, 55, 28857, 770, 49, 56, 28857, 770, 49, 57, - 28857, 770, 50, 48, 28857, 770, 50, 49, 28857, 770, 50, 50, 28857, 770, - 50, 51, 28857, 770, 50, 52, 28857, 778, 104, 80, 97, 522, 100, 97, 522, - 65, 85, 778, 98, 97, 114, 522, 111, 86, 522, 112, 99, 522, 100, 109, 778, - 100, 109, 178, 778, 100, 109, 179, 522, 73, 85, 522, 24179, 25104, 522, - 26157, 21644, 522, 22823, 27491, 522, 26126, 27835, 1034, 26666, 24335, - 20250, 31038, 522, 112, 65, 522, 110, 65, 522, 956, 65, 522, 109, 65, - 522, 107, 65, 522, 75, 66, 522, 77, 66, 522, 71, 66, 778, 99, 97, 108, - 1034, 107, 99, 97, 108, 522, 112, 70, 522, 110, 70, 522, 956, 70, 522, - 956, 103, 522, 109, 103, 522, 107, 103, 522, 72, 122, 778, 107, 72, 122, - 778, 77, 72, 122, 778, 71, 72, 122, 778, 84, 72, 122, 522, 956, 8467, - 522, 109, 8467, 522, 100, 8467, 522, 107, 8467, 522, 102, 109, 522, 110, - 109, 522, 956, 109, 522, 109, 109, 522, 99, 109, 522, 107, 109, 778, 109, - 109, 178, 778, 99, 109, 178, 522, 109, 178, 778, 107, 109, 178, 778, 109, - 109, 179, 778, 99, 109, 179, 522, 109, 179, 778, 107, 109, 179, 778, 109, - 8725, 115, 1034, 109, 8725, 115, 178, 522, 80, 97, 778, 107, 80, 97, 778, - 77, 80, 97, 778, 71, 80, 97, 778, 114, 97, 100, 1290, 114, 97, 100, 8725, - 115, 1546, 114, 97, 100, 8725, 115, 178, 522, 112, 115, 522, 110, 115, - 522, 956, 115, 522, 109, 115, 522, 112, 86, 522, 110, 86, 522, 956, 86, - 522, 109, 86, 522, 107, 86, 522, 77, 86, 522, 112, 87, 522, 110, 87, 522, - 956, 87, 522, 109, 87, 522, 107, 87, 522, 77, 87, 522, 107, 937, 522, 77, - 937, 1034, 97, 46, 109, 46, 522, 66, 113, 522, 99, 99, 522, 99, 100, - 1034, 67, 8725, 107, 103, 778, 67, 111, 46, 522, 100, 66, 522, 71, 121, - 522, 104, 97, 522, 72, 80, 522, 105, 110, 522, 75, 75, 522, 75, 77, 522, - 107, 116, 522, 108, 109, 522, 108, 110, 778, 108, 111, 103, 522, 108, - 120, 522, 109, 98, 778, 109, 105, 108, 778, 109, 111, 108, 522, 80, 72, - 1034, 112, 46, 109, 46, 778, 80, 80, 77, 522, 80, 82, 522, 115, 114, 522, - 83, 118, 522, 87, 98, 778, 86, 8725, 109, 778, 65, 8725, 109, 514, 49, - 26085, 514, 50, 26085, 514, 51, 26085, 514, 52, 26085, 514, 53, 26085, - 514, 54, 26085, 514, 55, 26085, 514, 56, 26085, 514, 57, 26085, 770, 49, - 48, 26085, 770, 49, 49, 26085, 770, 49, 50, 26085, 770, 49, 51, 26085, - 770, 49, 52, 26085, 770, 49, 53, 26085, 770, 49, 54, 26085, 770, 49, 55, - 26085, 770, 49, 56, 26085, 770, 49, 57, 26085, 770, 50, 48, 26085, 770, - 50, 49, 26085, 770, 50, 50, 26085, 770, 50, 51, 26085, 770, 50, 52, - 26085, 770, 50, 53, 26085, 770, 50, 54, 26085, 770, 50, 55, 26085, 770, - 50, 56, 26085, 770, 50, 57, 26085, 770, 51, 48, 26085, 770, 51, 49, - 26085, 778, 103, 97, 108, 259, 1098, 259, 1100, 259, 42863, 259, 294, - 259, 339, 259, 42791, 259, 43831, 259, 619, 259, 43858, 256, 35912, 256, - 26356, 256, 36554, 256, 36040, 256, 28369, 256, 20018, 256, 21477, 256, - 40860, 256, 40860, 256, 22865, 256, 37329, 256, 21895, 256, 22856, 256, - 25078, 256, 30313, 256, 32645, 256, 34367, 256, 34746, 256, 35064, 256, - 37007, 256, 27138, 256, 27931, 256, 28889, 256, 29662, 256, 33853, 256, - 37226, 256, 39409, 256, 20098, 256, 21365, 256, 27396, 256, 29211, 256, - 34349, 256, 40478, 256, 23888, 256, 28651, 256, 34253, 256, 35172, 256, - 25289, 256, 33240, 256, 34847, 256, 24266, 256, 26391, 256, 28010, 256, - 29436, 256, 37070, 256, 20358, 256, 20919, 256, 21214, 256, 25796, 256, - 27347, 256, 29200, 256, 30439, 256, 32769, 256, 34310, 256, 34396, 256, - 36335, 256, 38706, 256, 39791, 256, 40442, 256, 30860, 256, 31103, 256, - 32160, 256, 33737, 256, 37636, 256, 40575, 256, 35542, 256, 22751, 256, - 24324, 256, 31840, 256, 32894, 256, 29282, 256, 30922, 256, 36034, 256, - 38647, 256, 22744, 256, 23650, 256, 27155, 256, 28122, 256, 28431, 256, - 32047, 256, 32311, 256, 38475, 256, 21202, 256, 32907, 256, 20956, 256, - 20940, 256, 31260, 256, 32190, 256, 33777, 256, 38517, 256, 35712, 256, - 25295, 256, 27138, 256, 35582, 256, 20025, 256, 23527, 256, 24594, 256, - 29575, 256, 30064, 256, 21271, 256, 30971, 256, 20415, 256, 24489, 256, - 19981, 256, 27852, 256, 25976, 256, 32034, 256, 21443, 256, 22622, 256, - 30465, 256, 33865, 256, 35498, 256, 27578, 256, 36784, 256, 27784, 256, - 25342, 256, 33509, 256, 25504, 256, 30053, 256, 20142, 256, 20841, 256, - 20937, 256, 26753, 256, 31975, 256, 33391, 256, 35538, 256, 37327, 256, - 21237, 256, 21570, 256, 22899, 256, 24300, 256, 26053, 256, 28670, 256, - 31018, 256, 38317, 256, 39530, 256, 40599, 256, 40654, 256, 21147, 256, - 26310, 256, 27511, 256, 36706, 256, 24180, 256, 24976, 256, 25088, 256, - 25754, 256, 28451, 256, 29001, 256, 29833, 256, 31178, 256, 32244, 256, - 32879, 256, 36646, 256, 34030, 256, 36899, 256, 37706, 256, 21015, 256, - 21155, 256, 21693, 256, 28872, 256, 35010, 256, 35498, 256, 24265, 256, - 24565, 256, 25467, 256, 27566, 256, 31806, 256, 29557, 256, 20196, 256, - 22265, 256, 23527, 256, 23994, 256, 24604, 256, 29618, 256, 29801, 256, - 32666, 256, 32838, 256, 37428, 256, 38646, 256, 38728, 256, 38936, 256, - 20363, 256, 31150, 256, 37300, 256, 38584, 256, 24801, 256, 20102, 256, - 20698, 256, 23534, 256, 23615, 256, 26009, 256, 27138, 256, 29134, 256, - 30274, 256, 34044, 256, 36988, 256, 40845, 256, 26248, 256, 38446, 256, - 21129, 256, 26491, 256, 26611, 256, 27969, 256, 28316, 256, 29705, 256, - 30041, 256, 30827, 256, 32016, 256, 39006, 256, 20845, 256, 25134, 256, - 38520, 256, 20523, 256, 23833, 256, 28138, 256, 36650, 256, 24459, 256, - 24900, 256, 26647, 256, 29575, 256, 38534, 256, 21033, 256, 21519, 256, - 23653, 256, 26131, 256, 26446, 256, 26792, 256, 27877, 256, 29702, 256, - 30178, 256, 32633, 256, 35023, 256, 35041, 256, 37324, 256, 38626, 256, - 21311, 256, 28346, 256, 21533, 256, 29136, 256, 29848, 256, 34298, 256, - 38563, 256, 40023, 256, 40607, 256, 26519, 256, 28107, 256, 33256, 256, - 31435, 256, 31520, 256, 31890, 256, 29376, 256, 28825, 256, 35672, 256, - 20160, 256, 33590, 256, 21050, 256, 20999, 256, 24230, 256, 25299, 256, - 31958, 256, 23429, 256, 27934, 256, 26292, 256, 36667, 256, 34892, 256, - 38477, 256, 35211, 256, 24275, 256, 20800, 256, 21952, 256, 22618, 256, - 26228, 256, 20958, 256, 29482, 256, 30410, 256, 31036, 256, 31070, 256, - 31077, 256, 31119, 256, 38742, 256, 31934, 256, 32701, 256, 34322, 256, - 35576, 256, 36920, 256, 37117, 256, 39151, 256, 39164, 256, 39208, 256, - 40372, 256, 37086, 256, 38583, 256, 20398, 256, 20711, 256, 20813, 256, - 21193, 256, 21220, 256, 21329, 256, 21917, 256, 22022, 256, 22120, 256, - 22592, 256, 22696, 256, 23652, 256, 23662, 256, 24724, 256, 24936, 256, - 24974, 256, 25074, 256, 25935, 256, 26082, 256, 26257, 256, 26757, 256, - 28023, 256, 28186, 256, 28450, 256, 29038, 256, 29227, 256, 29730, 256, - 30865, 256, 31038, 256, 31049, 256, 31048, 256, 31056, 256, 31062, 256, - 31069, 256, 31117, 256, 31118, 256, 31296, 256, 31361, 256, 31680, 256, - 32244, 256, 32265, 256, 32321, 256, 32626, 256, 32773, 256, 33261, 256, - 33401, 256, 33401, 256, 33879, 256, 35088, 256, 35222, 256, 35585, 256, - 35641, 256, 36051, 256, 36104, 256, 36790, 256, 36920, 256, 38627, 256, - 38911, 256, 38971, 256, 24693, 256, 55376, 57070, 256, 33304, 256, 20006, - 256, 20917, 256, 20840, 256, 20352, 256, 20805, 256, 20864, 256, 21191, - 256, 21242, 256, 21917, 256, 21845, 256, 21913, 256, 21986, 256, 22618, - 256, 22707, 256, 22852, 256, 22868, 256, 23138, 256, 23336, 256, 24274, - 256, 24281, 256, 24425, 256, 24493, 256, 24792, 256, 24910, 256, 24840, - 256, 24974, 256, 24928, 256, 25074, 256, 25140, 256, 25540, 256, 25628, - 256, 25682, 256, 25942, 256, 26228, 256, 26391, 256, 26395, 256, 26454, - 256, 27513, 256, 27578, 256, 27969, 256, 28379, 256, 28363, 256, 28450, - 256, 28702, 256, 29038, 256, 30631, 256, 29237, 256, 29359, 256, 29482, - 256, 29809, 256, 29958, 256, 30011, 256, 30237, 256, 30239, 256, 30410, - 256, 30427, 256, 30452, 256, 30538, 256, 30528, 256, 30924, 256, 31409, - 256, 31680, 256, 31867, 256, 32091, 256, 32244, 256, 32574, 256, 32773, - 256, 33618, 256, 33775, 256, 34681, 256, 35137, 256, 35206, 256, 35222, - 256, 35519, 256, 35576, 256, 35531, 256, 35585, 256, 35582, 256, 35565, - 256, 35641, 256, 35722, 256, 36104, 256, 36664, 256, 36978, 256, 37273, - 256, 37494, 256, 38524, 256, 38627, 256, 38742, 256, 38875, 256, 38911, - 256, 38923, 256, 38971, 256, 39698, 256, 40860, 256, 55370, 56394, 256, - 55370, 56388, 256, 55372, 57301, 256, 15261, 256, 16408, 256, 16441, 256, - 55380, 56905, 256, 55383, 56528, 256, 55391, 57043, 256, 40771, 256, - 40846, 514, 102, 102, 514, 102, 105, 514, 102, 108, 770, 102, 102, 105, - 770, 102, 102, 108, 514, 383, 116, 514, 115, 116, 514, 1396, 1398, 514, - 1396, 1381, 514, 1396, 1387, 514, 1406, 1398, 514, 1396, 1389, 512, 1497, - 1460, 512, 1522, 1463, 262, 1506, 262, 1488, 262, 1491, 262, 1492, 262, - 1499, 262, 1500, 262, 1501, 262, 1512, 262, 1514, 262, 43, 512, 1513, - 1473, 512, 1513, 1474, 512, 64329, 1473, 512, 64329, 1474, 512, 1488, - 1463, 512, 1488, 1464, 512, 1488, 1468, 512, 1489, 1468, 512, 1490, 1468, - 512, 1491, 1468, 512, 1492, 1468, 512, 1493, 1468, 512, 1494, 1468, 512, - 1496, 1468, 512, 1497, 1468, 512, 1498, 1468, 512, 1499, 1468, 512, 1500, - 1468, 512, 1502, 1468, 512, 1504, 1468, 512, 1505, 1468, 512, 1507, 1468, - 512, 1508, 1468, 512, 1510, 1468, 512, 1511, 1468, 512, 1512, 1468, 512, - 1513, 1468, 512, 1514, 1468, 512, 1493, 1465, 512, 1489, 1471, 512, 1499, - 1471, 512, 1508, 1471, 514, 1488, 1500, 267, 1649, 268, 1649, 267, 1659, - 268, 1659, 269, 1659, 270, 1659, 267, 1662, 268, 1662, 269, 1662, 270, - 1662, 267, 1664, 268, 1664, 269, 1664, 270, 1664, 267, 1658, 268, 1658, - 269, 1658, 270, 1658, 267, 1663, 268, 1663, 269, 1663, 270, 1663, 267, - 1657, 268, 1657, 269, 1657, 270, 1657, 267, 1700, 268, 1700, 269, 1700, - 270, 1700, 267, 1702, 268, 1702, 269, 1702, 270, 1702, 267, 1668, 268, - 1668, 269, 1668, 270, 1668, 267, 1667, 268, 1667, 269, 1667, 270, 1667, - 267, 1670, 268, 1670, 269, 1670, 270, 1670, 267, 1671, 268, 1671, 269, - 1671, 270, 1671, 267, 1677, 268, 1677, 267, 1676, 268, 1676, 267, 1678, - 268, 1678, 267, 1672, 268, 1672, 267, 1688, 268, 1688, 267, 1681, 268, - 1681, 267, 1705, 268, 1705, 269, 1705, 270, 1705, 267, 1711, 268, 1711, - 269, 1711, 270, 1711, 267, 1715, 268, 1715, 269, 1715, 270, 1715, 267, - 1713, 268, 1713, 269, 1713, 270, 1713, 267, 1722, 268, 1722, 267, 1723, - 268, 1723, 269, 1723, 270, 1723, 267, 1728, 268, 1728, 267, 1729, 268, - 1729, 269, 1729, 270, 1729, 267, 1726, 268, 1726, 269, 1726, 270, 1726, - 267, 1746, 268, 1746, 267, 1747, 268, 1747, 267, 1709, 268, 1709, 269, - 1709, 270, 1709, 267, 1735, 268, 1735, 267, 1734, 268, 1734, 267, 1736, - 268, 1736, 267, 1655, 267, 1739, 268, 1739, 267, 1733, 268, 1733, 267, - 1737, 268, 1737, 267, 1744, 268, 1744, 269, 1744, 270, 1744, 269, 1609, - 270, 1609, 523, 1574, 1575, 524, 1574, 1575, 523, 1574, 1749, 524, 1574, - 1749, 523, 1574, 1608, 524, 1574, 1608, 523, 1574, 1735, 524, 1574, 1735, - 523, 1574, 1734, 524, 1574, 1734, 523, 1574, 1736, 524, 1574, 1736, 523, - 1574, 1744, 524, 1574, 1744, 525, 1574, 1744, 523, 1574, 1609, 524, 1574, - 1609, 525, 1574, 1609, 267, 1740, 268, 1740, 269, 1740, 270, 1740, 523, - 1574, 1580, 523, 1574, 1581, 523, 1574, 1605, 523, 1574, 1609, 523, 1574, - 1610, 523, 1576, 1580, 523, 1576, 1581, 523, 1576, 1582, 523, 1576, 1605, - 523, 1576, 1609, 523, 1576, 1610, 523, 1578, 1580, 523, 1578, 1581, 523, - 1578, 1582, 523, 1578, 1605, 523, 1578, 1609, 523, 1578, 1610, 523, 1579, - 1580, 523, 1579, 1605, 523, 1579, 1609, 523, 1579, 1610, 523, 1580, 1581, - 523, 1580, 1605, 523, 1581, 1580, 523, 1581, 1605, 523, 1582, 1580, 523, - 1582, 1581, 523, 1582, 1605, 523, 1587, 1580, 523, 1587, 1581, 523, 1587, - 1582, 523, 1587, 1605, 523, 1589, 1581, 523, 1589, 1605, 523, 1590, 1580, - 523, 1590, 1581, 523, 1590, 1582, 523, 1590, 1605, 523, 1591, 1581, 523, - 1591, 1605, 523, 1592, 1605, 523, 1593, 1580, 523, 1593, 1605, 523, 1594, - 1580, 523, 1594, 1605, 523, 1601, 1580, 523, 1601, 1581, 523, 1601, 1582, - 523, 1601, 1605, 523, 1601, 1609, 523, 1601, 1610, 523, 1602, 1581, 523, - 1602, 1605, 523, 1602, 1609, 523, 1602, 1610, 523, 1603, 1575, 523, 1603, - 1580, 523, 1603, 1581, 523, 1603, 1582, 523, 1603, 1604, 523, 1603, 1605, - 523, 1603, 1609, 523, 1603, 1610, 523, 1604, 1580, 523, 1604, 1581, 523, - 1604, 1582, 523, 1604, 1605, 523, 1604, 1609, 523, 1604, 1610, 523, 1605, - 1580, 523, 1605, 1581, 523, 1605, 1582, 523, 1605, 1605, 523, 1605, 1609, - 523, 1605, 1610, 523, 1606, 1580, 523, 1606, 1581, 523, 1606, 1582, 523, - 1606, 1605, 523, 1606, 1609, 523, 1606, 1610, 523, 1607, 1580, 523, 1607, - 1605, 523, 1607, 1609, 523, 1607, 1610, 523, 1610, 1580, 523, 1610, 1581, - 523, 1610, 1582, 523, 1610, 1605, 523, 1610, 1609, 523, 1610, 1610, 523, - 1584, 1648, 523, 1585, 1648, 523, 1609, 1648, 779, 32, 1612, 1617, 779, - 32, 1613, 1617, 779, 32, 1614, 1617, 779, 32, 1615, 1617, 779, 32, 1616, - 1617, 779, 32, 1617, 1648, 524, 1574, 1585, 524, 1574, 1586, 524, 1574, - 1605, 524, 1574, 1606, 524, 1574, 1609, 524, 1574, 1610, 524, 1576, 1585, - 524, 1576, 1586, 524, 1576, 1605, 524, 1576, 1606, 524, 1576, 1609, 524, - 1576, 1610, 524, 1578, 1585, 524, 1578, 1586, 524, 1578, 1605, 524, 1578, - 1606, 524, 1578, 1609, 524, 1578, 1610, 524, 1579, 1585, 524, 1579, 1586, - 524, 1579, 1605, 524, 1579, 1606, 524, 1579, 1609, 524, 1579, 1610, 524, - 1601, 1609, 524, 1601, 1610, 524, 1602, 1609, 524, 1602, 1610, 524, 1603, - 1575, 524, 1603, 1604, 524, 1603, 1605, 524, 1603, 1609, 524, 1603, 1610, - 524, 1604, 1605, 524, 1604, 1609, 524, 1604, 1610, 524, 1605, 1575, 524, - 1605, 1605, 524, 1606, 1585, 524, 1606, 1586, 524, 1606, 1605, 524, 1606, - 1606, 524, 1606, 1609, 524, 1606, 1610, 524, 1609, 1648, 524, 1610, 1585, - 524, 1610, 1586, 524, 1610, 1605, 524, 1610, 1606, 524, 1610, 1609, 524, - 1610, 1610, 525, 1574, 1580, 525, 1574, 1581, 525, 1574, 1582, 525, 1574, - 1605, 525, 1574, 1607, 525, 1576, 1580, 525, 1576, 1581, 525, 1576, 1582, - 525, 1576, 1605, 525, 1576, 1607, 525, 1578, 1580, 525, 1578, 1581, 525, - 1578, 1582, 525, 1578, 1605, 525, 1578, 1607, 525, 1579, 1605, 525, 1580, - 1581, 525, 1580, 1605, 525, 1581, 1580, 525, 1581, 1605, 525, 1582, 1580, - 525, 1582, 1605, 525, 1587, 1580, 525, 1587, 1581, 525, 1587, 1582, 525, - 1587, 1605, 525, 1589, 1581, 525, 1589, 1582, 525, 1589, 1605, 525, 1590, - 1580, 525, 1590, 1581, 525, 1590, 1582, 525, 1590, 1605, 525, 1591, 1581, - 525, 1592, 1605, 525, 1593, 1580, 525, 1593, 1605, 525, 1594, 1580, 525, - 1594, 1605, 525, 1601, 1580, 525, 1601, 1581, 525, 1601, 1582, 525, 1601, - 1605, 525, 1602, 1581, 525, 1602, 1605, 525, 1603, 1580, 525, 1603, 1581, - 525, 1603, 1582, 525, 1603, 1604, 525, 1603, 1605, 525, 1604, 1580, 525, - 1604, 1581, 525, 1604, 1582, 525, 1604, 1605, 525, 1604, 1607, 525, 1605, - 1580, 525, 1605, 1581, 525, 1605, 1582, 525, 1605, 1605, 525, 1606, 1580, - 525, 1606, 1581, 525, 1606, 1582, 525, 1606, 1605, 525, 1606, 1607, 525, - 1607, 1580, 525, 1607, 1605, 525, 1607, 1648, 525, 1610, 1580, 525, 1610, - 1581, 525, 1610, 1582, 525, 1610, 1605, 525, 1610, 1607, 526, 1574, 1605, - 526, 1574, 1607, 526, 1576, 1605, 526, 1576, 1607, 526, 1578, 1605, 526, - 1578, 1607, 526, 1579, 1605, 526, 1579, 1607, 526, 1587, 1605, 526, 1587, - 1607, 526, 1588, 1605, 526, 1588, 1607, 526, 1603, 1604, 526, 1603, 1605, - 526, 1604, 1605, 526, 1606, 1605, 526, 1606, 1607, 526, 1610, 1605, 526, - 1610, 1607, 782, 1600, 1614, 1617, 782, 1600, 1615, 1617, 782, 1600, - 1616, 1617, 523, 1591, 1609, 523, 1591, 1610, 523, 1593, 1609, 523, 1593, - 1610, 523, 1594, 1609, 523, 1594, 1610, 523, 1587, 1609, 523, 1587, 1610, - 523, 1588, 1609, 523, 1588, 1610, 523, 1581, 1609, 523, 1581, 1610, 523, - 1580, 1609, 523, 1580, 1610, 523, 1582, 1609, 523, 1582, 1610, 523, 1589, - 1609, 523, 1589, 1610, 523, 1590, 1609, 523, 1590, 1610, 523, 1588, 1580, - 523, 1588, 1581, 523, 1588, 1582, 523, 1588, 1605, 523, 1588, 1585, 523, - 1587, 1585, 523, 1589, 1585, 523, 1590, 1585, 524, 1591, 1609, 524, 1591, - 1610, 524, 1593, 1609, 524, 1593, 1610, 524, 1594, 1609, 524, 1594, 1610, - 524, 1587, 1609, 524, 1587, 1610, 524, 1588, 1609, 524, 1588, 1610, 524, - 1581, 1609, 524, 1581, 1610, 524, 1580, 1609, 524, 1580, 1610, 524, 1582, - 1609, 524, 1582, 1610, 524, 1589, 1609, 524, 1589, 1610, 524, 1590, 1609, - 524, 1590, 1610, 524, 1588, 1580, 524, 1588, 1581, 524, 1588, 1582, 524, - 1588, 1605, 524, 1588, 1585, 524, 1587, 1585, 524, 1589, 1585, 524, 1590, - 1585, 525, 1588, 1580, 525, 1588, 1581, 525, 1588, 1582, 525, 1588, 1605, - 525, 1587, 1607, 525, 1588, 1607, 525, 1591, 1605, 526, 1587, 1580, 526, - 1587, 1581, 526, 1587, 1582, 526, 1588, 1580, 526, 1588, 1581, 526, 1588, - 1582, 526, 1591, 1605, 526, 1592, 1605, 524, 1575, 1611, 523, 1575, 1611, - 781, 1578, 1580, 1605, 780, 1578, 1581, 1580, 781, 1578, 1581, 1580, 781, - 1578, 1581, 1605, 781, 1578, 1582, 1605, 781, 1578, 1605, 1580, 781, - 1578, 1605, 1581, 781, 1578, 1605, 1582, 780, 1580, 1605, 1581, 781, - 1580, 1605, 1581, 780, 1581, 1605, 1610, 780, 1581, 1605, 1609, 781, - 1587, 1581, 1580, 781, 1587, 1580, 1581, 780, 1587, 1580, 1609, 780, - 1587, 1605, 1581, 781, 1587, 1605, 1581, 781, 1587, 1605, 1580, 780, - 1587, 1605, 1605, 781, 1587, 1605, 1605, 780, 1589, 1581, 1581, 781, - 1589, 1581, 1581, 780, 1589, 1605, 1605, 780, 1588, 1581, 1605, 781, - 1588, 1581, 1605, 780, 1588, 1580, 1610, 780, 1588, 1605, 1582, 781, - 1588, 1605, 1582, 780, 1588, 1605, 1605, 781, 1588, 1605, 1605, 780, - 1590, 1581, 1609, 780, 1590, 1582, 1605, 781, 1590, 1582, 1605, 780, - 1591, 1605, 1581, 781, 1591, 1605, 1581, 781, 1591, 1605, 1605, 780, - 1591, 1605, 1610, 780, 1593, 1580, 1605, 780, 1593, 1605, 1605, 781, - 1593, 1605, 1605, 780, 1593, 1605, 1609, 780, 1594, 1605, 1605, 780, - 1594, 1605, 1610, 780, 1594, 1605, 1609, 780, 1601, 1582, 1605, 781, - 1601, 1582, 1605, 780, 1602, 1605, 1581, 780, 1602, 1605, 1605, 780, - 1604, 1581, 1605, 780, 1604, 1581, 1610, 780, 1604, 1581, 1609, 781, - 1604, 1580, 1580, 780, 1604, 1580, 1580, 780, 1604, 1582, 1605, 781, - 1604, 1582, 1605, 780, 1604, 1605, 1581, 781, 1604, 1605, 1581, 781, - 1605, 1581, 1580, 781, 1605, 1581, 1605, 780, 1605, 1581, 1610, 781, - 1605, 1580, 1581, 781, 1605, 1580, 1605, 781, 1605, 1582, 1580, 781, - 1605, 1582, 1605, 781, 1605, 1580, 1582, 781, 1607, 1605, 1580, 781, - 1607, 1605, 1605, 781, 1606, 1581, 1605, 780, 1606, 1581, 1609, 780, - 1606, 1580, 1605, 781, 1606, 1580, 1605, 780, 1606, 1580, 1609, 780, - 1606, 1605, 1610, 780, 1606, 1605, 1609, 780, 1610, 1605, 1605, 781, - 1610, 1605, 1605, 780, 1576, 1582, 1610, 780, 1578, 1580, 1610, 780, - 1578, 1580, 1609, 780, 1578, 1582, 1610, 780, 1578, 1582, 1609, 780, - 1578, 1605, 1610, 780, 1578, 1605, 1609, 780, 1580, 1605, 1610, 780, - 1580, 1581, 1609, 780, 1580, 1605, 1609, 780, 1587, 1582, 1609, 780, - 1589, 1581, 1610, 780, 1588, 1581, 1610, 780, 1590, 1581, 1610, 780, - 1604, 1580, 1610, 780, 1604, 1605, 1610, 780, 1610, 1581, 1610, 780, - 1610, 1580, 1610, 780, 1610, 1605, 1610, 780, 1605, 1605, 1610, 780, - 1602, 1605, 1610, 780, 1606, 1581, 1610, 781, 1602, 1605, 1581, 781, - 1604, 1581, 1605, 780, 1593, 1605, 1610, 780, 1603, 1605, 1610, 781, - 1606, 1580, 1581, 780, 1605, 1582, 1610, 781, 1604, 1580, 1605, 780, - 1603, 1605, 1605, 780, 1604, 1580, 1605, 780, 1606, 1580, 1581, 780, - 1580, 1581, 1610, 780, 1581, 1580, 1610, 780, 1605, 1580, 1610, 780, - 1601, 1605, 1610, 780, 1576, 1581, 1610, 781, 1603, 1605, 1605, 781, - 1593, 1580, 1605, 781, 1589, 1605, 1605, 780, 1587, 1582, 1610, 780, - 1606, 1580, 1610, 779, 1589, 1604, 1746, 779, 1602, 1604, 1746, 1035, - 1575, 1604, 1604, 1607, 1035, 1575, 1603, 1576, 1585, 1035, 1605, 1581, - 1605, 1583, 1035, 1589, 1604, 1593, 1605, 1035, 1585, 1587, 1608, 1604, - 1035, 1593, 1604, 1610, 1607, 1035, 1608, 1587, 1604, 1605, 779, 1589, - 1604, 1609, 4619, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, - 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 2059, 1580, 1604, 32, 1580, - 1604, 1575, 1604, 1607, 1035, 1585, 1740, 1575, 1604, 265, 44, 265, - 12289, 265, 12290, 265, 58, 265, 59, 265, 33, 265, 63, 265, 12310, 265, - 12311, 265, 8230, 265, 8229, 265, 8212, 265, 8211, 265, 95, 265, 95, 265, - 40, 265, 41, 265, 123, 265, 125, 265, 12308, 265, 12309, 265, 12304, 265, - 12305, 265, 12298, 265, 12299, 265, 12296, 265, 12297, 265, 12300, 265, - 12301, 265, 12302, 265, 12303, 265, 91, 265, 93, 258, 8254, 258, 8254, - 258, 8254, 258, 8254, 258, 95, 258, 95, 258, 95, 271, 44, 271, 12289, - 271, 46, 271, 59, 271, 58, 271, 63, 271, 33, 271, 8212, 271, 40, 271, 41, - 271, 123, 271, 125, 271, 12308, 271, 12309, 271, 35, 271, 38, 271, 42, - 271, 43, 271, 45, 271, 60, 271, 62, 271, 61, 271, 92, 271, 36, 271, 37, - 271, 64, 523, 32, 1611, 526, 1600, 1611, 523, 32, 1612, 523, 32, 1613, - 523, 32, 1614, 526, 1600, 1614, 523, 32, 1615, 526, 1600, 1615, 523, 32, - 1616, 526, 1600, 1616, 523, 32, 1617, 526, 1600, 1617, 523, 32, 1618, - 526, 1600, 1618, 267, 1569, 267, 1570, 268, 1570, 267, 1571, 268, 1571, - 267, 1572, 268, 1572, 267, 1573, 268, 1573, 267, 1574, 268, 1574, 269, - 1574, 270, 1574, 267, 1575, 268, 1575, 267, 1576, 268, 1576, 269, 1576, - 270, 1576, 267, 1577, 268, 1577, 267, 1578, 268, 1578, 269, 1578, 270, - 1578, 267, 1579, 268, 1579, 269, 1579, 270, 1579, 267, 1580, 268, 1580, - 269, 1580, 270, 1580, 267, 1581, 268, 1581, 269, 1581, 270, 1581, 267, - 1582, 268, 1582, 269, 1582, 270, 1582, 267, 1583, 268, 1583, 267, 1584, - 268, 1584, 267, 1585, 268, 1585, 267, 1586, 268, 1586, 267, 1587, 268, - 1587, 269, 1587, 270, 1587, 267, 1588, 268, 1588, 269, 1588, 270, 1588, - 267, 1589, 268, 1589, 269, 1589, 270, 1589, 267, 1590, 268, 1590, 269, - 1590, 270, 1590, 267, 1591, 268, 1591, 269, 1591, 270, 1591, 267, 1592, - 268, 1592, 269, 1592, 270, 1592, 267, 1593, 268, 1593, 269, 1593, 270, - 1593, 267, 1594, 268, 1594, 269, 1594, 270, 1594, 267, 1601, 268, 1601, - 269, 1601, 270, 1601, 267, 1602, 268, 1602, 269, 1602, 270, 1602, 267, - 1603, 268, 1603, 269, 1603, 270, 1603, 267, 1604, 268, 1604, 269, 1604, - 270, 1604, 267, 1605, 268, 1605, 269, 1605, 270, 1605, 267, 1606, 268, - 1606, 269, 1606, 270, 1606, 267, 1607, 268, 1607, 269, 1607, 270, 1607, - 267, 1608, 268, 1608, 267, 1609, 268, 1609, 267, 1610, 268, 1610, 269, - 1610, 270, 1610, 523, 1604, 1570, 524, 1604, 1570, 523, 1604, 1571, 524, - 1604, 1571, 523, 1604, 1573, 524, 1604, 1573, 523, 1604, 1575, 524, 1604, - 1575, 264, 33, 264, 34, 264, 35, 264, 36, 264, 37, 264, 38, 264, 39, 264, - 40, 264, 41, 264, 42, 264, 43, 264, 44, 264, 45, 264, 46, 264, 47, 264, - 48, 264, 49, 264, 50, 264, 51, 264, 52, 264, 53, 264, 54, 264, 55, 264, - 56, 264, 57, 264, 58, 264, 59, 264, 60, 264, 61, 264, 62, 264, 63, 264, - 64, 264, 65, 264, 66, 264, 67, 264, 68, 264, 69, 264, 70, 264, 71, 264, - 72, 264, 73, 264, 74, 264, 75, 264, 76, 264, 77, 264, 78, 264, 79, 264, - 80, 264, 81, 264, 82, 264, 83, 264, 84, 264, 85, 264, 86, 264, 87, 264, - 88, 264, 89, 264, 90, 264, 91, 264, 92, 264, 93, 264, 94, 264, 95, 264, - 96, 264, 97, 264, 98, 264, 99, 264, 100, 264, 101, 264, 102, 264, 103, - 264, 104, 264, 105, 264, 106, 264, 107, 264, 108, 264, 109, 264, 110, - 264, 111, 264, 112, 264, 113, 264, 114, 264, 115, 264, 116, 264, 117, - 264, 118, 264, 119, 264, 120, 264, 121, 264, 122, 264, 123, 264, 124, - 264, 125, 264, 126, 264, 10629, 264, 10630, 272, 12290, 272, 12300, 272, - 12301, 272, 12289, 272, 12539, 272, 12530, 272, 12449, 272, 12451, 272, - 12453, 272, 12455, 272, 12457, 272, 12515, 272, 12517, 272, 12519, 272, - 12483, 272, 12540, 272, 12450, 272, 12452, 272, 12454, 272, 12456, 272, - 12458, 272, 12459, 272, 12461, 272, 12463, 272, 12465, 272, 12467, 272, - 12469, 272, 12471, 272, 12473, 272, 12475, 272, 12477, 272, 12479, 272, - 12481, 272, 12484, 272, 12486, 272, 12488, 272, 12490, 272, 12491, 272, - 12492, 272, 12493, 272, 12494, 272, 12495, 272, 12498, 272, 12501, 272, - 12504, 272, 12507, 272, 12510, 272, 12511, 272, 12512, 272, 12513, 272, - 12514, 272, 12516, 272, 12518, 272, 12520, 272, 12521, 272, 12522, 272, - 12523, 272, 12524, 272, 12525, 272, 12527, 272, 12531, 272, 12441, 272, - 12442, 272, 12644, 272, 12593, 272, 12594, 272, 12595, 272, 12596, 272, - 12597, 272, 12598, 272, 12599, 272, 12600, 272, 12601, 272, 12602, 272, - 12603, 272, 12604, 272, 12605, 272, 12606, 272, 12607, 272, 12608, 272, - 12609, 272, 12610, 272, 12611, 272, 12612, 272, 12613, 272, 12614, 272, - 12615, 272, 12616, 272, 12617, 272, 12618, 272, 12619, 272, 12620, 272, - 12621, 272, 12622, 272, 12623, 272, 12624, 272, 12625, 272, 12626, 272, - 12627, 272, 12628, 272, 12629, 272, 12630, 272, 12631, 272, 12632, 272, - 12633, 272, 12634, 272, 12635, 272, 12636, 272, 12637, 272, 12638, 272, - 12639, 272, 12640, 272, 12641, 272, 12642, 272, 12643, 264, 162, 264, - 163, 264, 172, 264, 175, 264, 166, 264, 165, 264, 8361, 272, 9474, 272, - 8592, 272, 8593, 272, 8594, 272, 8595, 272, 9632, 272, 9675, 512, 55300, - 56473, 55300, 56506, 512, 55300, 56475, 55300, 56506, 512, 55300, 56485, - 55300, 56506, 512, 55300, 56625, 55300, 56615, 512, 55300, 56626, 55300, - 56615, 512, 55300, 57159, 55300, 57150, 512, 55300, 57159, 55300, 57175, - 512, 55301, 56505, 55301, 56506, 512, 55301, 56505, 55301, 56496, 512, - 55301, 56505, 55301, 56509, 512, 55301, 56760, 55301, 56751, 512, 55301, - 56761, 55301, 56751, 512, 55348, 56663, 55348, 56677, 512, 55348, 56664, - 55348, 56677, 512, 55348, 56671, 55348, 56686, 512, 55348, 56671, 55348, - 56687, 512, 55348, 56671, 55348, 56688, 512, 55348, 56671, 55348, 56689, - 512, 55348, 56671, 55348, 56690, 512, 55348, 56761, 55348, 56677, 512, - 55348, 56762, 55348, 56677, 512, 55348, 56763, 55348, 56686, 512, 55348, - 56764, 55348, 56686, 512, 55348, 56763, 55348, 56687, 512, 55348, 56764, - 55348, 56687, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, - 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, - 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, - 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, - 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, - 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, - 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, - 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, - 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, - 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, - 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, - 102, 262, 103, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, - 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, - 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, - 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, - 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, - 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, - 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, - 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, - 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, - 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 67, 262, 68, - 262, 71, 262, 74, 262, 75, 262, 78, 262, 79, 262, 80, 262, 81, 262, 83, - 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, - 262, 98, 262, 99, 262, 100, 262, 102, 262, 104, 262, 105, 262, 106, 262, - 107, 262, 108, 262, 109, 262, 110, 262, 112, 262, 113, 262, 114, 262, - 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, - 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, - 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, - 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, - 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, - 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, - 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, - 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, - 262, 66, 262, 68, 262, 69, 262, 70, 262, 71, 262, 74, 262, 75, 262, 76, - 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 83, 262, 84, 262, 85, - 262, 86, 262, 87, 262, 88, 262, 89, 262, 97, 262, 98, 262, 99, 262, 100, - 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, - 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, - 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, - 262, 122, 262, 65, 262, 66, 262, 68, 262, 69, 262, 70, 262, 71, 262, 73, - 262, 74, 262, 75, 262, 76, 262, 77, 262, 79, 262, 83, 262, 84, 262, 85, - 262, 86, 262, 87, 262, 88, 262, 89, 262, 97, 262, 98, 262, 99, 262, 100, - 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, - 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, - 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, - 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, - 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, - 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, - 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, - 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, - 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, - 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, - 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, - 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, - 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, - 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, - 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, - 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, - 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, - 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, - 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, - 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, - 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, - 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, - 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, - 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, - 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, - 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, - 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, - 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, - 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, - 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, - 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, - 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, - 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, - 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, - 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, - 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, - 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, - 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, - 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, - 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, - 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, - 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, - 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, - 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, - 120, 262, 121, 262, 122, 262, 305, 262, 567, 262, 913, 262, 914, 262, - 915, 262, 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 921, 262, - 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 928, 262, - 929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, - 936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, 948, 262, - 949, 262, 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, - 956, 262, 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, 962, 262, - 963, 262, 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, 969, 262, - 8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, 982, 262, - 913, 262, 914, 262, 915, 262, 916, 262, 917, 262, 918, 262, 919, 262, - 920, 262, 921, 262, 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, - 927, 262, 928, 262, 929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, - 934, 262, 935, 262, 936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, - 947, 262, 948, 262, 949, 262, 950, 262, 951, 262, 952, 262, 953, 262, - 954, 262, 955, 262, 956, 262, 957, 262, 958, 262, 959, 262, 960, 262, - 961, 262, 962, 262, 963, 262, 964, 262, 965, 262, 966, 262, 967, 262, - 968, 262, 969, 262, 8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, - 1009, 262, 982, 262, 913, 262, 914, 262, 915, 262, 916, 262, 917, 262, - 918, 262, 919, 262, 920, 262, 921, 262, 922, 262, 923, 262, 924, 262, - 925, 262, 926, 262, 927, 262, 928, 262, 929, 262, 1012, 262, 931, 262, - 932, 262, 933, 262, 934, 262, 935, 262, 936, 262, 937, 262, 8711, 262, - 945, 262, 946, 262, 947, 262, 948, 262, 949, 262, 950, 262, 951, 262, - 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, 957, 262, 958, 262, - 959, 262, 960, 262, 961, 262, 962, 262, 963, 262, 964, 262, 965, 262, - 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, 1013, 262, 977, 262, - 1008, 262, 981, 262, 1009, 262, 982, 262, 913, 262, 914, 262, 915, 262, - 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 921, 262, 922, 262, - 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 928, 262, 929, 262, - 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, 936, 262, - 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, 948, 262, 949, 262, - 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, - 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, 962, 262, 963, 262, - 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, - 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, 982, 262, 913, 262, - 914, 262, 915, 262, 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, - 921, 262, 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, - 928, 262, 929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, - 935, 262, 936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, - 948, 262, 949, 262, 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, - 955, 262, 956, 262, 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, - 962, 262, 963, 262, 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, - 969, 262, 8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, - 982, 262, 988, 262, 989, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, - 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 48, 262, 49, 262, 50, - 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 48, - 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, - 262, 57, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, - 262, 55, 262, 56, 262, 57, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, - 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 1575, 262, 1576, 262, - 1580, 262, 1583, 262, 1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, - 262, 1603, 262, 1604, 262, 1605, 262, 1606, 262, 1587, 262, 1593, 262, - 1601, 262, 1589, 262, 1602, 262, 1585, 262, 1588, 262, 1578, 262, 1579, - 262, 1582, 262, 1584, 262, 1590, 262, 1592, 262, 1594, 262, 1646, 262, - 1722, 262, 1697, 262, 1647, 262, 1576, 262, 1580, 262, 1607, 262, 1581, - 262, 1610, 262, 1603, 262, 1604, 262, 1605, 262, 1606, 262, 1587, 262, - 1593, 262, 1601, 262, 1589, 262, 1602, 262, 1588, 262, 1578, 262, 1579, - 262, 1582, 262, 1590, 262, 1594, 262, 1580, 262, 1581, 262, 1610, 262, - 1604, 262, 1606, 262, 1587, 262, 1593, 262, 1589, 262, 1602, 262, 1588, - 262, 1582, 262, 1590, 262, 1594, 262, 1722, 262, 1647, 262, 1576, 262, - 1580, 262, 1607, 262, 1581, 262, 1591, 262, 1610, 262, 1603, 262, 1605, - 262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, 1602, 262, - 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1590, 262, 1592, 262, 1594, - 262, 1646, 262, 1697, 262, 1575, 262, 1576, 262, 1580, 262, 1583, 262, - 1607, 262, 1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, 262, 1604, - 262, 1605, 262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, - 1602, 262, 1585, 262, 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1584, - 262, 1590, 262, 1592, 262, 1594, 262, 1576, 262, 1580, 262, 1583, 262, - 1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, 262, 1604, 262, 1605, - 262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, 1602, 262, - 1585, 262, 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1584, 262, 1590, - 262, 1592, 262, 1594, 514, 48, 46, 514, 48, 44, 514, 49, 44, 514, 50, 44, - 514, 51, 44, 514, 52, 44, 514, 53, 44, 514, 54, 44, 514, 55, 44, 514, 56, - 44, 514, 57, 44, 770, 40, 65, 41, 770, 40, 66, 41, 770, 40, 67, 41, 770, - 40, 68, 41, 770, 40, 69, 41, 770, 40, 70, 41, 770, 40, 71, 41, 770, 40, - 72, 41, 770, 40, 73, 41, 770, 40, 74, 41, 770, 40, 75, 41, 770, 40, 76, - 41, 770, 40, 77, 41, 770, 40, 78, 41, 770, 40, 79, 41, 770, 40, 80, 41, - 770, 40, 81, 41, 770, 40, 82, 41, 770, 40, 83, 41, 770, 40, 84, 41, 770, - 40, 85, 41, 770, 40, 86, 41, 770, 40, 87, 41, 770, 40, 88, 41, 770, 40, - 89, 41, 770, 40, 90, 41, 770, 12308, 83, 12309, 263, 67, 263, 82, 519, - 67, 68, 519, 87, 90, 266, 65, 266, 66, 266, 67, 266, 68, 266, 69, 266, - 70, 266, 71, 266, 72, 266, 73, 266, 74, 266, 75, 266, 76, 266, 77, 266, - 78, 266, 79, 266, 80, 266, 81, 266, 82, 266, 83, 266, 84, 266, 85, 266, - 86, 266, 87, 266, 88, 266, 89, 266, 90, 522, 72, 86, 522, 77, 86, 522, - 83, 68, 522, 83, 83, 778, 80, 80, 86, 522, 87, 67, 515, 77, 67, 515, 77, - 68, 515, 77, 82, 522, 68, 74, 522, 12411, 12363, 522, 12467, 12467, 266, - 12469, 266, 25163, 266, 23383, 266, 21452, 266, 12487, 266, 20108, 266, - 22810, 266, 35299, 266, 22825, 266, 20132, 266, 26144, 266, 28961, 266, - 26009, 266, 21069, 266, 24460, 266, 20877, 266, 26032, 266, 21021, 266, - 32066, 266, 29983, 266, 36009, 266, 22768, 266, 21561, 266, 28436, 266, - 25237, 266, 25429, 266, 19968, 266, 19977, 266, 36938, 266, 24038, 266, - 20013, 266, 21491, 266, 25351, 266, 36208, 266, 25171, 266, 31105, 266, - 31354, 266, 21512, 266, 28288, 266, 26377, 266, 26376, 266, 30003, 266, - 21106, 266, 21942, 266, 37197, 770, 12308, 26412, 12309, 770, 12308, - 19977, 12309, 770, 12308, 20108, 12309, 770, 12308, 23433, 12309, 770, - 12308, 28857, 12309, 770, 12308, 25171, 12309, 770, 12308, 30423, 12309, - 770, 12308, 21213, 12309, 770, 12308, 25943, 12309, 263, 24471, 263, - 21487, 256, 20029, 256, 20024, 256, 20033, 256, 55360, 56610, 256, 20320, - 256, 20398, 256, 20411, 256, 20482, 256, 20602, 256, 20633, 256, 20711, - 256, 20687, 256, 13470, 256, 55361, 56890, 256, 20813, 256, 20820, 256, - 20836, 256, 20855, 256, 55361, 56604, 256, 13497, 256, 20839, 256, 20877, - 256, 55361, 56651, 256, 20887, 256, 20900, 256, 20172, 256, 20908, 256, - 20917, 256, 55396, 56799, 256, 20981, 256, 20995, 256, 13535, 256, 21051, - 256, 21062, 256, 21106, 256, 21111, 256, 13589, 256, 21191, 256, 21193, - 256, 21220, 256, 21242, 256, 21253, 256, 21254, 256, 21271, 256, 21321, - 256, 21329, 256, 21338, 256, 21363, 256, 21373, 256, 21375, 256, 21375, - 256, 21375, 256, 55362, 56876, 256, 28784, 256, 21450, 256, 21471, 256, - 55362, 57187, 256, 21483, 256, 21489, 256, 21510, 256, 21662, 256, 21560, - 256, 21576, 256, 21608, 256, 21666, 256, 21750, 256, 21776, 256, 21843, - 256, 21859, 256, 21892, 256, 21892, 256, 21913, 256, 21931, 256, 21939, - 256, 21954, 256, 22294, 256, 22022, 256, 22295, 256, 22097, 256, 22132, - 256, 20999, 256, 22766, 256, 22478, 256, 22516, 256, 22541, 256, 22411, - 256, 22578, 256, 22577, 256, 22700, 256, 55365, 56548, 256, 22770, 256, - 22775, 256, 22790, 256, 22810, 256, 22818, 256, 22882, 256, 55365, 57000, - 256, 55365, 57066, 256, 23020, 256, 23067, 256, 23079, 256, 23000, 256, - 23142, 256, 14062, 256, 14076, 256, 23304, 256, 23358, 256, 23358, 256, - 55366, 56776, 256, 23491, 256, 23512, 256, 23527, 256, 23539, 256, 55366, - 57112, 256, 23551, 256, 23558, 256, 24403, 256, 23586, 256, 14209, 256, - 23648, 256, 23662, 256, 23744, 256, 23693, 256, 55367, 56804, 256, 23875, - 256, 55367, 56806, 256, 23918, 256, 23915, 256, 23932, 256, 24033, 256, - 24034, 256, 14383, 256, 24061, 256, 24104, 256, 24125, 256, 24169, 256, - 14434, 256, 55368, 56707, 256, 14460, 256, 24240, 256, 24243, 256, 24246, - 256, 24266, 256, 55400, 57234, 256, 24318, 256, 55368, 57137, 256, 55368, - 57137, 256, 33281, 256, 24354, 256, 24354, 256, 14535, 256, 55372, 57016, - 256, 55384, 56794, 256, 24418, 256, 24427, 256, 14563, 256, 24474, 256, - 24525, 256, 24535, 256, 24569, 256, 24705, 256, 14650, 256, 14620, 256, - 24724, 256, 55369, 57044, 256, 24775, 256, 24904, 256, 24908, 256, 24910, - 256, 24908, 256, 24954, 256, 24974, 256, 25010, 256, 24996, 256, 25007, - 256, 25054, 256, 25074, 256, 25078, 256, 25104, 256, 25115, 256, 25181, - 256, 25265, 256, 25300, 256, 25424, 256, 55370, 57100, 256, 25405, 256, - 25340, 256, 25448, 256, 25475, 256, 25572, 256, 55370, 57329, 256, 25634, - 256, 25541, 256, 25513, 256, 14894, 256, 25705, 256, 25726, 256, 25757, - 256, 25719, 256, 14956, 256, 25935, 256, 25964, 256, 55372, 56330, 256, - 26083, 256, 26360, 256, 26185, 256, 15129, 256, 26257, 256, 15112, 256, - 15076, 256, 20882, 256, 20885, 256, 26368, 256, 26268, 256, 32941, 256, - 17369, 256, 26391, 256, 26395, 256, 26401, 256, 26462, 256, 26451, 256, - 55372, 57283, 256, 15177, 256, 26618, 256, 26501, 256, 26706, 256, 26757, - 256, 55373, 56429, 256, 26766, 256, 26655, 256, 26900, 256, 15261, 256, - 26946, 256, 27043, 256, 27114, 256, 27304, 256, 55373, 56995, 256, 27355, - 256, 15384, 256, 27425, 256, 55374, 56487, 256, 27476, 256, 15438, 256, - 27506, 256, 27551, 256, 27578, 256, 27579, 256, 55374, 56973, 256, 55367, - 56587, 256, 55374, 57082, 256, 27726, 256, 55375, 56508, 256, 27839, 256, - 27853, 256, 27751, 256, 27926, 256, 27966, 256, 28023, 256, 27969, 256, - 28009, 256, 28024, 256, 28037, 256, 55375, 56606, 256, 27956, 256, 28207, - 256, 28270, 256, 15667, 256, 28363, 256, 28359, 256, 55375, 57041, 256, - 28153, 256, 28526, 256, 55375, 57182, 256, 55375, 57230, 256, 28614, 256, - 28729, 256, 28702, 256, 28699, 256, 15766, 256, 28746, 256, 28797, 256, - 28791, 256, 28845, 256, 55361, 56613, 256, 28997, 256, 55376, 56931, 256, - 29084, 256, 55376, 57259, 256, 29224, 256, 29237, 256, 29264, 256, 55377, - 56840, 256, 29312, 256, 29333, 256, 55377, 57141, 256, 55378, 56340, 256, - 29562, 256, 29579, 256, 16044, 256, 29605, 256, 16056, 256, 16056, 256, - 29767, 256, 29788, 256, 29809, 256, 29829, 256, 29898, 256, 16155, 256, - 29988, 256, 55379, 56374, 256, 30014, 256, 55379, 56466, 256, 30064, 256, - 55368, 56735, 256, 30224, 256, 55379, 57249, 256, 55379, 57272, 256, - 55380, 56388, 256, 16380, 256, 16392, 256, 30452, 256, 55380, 56563, 256, - 55380, 56562, 256, 55380, 56601, 256, 55380, 56627, 256, 30494, 256, - 30495, 256, 30495, 256, 30538, 256, 16441, 256, 30603, 256, 16454, 256, - 16534, 256, 55381, 56349, 256, 30798, 256, 30860, 256, 30924, 256, 16611, - 256, 55381, 56870, 256, 31062, 256, 55381, 56986, 256, 55381, 57029, 256, - 31119, 256, 31211, 256, 16687, 256, 31296, 256, 31306, 256, 31311, 256, - 55382, 56700, 256, 55382, 56999, 256, 55382, 56999, 256, 31470, 256, - 16898, 256, 55382, 57259, 256, 31686, 256, 31689, 256, 16935, 256, 55383, - 56448, 256, 31954, 256, 17056, 256, 31976, 256, 31971, 256, 32000, 256, - 55383, 57222, 256, 32099, 256, 17153, 256, 32199, 256, 32258, 256, 32325, - 256, 17204, 256, 55384, 56872, 256, 55384, 56903, 256, 17241, 256, 55384, - 57049, 256, 32634, 256, 55384, 57150, 256, 32661, 256, 32762, 256, 32773, - 256, 55385, 56538, 256, 55385, 56611, 256, 32864, 256, 55385, 56744, 256, - 32880, 256, 55372, 57183, 256, 17365, 256, 32946, 256, 33027, 256, 17419, - 256, 33086, 256, 23221, 256, 55385, 57255, 256, 55385, 57269, 256, 55372, - 57235, 256, 55372, 57244, 256, 33281, 256, 33284, 256, 36766, 256, 17515, - 256, 33425, 256, 33419, 256, 33437, 256, 21171, 256, 33457, 256, 33459, - 256, 33469, 256, 33510, 256, 55386, 57148, 256, 33509, 256, 33565, 256, - 33635, 256, 33709, 256, 33571, 256, 33725, 256, 33767, 256, 33879, 256, - 33619, 256, 33738, 256, 33740, 256, 33756, 256, 55387, 56374, 256, 55387, - 56683, 256, 55387, 56533, 256, 17707, 256, 34033, 256, 34035, 256, 34070, - 256, 55388, 57290, 256, 34148, 256, 55387, 57132, 256, 17757, 256, 17761, - 256, 55387, 57265, 256, 55388, 56530, 256, 17771, 256, 34384, 256, 34396, - 256, 34407, 256, 34409, 256, 34473, 256, 34440, 256, 34574, 256, 34530, - 256, 34681, 256, 34600, 256, 34667, 256, 34694, 256, 17879, 256, 34785, - 256, 34817, 256, 17913, 256, 34912, 256, 34915, 256, 55389, 56935, 256, - 35031, 256, 35038, 256, 17973, 256, 35066, 256, 13499, 256, 55390, 56494, - 256, 55390, 56678, 256, 18110, 256, 18119, 256, 35488, 256, 35565, 256, - 35722, 256, 35925, 256, 55391, 56488, 256, 36011, 256, 36033, 256, 36123, - 256, 36215, 256, 55391, 57135, 256, 55362, 56324, 256, 36299, 256, 36284, - 256, 36336, 256, 55362, 56542, 256, 36564, 256, 36664, 256, 55393, 56786, - 256, 55393, 56813, 256, 37012, 256, 37105, 256, 37137, 256, 55393, 57134, - 256, 37147, 256, 37432, 256, 37591, 256, 37592, 256, 37500, 256, 37881, - 256, 37909, 256, 55394, 57338, 256, 38283, 256, 18837, 256, 38327, 256, - 55395, 56695, 256, 18918, 256, 38595, 256, 23986, 256, 38691, 256, 55396, - 56645, 256, 55396, 56858, 256, 19054, 256, 19062, 256, 38880, 256, 55397, - 56330, 256, 19122, 256, 55397, 56470, 256, 38923, 256, 38923, 256, 38953, - 256, 55397, 56758, 256, 39138, 256, 19251, 256, 39209, 256, 39335, 256, - 39362, 256, 39422, 256, 19406, 256, 55398, 57136, 256, 39698, 256, 40000, - 256, 40189, 256, 19662, 256, 19693, 256, 40295, 256, 55400, 56526, 256, - 19704, 256, 55400, 56581, 256, 55400, 56846, 256, 55400, 56977, 256, - 40635, 256, 19798, 256, 40697, 256, 40702, 256, 40709, 256, 40719, 256, - 40726, 256, 40763, 256, 55401, 56832, -}; - -/* index tables for the decomposition data */ -#define DECOMP_SHIFT1 6 -#define DECOMP_SHIFT2 4 -static const unsigned char decomp_index0[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 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, 13, 14, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 16, 5, 5, 5, 5, 17, 18, - 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, 19, 20, - 5, 5, 5, 5, 5, 21, 22, 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, - 23, 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, 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, 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, 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, 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, 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, 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, 5, 5, 5, 5, 5, 5, 5, 5, -}; - -static const unsigned short decomp_index1[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 0, 0, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, - 25, 0, 26, 27, 0, 0, 0, 0, 0, 28, 0, 0, 29, 30, 31, 32, 33, 34, 35, 0, - 36, 37, 38, 0, 39, 0, 40, 0, 41, 0, 0, 0, 0, 42, 43, 44, 45, 0, 0, 0, 0, - 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 48, 0, 0, 0, - 0, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 52, 0, 53, 0, 0, 0, 0, - 0, 0, 54, 55, 0, 0, 0, 0, 0, 56, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 58, 59, 0, 0, 0, 60, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, - 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, - 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 67, 0, 68, 0, 0, 69, 0, 0, 0, 70, - 71, 72, 73, 74, 75, 76, 77, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 81, 0, - 82, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 84, 85, 86, 87, 88, 89, 0, 90, 91, 92, 0, 0, 0, 0, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 0, 131, 132, 133, 134, 0, 0, 0, - 0, 0, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 0, - 0, 0, 147, 0, 148, 149, 150, 0, 151, 152, 153, 0, 154, 0, 0, 0, 155, 0, - 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 0, - 0, 0, 0, 0, 0, 167, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 171, 0, 0, 0, 0, 0, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 0, 0, 187, 0, 0, 188, 189, 190, 191, 192, 0, - 193, 194, 195, 196, 197, 0, 198, 0, 0, 0, 199, 200, 201, 202, 203, 204, - 205, 0, 0, 0, 0, 0, 0, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 0, 0, - 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 0, 0, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 0, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 0, 307, 308, 309, 310, 311, 312, 313, 314, 0, 0, 315, - 0, 316, 0, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 345, 346, 0, 0, 0, 0, 0, 0, 0, - 347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 351, 352, 0, 0, 0, 0, 353, 354, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 431, 432, 433, 434, 435, 0, 436, 0, - 0, 437, 0, 0, 0, 0, 0, 0, 438, 439, 440, 441, 442, 443, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 445, - 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const unsigned short decomp_index2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 6, 0, 0, 0, 0, 8, 0, 0, 11, 13, 15, 18, 0, 0, 20, 23, 25, 0, 27, - 31, 35, 0, 39, 42, 45, 48, 51, 54, 0, 57, 60, 63, 66, 69, 72, 75, 78, 81, - 0, 84, 87, 90, 93, 96, 99, 0, 0, 102, 105, 108, 111, 114, 0, 0, 117, 120, - 123, 126, 129, 132, 0, 135, 138, 141, 144, 147, 150, 153, 156, 159, 0, - 162, 165, 168, 171, 174, 177, 0, 0, 180, 183, 186, 189, 192, 0, 195, 198, - 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, - 243, 0, 0, 246, 249, 252, 255, 258, 261, 264, 267, 270, 273, 276, 279, - 282, 285, 288, 291, 294, 297, 300, 303, 0, 0, 306, 309, 312, 315, 318, - 321, 324, 327, 330, 0, 333, 336, 339, 342, 345, 348, 0, 351, 354, 357, - 360, 363, 366, 369, 372, 0, 0, 375, 378, 381, 384, 387, 390, 393, 0, 0, - 396, 399, 402, 405, 408, 411, 0, 0, 414, 417, 420, 423, 426, 429, 432, - 435, 438, 441, 444, 447, 450, 453, 456, 459, 462, 465, 0, 0, 468, 471, - 474, 477, 480, 483, 486, 489, 492, 495, 498, 501, 504, 507, 510, 513, - 516, 519, 522, 525, 528, 531, 534, 537, 539, 542, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 545, 548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 581, 584, 587, - 590, 593, 596, 599, 602, 605, 608, 611, 614, 617, 620, 623, 0, 626, 629, - 632, 635, 638, 641, 0, 0, 644, 647, 650, 653, 656, 659, 662, 665, 668, - 671, 674, 677, 680, 683, 686, 689, 0, 0, 692, 695, 698, 701, 704, 707, - 710, 713, 716, 719, 722, 725, 728, 731, 734, 737, 740, 743, 746, 749, - 752, 755, 758, 761, 764, 767, 770, 773, 776, 779, 782, 785, 788, 791, - 794, 797, 0, 0, 800, 803, 0, 0, 0, 0, 0, 0, 806, 809, 812, 815, 818, 821, - 824, 827, 830, 833, 836, 839, 842, 845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 848, 850, 852, 854, 856, 858, 860, 862, 864, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 866, 869, 872, 875, 878, 881, 0, 0, 884, 886, 888, - 890, 892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 894, 896, 0, 898, 900, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 903, 0, 0, 0, 0, 0, 905, 0, 0, 0, - 908, 0, 0, 0, 0, 0, 910, 913, 916, 919, 921, 924, 927, 0, 930, 0, 933, - 936, 939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 942, 945, 948, 951, 954, 957, 960, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 963, 966, 969, 972, 975, - 0, 978, 980, 982, 984, 987, 990, 992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 994, - 996, 998, 0, 1000, 1002, 0, 0, 0, 1004, 0, 0, 0, 0, 0, 0, 1006, 1009, 0, - 1012, 0, 0, 0, 1015, 0, 0, 0, 0, 1018, 1021, 1024, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1027, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1030, 0, 0, - 0, 0, 0, 0, 1033, 1036, 0, 1039, 0, 0, 0, 1042, 0, 0, 0, 0, 1045, 1048, - 1051, 0, 0, 0, 0, 0, 0, 0, 1054, 1057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1060, - 1063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1066, 1069, 1072, 1075, 0, - 0, 1078, 1081, 0, 0, 1084, 1087, 1090, 1093, 1096, 1099, 0, 0, 1102, - 1105, 1108, 1111, 1114, 1117, 0, 0, 1120, 1123, 1126, 1129, 1132, 1135, - 1138, 1141, 1144, 1147, 1150, 1153, 0, 0, 1156, 1159, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1165, 1168, - 1171, 1174, 1177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1180, 1183, - 1186, 1189, 0, 0, 0, 0, 0, 0, 0, 1192, 0, 1195, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1201, 0, 0, 0, 0, 0, 0, 0, 1204, 0, 0, 1207, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1210, 1213, 1216, - 1219, 1222, 1225, 1228, 1231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1234, - 1237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1240, 1243, 0, 1246, - 0, 0, 0, 1249, 0, 0, 1252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1255, 1258, 1261, 0, 0, 1264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1267, - 0, 0, 1270, 1273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1276, - 1279, 0, 0, 0, 0, 0, 0, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1285, 1288, 1291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1294, 0, 0, 0, 0, 0, 0, 0, 1297, 0, 0, 0, 0, 0, 0, 1300, 1303, 0, 1306, - 1309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1312, 1315, 1318, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1321, 0, 1324, 1327, 1330, 0, 0, 0, 0, - 1333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1336, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1339, 1342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1345, 0, 0, 0, 0, 0, 0, 1347, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1350, 0, 0, 0, 0, 1353, 0, 0, 0, 0, 1356, 0, 0, - 0, 0, 1359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1362, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1365, 0, 1368, 1371, 1374, 1377, 1380, 0, 0, 0, 0, 0, 0, 0, - 1383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1386, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1389, 0, 0, 0, 0, 1392, 0, 0, 0, 0, 1395, 0, 0, 0, 0, - 1398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1401, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1407, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1409, 0, 1412, 0, 1415, 0, - 1418, 0, 1421, 0, 0, 0, 1424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1427, 0, 1430, 0, 0, 1433, 1436, 0, 1439, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1442, 1444, 1446, 0, 1448, 1450, 1452, 1454, 1456, 1458, 1460, 1462, - 1464, 1466, 1468, 0, 1470, 1472, 1474, 1476, 1478, 1480, 1482, 1484, - 1486, 1488, 1490, 1492, 1494, 1496, 1498, 1500, 1502, 1504, 0, 1506, - 1508, 1510, 1512, 1514, 1516, 1518, 1520, 1522, 1524, 1526, 1528, 1530, - 1532, 1534, 1536, 1538, 1540, 1542, 1544, 1546, 1548, 1550, 1552, 1554, - 1556, 1558, 1560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1562, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1564, 1566, 1568, 1570, - 1572, 1574, 1576, 1578, 1580, 1582, 1584, 1586, 1588, 1590, 1592, 1594, - 1596, 1598, 1600, 1602, 1604, 1606, 1608, 1610, 1612, 1614, 1616, 1618, - 1620, 1622, 1624, 1626, 1628, 1630, 1632, 1634, 1636, 1638, 1641, 1644, - 1647, 1650, 1653, 1656, 1659, 1662, 1665, 1668, 1671, 1674, 1677, 1680, - 1683, 1686, 1689, 1692, 1695, 1698, 1701, 1704, 1707, 1710, 1713, 1716, - 1719, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743, 1746, 1749, 1752, - 1755, 1758, 1761, 1764, 1767, 1770, 1773, 1776, 1779, 1782, 1785, 1788, - 1791, 1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1818, 1821, 1824, - 1827, 1830, 1833, 1836, 1839, 1842, 1845, 1848, 1851, 1854, 1857, 1860, - 1863, 1866, 1869, 1872, 1875, 1878, 1881, 1884, 1887, 1890, 1893, 1896, - 1899, 1902, 1905, 1908, 1911, 1914, 1917, 1920, 1923, 1926, 1929, 1932, - 1935, 1938, 1941, 1944, 1947, 1950, 1953, 1956, 1959, 1962, 1965, 1968, - 1971, 1974, 1977, 1980, 1983, 1986, 1989, 1992, 1995, 1998, 2001, 2004, - 2007, 2010, 2013, 2016, 2019, 2022, 2025, 2028, 2031, 2034, 2037, 2040, - 2043, 2046, 2049, 2052, 2055, 2058, 2061, 2064, 2067, 2070, 2073, 2076, - 2079, 2082, 2085, 2088, 2091, 2094, 2097, 2100, 2103, 0, 0, 0, 0, 2106, - 2109, 2112, 2115, 2118, 2121, 2124, 2127, 2130, 2133, 2136, 2139, 2142, - 2145, 2148, 2151, 2154, 2157, 2160, 2163, 2166, 2169, 2172, 2175, 2178, - 2181, 2184, 2187, 2190, 2193, 2196, 2199, 2202, 2205, 2208, 2211, 2214, - 2217, 2220, 2223, 2226, 2229, 2232, 2235, 2238, 2241, 2244, 2247, 2250, - 2253, 2256, 2259, 2262, 2265, 2268, 2271, 2274, 2277, 2280, 2283, 2286, - 2289, 2292, 2295, 2298, 2301, 2304, 2307, 2310, 2313, 2316, 2319, 2322, - 2325, 2328, 2331, 2334, 2337, 2340, 2343, 2346, 2349, 2352, 2355, 2358, - 2361, 2364, 2367, 2370, 2373, 0, 0, 0, 0, 0, 0, 2376, 2379, 2382, 2385, - 2388, 2391, 2394, 2397, 2400, 2403, 2406, 2409, 2412, 2415, 2418, 2421, - 2424, 2427, 2430, 2433, 2436, 2439, 0, 0, 2442, 2445, 2448, 2451, 2454, - 2457, 0, 0, 2460, 2463, 2466, 2469, 2472, 2475, 2478, 2481, 2484, 2487, - 2490, 2493, 2496, 2499, 2502, 2505, 2508, 2511, 2514, 2517, 2520, 2523, - 2526, 2529, 2532, 2535, 2538, 2541, 2544, 2547, 2550, 2553, 2556, 2559, - 2562, 2565, 2568, 2571, 0, 0, 2574, 2577, 2580, 2583, 2586, 2589, 0, 0, - 2592, 2595, 2598, 2601, 2604, 2607, 2610, 2613, 0, 2616, 0, 2619, 0, - 2622, 0, 2625, 2628, 2631, 2634, 2637, 2640, 2643, 2646, 2649, 2652, - 2655, 2658, 2661, 2664, 2667, 2670, 2673, 2676, 2679, 2681, 2684, 2686, - 2689, 2691, 2694, 2696, 2699, 2701, 2704, 2706, 2709, 0, 0, 2711, 2714, - 2717, 2720, 2723, 2726, 2729, 2732, 2735, 2738, 2741, 2744, 2747, 2750, - 2753, 2756, 2759, 2762, 2765, 2768, 2771, 2774, 2777, 2780, 2783, 2786, - 2789, 2792, 2795, 2798, 2801, 2804, 2807, 2810, 2813, 2816, 2819, 2822, - 2825, 2828, 2831, 2834, 2837, 2840, 2843, 2846, 2849, 2852, 2855, 2858, - 2861, 2864, 2867, 0, 2870, 2873, 2876, 2879, 2882, 2885, 2887, 2890, - 2893, 2895, 2898, 2901, 2904, 2907, 2910, 0, 2913, 2916, 2919, 2922, - 2924, 2927, 2929, 2932, 2935, 2938, 2941, 2944, 2947, 2950, 0, 0, 2952, - 2955, 2958, 2961, 2964, 2967, 0, 2969, 2972, 2975, 2978, 2981, 2984, - 2987, 2989, 2992, 2995, 2998, 3001, 3004, 3007, 3010, 3012, 3015, 3018, - 3020, 0, 0, 3022, 3025, 3028, 0, 3031, 3034, 3037, 3040, 3042, 3045, - 3047, 3050, 3052, 0, 3055, 3057, 3059, 3061, 3063, 3065, 3067, 3069, - 3071, 3073, 3075, 0, 0, 0, 0, 0, 0, 3077, 0, 0, 0, 0, 0, 3079, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3082, 3084, 3087, 0, 0, 0, 0, 0, 0, 0, 0, - 3091, 0, 0, 0, 3093, 3096, 0, 3100, 3103, 0, 0, 0, 0, 3107, 0, 3110, 0, - 0, 0, 0, 0, 0, 0, 0, 3113, 3116, 3119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3122, 0, 0, 0, 0, 0, 0, 0, 3127, 3129, 3131, 0, 0, 3133, 3135, - 3137, 3139, 3141, 3143, 3145, 3147, 3149, 3151, 3153, 3155, 3157, 3159, - 3161, 3163, 3165, 3167, 3169, 3171, 3173, 3175, 3177, 3179, 3181, 3183, - 3185, 0, 3187, 3189, 3191, 3193, 3195, 3197, 3199, 3201, 3203, 3205, - 3207, 3209, 3211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3213, 0, 0, 0, 0, 0, - 0, 0, 3216, 3220, 3224, 3226, 0, 3229, 3233, 3237, 0, 3239, 3242, 3244, - 3246, 3248, 3250, 3252, 3254, 3256, 3258, 3260, 0, 3262, 3264, 0, 0, - 3267, 3269, 3271, 3273, 3275, 0, 0, 3277, 3280, 3284, 0, 3287, 0, 3289, - 0, 3291, 0, 3293, 3295, 3297, 3299, 0, 3301, 3303, 3305, 0, 3307, 3309, - 3311, 3313, 3315, 3317, 3319, 0, 3321, 3325, 3327, 3329, 3331, 3333, 0, - 0, 0, 0, 3335, 3337, 3339, 3341, 3343, 0, 0, 0, 0, 0, 0, 3345, 3349, - 3353, 3358, 3362, 3366, 3370, 3374, 3378, 3382, 3386, 3390, 3394, 3398, - 3402, 3406, 3409, 3411, 3414, 3418, 3421, 3423, 3426, 3430, 3435, 3438, - 3440, 3443, 3447, 3449, 3451, 3453, 3455, 3457, 3460, 3464, 3467, 3469, - 3472, 3476, 3481, 3484, 3486, 3489, 3493, 3495, 3497, 3499, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3505, 3508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3511, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3514, 3517, 3520, 0, 0, 0, 0, - 3523, 0, 0, 0, 0, 3526, 0, 0, 3529, 0, 0, 0, 0, 0, 0, 0, 3532, 0, 3535, - 0, 0, 0, 0, 0, 3538, 3541, 0, 3545, 3548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3552, 0, 0, 3555, 0, 0, 3558, 0, 3561, 0, 0, 0, 0, 0, - 0, 3564, 0, 3567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3570, 3573, 3576, 3579, - 3582, 0, 0, 3585, 3588, 0, 0, 3591, 3594, 0, 0, 0, 0, 0, 0, 3597, 3600, - 0, 0, 3603, 3606, 0, 0, 3609, 3612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3615, 3618, 3621, 3624, 3627, 3630, 3633, 3636, 0, 0, - 0, 0, 0, 0, 3639, 3642, 3645, 3648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3651, 3653, 0, 0, 0, 0, 0, 3655, 3657, 3659, 3661, 3663, 3665, 3667, - 3669, 3671, 3673, 3676, 3679, 3682, 3685, 3688, 3691, 3694, 3697, 3700, - 3703, 3706, 3710, 3714, 3718, 3722, 3726, 3730, 3734, 3738, 3742, 3747, - 3752, 3757, 3762, 3767, 3772, 3777, 3782, 3787, 3792, 3797, 3800, 3803, - 3806, 3809, 3812, 3815, 3818, 3821, 3824, 3828, 3832, 3836, 3840, 3844, - 3848, 3852, 3856, 3860, 3864, 3868, 3872, 3876, 3880, 3884, 3888, 3892, - 3896, 3900, 3904, 3908, 3912, 3916, 3920, 3924, 3928, 3932, 3936, 3940, - 3944, 3948, 3952, 3956, 3960, 3964, 3968, 3972, 3974, 3976, 3978, 3980, - 3982, 3984, 3986, 3988, 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, - 4006, 4008, 4010, 4012, 4014, 4016, 4018, 4020, 4022, 4024, 4026, 4028, - 4030, 4032, 4034, 4036, 4038, 4040, 4042, 4044, 4046, 4048, 4050, 4052, - 4054, 4056, 4058, 4060, 4062, 4064, 4066, 4068, 4070, 4072, 4074, 4076, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4078, 0, 0, 0, 0, 0, - 0, 0, 4083, 4087, 4090, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4094, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4097, - 4099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4103, 0, 0, 0, 4105, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4107, 4109, 4111, 4113, 4115, 4117, 4119, 4121, - 4123, 4125, 4127, 4129, 4131, 4133, 4135, 4137, 4139, 4141, 4143, 4145, - 4147, 4149, 4151, 4153, 4155, 4157, 4159, 4161, 4163, 4165, 4167, 4169, - 4171, 4173, 4175, 4177, 4179, 4181, 4183, 4185, 4187, 4189, 4191, 4193, - 4195, 4197, 4199, 4201, 4203, 4205, 4207, 4209, 4211, 4213, 4215, 4217, - 4219, 4221, 4223, 4225, 4227, 4229, 4231, 4233, 4235, 4237, 4239, 4241, - 4243, 4245, 4247, 4249, 4251, 4253, 4255, 4257, 4259, 4261, 4263, 4265, - 4267, 4269, 4271, 4273, 4275, 4277, 4279, 4281, 4283, 4285, 4287, 4289, - 4291, 4293, 4295, 4297, 4299, 4301, 4303, 4305, 4307, 4309, 4311, 4313, - 4315, 4317, 4319, 4321, 4323, 4325, 4327, 4329, 4331, 4333, 4335, 4337, - 4339, 4341, 4343, 4345, 4347, 4349, 4351, 4353, 4355, 4357, 4359, 4361, - 4363, 4365, 4367, 4369, 4371, 4373, 4375, 4377, 4379, 4381, 4383, 4385, - 4387, 4389, 4391, 4393, 4395, 4397, 4399, 4401, 4403, 4405, 4407, 4409, - 4411, 4413, 4415, 4417, 4419, 4421, 4423, 4425, 4427, 4429, 4431, 4433, - 4435, 4437, 4439, 4441, 4443, 4445, 4447, 4449, 4451, 4453, 4455, 4457, - 4459, 4461, 4463, 4465, 4467, 4469, 4471, 4473, 4475, 4477, 4479, 4481, - 4483, 4485, 4487, 4489, 4491, 4493, 4495, 4497, 4499, 4501, 4503, 4505, - 4507, 4509, 4511, 4513, 4515, 4517, 4519, 4521, 4523, 4525, 4527, 4529, - 4531, 4533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4535, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4537, 0, 4539, 4541, 4543, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4545, 0, 4548, 0, 4551, 0, - 4554, 0, 4557, 0, 4560, 0, 4563, 0, 4566, 0, 4569, 0, 4572, 0, 4575, 0, - 4578, 0, 0, 4581, 0, 4584, 0, 4587, 0, 0, 0, 0, 0, 0, 4590, 4593, 0, - 4596, 4599, 0, 4602, 4605, 0, 4608, 4611, 0, 4614, 4617, 0, 0, 0, 0, 0, - 0, 4620, 0, 0, 0, 0, 0, 0, 4623, 4626, 0, 4629, 4632, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4635, 0, 4638, 0, 4641, 0, 4644, 0, 4647, 0, 4650, 0, - 4653, 0, 4656, 0, 4659, 0, 4662, 0, 4665, 0, 4668, 0, 0, 4671, 0, 4674, - 0, 4677, 0, 0, 0, 0, 0, 0, 4680, 4683, 0, 4686, 4689, 0, 4692, 4695, 0, - 4698, 4701, 0, 4704, 4707, 0, 0, 0, 0, 0, 0, 4710, 0, 0, 4713, 4716, - 4719, 4722, 0, 0, 0, 4725, 4728, 0, 4731, 4733, 4735, 4737, 4739, 4741, - 4743, 4745, 4747, 4749, 4751, 4753, 4755, 4757, 4759, 4761, 4763, 4765, - 4767, 4769, 4771, 4773, 4775, 4777, 4779, 4781, 4783, 4785, 4787, 4789, - 4791, 4793, 4795, 4797, 4799, 4801, 4803, 4805, 4807, 4809, 4811, 4813, - 4815, 4817, 4819, 4821, 4823, 4825, 4827, 4829, 4831, 4833, 4835, 4837, - 4839, 4841, 4843, 4845, 4847, 4849, 4851, 4853, 4855, 4857, 4859, 4861, - 4863, 4865, 4867, 4869, 4871, 4873, 4875, 4877, 4879, 4881, 4883, 4885, - 4887, 4889, 4891, 4893, 4895, 4897, 4899, 4901, 4903, 4905, 4907, 4909, - 4911, 4913, 4915, 4917, 0, 0, 0, 4919, 4921, 4923, 4925, 4927, 4929, - 4931, 4933, 4935, 4937, 4939, 4941, 4943, 4945, 4947, 4951, 4955, 4959, - 4963, 4967, 4971, 4975, 4979, 4983, 4987, 4991, 4995, 4999, 5003, 5008, - 5013, 5018, 5023, 5028, 5033, 5038, 5043, 5048, 5053, 5058, 5063, 5068, - 5073, 5078, 5086, 0, 5093, 5097, 5101, 5105, 5109, 5113, 5117, 5121, - 5125, 5129, 5133, 5137, 5141, 5145, 5149, 5153, 5157, 5161, 5165, 5169, - 5173, 5177, 5181, 5185, 5189, 5193, 5197, 5201, 5205, 5209, 5213, 5217, - 5221, 5225, 5229, 5233, 5237, 5239, 5241, 5243, 0, 0, 0, 0, 0, 0, 0, 0, - 5245, 5249, 5252, 5255, 5258, 5261, 5264, 5267, 5270, 5273, 5276, 5279, - 5282, 5285, 5288, 5291, 5294, 5296, 5298, 5300, 5302, 5304, 5306, 5308, - 5310, 5312, 5314, 5316, 5318, 5320, 5322, 5325, 5328, 5331, 5334, 5337, - 5340, 5343, 5346, 5349, 5352, 5355, 5358, 5361, 5364, 5370, 5375, 0, - 5378, 5380, 5382, 5384, 5386, 5388, 5390, 5392, 5394, 5396, 5398, 5400, - 5402, 5404, 5406, 5408, 5410, 5412, 5414, 5416, 5418, 5420, 5422, 5424, - 5426, 5428, 5430, 5432, 5434, 5436, 5438, 5440, 5442, 5444, 5446, 5448, - 5450, 5452, 5454, 5456, 5458, 5460, 5462, 5464, 5466, 5468, 5470, 5472, - 5474, 5476, 5479, 5482, 5485, 5488, 5491, 5494, 5497, 5500, 5503, 5506, - 5509, 5512, 5515, 5518, 5521, 5524, 5527, 5530, 5533, 5536, 5539, 5542, - 5545, 5548, 5552, 5556, 5560, 5563, 5567, 5570, 5574, 5576, 5578, 5580, - 5582, 5584, 5586, 5588, 5590, 5592, 5594, 5596, 5598, 5600, 5602, 5604, - 5606, 5608, 5610, 5612, 5614, 5616, 5618, 5620, 5622, 5624, 5626, 5628, - 5630, 5632, 5634, 5636, 5638, 5640, 5642, 5644, 5646, 5648, 5650, 5652, - 5654, 5656, 5658, 5660, 5662, 5664, 5666, 0, 5668, 5673, 5678, 5683, - 5687, 5692, 5696, 5700, 5706, 5711, 5715, 5719, 5723, 5728, 5733, 5737, - 5741, 5744, 5748, 5753, 5758, 5761, 5767, 5774, 5780, 5784, 5790, 5796, - 5801, 5805, 5809, 5813, 5818, 5824, 5829, 5833, 5837, 5841, 5844, 5847, - 5850, 5853, 5857, 5861, 5867, 5871, 5876, 5882, 5886, 5889, 5892, 5898, - 5903, 5909, 5913, 5919, 5922, 5926, 5930, 5934, 5938, 5942, 5947, 5951, - 5954, 5958, 5962, 5966, 5971, 5975, 5979, 5983, 5989, 5994, 5997, 6003, - 6006, 6011, 6016, 6020, 6024, 6028, 6033, 6036, 6040, 6045, 6048, 6054, - 6058, 6061, 6064, 6067, 6070, 6073, 6076, 6079, 6082, 6085, 6088, 6092, - 6096, 6100, 6104, 6108, 6112, 6116, 6120, 6124, 6128, 6132, 6136, 6140, - 6144, 6148, 6152, 6155, 6158, 6162, 6165, 6168, 6171, 6175, 6179, 6182, - 6185, 6188, 6191, 6194, 6199, 6202, 6205, 6208, 6211, 6214, 6217, 6220, - 6223, 6227, 6232, 6235, 6238, 6241, 6244, 6247, 6250, 6253, 6257, 6261, - 6265, 6269, 6272, 6275, 6278, 6281, 6284, 6287, 6290, 6293, 6296, 6299, - 6303, 6307, 6310, 6314, 6318, 6322, 6325, 6329, 6333, 6338, 6341, 6345, - 6349, 6353, 6357, 6363, 6370, 6373, 6376, 6379, 6382, 6385, 6388, 6391, - 6394, 6397, 6400, 6403, 6406, 6409, 6412, 6415, 6418, 6421, 6424, 6429, - 6432, 6435, 6438, 6443, 6447, 6450, 6453, 6456, 6459, 6462, 6465, 6468, - 6471, 6474, 6477, 6481, 6484, 6487, 6491, 6495, 6498, 6503, 6507, 6510, - 6513, 6516, 6519, 6523, 6527, 6530, 6533, 6536, 6539, 6542, 6545, 6548, - 6551, 6554, 6558, 6562, 6566, 6570, 6574, 6578, 6582, 6586, 6590, 6594, - 6598, 6602, 6606, 6610, 6614, 6618, 6622, 6626, 6630, 6634, 6638, 6642, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6646, 6648, 0, 0, 6650, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6652, 6654, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6656, 6658, 6660, - 6662, 6664, 6666, 6668, 6670, 6672, 6674, 6676, 6678, 6680, 6682, 6684, - 6686, 6688, 6690, 6692, 6694, 6696, 6698, 6700, 6702, 6704, 6706, 6708, - 6710, 6712, 6714, 6716, 6718, 6720, 6722, 6724, 6726, 6728, 6730, 6732, - 6734, 6736, 6738, 6740, 6742, 6744, 6746, 6748, 6750, 6752, 6754, 6756, - 6758, 6760, 6762, 6764, 6766, 6768, 6770, 6772, 6774, 6776, 6778, 6780, - 6782, 6784, 6786, 6788, 6790, 6792, 6794, 6796, 6798, 6800, 6802, 6804, - 6806, 6808, 6810, 6812, 6814, 6816, 6818, 6820, 6822, 6824, 6826, 6828, - 6830, 6832, 6834, 6836, 6838, 6840, 6842, 6844, 6846, 6848, 6850, 6852, - 6854, 6856, 6858, 6860, 6862, 6864, 6866, 6868, 6870, 6872, 6874, 6876, - 6878, 6880, 6882, 6884, 6886, 6888, 6890, 6892, 6894, 6896, 6898, 6900, - 6902, 6904, 6906, 6908, 6910, 6912, 6914, 6916, 6918, 6920, 6922, 6924, - 6926, 6928, 6930, 6932, 6934, 6936, 6938, 6940, 6942, 6944, 6946, 6948, - 6950, 6952, 6954, 6956, 6958, 6960, 6962, 6964, 6966, 6968, 6970, 6972, - 6974, 6976, 6978, 6980, 6982, 6984, 6986, 6988, 6990, 6992, 6994, 6996, - 6998, 7000, 7002, 7004, 7006, 7008, 7010, 7012, 7014, 7016, 7018, 7020, - 7022, 7024, 7026, 7028, 7030, 7032, 7034, 7036, 7038, 7040, 7042, 7044, - 7046, 7048, 7050, 7052, 7054, 7056, 7058, 7060, 7062, 7064, 7066, 7068, - 7070, 7072, 7074, 7076, 7078, 7080, 7082, 7084, 7086, 7088, 7090, 7092, - 7094, 7096, 7098, 7100, 7102, 7104, 7106, 7108, 7110, 7112, 7114, 7116, - 7118, 7120, 7122, 7124, 7126, 7128, 7130, 7132, 7134, 7136, 7138, 7140, - 7142, 7144, 7146, 7148, 7150, 7152, 7154, 7156, 7158, 7160, 7162, 7164, - 7166, 7168, 7170, 7172, 7174, 7176, 7178, 7180, 7182, 7184, 7186, 7188, - 7190, 7192, 7194, 7196, 7198, 7200, 7202, 0, 0, 7204, 0, 7206, 0, 0, - 7208, 7210, 7212, 7214, 7216, 7218, 7220, 7222, 7224, 7226, 0, 7228, 0, - 7230, 0, 0, 7232, 7234, 0, 0, 0, 7236, 7238, 7240, 7242, 7244, 7246, - 7248, 7250, 7252, 7254, 7256, 7258, 7260, 7262, 7264, 7266, 7268, 7270, - 7272, 7274, 7276, 7278, 7280, 7282, 7284, 7286, 7288, 7290, 7292, 7294, - 7296, 7298, 7300, 7302, 7304, 7306, 7308, 7310, 7312, 7314, 7316, 7318, - 7320, 7322, 7324, 7326, 7328, 7330, 7332, 7334, 7336, 7338, 7340, 7342, - 7344, 7346, 7348, 7350, 7352, 7354, 7356, 7358, 7360, 7362, 7364, 7366, - 7368, 7371, 0, 0, 7373, 7375, 7377, 7379, 7381, 7383, 7385, 7387, 7389, - 7391, 7393, 7395, 7397, 7399, 7401, 7403, 7405, 7407, 7409, 7411, 7413, - 7415, 7417, 7419, 7421, 7423, 7425, 7427, 7429, 7431, 7433, 7435, 7437, - 7439, 7441, 7443, 7445, 7447, 7449, 7451, 7453, 7455, 7457, 7459, 7461, - 7463, 7465, 7467, 7469, 7471, 7473, 7475, 7477, 7479, 7481, 7483, 7485, - 7487, 7489, 7491, 7493, 7495, 7497, 7499, 7501, 7503, 7505, 7507, 7509, - 7511, 7513, 7515, 7517, 7519, 7521, 7523, 7525, 7527, 7529, 7531, 7533, - 7535, 7537, 7539, 7541, 7543, 7545, 7547, 7549, 7551, 7553, 7555, 7557, - 7559, 7561, 7563, 7566, 7569, 7572, 7574, 7576, 7578, 7581, 7584, 7587, - 7589, 0, 0, 0, 0, 0, 0, 7591, 7594, 7597, 7600, 7604, 7608, 7611, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7614, 7617, 7620, 7623, 7626, 0, 0, 0, 0, - 0, 7629, 0, 7632, 7635, 7637, 7639, 7641, 7643, 7645, 7647, 7649, 7651, - 7653, 7655, 7658, 7661, 7664, 7667, 7670, 7673, 7676, 7679, 7682, 7685, - 7688, 7691, 0, 7694, 7697, 7700, 7703, 7706, 0, 7709, 0, 7712, 7715, 0, - 7718, 7721, 0, 7724, 7727, 7730, 7733, 7736, 7739, 7742, 7745, 7748, - 7751, 7754, 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, 7772, 7774, - 7776, 7778, 7780, 7782, 7784, 7786, 7788, 7790, 7792, 7794, 7796, 7798, - 7800, 7802, 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, 7820, 7822, - 7824, 7826, 7828, 7830, 7832, 7834, 7836, 7838, 7840, 7842, 7844, 7846, - 7848, 7850, 7852, 7854, 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, - 7872, 7874, 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, 7892, 7894, - 7896, 7898, 7900, 7902, 7904, 7906, 7908, 7910, 7912, 7914, 7916, 7918, - 7920, 7922, 7924, 7926, 7928, 7930, 7932, 7934, 7936, 7938, 7940, 7942, - 7944, 7946, 7948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7950, 7952, 7954, 7956, 7958, 7960, 7962, 7964, 7966, 7968, 7970, 7972, - 7974, 7976, 7978, 7980, 7982, 7984, 7986, 7988, 7990, 7992, 7994, 7996, - 7999, 8002, 8005, 8008, 8011, 8014, 8017, 8020, 8023, 8026, 8029, 8032, - 8035, 8038, 8041, 8044, 8047, 8050, 8052, 8054, 8056, 8058, 8061, 8064, - 8067, 8070, 8073, 8076, 8079, 8082, 8085, 8088, 8091, 8094, 8097, 8100, - 8103, 8106, 8109, 8112, 8115, 8118, 8121, 8124, 8127, 8130, 8133, 8136, - 8139, 8142, 8145, 8148, 8151, 8154, 8157, 8160, 8163, 8166, 8169, 8172, - 8175, 8178, 8181, 8184, 8187, 8190, 8193, 8196, 8199, 8202, 8205, 8208, - 8211, 8214, 8217, 8220, 8223, 8226, 8229, 8232, 8235, 8238, 8241, 8244, - 8247, 8250, 8253, 8256, 8259, 8262, 8265, 8268, 8271, 8274, 8277, 8280, - 8283, 8286, 8289, 8292, 8295, 8298, 8301, 8304, 8307, 8310, 8313, 8316, - 8319, 8322, 8325, 8328, 8331, 8334, 8337, 8340, 8344, 8348, 8352, 8356, - 8360, 8364, 8367, 8370, 8373, 8376, 8379, 8382, 8385, 8388, 8391, 8394, - 8397, 8400, 8403, 8406, 8409, 8412, 8415, 8418, 8421, 8424, 8427, 8430, - 8433, 8436, 8439, 8442, 8445, 8448, 8451, 8454, 8457, 8460, 8463, 8466, - 8469, 8472, 8475, 8478, 8481, 8484, 8487, 8490, 8493, 8496, 8499, 8502, - 8505, 8508, 8511, 8514, 8517, 8520, 8523, 8526, 8529, 8532, 8535, 8538, - 8541, 8544, 8547, 8550, 8553, 8556, 8559, 8562, 8565, 8568, 8571, 8574, - 8577, 8580, 8583, 8586, 8589, 8592, 8595, 8598, 8601, 8604, 8607, 8610, - 8613, 8616, 8619, 8622, 8625, 8628, 8631, 8634, 8637, 8640, 8643, 8646, - 8649, 8652, 8655, 8658, 8661, 8664, 8667, 8670, 8673, 8676, 8679, 8682, - 8685, 8688, 8691, 8694, 8697, 8700, 8703, 8706, 8709, 8712, 8715, 8718, - 8721, 8724, 8727, 8730, 8733, 8736, 8739, 8742, 8745, 8748, 8751, 8754, - 8757, 8760, 8763, 8766, 8769, 8772, 8775, 8778, 8781, 8784, 8787, 8790, - 8794, 8798, 8802, 8805, 8808, 8811, 8814, 8817, 8820, 8823, 8826, 8829, - 8832, 8835, 8838, 8841, 8844, 8847, 8850, 8853, 8856, 8859, 8862, 8865, - 8868, 8871, 8874, 8877, 8880, 8883, 8886, 8889, 8892, 8895, 8898, 8901, - 8904, 8907, 8910, 8913, 8916, 8919, 8922, 8925, 8928, 8931, 8934, 8937, - 8940, 8943, 8946, 8949, 8952, 8955, 8958, 8961, 8964, 8967, 8970, 8973, - 8976, 8979, 8982, 8985, 8988, 8991, 8994, 8997, 9000, 9003, 9006, 9009, - 9012, 9015, 9018, 0, 0, 9021, 9025, 9029, 9033, 9037, 9041, 9045, 9049, - 9053, 9057, 9061, 9065, 9069, 9073, 9077, 9081, 9085, 9089, 9093, 9097, - 9101, 9105, 9109, 9113, 9117, 9121, 9125, 9129, 9133, 9137, 9141, 9145, - 9149, 9153, 9157, 9161, 9165, 9169, 9173, 9177, 9181, 9185, 9189, 9193, - 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9233, 9237, 9241, - 9245, 9249, 9253, 9257, 9261, 9265, 9269, 9273, 0, 0, 9277, 9281, 9285, - 9289, 9293, 9297, 9301, 9305, 9309, 9313, 9317, 9321, 9325, 9329, 9333, - 9337, 9341, 9345, 9349, 9353, 9357, 9361, 9365, 9369, 9373, 9377, 9381, - 9385, 9389, 9393, 9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, - 9433, 9437, 9441, 9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, - 9481, 9485, 9489, 0, 0, 0, 0, 0, 0, 0, 0, 9493, 9497, 9501, 9506, 9511, - 9516, 9521, 9526, 9531, 9536, 9540, 9559, 9568, 0, 0, 0, 9573, 9575, - 9577, 9579, 9581, 9583, 9585, 9587, 9589, 9591, 0, 0, 0, 0, 0, 0, 9593, - 9595, 9597, 9599, 9601, 9603, 9605, 9607, 9609, 9611, 9613, 9615, 9617, - 9619, 9621, 9623, 9625, 9627, 9629, 9631, 9633, 0, 0, 9635, 9637, 9639, - 9641, 9643, 9645, 9647, 9649, 9651, 9653, 9655, 9657, 0, 9659, 9661, - 9663, 9665, 9667, 9669, 9671, 9673, 9675, 9677, 9679, 9681, 9683, 9685, - 9687, 9689, 9691, 9693, 9695, 0, 9697, 9699, 9701, 9703, 0, 0, 0, 0, - 9705, 9708, 9711, 0, 9714, 0, 9717, 9720, 9723, 9726, 9729, 9732, 9735, - 9738, 9741, 9744, 9747, 9749, 9751, 9753, 9755, 9757, 9759, 9761, 9763, - 9765, 9767, 9769, 9771, 9773, 9775, 9777, 9779, 9781, 9783, 9785, 9787, - 9789, 9791, 9793, 9795, 9797, 9799, 9801, 9803, 9805, 9807, 9809, 9811, - 9813, 9815, 9817, 9819, 9821, 9823, 9825, 9827, 9829, 9831, 9833, 9835, - 9837, 9839, 9841, 9843, 9845, 9847, 9849, 9851, 9853, 9855, 9857, 9859, - 9861, 9863, 9865, 9867, 9869, 9871, 9873, 9875, 9877, 9879, 9881, 9883, - 9885, 9887, 9889, 9891, 9893, 9895, 9897, 9899, 9901, 9903, 9905, 9907, - 9909, 9911, 9913, 9915, 9917, 9919, 9921, 9923, 9925, 9927, 9929, 9931, - 9933, 9935, 9937, 9939, 9941, 9943, 9945, 9947, 9949, 9951, 9953, 9955, - 9957, 9959, 9961, 9963, 9965, 9967, 9969, 9971, 9973, 9975, 9977, 9979, - 9981, 9984, 9987, 9990, 9993, 9996, 9999, 10002, 0, 0, 0, 0, 10005, - 10007, 10009, 10011, 10013, 10015, 10017, 10019, 10021, 10023, 10025, - 10027, 10029, 10031, 10033, 10035, 10037, 10039, 10041, 10043, 10045, - 10047, 10049, 10051, 10053, 10055, 10057, 10059, 10061, 10063, 10065, - 10067, 10069, 10071, 10073, 10075, 10077, 10079, 10081, 10083, 10085, - 10087, 10089, 10091, 10093, 10095, 10097, 10099, 10101, 10103, 10105, - 10107, 10109, 10111, 10113, 10115, 10117, 10119, 10121, 10123, 10125, - 10127, 10129, 10131, 10133, 10135, 10137, 10139, 10141, 10143, 10145, - 10147, 10149, 10151, 10153, 10155, 10157, 10159, 10161, 10163, 10165, - 10167, 10169, 10171, 10173, 10175, 10177, 10179, 10181, 10183, 10185, - 10187, 10189, 10191, 10193, 10195, 10197, 10199, 10201, 10203, 10205, - 10207, 10209, 10211, 10213, 10215, 10217, 10219, 10221, 10223, 10225, - 10227, 10229, 10231, 10233, 10235, 10237, 10239, 10241, 10243, 10245, - 10247, 10249, 10251, 10253, 10255, 10257, 10259, 10261, 10263, 10265, - 10267, 10269, 10271, 10273, 10275, 10277, 10279, 10281, 10283, 10285, - 10287, 10289, 10291, 10293, 10295, 10297, 10299, 10301, 10303, 10305, - 10307, 10309, 10311, 10313, 10315, 10317, 10319, 10321, 10323, 10325, - 10327, 10329, 10331, 10333, 10335, 10337, 10339, 10341, 10343, 10345, - 10347, 10349, 10351, 10353, 10355, 10357, 10359, 10361, 10363, 10365, - 10367, 10369, 10371, 10373, 10375, 10377, 10379, 10381, 10383, 0, 0, 0, - 10385, 10387, 10389, 10391, 10393, 10395, 0, 0, 10397, 10399, 10401, - 10403, 10405, 10407, 0, 0, 10409, 10411, 10413, 10415, 10417, 10419, 0, - 0, 10421, 10423, 10425, 0, 0, 0, 10427, 10429, 10431, 10433, 10435, - 10437, 10439, 0, 10441, 10443, 10445, 10447, 10449, 10451, 10453, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 10455, 0, 10460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 10465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10470, 10475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10480, 10485, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10490, 10495, 0, 10500, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10505, 10510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10515, 10520, 10525, 10530, 10535, 10540, 10545, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10550, 10555, 10560, - 10565, 10570, 10575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10580, - 10582, 10584, 10586, 10588, 10590, 10592, 10594, 10596, 10598, 10600, - 10602, 10604, 10606, 10608, 10610, 10612, 10614, 10616, 10618, 10620, - 10622, 10624, 10626, 10628, 10630, 10632, 10634, 10636, 10638, 10640, - 10642, 10644, 10646, 10648, 10650, 10652, 10654, 10656, 10658, 10660, - 10662, 10664, 10666, 10668, 10670, 10672, 10674, 10676, 10678, 10680, - 10682, 10684, 10686, 10688, 10690, 10692, 10694, 10696, 10698, 10700, - 10702, 10704, 10706, 10708, 10710, 10712, 10714, 10716, 10718, 10720, - 10722, 10724, 10726, 10728, 10730, 10732, 10734, 10736, 10738, 10740, - 10742, 10744, 10746, 10748, 0, 10750, 10752, 10754, 10756, 10758, 10760, - 10762, 10764, 10766, 10768, 10770, 10772, 10774, 10776, 10778, 10780, - 10782, 10784, 10786, 10788, 10790, 10792, 10794, 10796, 10798, 10800, - 10802, 10804, 10806, 10808, 10810, 10812, 10814, 10816, 10818, 10820, - 10822, 10824, 10826, 10828, 10830, 10832, 10834, 10836, 10838, 10840, - 10842, 10844, 10846, 10848, 10850, 10852, 10854, 10856, 10858, 10860, - 10862, 10864, 10866, 10868, 10870, 10872, 10874, 10876, 10878, 10880, - 10882, 10884, 10886, 10888, 10890, 0, 10892, 10894, 0, 0, 10896, 0, 0, - 10898, 10900, 0, 0, 10902, 10904, 10906, 10908, 0, 10910, 10912, 10914, - 10916, 10918, 10920, 10922, 10924, 10926, 10928, 10930, 10932, 0, 10934, - 0, 10936, 10938, 10940, 10942, 10944, 10946, 10948, 0, 10950, 10952, - 10954, 10956, 10958, 10960, 10962, 10964, 10966, 10968, 10970, 10972, - 10974, 10976, 10978, 10980, 10982, 10984, 10986, 10988, 10990, 10992, - 10994, 10996, 10998, 11000, 11002, 11004, 11006, 11008, 11010, 11012, - 11014, 11016, 11018, 11020, 11022, 11024, 11026, 11028, 11030, 11032, - 11034, 11036, 11038, 11040, 11042, 11044, 11046, 11048, 11050, 11052, - 11054, 11056, 11058, 11060, 11062, 11064, 11066, 11068, 11070, 11072, - 11074, 11076, 11078, 0, 11080, 11082, 11084, 11086, 0, 0, 11088, 11090, - 11092, 11094, 11096, 11098, 11100, 11102, 0, 11104, 11106, 11108, 11110, - 11112, 11114, 11116, 0, 11118, 11120, 11122, 11124, 11126, 11128, 11130, - 11132, 11134, 11136, 11138, 11140, 11142, 11144, 11146, 11148, 11150, - 11152, 11154, 11156, 11158, 11160, 11162, 11164, 11166, 11168, 11170, - 11172, 0, 11174, 11176, 11178, 11180, 0, 11182, 11184, 11186, 11188, - 11190, 0, 11192, 0, 0, 0, 11194, 11196, 11198, 11200, 11202, 11204, - 11206, 0, 11208, 11210, 11212, 11214, 11216, 11218, 11220, 11222, 11224, - 11226, 11228, 11230, 11232, 11234, 11236, 11238, 11240, 11242, 11244, - 11246, 11248, 11250, 11252, 11254, 11256, 11258, 11260, 11262, 11264, - 11266, 11268, 11270, 11272, 11274, 11276, 11278, 11280, 11282, 11284, - 11286, 11288, 11290, 11292, 11294, 11296, 11298, 11300, 11302, 11304, - 11306, 11308, 11310, 11312, 11314, 11316, 11318, 11320, 11322, 11324, - 11326, 11328, 11330, 11332, 11334, 11336, 11338, 11340, 11342, 11344, - 11346, 11348, 11350, 11352, 11354, 11356, 11358, 11360, 11362, 11364, - 11366, 11368, 11370, 11372, 11374, 11376, 11378, 11380, 11382, 11384, - 11386, 11388, 11390, 11392, 11394, 11396, 11398, 11400, 11402, 11404, - 11406, 11408, 11410, 11412, 11414, 11416, 11418, 11420, 11422, 11424, - 11426, 11428, 11430, 11432, 11434, 11436, 11438, 11440, 11442, 11444, - 11446, 11448, 11450, 11452, 11454, 11456, 11458, 11460, 11462, 11464, - 11466, 11468, 11470, 11472, 11474, 11476, 11478, 11480, 11482, 11484, - 11486, 11488, 11490, 11492, 11494, 11496, 11498, 11500, 11502, 11504, - 11506, 11508, 11510, 11512, 11514, 11516, 11518, 11520, 11522, 11524, - 11526, 11528, 11530, 11532, 11534, 11536, 11538, 11540, 11542, 11544, - 11546, 11548, 11550, 11552, 11554, 11556, 11558, 11560, 11562, 11564, - 11566, 11568, 11570, 11572, 11574, 11576, 11578, 11580, 11582, 11584, - 11586, 11588, 11590, 11592, 11594, 11596, 11598, 11600, 11602, 11604, - 11606, 11608, 11610, 11612, 11614, 11616, 11618, 11620, 11622, 11624, - 11626, 11628, 11630, 11632, 11634, 11636, 11638, 11640, 11642, 11644, - 11646, 11648, 11650, 11652, 11654, 11656, 11658, 11660, 11662, 11664, - 11666, 11668, 11670, 11672, 11674, 11676, 11678, 11680, 11682, 11684, - 11686, 11688, 11690, 11692, 11694, 11696, 11698, 11700, 11702, 11704, - 11706, 11708, 11710, 11712, 11714, 11716, 11718, 11720, 11722, 11724, - 11726, 11728, 11730, 11732, 11734, 11736, 11738, 11740, 11742, 11744, - 11746, 11748, 11750, 11752, 11754, 11756, 11758, 11760, 11762, 11764, - 11766, 11768, 11770, 11772, 11774, 11776, 11778, 11780, 11782, 11784, - 11786, 11788, 11790, 11792, 11794, 11796, 11798, 11800, 11802, 11804, - 11806, 11808, 11810, 11812, 11814, 11816, 11818, 11820, 11822, 11824, - 11826, 11828, 11830, 11832, 11834, 11836, 11838, 11840, 11842, 11844, - 11846, 11848, 11850, 11852, 11854, 11856, 11858, 11860, 11862, 11864, - 11866, 11868, 11870, 11872, 11874, 11876, 11878, 11880, 11882, 11884, - 11886, 0, 0, 11888, 11890, 11892, 11894, 11896, 11898, 11900, 11902, - 11904, 11906, 11908, 11910, 11912, 11914, 11916, 11918, 11920, 11922, - 11924, 11926, 11928, 11930, 11932, 11934, 11936, 11938, 11940, 11942, - 11944, 11946, 11948, 11950, 11952, 11954, 11956, 11958, 11960, 11962, - 11964, 11966, 11968, 11970, 11972, 11974, 11976, 11978, 11980, 11982, - 11984, 11986, 11988, 11990, 11992, 11994, 11996, 11998, 12000, 12002, - 12004, 12006, 12008, 12010, 12012, 12014, 12016, 12018, 12020, 12022, - 12024, 12026, 12028, 12030, 12032, 12034, 12036, 12038, 12040, 12042, - 12044, 12046, 12048, 12050, 12052, 12054, 12056, 12058, 12060, 12062, - 12064, 12066, 12068, 12070, 12072, 12074, 12076, 12078, 12080, 12082, - 12084, 12086, 12088, 12090, 12092, 12094, 12096, 12098, 12100, 12102, - 12104, 12106, 12108, 12110, 12112, 12114, 12116, 12118, 12120, 12122, - 12124, 12126, 12128, 12130, 12132, 12134, 12136, 12138, 12140, 12142, - 12144, 12146, 12148, 12150, 12152, 12154, 12156, 12158, 12160, 12162, - 12164, 12166, 12168, 12170, 12172, 12174, 12176, 12178, 12180, 12182, - 12184, 12186, 12188, 12190, 12192, 12194, 12196, 12198, 12200, 12202, - 12204, 12206, 12208, 12210, 12212, 12214, 12216, 12218, 12220, 12222, - 12224, 12226, 12228, 12230, 12232, 12234, 12236, 12238, 12240, 12242, - 12244, 12246, 12248, 12250, 12252, 12254, 12256, 12258, 12260, 12262, - 12264, 12266, 12268, 12270, 12272, 12274, 12276, 12278, 12280, 12282, - 12284, 12286, 12288, 12290, 12292, 12294, 12296, 12298, 12300, 12302, - 12304, 12306, 12308, 12310, 12312, 12314, 12316, 12318, 12320, 12322, - 12324, 12326, 12328, 12330, 12332, 12334, 12336, 12338, 12340, 12342, - 12344, 12346, 12348, 12350, 12352, 12354, 12356, 12358, 12360, 12362, - 12364, 12366, 12368, 12370, 12372, 12374, 12376, 12378, 12380, 12382, - 12384, 12386, 12388, 12390, 12392, 12394, 12396, 12398, 12400, 12402, - 12404, 12406, 12408, 12410, 12412, 12414, 12416, 12418, 12420, 12422, - 12424, 12426, 12428, 12430, 12432, 12434, 12436, 12438, 12440, 12442, - 12444, 12446, 12448, 12450, 12452, 12454, 12456, 12458, 12460, 12462, - 12464, 12466, 12468, 12470, 0, 0, 12472, 12474, 12476, 12478, 12480, - 12482, 12484, 12486, 12488, 12490, 12492, 12494, 12496, 12498, 12500, - 12502, 12504, 12506, 12508, 12510, 12512, 12514, 12516, 12518, 12520, - 12522, 12524, 12526, 12528, 12530, 12532, 12534, 12536, 12538, 12540, - 12542, 12544, 12546, 12548, 12550, 12552, 12554, 12556, 12558, 12560, - 12562, 12564, 12566, 12568, 12570, 12572, 12574, 12576, 12578, 0, 12580, - 12582, 12584, 12586, 12588, 12590, 12592, 12594, 12596, 12598, 12600, - 12602, 12604, 12606, 12608, 12610, 12612, 12614, 12616, 12618, 12620, - 12622, 12624, 12626, 12628, 12630, 12632, 0, 12634, 12636, 0, 12638, 0, - 0, 12640, 0, 12642, 12644, 12646, 12648, 12650, 12652, 12654, 12656, - 12658, 12660, 0, 12662, 12664, 12666, 12668, 0, 12670, 0, 12672, 0, 0, 0, - 0, 0, 0, 12674, 0, 0, 0, 0, 12676, 0, 12678, 0, 12680, 0, 12682, 12684, - 12686, 0, 12688, 12690, 0, 12692, 0, 0, 12694, 0, 12696, 0, 12698, 0, - 12700, 0, 12702, 0, 12704, 12706, 0, 12708, 0, 0, 12710, 12712, 12714, - 12716, 0, 12718, 12720, 12722, 12724, 12726, 12728, 12730, 0, 12732, - 12734, 12736, 12738, 0, 12740, 12742, 12744, 12746, 0, 12748, 0, 12750, - 12752, 12754, 12756, 12758, 12760, 12762, 12764, 12766, 12768, 0, 12770, - 12772, 12774, 12776, 12778, 12780, 12782, 12784, 12786, 12788, 12790, - 12792, 12794, 12796, 12798, 12800, 12802, 0, 0, 0, 0, 0, 12804, 12806, - 12808, 0, 12810, 12812, 12814, 12816, 12818, 0, 12820, 12822, 12824, - 12826, 12828, 12830, 12832, 12834, 12836, 12838, 12840, 12842, 12844, - 12846, 12848, 12850, 12852, 0, 0, 0, 0, 12854, 12857, 12860, 12863, - 12866, 12869, 12872, 12875, 12878, 12881, 12884, 0, 0, 0, 0, 0, 12887, - 12891, 12895, 12899, 12903, 12907, 12911, 12915, 12919, 12923, 12927, - 12931, 12935, 12939, 12943, 12947, 12951, 12955, 12959, 12963, 12967, - 12971, 12975, 12979, 12983, 12987, 12991, 12995, 12997, 12999, 13002, 0, - 13005, 13007, 13009, 13011, 13013, 13015, 13017, 13019, 13021, 13023, - 13025, 13027, 13029, 13031, 13033, 13035, 13037, 13039, 13041, 13043, - 13045, 13047, 13049, 13051, 13053, 13055, 13057, 13060, 13063, 13066, - 13069, 13073, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13076, 13079, 13082, 0, 0, 0, - 13085, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13088, 13091, 13094, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13096, 13098, 13100, 13102, 13104, - 13106, 13108, 13110, 13112, 13114, 13116, 13118, 13120, 13122, 13124, - 13126, 13128, 13130, 13132, 13134, 13136, 13138, 13140, 13142, 13144, - 13146, 13148, 13150, 13152, 13154, 13156, 13158, 13160, 13162, 13164, - 13166, 13168, 13170, 13172, 13174, 13176, 13178, 13180, 13182, 0, 0, 0, - 0, 13184, 13188, 13192, 13196, 13200, 13204, 13208, 13212, 13216, 0, 0, - 0, 0, 0, 0, 0, 13220, 13222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 13224, 13226, 13228, 13230, 13233, 13235, 13237, 13239, 13241, 13243, - 13245, 13247, 13249, 13251, 13254, 13256, 13258, 13260, 13262, 13265, - 13267, 13269, 13271, 13274, 13276, 13278, 13280, 13282, 13284, 13287, - 13289, 13291, 13293, 13295, 13297, 13299, 13301, 13303, 13305, 13307, - 13309, 13311, 13313, 13315, 13317, 13319, 13321, 13323, 13325, 13327, - 13329, 13331, 13333, 13336, 13338, 13340, 13342, 13345, 13347, 13349, - 13351, 13353, 13355, 13357, 13359, 13361, 13363, 13365, 13367, 13369, - 13371, 13373, 13375, 13377, 13379, 13381, 13383, 13385, 13387, 13389, - 13391, 13393, 13395, 13397, 13399, 13401, 13403, 13405, 13407, 13409, - 13412, 13414, 13416, 13418, 13420, 13422, 13424, 13427, 13430, 13432, - 13434, 13436, 13438, 13440, 13442, 13444, 13446, 13448, 13450, 13453, - 13455, 13457, 13459, 13461, 13464, 13466, 13468, 13470, 13472, 13474, - 13476, 13478, 13480, 13482, 13485, 13487, 13490, 13492, 13494, 13496, - 13498, 13500, 13502, 13504, 13506, 13508, 13510, 13512, 13515, 13517, - 13519, 13521, 13523, 13525, 13528, 13530, 13533, 13536, 13538, 13540, - 13542, 13544, 13547, 13550, 13552, 13554, 13556, 13558, 13560, 13562, - 13564, 13566, 13568, 13570, 13572, 13575, 13577, 13579, 13581, 13583, - 13585, 13587, 13589, 13591, 13593, 13595, 13597, 13599, 13601, 13603, - 13605, 13607, 13609, 13611, 13613, 13616, 13618, 13620, 13622, 13624, - 13626, 13629, 13631, 13633, 13635, 13637, 13639, 13641, 13643, 13645, - 13647, 13649, 13651, 13654, 13656, 13658, 13660, 13662, 13664, 13666, - 13668, 13670, 13672, 13674, 13676, 13678, 13680, 13682, 13684, 13686, - 13688, 13690, 13693, 13695, 13697, 13699, 13701, 13703, 13706, 13708, - 13710, 13712, 13714, 13716, 13718, 13720, 13722, 13725, 13727, 13729, - 13731, 13734, 13736, 13738, 13740, 13742, 13744, 13746, 13749, 13752, - 13755, 13757, 13760, 13762, 13764, 13766, 13768, 13770, 13772, 13774, - 13776, 13778, 13780, 13783, 13785, 13787, 13789, 13791, 13793, 13795, - 13798, 13800, 13802, 13805, 13808, 13810, 13812, 13814, 13816, 13818, - 13820, 13822, 13824, 13826, 13829, 13831, 13834, 13836, 13839, 13841, - 13843, 13845, 13848, 13850, 13852, 13855, 13858, 13860, 13862, 13864, - 13866, 13868, 13870, 13872, 13874, 13876, 13878, 13880, 13882, 13884, - 13887, 13889, 13892, 13894, 13897, 13899, 13902, 13905, 13908, 13910, - 13912, 13914, 13917, 13920, 13923, 13926, 13928, 13930, 13932, 13934, - 13936, 13938, 13940, 13942, 13945, 13947, 13949, 13951, 13953, 13956, - 13958, 13961, 13964, 13966, 13968, 13970, 13972, 13974, 13976, 13979, - 13982, 13985, 13987, 13989, 13992, 13994, 13996, 13998, 14001, 14003, - 14005, 14007, 14009, 14011, 14014, 14016, 14018, 14020, 14022, 14024, - 14026, 14029, 14032, 14034, 14037, 14039, 14042, 14044, 14046, 14048, - 14051, 14054, 14056, 14059, 14061, 14064, 14066, 14068, 14070, 14072, - 14074, 14076, 14079, 14082, 14085, 14088, 14090, 14092, 14094, 14096, - 14098, 14100, 14102, 14104, 14106, 14108, 14110, 14112, 14115, 14117, - 14119, 14121, 14123, 14125, 14127, 14129, 14131, 14133, 14135, 14137, - 14139, 14142, 14145, 14148, 14150, 14152, 14154, 14156, 14159, 14161, - 14164, 14166, 14168, 14171, 14174, 14176, 14178, 14180, 14182, 14184, - 14186, 14188, 14190, 14192, 14194, 14196, 14198, 14200, 14202, 14204, - 14206, 14208, 14210, 14212, 14215, 14217, 14219, 14221, 14223, 14225, - 14228, 14231, 14233, 14235, 14237, 14239, 14241, 14243, 14246, 14248, - 14250, 14252, 14254, 14257, 14260, 14262, 14264, 14266, 14269, 14271, - 14273, 14276, 14279, 14281, 14283, 14285, 14288, 14290, 14292, 14294, - 14296, 14298, 14300, 14302, 14305, 14307, 14309, 14311, 14314, 14316, - 14318, 14320, 14322, 14325, 14328, 14330, 14332, 14334, 14337, 14339, - 14342, 14344, 14346, 14348, 14351, 14353, 14355, 14357, 14359, 14361, - 14363, 14365, 14368, 14370, 14372, 14374, 14376, 14378, 14380, 14383, - 14385, 14388, 14391, 14394, 14396, 14398, 14400, 14402, 14404, 14406, - 14408, 14410, 0, 0, -}; - -/* NFC pairs */ -#define COMP_SHIFT1 2 -#define COMP_SHIFT2 1 -static const unsigned short comp_index0[] = { - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, - 5, 6, 7, 0, 0, 0, 0, 8, 0, 9, 10, 0, 0, 0, 11, 12, 13, 14, 0, 0, 0, 0, 0, - 15, 16, 17, 0, 0, 0, 0, 18, 19, 20, 21, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, - 23, 24, 25, 26, 0, 0, 0, 0, 27, 28, 29, 30, 0, 0, 0, 0, 31, 32, 33, 34, - 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 36, 0, 37, 38, 39, 0, 0, 0, 40, 41, 42, - 43, 0, 0, 0, 0, 44, 45, 46, 0, 0, 0, 0, 0, 47, 48, 49, 50, 0, 0, 0, 51, - 52, 53, 54, 0, 0, 0, 0, 55, 56, 0, 0, 0, 0, 0, 0, 57, 58, 59, 60, 0, 0, - 0, 0, 61, 62, 63, 0, 0, 0, 0, 0, 64, 65, 66, 67, 0, 0, 0, 68, 69, 70, 71, - 0, 0, 0, 0, 72, 0, 73, 0, 0, 0, 0, 0, 74, 0, 75, 0, 0, 0, 0, 0, 76, 0, 0, - 0, 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 80, 81, 82, 83, 0, 0, 0, 0, 84, - 85, 86, 0, 0, 0, 0, 0, 87, 88, 0, 89, 0, 0, 0, 90, 91, 0, 92, 0, 0, 0, 0, - 0, 93, 94, 95, 0, 0, 0, 0, 96, 97, 98, 99, 0, 0, 0, 0, 100, 0, 0, 0, 0, - 0, 0, 101, 102, 0, 103, 0, 0, 0, 0, 104, 105, 106, 107, 0, 0, 0, 0, 108, - 109, 110, 111, 0, 0, 0, 0, 112, 113, 0, 0, 0, 0, 0, 114, 115, 116, 117, - 0, 0, 0, 0, 118, 119, 120, 121, 0, 0, 0, 0, 122, 0, 123, 0, 0, 0, 0, 124, - 125, 126, 127, 128, 0, 0, 0, 129, 130, 131, 132, 0, 0, 0, 0, 133, 134, 0, - 0, 0, 0, 0, 0, 135, 136, 137, 138, 0, 0, 0, 139, 140, 141, 142, 0, 0, 0, - 0, 0, 143, 144, 145, 0, 0, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0, 150, 0, - 151, 0, 0, 0, 0, 152, 153, 154, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, - 156, 157, 158, 0, 0, 0, 0, 0, 159, 160, 161, 162, 0, 0, 0, 163, 0, 0, 0, - 164, 0, 0, 0, 165, 166, 0, 0, 0, 0, 0, 0, 167, 0, 0, 0, 0, 0, 0, 0, 168, - 0, 0, 0, 0, 0, 0, 169, 170, 0, 0, 0, 0, 0, 0, 171, 0, 0, 0, 0, 0, 0, 0, - 172, 173, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 175, 176, 0, 0, 0, 0, - 0, 0, 177, 178, 0, 0, 0, 0, 0, 0, 179, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, - 0, 0, 0, 181, 182, 183, 0, 0, 0, 0, 0, 184, 185, 0, 0, 0, 0, 0, 0, 186, - 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, 0, 0, 0, 0, 188, 189, 0, 0, 0, 0, 0, 0, - 190, 0, 0, 0, 0, 0, 0, 0, 191, 192, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, - 0, 194, 195, 0, 0, 0, 0, 0, 0, 196, 197, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, - 0, 0, 0, 0, 199, 0, 0, 0, 0, 0, 0, 200, 201, 202, 0, 0, 0, 0, 0, 203, - 204, 0, 0, 0, 0, 0, 0, 205, 206, 0, 0, 0, 0, 0, 0, 207, 0, 0, 0, 0, 0, 0, - 208, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 0, 0, 0, 210, 0, 0, 0, 0, 0, - 0, 0, 211, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, - 0, 0, 0, 0, 214, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, - 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, 0, 219, 0, - 0, 0, 0, 0, 0, 220, 221, 222, 0, 0, 0, 0, 0, 223, 224, 225, 0, 0, 0, 0, - 0, 226, 227, 228, 0, 0, 0, 0, 0, 229, 230, 231, 0, 0, 0, 0, 0, 0, 232, 0, - 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 235, 0, - 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 0, 238, - 0, 0, 0, 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, - 241, 0, 0, 0, 0, 0, 0, 242, 0, 243, 244, 0, 0, 0, 0, 245, 246, 0, 0, 0, - 0, 0, 247, 0, 248, 0, 249, 0, 0, 0, 250, 251, 252, 0, 0, 0, 0, 0, 253, 0, - 254, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 256, 257, 258, 0, 0, 0, 0, 0, - 259, 0, 260, 0, 261, 0, 0, 0, 0, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 263, 0, - 0, 0, 264, 265, 266, 0, 267, 0, 0, 0, 268, 0, 269, 0, 0, 0, 0, 0, 270, 0, - 271, 272, 0, 0, 0, 0, 273, 274, 0, 275, 0, 0, 0, 276, 0, 277, 0, 0, 0, 0, - 0, 0, 0, 278, 0, 0, 0, 0, 0, 279, 280, 281, 282, 0, 0, 0, 0, 283, 284, 0, - 285, 0, 0, 0, 286, 0, 0, 0, 287, 0, 0, 0, 288, 0, 0, 0, 289, 0, 0, 0, 0, - 0, 0, 290, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 292, 0, 0, 0, 0, 0, 0, - 0, 293, 0, 0, 0, 0, 0, 0, 294, 0, 0, 0, 0, 0, 0, 0, 295, 0, 0, 0, 0, 0, - 0, 0, 296, 0, 0, 0, 0, 0, 0, 0, 297, 0, 0, 0, 0, 0, 0, 298, 299, 0, 0, 0, - 0, 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, 301, 0, 0, 0, 0, 0, 0, 0, 302, 0, 0, - 0, 0, 0, 0, 0, 303, 0, 0, 0, 0, 0, 0, 304, 0, 0, 0, 0, 0, 0, 0, 305, 0, - 0, 0, 0, 0, 0, 0, 306, 0, 0, 0, 0, 0, 0, 307, 0, 0, 0, 0, 0, 0, 0, 308, - 0, 0, 0, 0, 0, 0, 0, 309, 0, 0, 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, 0, - 311, 312, 0, 0, 0, 0, 0, 0, 313, 0, 0, 0, 0, 0, 0, 0, 314, 0, 0, 0, 0, 0, - 0, 0, 315, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 317, 0, 0, 0, 0, - 0, 0, 0, 318, 0, 0, 0, 0, 0, 0, 0, 319, 0, 0, 0, 0, 0, 0, 0, 320, 0, 0, - 0, 0, 0, 0, 0, 321, 0, 0, 0, 0, 0, 0, 322, 0, 0, 0, 0, 0, 0, 0, 323, 0, - 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 326, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 328, 0, 0, 0, 0, - 0, 0, 329, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, 0, 0, 331, 0, 0, 0, - 0, 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, 0, 0, 334, 0, 0, - 0, 0, 0, 0, 0, 335, 0, 0, 0, 0, 0, 0, 0, 336, 337, 0, 0, 0, 0, 0, 0, 0, - 338, 0, 0, 0, 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, 0, 340, 0, 0, 0, 0, 0, 0, - 0, 341, 0, 0, 0, 0, 0, 0, 0, 342, 0, 0, 0, 0, 0, 0, 0, 343, 0, 0, 0, 0, - 0, 0, 344, 0, 0, 0, 0, 0, 0, 0, 345, 346, 0, 0, 0, 0, 0, 0, 347, 0, 0, 0, - 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 350, 0, - 0, 0, 0, 0, 0, 0, 351, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 0, 353, - 0, 0, 0, 0, 0, 0, 0, 354, 0, 0, 0, 0, 0, 0, 0, 355, 0, 0, 0, 0, 0, 0, 0, - 356, 0, 0, 0, 0, 0, 0, 357, 0, 0, 0, 0, 0, 0, 0, 358, 0, 0, 0, 0, 0, 0, - 0, 359, 0, 0, 0, 0, 0, 0, 0, 360, 0, 0, 0, 0, 0, 0, 361, 0, 362, 0, 0, 0, - 0, 0, 0, 0, 363, 0, 0, 0, 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, 0, 0, 365, 0, - 0, 0, 0, 0, 0, 0, 366, 0, 0, 0, 0, 0, 0, 367, 0, 0, 0, 0, 0, 0, 0, 368, - 0, 0, 0, 0, 0, 0, 369, 370, 0, 0, 0, 0, 0, 0, 371, 0, 0, 0, 0, 0, 0, 0, - 372, 0, 0, 0, 0, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 374, 0, 0, 0, 0, 0, 0, - 0, 375, 0, 0, 376, 0, 0, 0, 0, 377, 0, 0, 378, 0, 0, 0, 0, 0, 0, 0, 379, - 0, 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, 0, 0, 0, - 382, 0, 0, 0, 0, 0, 0, 0, 383, 0, 0, 0, 0, 0, 0, 0, 384, 0, 0, 0, 385, 0, - 0, 386, 0, 0, 0, 0, 387, 0, 0, 388, 0, 0, 0, 0, 0, 0, 0, 389, 0, 0, 0, 0, - 0, 0, 0, 390, 0, 0, 0, 0, 0, 0, 391, 0, 0, 0, 0, 0, 0, 0, 392, 0, 0, 0, - 0, 0, 0, 0, 393, 0, 0, 0, 0, 0, 0, 0, 394, 0, 0, 0, 395, 0, 0, 0, 0, 0, - 0, 0, 396, 0, 0, 0, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, 0, 398, 0, 0, 0, 0, - 0, 0, 0, 399, 0, 0, 400, 0, 0, 0, 0, 401, 0, 0, 402, 0, 0, 0, 0, 0, 0, 0, - 403, 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, 0, 0, 0, 0, 405, 0, 0, 0, 0, 0, 0, - 0, 406, 0, 0, 0, 0, 0, 0, 0, 407, 0, 0, 0, 0, 0, 0, 0, 408, 0, 0, 0, 409, - 0, 0, 410, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, 0, - 0, 0, 0, 0, 414, 0, 0, 0, 0, 0, 0, 415, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, - 0, 0, 0, 0, 0, 417, 0, 0, 0, 0, 0, 0, 0, 418, 0, 0, 0, 419, 0, 0, 420, 0, - 0, 0, 0, 421, 0, 0, 422, 0, 0, 0, 423, 0, 0, 0, 424, 0, 0, 0, 425, 0, 0, - 0, 426, 0, 0, 0, 427, 0, 0, 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, 0, 0, 429, 0, - 0, 0, 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, 0, 0, 431, 0, 0, 432, 0, 0, 0, 0, - 433, 0, 0, 434, 0, 0, 0, 435, 0, 0, 0, 436, 0, 0, 0, 437, 0, 0, 0, 438, - 0, 0, 0, 439, 0, 0, 440, 0, 0, 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, 0, - 442, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 444, 0, 0, 0, 0, 0, 0, - 0, 445, 0, 0, 0, 0, 0, 0, 0, 446, 0, 0, 0, 447, 0, 0, 0, 448, 0, 0, 0, - 449, 0, 0, 450, 0, 0, 0, 0, 0, 0, 0, 451, 0, 0, 0, 0, 0, 0, 0, 452, 0, 0, - 0, 0, 0, 0, 0, 453, 0, 0, 0, 0, 0, 0, 454, 0, 0, 0, 0, 0, 0, 0, 455, 0, - 0, 0, 0, 0, 0, 0, 456, 0, 0, 0, 0, 0, 0, 0, 457, 0, 0, 0, 0, 0, 0, 458, - 0, 0, 0, 0, 0, 0, 0, 459, 0, 0, 0, 0, 0, 0, 0, 460, 0, 0, 0, 461, 0, 0, - 0, 462, 0, 0, 0, 0, 0, 0, 463, 0, 0, 0, 0, 0, 0, 0, 464, 0, 0, 0, 465, 0, - 0, 0, 466, 0, 0, 0, 0, 0, 0, 467, 0, 0, 0, 0, 0, 0, 0, 468, 0, 0, 0, 0, - 0, 0, 0, 469, 0, 0, 0, 0, 0, 0, 0, 470, 0, 0, 0, 0, 0, 0, 471, 0, 0, 0, - 0, 0, 0, 0, 472, 0, 0, 0, 0, 0, 0, 0, 473, 0, 0, 0, 0, 0, 0, 0, 474, 0, - 0, 0, 0, 0, 0, 475, 0, 0, 0, 0, 0, 0, 0, 476, 0, 0, 0, 0, 0, 0, 0, 477, - 0, 0, 0, 0, 0, 0, 0, 478, 0, 0, 0, 0, 0, 0, 479, 0, 0, 0, 0, 0, 0, 0, - 480, 0, 0, 0, 0, 0, 0, 0, 481, 0, 0, 0, 0, 0, 0, 0, 482, 0, 0, 0, 0, 0, - 0, 483, 0, 0, 0, 0, 0, 0, 0, 484, 0, 0, 0, 0, 0, 0, 0, 485, 0, 0, 0, 0, - 0, 0, 0, 486, 0, 0, 0, 0, 0, 0, 487, 0, 0, 0, 0, 0, 0, 0, 488, 0, 0, 0, - 0, 0, 0, 0, 489, 0, 0, 0, 0, 0, 0, 0, 490, 0, 0, 0, 0, 0, 0, 491, 0, 0, - 0, 0, 0, 0, 0, 492, 0, 0, 0, 0, 0, 0, 0, 493, 0, 0, 0, 0, 0, 0, 0, 494, - 0, 0, 0, 0, 0, 0, 495, 0, 0, 0, 0, 0, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, - 497, 0, 0, 0, 0, 0, 0, 0, 498, 0, 0, 0, 0, 0, 0, 499, 0, 0, 0, 0, 0, 0, - 0, 500, 0, 0, 0, 0, 0, 0, 0, 501, 0, 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, 0, - 0, 0, 503, 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, 0, 0, 0, 0, 0, 505, 0, 0, 0, - 0, 0, 0, 0, 506, 0, 0, 0, 0, 0, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 508, 0, 0, 0, 0, 0, 0, 0, 509, 0, 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, - 0, 0, 511, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, 0, 0, 0, 0, 513, 0, 0, 0, 0, - 0, 0, 0, 514, 0, 0, 0, 0, 0, 0, 0, 515, 0, 0, 0, 0, 0, 0, 516, 0, 0, 0, - 0, 0, 0, 0, 517, 0, 0, 0, 0, 0, 0, 0, 518, 0, 0, 0, 0, 0, 0, 0, 519, 0, - 0, 0, 0, 0, 0, 520, 0, 0, 0, 0, 0, 0, 0, 521, 0, 0, 0, 0, 0, 0, 0, 522, - 0, 0, 0, 0, 0, 0, 0, 523, 0, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 0, 0, 0, - 525, 0, 0, 0, 0, 0, 0, 0, 526, 0, 0, 0, 0, 0, 0, 0, 527, 0, 0, 0, 0, 0, - 0, 528, 0, 0, 0, 0, 0, 0, 0, 529, 0, 0, 0, 0, 0, 0, 0, 530, 0, 0, 0, 0, - 0, 0, 0, 531, 0, 0, 0, 0, 0, 0, 532, 0, 0, 0, 0, 0, 0, 0, 533, 0, 0, 0, - 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 536, 0, 0, - 0, 0, 0, 0, 0, 537, 0, 0, 0, 0, 0, 0, 0, 538, 0, 0, 0, 0, 0, 0, 0, 539, - 0, 0, 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, 0, 0, 541, 0, 0, 0, 0, 0, 0, 0, - 542, 0, 0, 0, 0, 0, 0, 0, 543, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 0, - 0, 545, 0, 0, 0, 0, 0, 0, 0, 546, 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, 0, 0, - 0, 0, 548, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 550, 0, 0, 0, - 0, 0, 0, 0, 551, 0, 0, 0, 0, 0, 0, 552, 0, 0, 0, 0, 0, 0, 0, 553, 0, 0, - 0, 0, 0, 0, 0, 554, 0, 0, 0, 0, 0, 0, 0, 555, 0, 0, 0, 0, 0, 0, 0, 556, - 0, 0, 0, 0, 0, 0, 557, 0, 0, 0, 0, 0, 0, 0, 558, 0, 0, 0, 0, 0, 0, 0, - 559, 0, 0, 0, 0, 0, 0, 0, 560, 0, 0, 0, 0, 0, 0, 0, 561, 0, 0, 0, 0, 0, - 0, 0, 562, 0, 0, 0, 0, 0, 0, 0, 563, 0, 0, 0, 0, 0, 0, 564, -}; - -static const unsigned short comp_index1[] = { - 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, - 0, 11, 12, 0, 13, 0, 0, 0, 0, 0, 0, 14, 15, 0, 0, 0, 0, 16, 0, 0, 0, 0, - 0, 17, 18, 0, 19, 0, 20, 0, 0, 0, 0, 21, 0, 0, 0, 22, 0, 23, 0, 0, 24, 0, - 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 33, 34, 0, 35, 0, 36, 37, 38, 0, 0, - 0, 0, 0, 39, 0, 0, 0, 40, 41, 42, 43, 0, 44, 0, 0, 0, 0, 45, 0, 0, 0, 0, - 0, 46, 0, 47, 0, 48, 0, 0, 49, 0, 50, 0, 51, 0, 0, 52, 53, 54, 55, 56, - 57, 58, 0, 59, 0, 0, 60, 61, 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, 64, 0, 0, - 65, 0, 66, 0, 0, 67, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 69, 0, 0, 70, 0, 71, - 72, 0, 73, 0, 74, 0, 0, 75, 0, 0, 0, 0, 76, 0, 0, 77, 78, 0, 79, 0, 80, - 0, 0, 81, 0, 82, 83, 0, 84, 0, 0, 0, 0, 0, 85, 86, 87, 88, 89, 90, 91, 0, - 92, 0, 0, 93, 0, 0, 0, 94, 0, 0, 95, 0, 0, 0, 96, 0, 0, 97, 0, 98, 99, 0, - 100, 0, 101, 0, 0, 102, 0, 103, 104, 0, 105, 0, 106, 0, 0, 107, 0, 108, - 0, 0, 0, 109, 0, 110, 0, 0, 111, 0, 112, 113, 0, 114, 0, 0, 0, 0, 0, 115, - 116, 117, 118, 119, 120, 121, 0, 122, 123, 0, 124, 125, 0, 0, 0, 126, 0, - 0, 127, 0, 0, 128, 129, 0, 130, 131, 0, 0, 0, 0, 0, 132, 0, 0, 0, 133, - 134, 135, 136, 137, 0, 0, 0, 138, 0, 0, 139, 140, 0, 141, 0, 142, 0, 0, - 143, 0, 0, 0, 0, 144, 0, 145, 146, 147, 148, 149, 150, 151, 0, 152, 153, - 0, 154, 0, 0, 155, 0, 0, 0, 0, 156, 157, 0, 0, 0, 0, 0, 158, 159, 0, 160, - 0, 161, 162, 0, 0, 0, 163, 0, 164, 0, 0, 165, 0, 166, 167, 0, 168, 0, - 169, 170, 171, 172, 173, 174, 175, 0, 176, 0, 177, 178, 179, 0, 0, 0, 0, - 0, 180, 0, 0, 0, 181, 182, 183, 184, 0, 185, 186, 0, 0, 0, 0, 0, 187, 0, - 188, 0, 189, 0, 0, 190, 0, 191, 0, 192, 193, 0, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 0, 202, 203, 0, 0, 0, 204, 0, 0, 0, 205, 0, 0, 0, 0, - 0, 206, 0, 0, 0, 0, 207, 0, 0, 208, 0, 209, 0, 0, 210, 0, 211, 0, 0, 0, - 0, 212, 0, 0, 213, 0, 214, 215, 0, 216, 0, 217, 0, 0, 218, 219, 0, 0, 0, - 0, 0, 0, 220, 221, 0, 222, 0, 223, 0, 0, 224, 0, 225, 226, 0, 227, 0, 0, - 0, 0, 0, 228, 229, 230, 231, 232, 233, 234, 0, 235, 0, 0, 236, 0, 0, 0, - 237, 0, 0, 238, 0, 0, 0, 239, 0, 0, 240, 0, 241, 242, 0, 243, 0, 244, 0, - 0, 245, 0, 0, 0, 0, 0, 246, 247, 0, 248, 0, 249, 0, 0, 250, 0, 251, 0, 0, - 0, 252, 0, 253, 0, 0, 254, 0, 255, 256, 0, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 266, 0, 267, 268, 0, 0, 0, 269, 0, 0, 270, 0, 0, - 0, 0, 0, 0, 271, 272, 0, 273, 274, 0, 0, 0, 275, 0, 276, 0, 0, 0, 277, - 278, 279, 280, 281, 0, 0, 0, 282, 0, 0, 283, 284, 0, 285, 0, 286, 0, 0, - 287, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 289, 0, 290, 0, 0, 0, 0, 291, 292, - 0, 0, 293, 0, 0, 0, 0, 294, 295, 0, 0, 0, 0, 0, 0, 296, 0, 297, 0, 0, 0, - 0, 298, 0, 0, 299, 300, 0, 0, 301, 0, 0, 302, 0, 0, 0, 0, 0, 0, 303, 304, - 0, 0, 305, 0, 0, 306, 0, 307, 308, 0, 0, 0, 0, 0, 309, 310, 0, 0, 0, 0, - 0, 0, 311, 0, 312, 0, 0, 313, 0, 0, 0, 0, 0, 314, 315, 0, 0, 316, 0, 0, - 0, 0, 317, 318, 0, 0, 0, 0, 0, 0, 319, 0, 320, 0, 0, 0, 0, 321, 0, 0, - 322, 323, 0, 0, 324, 0, 0, 325, 0, 0, 0, 0, 0, 0, 326, 327, 0, 0, 328, 0, - 0, 329, 0, 330, 331, 0, 0, 0, 0, 0, 332, 333, 0, 0, 0, 0, 0, 0, 334, 0, - 335, 0, 0, 336, 0, 0, 0, 0, 0, 337, 338, 0, 0, 339, 0, 0, 340, 341, 0, 0, - 342, 0, 0, 343, 0, 0, 0, 0, 0, 0, 344, 0, 0, 345, 0, 0, 346, 0, 0, 0, 0, - 0, 347, 0, 0, 348, 0, 0, 349, 0, 0, 350, 0, 0, 0, 351, 0, 0, 0, 0, 0, 0, - 352, 0, 353, 0, 0, 354, 0, 0, 0, 0, 0, 0, 355, 0, 0, 0, 356, 357, 0, 0, - 358, 0, 0, 0, 359, 0, 0, 360, 361, 0, 0, 362, 0, 0, 0, 363, 0, 0, 364, - 365, 0, 0, 366, 0, 0, 0, 367, 0, 0, 368, 369, 0, 0, 370, 0, 0, 0, 371, 0, - 0, 0, 372, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 374, 0, 0, 375, 0, 0, 376, 0, - 0, 377, 0, 0, 0, 0, 0, 0, 378, 0, 0, 379, 0, 0, 380, 0, 0, 0, 0, 0, 381, - 0, 382, 0, 383, 384, 0, 0, 0, 0, 0, 0, 385, 386, 0, 0, 0, 0, 0, 0, 387, - 0, 0, 0, 388, 0, 0, 389, 0, 0, 390, 0, 0, 0, 0, 391, 0, 392, 393, 0, 0, - 0, 394, 0, 0, 0, 395, 0, 0, 396, 0, 0, 0, 0, 0, 0, 397, 0, 0, 0, 398, 0, - 399, 400, 0, 0, 0, 401, 0, 0, 0, 402, 0, 0, 403, 0, 0, 404, 0, 0, 0, 0, - 0, 0, 405, 0, 0, 406, 0, 0, 0, 0, 407, 0, 408, 0, 0, 0, 0, 409, 0, 0, - 410, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 414, 0, 0, 0, 0, 0, - 0, 415, 416, 0, 417, 418, 0, 0, 0, 419, 0, 0, 420, 0, 0, 0, 0, 421, 0, 0, - 422, 0, 0, 423, 0, 0, 0, 424, 0, 425, 426, 0, 0, 0, 427, 0, 0, 0, 0, 0, - 0, 428, 429, 0, 0, 0, 0, 0, 0, 430, 0, 0, 431, 0, 0, 0, 0, 432, 0, 433, - 0, 0, 0, 0, 434, 0, 435, 0, 0, 0, 0, 0, 0, 436, 437, 0, 0, 438, 0, 0, - 439, 0, 440, 441, 0, 0, 0, 442, 0, 0, 443, 0, 444, 445, 0, 446, 447, 0, - 0, 448, 0, 0, 0, 449, 0, 450, 451, 0, 0, 0, 452, 0, 0, 0, 0, 0, 453, 0, - 454, 455, 0, 456, 457, 0, 0, 0, 0, 0, 0, 458, 0, 0, 459, 0, 460, 461, 0, - 0, 0, 462, 0, 0, 463, 0, 464, 465, 0, 466, 467, 0, 0, 468, 0, 0, 0, 469, - 0, 470, 471, 0, 0, 0, 472, 0, 0, 0, 0, 0, 473, 0, 474, 475, 0, 476, 477, - 0, 0, 0, 0, 0, 0, 478, 0, 0, 479, 0, 0, 480, 0, 0, 0, 0, 0, 481, 0, 0, - 482, 0, 0, 0, 483, 0, 0, 484, 0, 0, 485, 0, 0, 0, 0, 0, 0, 486, 0, 0, - 487, 488, 0, 489, 0, 0, 490, 0, 0, 0, 0, 0, 0, 491, 0, 0, 492, 0, 0, 493, - 0, 0, 0, 494, 0, 0, 495, 0, 0, 0, 0, 0, 0, 496, 0, 0, 0, 497, 0, 0, 0, - 498, 499, 0, 0, 0, 500, 0, 0, 0, 0, 0, 501, 502, 0, 503, 0, 0, 0, 504, 0, - 0, 0, 505, 0, 0, 506, 507, 0, 0, 0, 0, 0, 508, 0, 0, 0, 509, 510, 0, 0, - 0, 0, 0, 511, 0, 0, 0, 512, 513, 0, 514, 0, 0, 0, 0, 515, 0, 0, 516, 0, - 0, 517, 0, 0, 0, 0, 0, 0, 518, 0, 0, 519, 0, 0, 520, 0, 0, 521, 0, 0, 0, - 0, 0, 0, 522, 0, 0, 523, 0, 0, 524, 0, 0, 525, 0, 0, 0, 0, 0, 0, 526, 0, - 0, 0, 527, 0, 0, 528, 0, 0, 529, 0, 0, 530, 0, 0, 0, 531, 0, 0, 0, 0, 0, - 0, 532, 533, 534, 0, 0, 0, 0, 0, 535, 536, 0, 0, 0, 0, 0, 537, 0, 0, 538, - 0, 0, 539, 0, 0, 0, 0, 0, 0, 540, 0, 541, 0, 0, 0, 0, 0, 542, 543, 0, 0, - 0, 0, 0, 544, 0, 0, 545, 0, 0, 546, 0, 0, 0, 0, 0, 0, 547, 0, 0, 548, 0, - 0, 549, 0, 0, 550, 0, 0, 0, 0, 551, 0, 0, 0, 0, 0, 552, 553, 0, 0, 0, 0, - 0, 554, 0, 0, 555, 0, 0, 556, 0, 0, 0, 0, 0, 0, 557, 0, 0, 558, 0, 0, - 559, 0, 0, 560, 0, 0, 0, 0, 561, 0, 0, 562, 0, 0, 0, 0, 0, 0, 563, 0, 0, - 564, 0, 0, 565, 0, 0, 0, 0, 0, 566, 567, 0, 0, 0, 0, 0, 568, 0, 0, 569, - 0, 0, 570, 0, 0, 0, 0, 0, 0, 571, 0, 0, 572, 0, 0, 573, 0, 0, 574, 0, 0, - 0, 0, 575, 0, 0, 0, 0, 0, 576, 577, 0, 0, 0, 0, 0, 578, 0, 0, 579, 0, 0, - 580, 0, 0, 0, 0, 0, 0, 581, 0, 0, 582, 0, 0, 583, 0, 0, 584, 0, 0, 0, 0, - 585, 0, 0, 0, 0, 0, 586, 587, 0, 0, 0, 0, 0, 588, 0, 0, 0, 0, 589, 0, - 590, 0, 0, 0, 0, 591, 0, 592, 0, 0, 0, 0, 593, 0, 0, 594, 0, 0, 0, 0, 0, - 0, 595, 0, 0, 596, 0, 0, 597, 0, 0, 0, 0, 0, 598, 599, 0, 0, 0, 0, 0, - 600, 0, 0, 0, 0, 601, 0, 602, 0, 0, 0, 0, 603, 0, 604, 0, 0, 0, 0, 605, - 0, 0, 0, 0, 0, 606, 0, 0, 607, 0, 0, 608, 0, 0, 609, 0, 0, 0, 0, 0, 0, - 610, 0, 0, 611, 0, 0, 612, 0, 0, 0, 0, 613, 0, 614, 0, 0, 0, 0, 615, 0, - 0, 0, 0, 0, 616, 0, 0, 617, 0, 0, 618, 0, 0, 619, 0, 0, 0, 0, 0, 0, 620, - 0, 0, 621, 0, 0, 622, 0, 0, 623, 0, 0, 0, 0, 0, 0, 624, 0, 0, 625, 0, 0, - 626, 0, 0, 0, 0, 627, 0, 628, 0, 0, 0, 0, 0, 0, 629, 0, 0, 630, 0, 0, 0, - 0, 631, 0, 632, 0, 0, 0, 0, 0, 633, 0, 0, 634, 0, 0, 635, 0, 0, 636, 0, - 0, 0, 0, 0, 0, 637, 0, 0, 638, 0, 0, 639, 0, 0, 640, 0, 0, 0, 0, 0, 0, - 641, 0, 0, 642, 0, 0, 643, 0, 0, 644, 0, 0, 0, 0, 0, 0, 645, 0, 0, 646, - 0, 0, 647, 0, 0, 648, 0, 0, 0, 0, 0, 0, 649, 0, 0, 650, 0, 0, 651, 0, 0, - 652, 0, 0, 0, 0, 0, 0, 653, 0, 0, 654, 0, 0, 655, 0, 0, 656, 0, 0, 0, 0, - 0, 0, 657, 0, 0, 658, 0, 0, 659, 0, 0, 660, 0, 0, 0, 0, 0, 0, 661, 0, 0, - 662, 0, 0, 663, 0, 0, 664, 0, 0, 0, 0, 0, 0, 665, 0, 0, 666, 0, 0, 667, - 0, 0, 668, 0, 0, 0, 0, 0, 0, 669, 0, 0, 670, 0, 0, 671, 0, 0, 672, 0, 0, - 0, 0, 0, 0, 673, 0, 0, 0, 674, 0, 0, 675, 0, 0, 676, 0, 0, 677, 0, 0, 0, - 0, 0, 0, 678, 0, 0, 679, 0, 0, 680, 0, 0, 681, 0, 0, 0, 0, 0, 0, 682, 0, - 0, 683, 0, 0, 684, 0, 0, 685, 0, 0, 0, 0, 0, 0, 686, 0, 0, 687, 0, 0, - 688, 0, 0, 689, 0, 0, 0, 0, 0, 0, 690, 0, 0, 691, 0, 0, 692, 0, 0, 693, - 0, 0, 0, 0, 0, 0, 694, 0, 0, 695, 0, 0, 696, 0, 0, 697, 0, 0, 0, 0, 0, 0, - 698, 0, 0, 699, 0, 0, 700, 0, 0, 701, 0, 0, 0, 0, 0, 0, 702, 0, 0, 703, - 0, 0, 704, 0, 0, 705, 0, 0, 0, 0, 0, 0, 706, 0, 0, 707, 0, 0, 708, 0, 0, - 709, 0, 0, 0, 0, 0, 0, 710, 0, 0, 711, 0, 0, 712, 0, 0, 713, 0, 0, 0, 0, - 0, 0, 714, 0, 0, 715, 0, 0, 716, 0, 0, 717, 0, 0, 0, 0, 0, 0, 718, 0, 0, - 719, 0, 0, 720, 0, 0, 721, 0, 0, 0, 722, 0, 0, 0, 0, 0, 0, 723, 0, 0, - 724, 0, 0, 725, 0, 0, 726, 0, 0, 0, 727, 0, 0, 0, 728, 729, 0, 0, 730, 0, - 0, 0, 0, 0, 0, 731, -}; - -static const unsigned int comp_data[] = { - 0, 0, 0, 8814, 0, 8800, 0, 8815, 192, 193, 194, 195, 256, 258, 550, 196, - 7842, 197, 0, 461, 512, 514, 0, 7840, 0, 7680, 260, 0, 7682, 0, 0, 7684, - 7686, 0, 0, 262, 264, 0, 266, 0, 0, 268, 0, 199, 7690, 0, 0, 270, 0, - 7692, 0, 7696, 0, 7698, 7694, 0, 200, 201, 202, 7868, 274, 276, 278, 203, - 7866, 0, 0, 282, 516, 518, 0, 7864, 0, 552, 280, 7704, 0, 7706, 7710, 0, - 0, 500, 284, 0, 7712, 286, 288, 0, 0, 486, 0, 290, 292, 0, 7714, 7718, 0, - 542, 0, 7716, 0, 7720, 7722, 0, 204, 205, 206, 296, 298, 300, 304, 207, - 7880, 0, 0, 463, 520, 522, 0, 7882, 302, 0, 0, 7724, 308, 0, 0, 7728, 0, - 488, 0, 7730, 0, 310, 7732, 0, 0, 313, 0, 317, 0, 7734, 0, 315, 0, 7740, - 7738, 0, 0, 7742, 7744, 0, 0, 7746, 504, 323, 0, 209, 7748, 0, 0, 327, 0, - 7750, 0, 325, 0, 7754, 7752, 0, 210, 211, 212, 213, 332, 334, 558, 214, - 7886, 0, 336, 465, 524, 526, 416, 7884, 490, 0, 0, 7764, 7766, 0, 0, 340, - 7768, 0, 0, 344, 528, 530, 0, 7770, 0, 342, 7774, 0, 0, 346, 348, 0, - 7776, 0, 0, 352, 0, 7778, 536, 350, 7786, 0, 0, 356, 0, 7788, 538, 354, - 0, 7792, 7790, 0, 217, 218, 219, 360, 362, 364, 0, 220, 7910, 366, 368, - 467, 532, 534, 431, 7908, 7794, 0, 370, 7798, 0, 7796, 0, 7804, 0, 7806, - 7808, 7810, 372, 0, 7814, 7812, 0, 7816, 7818, 7820, 7922, 221, 374, - 7928, 562, 0, 7822, 376, 7926, 0, 0, 7924, 0, 377, 7824, 0, 379, 0, 0, - 381, 0, 7826, 7828, 0, 224, 225, 226, 227, 257, 259, 551, 228, 7843, 229, - 0, 462, 513, 515, 0, 7841, 0, 7681, 261, 0, 7683, 0, 0, 7685, 7687, 0, 0, - 263, 265, 0, 267, 0, 0, 269, 0, 231, 7691, 0, 0, 271, 0, 7693, 0, 7697, - 0, 7699, 7695, 0, 232, 233, 234, 7869, 275, 277, 279, 235, 7867, 0, 0, - 283, 517, 519, 0, 7865, 0, 553, 281, 7705, 0, 7707, 7711, 0, 0, 501, 285, - 0, 7713, 287, 289, 0, 0, 487, 0, 291, 293, 0, 7715, 7719, 0, 543, 0, - 7717, 0, 7721, 7723, 0, 7830, 0, 236, 237, 238, 297, 299, 301, 0, 239, - 7881, 0, 0, 464, 521, 523, 0, 7883, 303, 0, 0, 7725, 309, 0, 0, 496, 0, - 7729, 0, 489, 0, 7731, 0, 311, 7733, 0, 0, 314, 0, 318, 0, 7735, 0, 316, - 0, 7741, 7739, 0, 0, 7743, 7745, 0, 0, 7747, 505, 324, 0, 241, 7749, 0, - 0, 328, 0, 7751, 0, 326, 0, 7755, 7753, 0, 242, 243, 244, 245, 333, 335, - 559, 246, 7887, 0, 337, 466, 525, 527, 417, 7885, 491, 0, 0, 7765, 7767, - 0, 0, 341, 7769, 0, 0, 345, 529, 531, 0, 7771, 0, 343, 7775, 0, 0, 347, - 349, 0, 7777, 0, 0, 353, 0, 7779, 537, 351, 7787, 7831, 0, 357, 0, 7789, - 539, 355, 0, 7793, 7791, 0, 249, 250, 251, 361, 363, 365, 0, 252, 7911, - 367, 369, 468, 533, 535, 432, 7909, 7795, 0, 371, 7799, 0, 7797, 0, 7805, - 0, 7807, 7809, 7811, 373, 0, 7815, 7813, 0, 7832, 0, 7817, 7819, 7821, - 7923, 253, 375, 7929, 563, 0, 7823, 255, 7927, 7833, 0, 7925, 0, 378, - 7825, 0, 380, 0, 0, 382, 0, 7827, 7829, 0, 8173, 901, 8129, 0, 7846, - 7844, 0, 7850, 7848, 0, 478, 0, 0, 506, 0, 508, 482, 0, 0, 7688, 7872, - 7870, 0, 7876, 7874, 0, 0, 7726, 7890, 7888, 0, 7894, 7892, 0, 0, 7756, - 556, 0, 0, 7758, 554, 0, 0, 510, 475, 471, 469, 0, 0, 473, 7847, 7845, 0, - 7851, 7849, 0, 479, 0, 0, 507, 0, 509, 483, 0, 0, 7689, 7873, 7871, 0, - 7877, 7875, 0, 0, 7727, 7891, 7889, 0, 7895, 7893, 0, 0, 7757, 557, 0, 0, - 7759, 555, 0, 0, 511, 476, 472, 470, 0, 0, 474, 7856, 7854, 0, 7860, - 7858, 0, 7857, 7855, 0, 7861, 7859, 0, 7700, 7702, 7701, 7703, 7760, - 7762, 7761, 7763, 7780, 0, 7781, 0, 7782, 0, 7783, 0, 0, 7800, 0, 7801, - 0, 7802, 0, 7803, 7835, 0, 7900, 7898, 0, 7904, 7902, 0, 0, 7906, 7901, - 7899, 0, 7905, 7903, 0, 0, 7907, 7914, 7912, 0, 7918, 7916, 0, 0, 7920, - 7915, 7913, 0, 7919, 7917, 0, 0, 7921, 0, 494, 492, 0, 493, 0, 480, 0, - 481, 0, 0, 7708, 0, 7709, 560, 0, 561, 0, 0, 495, 8122, 902, 8121, 8120, - 7944, 7945, 0, 8124, 8136, 904, 7960, 7961, 8138, 905, 7976, 7977, 0, - 8140, 8154, 906, 8153, 8152, 0, 938, 7992, 7993, 8184, 908, 8008, 8009, - 0, 8172, 8170, 910, 8169, 8168, 0, 939, 0, 8025, 8186, 911, 8040, 8041, - 0, 8188, 0, 8116, 0, 8132, 8048, 940, 8113, 8112, 7936, 7937, 8118, 8115, - 8050, 941, 7952, 7953, 8052, 942, 7968, 7969, 8134, 8131, 8054, 943, - 8145, 8144, 0, 970, 7984, 7985, 8150, 0, 8056, 972, 8000, 8001, 8164, - 8165, 8058, 973, 8161, 8160, 0, 971, 8016, 8017, 8166, 0, 8060, 974, - 8032, 8033, 8182, 8179, 8146, 912, 8151, 0, 8162, 944, 8167, 0, 0, 8180, - 0, 979, 0, 980, 0, 1031, 0, 1232, 0, 1234, 0, 1027, 1024, 0, 0, 1238, 0, - 1025, 0, 1217, 0, 1244, 0, 1246, 1037, 0, 1250, 1049, 0, 1252, 0, 1036, - 0, 1254, 1262, 1038, 0, 1264, 1266, 0, 0, 1268, 0, 1272, 0, 1260, 0, - 1233, 0, 1235, 0, 1107, 1104, 0, 0, 1239, 0, 1105, 0, 1218, 0, 1245, 0, - 1247, 1117, 0, 1251, 1081, 0, 1253, 0, 1116, 0, 1255, 1263, 1118, 0, - 1265, 1267, 0, 0, 1269, 0, 1273, 0, 1261, 0, 1111, 1142, 0, 1143, 0, 0, - 1242, 0, 1243, 0, 1258, 0, 1259, 1570, 1571, 1573, 0, 0, 1572, 0, 1574, - 0, 1730, 0, 1747, 0, 1728, 0, 2345, 0, 2353, 0, 2356, 2507, 2508, 2891, - 2888, 2892, 0, 2964, 0, 0, 3018, 3020, 0, 0, 3019, 0, 3144, 0, 3264, - 3274, 3271, 3272, 0, 0, 3275, 0, 3402, 3404, 0, 0, 3403, 0, 3546, 3548, - 3550, 0, 3549, 4134, 0, 0, 6918, 0, 6920, 0, 6922, 0, 6924, 0, 6926, 0, - 6930, 0, 6971, 0, 6973, 0, 6976, 0, 6977, 0, 6979, 7736, 0, 7737, 0, - 7772, 0, 7773, 0, 7784, 0, 7785, 0, 7852, 0, 0, 7862, 7853, 0, 0, 7863, - 7878, 0, 7879, 0, 7896, 0, 7897, 0, 7938, 7940, 7942, 8064, 7939, 7941, - 7943, 8065, 0, 8066, 0, 8067, 0, 8068, 0, 8069, 0, 8070, 0, 8071, 7946, - 7948, 7950, 8072, 7947, 7949, 7951, 8073, 0, 8074, 0, 8075, 0, 8076, 0, - 8077, 0, 8078, 0, 8079, 7954, 7956, 7955, 7957, 7962, 7964, 7963, 7965, - 7970, 7972, 7974, 8080, 7971, 7973, 7975, 8081, 0, 8082, 0, 8083, 0, - 8084, 0, 8085, 0, 8086, 0, 8087, 7978, 7980, 7982, 8088, 7979, 7981, - 7983, 8089, 0, 8090, 0, 8091, 0, 8092, 0, 8093, 0, 8094, 0, 8095, 7986, - 7988, 7990, 0, 7987, 7989, 7991, 0, 7994, 7996, 7998, 0, 7995, 7997, - 7999, 0, 8002, 8004, 8003, 8005, 8010, 8012, 8011, 8013, 8018, 8020, - 8022, 0, 8019, 8021, 8023, 0, 8027, 8029, 8031, 0, 8034, 8036, 8038, - 8096, 8035, 8037, 8039, 8097, 0, 8098, 0, 8099, 0, 8100, 0, 8101, 0, - 8102, 0, 8103, 8042, 8044, 8046, 8104, 8043, 8045, 8047, 8105, 0, 8106, - 0, 8107, 0, 8108, 0, 8109, 0, 8110, 0, 8111, 0, 8114, 0, 8130, 0, 8178, - 0, 8119, 8141, 8142, 8143, 0, 0, 8135, 0, 8183, 8157, 8158, 8159, 0, 0, - 8602, 0, 8603, 0, 8622, 0, 8653, 0, 8655, 0, 8654, 0, 8708, 0, 8713, 0, - 8716, 0, 8740, 0, 8742, 0, 8769, 0, 8772, 0, 8775, 0, 8777, 0, 8813, 0, - 8802, 0, 8816, 0, 8817, 0, 8820, 0, 8821, 0, 8824, 0, 8825, 0, 8832, 0, - 8833, 0, 8928, 0, 8929, 0, 8836, 0, 8837, 0, 8840, 0, 8841, 0, 8930, 0, - 8931, 0, 8876, 0, 8877, 0, 8878, 0, 8879, 0, 8938, 0, 8939, 0, 8940, 0, - 8941, 12436, 0, 12364, 0, 12366, 0, 12368, 0, 12370, 0, 12372, 0, 12374, - 0, 12376, 0, 12378, 0, 12380, 0, 12382, 0, 12384, 0, 12386, 0, 12389, 0, - 12391, 0, 12393, 0, 12400, 12401, 12403, 12404, 12406, 12407, 12409, - 12410, 12412, 12413, 12446, 0, 12532, 0, 12460, 0, 12462, 0, 12464, 0, - 12466, 0, 12468, 0, 12470, 0, 12472, 0, 12474, 0, 12476, 0, 12478, 0, - 12480, 0, 12482, 0, 12485, 0, 12487, 0, 12489, 0, 12496, 12497, 12499, - 12500, 12502, 12503, 12505, 12506, 12508, 12509, 12535, 0, 12536, 0, - 12537, 0, 12538, 0, 12542, 0, 69786, 0, 69788, 0, 69803, 0, 0, 69934, 0, - 69935, 70475, 70476, 70844, 70843, 70846, 0, 0, 71098, 0, 71099, -}; - diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index d32cace64..9ec2d8563 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -60,6 +60,7 @@ hb_unicode_combining_class_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED, return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED; } +#ifndef HB_DISABLE_DEPRECATED static unsigned int hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED, hb_codepoint_t unicode HB_UNUSED, @@ -67,6 +68,7 @@ hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED, { return 1; } +#endif static hb_unicode_general_category_t hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED, @@ -113,6 +115,7 @@ hb_unicode_decompose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED, } +#ifndef HB_DISABLE_DEPRECATED static unsigned int hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED, hb_codepoint_t u HB_UNUSED, @@ -121,17 +124,18 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED { return 0; } +#endif +extern "C" hb_unicode_funcs_t *hb_ucd_get_unicode_funcs (); extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); -extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs (); hb_unicode_funcs_t * hb_unicode_funcs_get_default () { -#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_UCDN) - return hb_ucdn_get_unicode_funcs (); +#if !defined(HB_NO_UNICODE_FUNCS) && !defined(HB_NO_UCD) + return hb_ucd_get_unicode_funcs (); #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB) return hb_glib_get_unicode_funcs (); #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) @@ -144,7 +148,7 @@ hb_unicode_funcs_get_default () #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL) #error "Could not find any Unicode functions implementation, you have to provide your own" -#error "Consider building hb-ucdn.c. If you absolutely want to build without any, check the code." +#error "Consider building hb-ucd.cc. If you absolutely want to build without any, check the code." #endif /** @@ -425,6 +429,7 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, return ufuncs->decompose (ab, a, b); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_unicode_decompose_compatibility: * @ufuncs: Unicode functions. @@ -445,6 +450,7 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, { return ufuncs->decompose_compatibility (u, decomposed); } +#endif /* See hb-unicode.hh for details. */ diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh index 82ebb1064..80624c0ec 100644 --- a/src/hb-unicode.hh +++ b/src/hb-unicode.hh @@ -42,19 +42,19 @@ extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256]; #define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \ HB_UNICODE_FUNC_IMPLEMENT (combining_class) \ - HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \ + HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (eastasian_width)) \ HB_UNICODE_FUNC_IMPLEMENT (general_category) \ HB_UNICODE_FUNC_IMPLEMENT (mirroring) \ HB_UNICODE_FUNC_IMPLEMENT (script) \ HB_UNICODE_FUNC_IMPLEMENT (compose) \ HB_UNICODE_FUNC_IMPLEMENT (decompose) \ - HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \ + HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility)) \ /* ^--- Add new callbacks here */ /* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */ #define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \ HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \ - HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \ + HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width)) \ HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \ HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \ HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \ @@ -89,7 +89,11 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE unsigned int decompose_compatibility (hb_codepoint_t u, hb_codepoint_t *decomposed) { +#ifdef HB_DISABLE_DEPRECATED + unsigned int ret = 0; +#else unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility); +#endif if (ret == 1 && u == decomposed[0]) { decomposed[0] = 0; return 0; diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 4bbbf6122..f97ed91fc 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -698,7 +698,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ ()); + active_features.remove (feature - active_features.arrayZ); } } @@ -728,12 +728,12 @@ retry: #define ALLOCATE_ARRAY(Type, name, len) \ Type *name = (Type *) scratch; \ - { \ + do { \ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ assert (_consumed <= scratch_size); \ scratch += _consumed; \ scratch_size -= _consumed; \ - } + } while (0) #define utf16_index() var1.u32 @@ -889,8 +889,8 @@ retry: &items[i].a, script_tags[i], language_tag, - range_char_counts.arrayZ (), - range_properties.arrayZ (), + range_char_counts.arrayZ, + range_properties.arrayZ, range_properties.length, pchars + chars_offset, item_chars_len, @@ -930,8 +930,8 @@ retry: &items[i].a, script_tags[i], language_tag, - range_char_counts.arrayZ (), - range_properties.arrayZ (), + range_char_counts.arrayZ, + range_properties.arrayZ, range_properties.length, pchars + chars_offset, log_clusters + chars_offset, @@ -967,7 +967,7 @@ retry: vis_clusters[i] = (uint32_t) -1; for (unsigned int i = 0; i < buffer->len; i++) { uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; - *p = MIN (*p, buffer->info[i].cluster); + *p = hb_min (*p, buffer->info[i].cluster); } for (unsigned int i = 1; i < glyphs_len; i++) if (vis_clusters[i] == (uint32_t) -1) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index e0b7fb0cb..de16c97dd 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -49,35 +49,34 @@ struct hb_vector_t { allocated = o.allocated; length = o.length; - arrayZ_ = o.arrayZ_; + arrayZ = o.arrayZ; o.init (); } ~hb_vector_t () { fini (); } - unsigned int length; private: int allocated; /* == -1 means allocation failed. */ - Type *arrayZ_; public: + unsigned int length; + public: + Type *arrayZ; void init () { allocated = length = 0; - arrayZ_ = nullptr; + arrayZ = nullptr; } void fini () { - if (arrayZ_) - free (arrayZ_); + free (arrayZ); init (); } void fini_deep () { - Type *array = arrayZ(); unsigned int count = length; for (unsigned int i = 0; i < count; i++) - array[i].fini (); + arrayZ[i].fini (); fini (); } @@ -95,33 +94,31 @@ struct hb_vector_t fini (); allocated = o.allocated; length = o.length; - arrayZ_ = o.arrayZ_; + arrayZ = o.arrayZ; o.init (); return *this; } hb_bytes_t as_bytes () const - { return hb_bytes_t ((const char *) arrayZ(), length * item_size); } + { return hb_bytes_t ((const char *) arrayZ, length * item_size); } bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); } + bool operator != (const hb_vector_t &o) const { return !(*this == o); } uint32_t hash () const { return as_array ().hash (); } - const Type * arrayZ () const { return arrayZ_; } - Type * arrayZ () { return arrayZ_; } - Type& operator [] (int i_) { unsigned int i = (unsigned int) i_; if (unlikely (i >= length)) return Crap (Type); - return arrayZ()[i]; + return arrayZ[i]; } const Type& operator [] (int i_) const { unsigned int i = (unsigned int) i_; if (unlikely (i >= length)) return Null(Type); - return arrayZ()[i]; + return arrayZ[i]; } Type& tail () { return (*this)[length - 1]; } @@ -134,8 +131,8 @@ struct hb_vector_t template hb_vector_t& operator << (T&& v) { push (hb_forward (v)); return *this; } - hb_array_t< Type> as_array () { return hb_array (arrayZ(), length); } - hb_array_t as_array () const { return hb_array (arrayZ(), length); } + hb_array_t< Type> as_array () { return hb_array (arrayZ, length); } + hb_array_t as_array () const { return hb_array (arrayZ, length); } /* Iterator. */ typedef hb_array_t iter_t; @@ -155,21 +152,21 @@ struct hb_vector_t { return as_array ().sub_array (start_offset, count);} hb_sorted_array_t as_sorted_array () - { return hb_sorted_array (arrayZ(), length); } + { return hb_sorted_array (arrayZ, length); } hb_sorted_array_t as_sorted_array () const - { return hb_sorted_array (arrayZ(), length); } + { return hb_sorted_array (arrayZ, length); } - template explicit operator T * () { return arrayZ(); } - template explicit operator const T * () const { return arrayZ(); } + template explicit operator T * () { return arrayZ; } + template explicit operator const T * () const { return arrayZ; } - Type * operator + (unsigned int i) { return arrayZ() + i; } - const Type * operator + (unsigned int i) const { return arrayZ() + i; } + Type * operator + (unsigned int i) { return arrayZ + i; } + const Type * operator + (unsigned int i) const { return arrayZ + i; } Type *push () { if (unlikely (!resize (length + 1))) return &Crap(Type); - return &arrayZ()[length - 1]; + return &arrayZ[length - 1]; } template Type *push (T&& v) @@ -202,7 +199,7 @@ struct hb_vector_t (new_allocated < (unsigned) allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); if (likely (!overflows)) - new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type)); + new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); if (unlikely (!new_array)) { @@ -210,7 +207,7 @@ struct hb_vector_t return false; } - arrayZ_ = new_array; + arrayZ = new_array; allocated = new_allocated; return true; @@ -223,7 +220,7 @@ struct hb_vector_t return false; if (size > length) - memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ())); + memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); length = size; return true; @@ -232,16 +229,15 @@ struct hb_vector_t Type pop () { if (!length) return Null(Type); - return hb_move (arrayZ()[--length]); /* Does this move actually work? */ + return hb_move (arrayZ[--length]); /* Does this move actually work? */ } void remove (unsigned int i) { if (unlikely (i >= length)) return; - Type *array = arrayZ(); - memmove (static_cast (&array[i]), - static_cast (&array[i + 1]), + memmove (static_cast (&arrayZ[i]), + static_cast (&arrayZ[i + 1]), (length - i - 1) * sizeof (Type)); length--; } @@ -256,19 +252,17 @@ struct hb_vector_t template Type *find (T v) { - Type *array = arrayZ(); for (unsigned int i = 0; i < length; i++) - if (array[i] == v) - return &array[i]; + if (arrayZ[i] == v) + return &arrayZ[i]; return nullptr; } template const Type *find (T v) const { - const Type *array = arrayZ(); for (unsigned int i = 0; i < length; i++) - if (array[i] == v) - return &array[i]; + if (arrayZ[i] == v) + return &arrayZ[i]; return nullptr; } @@ -288,8 +282,8 @@ struct hb_vector_t template struct hb_sorted_vector_t : hb_vector_t { - hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ(), this->length); } - hb_sorted_array_t as_array () const { return hb_sorted_array (this->arrayZ(), this->length); } + hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->length); } + hb_sorted_array_t as_array () const { return hb_sorted_array (this->arrayZ, this->length); } /* Iterator. */ typedef hb_sorted_array_t const_iter_t; diff --git a/src/hb-version.h b/src/hb-version.h index 783e37b08..1eca37a58 100644 --- a/src/hb-version.h +++ b/src/hb-version.h @@ -37,10 +37,10 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 2 -#define HB_VERSION_MINOR 4 -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MINOR 5 +#define HB_VERSION_MICRO 1 -#define HB_VERSION_STRING "2.4.0" +#define HB_VERSION_STRING "2.5.1" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ diff --git a/src/hb-warning.cc b/src/hb-warning.cc index 9fb410038..60c7445b7 100644 --- a/src/hb-warning.cc +++ b/src/hb-warning.cc @@ -26,12 +26,12 @@ #include "hb.hh" -#if defined(HB_ATOMIC_INT_NIL) +#ifdef HB_ATOMIC_INT_NIL #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe" #error "Check hb-atomic.hh for possible resolutions." #endif -#if defined(HB_MUTEX_IMPL_NIL) +#ifdef HB_MUTEX_IMPL_NIL #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe" #error "Check hb-mutex.hh for possible resolutions." #endif diff --git a/src/hb.hh b/src/hb.hh index 0336ed568..e6d22fe3b 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -29,8 +29,9 @@ #ifndef HB_HH #define HB_HH + #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC -#if defined(_MSC_VER) +#ifdef _MSC_VER #pragma warning( disable: 4068 ) /* Unknown pragma */ #endif #if defined(__GNUC__) || defined(__clang__) @@ -65,6 +66,8 @@ #pragma GCC diagnostic error "-Wcast-align" #pragma GCC diagnostic error "-Wcast-function-type" #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic error "-Wdouble-promotion" +#pragma GCC diagnostic error "-Wextra-semi-stmt" #pragma GCC diagnostic error "-Wformat-security" #pragma GCC diagnostic error "-Wimplicit-function-declaration" #pragma GCC diagnostic error "-Winit-self" @@ -94,6 +97,7 @@ /* Warning. To be investigated if happens. */ #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined" +#pragma GCC diagnostic warning "-Wdeprecated" #pragma GCC diagnostic warning "-Wdisabled-optimization" #pragma GCC diagnostic warning "-Wformat=2" #pragma GCC diagnostic warning "-Wignored-pragma-optimize" @@ -121,14 +125,15 @@ #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang #pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic ignored "-Wtype-limits" +#pragma GCC diagnostic ignored "-Wc++11-compat" // only gcc raises it #endif #endif #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif + +#include "hb-config.hh" + /* * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to @@ -200,7 +205,7 @@ extern "C" void hb_free_impl(void *ptr); #define realloc hb_realloc_impl #define free hb_free_impl -#if defined(hb_memalign_impl) +#ifdef hb_memalign_impl extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); #define posix_memalign hb_memalign_impl #else @@ -312,7 +317,7 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); # define HB_FALLTHROUGH /* FALLTHROUGH */ #endif -#if defined(__clang__) +#ifdef __clang__ /* Disable certain sanitizer errors. */ /* https://github.com/harfbuzz/harfbuzz/issues/1247 */ #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow"))) @@ -343,19 +348,27 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); # if defined(_WIN32_WCE) /* Some things not defined on Windows CE. */ # define vsnprintf _vsnprintf -# define getenv(Name) nullptr +# ifndef HB_NO_GETENV +# define HB_NO_GETENV +# endif # if _WIN32_WCE < 0x800 # define setlocale(Category, Locale) "C" static int errno = 0; /* Use something better? */ # endif # elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -# define getenv(Name) nullptr +# ifndef HB_NO_GETENV +# define HB_NO_GETENV +# endif # endif # if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf # endif #endif +#ifdef HB_NO_GETENV +#define getenv(Name) nullptr +#endif + #if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT) /* atexit() is only safe to be called from shared libraries on certain * platforms. Whitelist. @@ -434,12 +447,12 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); * * https://bugs.chromium.org/p/chromium/issues/detail?id=860184 */ -#if !defined(HB_VECTOR_SIZE) +#ifndef HB_VECTOR_SIZE # define HB_VECTOR_SIZE 0 #endif /* The `vector_size' attribute was introduced in gcc 3.1. */ -#if !defined(HB_VECTOR_SIZE) +#ifndef HB_VECTOR_SIZE # if defined( __GNUC__ ) && ( __GNUC__ >= 4 ) # define HB_VECTOR_SIZE 128 # else @@ -455,16 +468,6 @@ typedef uint64_t hb_vector_size_impl_t; #endif -/* HB_NDEBUG disables some sanity checks that are very safe to disable and - * should be disabled in production systems. If NDEBUG is defined, enable - * HB_NDEBUG; but if it's desirable that normal assert()s (which are very - * light-weight) to be enabled, then HB_DEBUG can be defined to disable - * the costlier checks. */ -#ifdef NDEBUG -#define HB_NDEBUG 1 -#endif - - /* Flags */ /* Enable bitwise ops on enums marked as flags_t */ diff --git a/src/test-algs.cc b/src/test-algs.cc index 163a79ad3..333a89242 100644 --- a/src/test-algs.cc +++ b/src/test-algs.cc @@ -62,5 +62,30 @@ main (int argc, char **argv) A a; hb_invoke (&A::a, a); + assert (1 == hb_min (8, 1)); + assert (8 == hb_max (8, 1)); + + int x = 1, y = 2; + hb_min (x, 3); + hb_min (3, x); + hb_min (x, 4 + 3); + int &z = hb_min (x, y); + z = 3; + assert (x == 3); + + hb_pair_t xp = hb_pair_t (nullptr, 0); + xp = hb_pair_t (nullptr, 1); + xp = hb_pair_t (nullptr, 1); + + assert (3 == hb_partial (hb_min, 3) (4)); + assert (3 == hb_partial<1> (hb_min, 4) (3)); + + auto M0 = hb_partial<2> (hb_max, 0); + assert (M0 (-2) == 0); + assert (M0 (+2) == 2); + + assert (hb_add (2) (5) == 7); + assert (hb_add (5) (2) == 7); + return 0; } diff --git a/src/test-iter.cc b/src/test-iter.cc index 3de340145..156a5fcad 100644 --- a/src/test-iter.cc +++ b/src/test-iter.cc @@ -43,6 +43,7 @@ struct array_iter_t : hb_iter_with_fallback_t, T&> void __forward__ (unsigned n) { arr += n; } void __rewind__ (unsigned n) { arr -= n; } unsigned __len__ () const { return arr.length; } + bool operator != (const array_iter_t& o) { return arr != o.arr; } private: hb_array_t arr; @@ -56,7 +57,7 @@ struct some_array_t typedef array_iter_t iter_t; array_iter_t iter () { return array_iter_t (arr); } operator array_iter_t () { return iter (); } - operator hb_iter_t > () { return iter (); } + operator hb_iter_t> () { return iter (); } private: hb_array_t arr; @@ -64,14 +65,10 @@ struct some_array_t template + hb_requires (hb_is_iterator (Iter))> static void -test_iterator (Iter it) +test_iterator_non_default_constructable (Iter it) { - Iter default_constructed; - - assert (!default_constructed); - /* Iterate over a copy of it. */ for (auto c = it.iter (); c; c++) *c; @@ -80,6 +77,10 @@ test_iterator (Iter it) for (auto c = +it; c; c++) *c; + /* Range-based for over a copy. */ + for (auto _ : +it) + (void) _; + it += it.len (); it = it + 10; it = 10 + it; @@ -90,11 +91,25 @@ test_iterator (Iter it) static_assert (true || it.is_sorted_iterator, ""); } +template +static void +test_iterator (Iter it) +{ + Iter default_constructed; + assert (!default_constructed); + + test_iterator_non_default_constructable (it); +} + template + hb_requires (hb_is_iterable (Iterable))> static void test_iterable (const Iterable &lst = Null(Iterable)) { + for (auto _ : lst) + (void) _; + // Test that can take iterator from. test_iterator (lst.iter ()); } @@ -110,7 +125,7 @@ main (int argc, char **argv) array_iter_t s2 (v); /* Implicit conversion from vector. */ array_iter_t t (dst); - static_assert (hb_is_random_access_iterator (array_iter_t), ""); + static_assert (array_iter_t::is_random_access_iterator, ""); some_array_t a (src); @@ -125,6 +140,7 @@ main (int argc, char **argv) test_iterable (v); hb_set_t st; + st << 1 << 15 << 43; test_iterable (st); hb_sorted_array_t sa; (void) static_cast, hb_sorted_array_t::item_t>&> (sa); @@ -134,34 +150,80 @@ main (int argc, char **argv) (void) static_cast, int&>&> (sa); test_iterable (sa); - test_iterable > (); - test_iterable > (); - test_iterable > (); + test_iterable> (); + test_iterable> (); + test_iterable> (); test_iterable (); test_iterable (); test_iterator (hb_zip (st, v)); + test_iterator_non_default_constructable (hb_enumerate (st)); + test_iterator_non_default_constructable (hb_enumerate (st, -5)); + test_iterator_non_default_constructable (hb_enumerate (hb_iter (st))); + test_iterator_non_default_constructable (hb_enumerate (hb_iter (st) + 1)); + test_iterator_non_default_constructable (hb_iter (st) | hb_filter ()); + test_iterator_non_default_constructable (hb_iter (st) | hb_map (hb_lidentity)); - hb_any (st); + assert (true == hb_all (st)); + assert (false == hb_all (st, 42u)); + assert (true == hb_any (st)); + assert (false == hb_any (st, 14u)); + assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; })); + assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; })); + assert (true == hb_any (st, 15u)); + assert (false == hb_none (st)); + assert (false == hb_none (st, 15u)); + assert (true == hb_none (st, 17u)); - hb_array_t > pa; + hb_array_t> pa; pa->as_array (); + hb_map_t m; + + hb_iter (st); + hb_iter (&st); + + hb_iter (src) - | hb_map (hb_identity) + | hb_map (m) + | hb_map (&m) | hb_filter () + | hb_filter (st) + | hb_filter (&st) | hb_filter (hb_bool) | hb_filter (hb_bool, hb_identity) | hb_sink (st) ; + + hb_iter (src) + | hb_sink (hb_array (dst)) + ; + + hb_iter (src) | hb_apply (&st) ; + hb_iter (src) - | hb_map ([&] (int i) -> int { return 1; }) - | hb_reduce ([&] (int acc, int value) -> int { return acc; }, 2) + | hb_map ([] (int i) { return 1; }) + | hb_reduce ([=] (int acc, int value) { return acc; }, 2) + ; + + using map_pair_t = hb_item_type; + + hb_iter (m) + | hb_map ([] (map_pair_t p) { return p.first * p.second; }) + ; + + m.keys (); + using map_key_t = decltype (*m.keys()); + + hb_iter (m.keys ()) + | hb_filter ([] (map_key_t k) { return k < 42; }) + | hb_drain + ; + + m.values (); + using map_value_t = decltype (*m.values()); + + hb_iter (m.values ()) + | hb_filter ([] (map_value_t k) { return k < 42; }) + | hb_drain ; unsigned int temp1 = 10; @@ -189,8 +251,8 @@ main (int argc, char **argv) unsigned int temp3 = 0; + hb_iter(src) - | hb_map([&] (int i) -> int { return ++temp3; }) - | hb_reduce([&] (float acc, int value) -> float { return acc + value; }, 0) + | hb_map([&] (int i) { return ++temp3; }) + | hb_reduce([&] (float acc, int value) { return acc + value; }, 0) ; hb_map_destroy (result); @@ -202,5 +264,18 @@ main (int argc, char **argv) long vl; s >> vl; + hb_iota (); + hb_iota (3); + hb_iota (3, 2); + hb_range (); + assert (hb_range (9).len () == 9); + assert (hb_range (2, 9).len () == 7); + assert (hb_range (2, 9, 3).len () == 3); + assert (hb_range (2, 8, 3).len () == 2); + assert (hb_range (2, 7, 3).len () == 2); + assert (hb_range (-2, -9, -3).len () == 3); + assert (hb_range (-2, -8, -3).len () == 2); + assert (hb_range (-2, -7, -3).len () == 2); + return 0; } diff --git a/src/test-meta.cc b/src/test-meta.cc new file mode 100644 index 000000000..0b6e02c26 --- /dev/null +++ b/src/test-meta.cc @@ -0,0 +1,128 @@ +/* + * Copyright © 2019 Facebook, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Facebook Author(s): Behdad Esfahbod + */ + +#include "hb.hh" +#include "hb-meta.hh" + +#include + +int +main (int argc, char **argv) +{ + static_assert (hb_is_convertible (void, void), ""); + static_assert (hb_is_convertible (void, const void), ""); + static_assert (hb_is_convertible (const void, void), ""); + + static_assert (hb_is_convertible (int, int), ""); + static_assert (hb_is_convertible (char, int), ""); + static_assert (hb_is_convertible (long, int), ""); + + static_assert (hb_is_convertible (int, int), ""); + + static_assert (hb_is_convertible (const int, int), ""); + static_assert (hb_is_convertible (int, const int), ""); + static_assert (hb_is_convertible (const int, const int), ""); + + static_assert (hb_is_convertible (int&, int), ""); + static_assert (!hb_is_convertible (int, int&), ""); + + static_assert (hb_is_convertible (int, const int&), ""); + static_assert (!hb_is_convertible (const int, int&), ""); + static_assert (hb_is_convertible (const int, const int&), ""); + static_assert (hb_is_convertible (int&, const int), ""); + static_assert (hb_is_convertible (const int&, int), ""); + static_assert (hb_is_convertible (const int&, const int), ""); + static_assert (hb_is_convertible (const int&, const int), ""); + + struct X {}; + struct Y : X {}; + + static_assert (hb_is_convertible (const X &, const X), ""); + static_assert (hb_is_convertible (X &, const X), ""); + static_assert (hb_is_convertible (X &, const X &), ""); + static_assert (hb_is_convertible (X, const X &), ""); + static_assert (hb_is_convertible (const X, const X &), ""); + static_assert (!hb_is_convertible (const X, X &), ""); + static_assert (!hb_is_convertible (X, X &), ""); + static_assert (hb_is_convertible (X &, X &), ""); + + static_assert (hb_is_convertible (int&, long), ""); + static_assert (!hb_is_convertible (int&, long&), ""); + + static_assert (hb_is_convertible (int *, int *), ""); + static_assert (hb_is_convertible (int *, const int *), ""); + static_assert (!hb_is_convertible (const int *, int *), ""); + static_assert (!hb_is_convertible (int *, long *), ""); + static_assert (hb_is_convertible (int *, void *), ""); + static_assert (!hb_is_convertible (void *, int *), ""); + + static_assert (hb_is_base_of (void, void), ""); + static_assert (hb_is_base_of (void, int), ""); + static_assert (!hb_is_base_of (int, void), ""); + + static_assert (hb_is_base_of (int, int), ""); + static_assert (hb_is_base_of (const int, int), ""); + static_assert (hb_is_base_of (int, const int), ""); + + static_assert (hb_is_base_of (X, X), ""); + static_assert (hb_is_base_of (X, Y), ""); + static_assert (hb_is_base_of (const X, Y), ""); + static_assert (hb_is_base_of (X, const Y), ""); + static_assert (!hb_is_base_of (Y, X), ""); + + static_assert (hb_is_constructible (int), ""); + static_assert (hb_is_constructible (int, int), ""); + static_assert (hb_is_constructible (int, char), ""); + static_assert (hb_is_constructible (int, long), ""); + static_assert (!hb_is_constructible (int, X), ""); + static_assert (!hb_is_constructible (int, int, int), ""); + static_assert (hb_is_constructible (X), ""); + static_assert (!hb_is_constructible (X, int), ""); + static_assert (hb_is_constructible (X, X), ""); + static_assert (!hb_is_constructible (X, X, X), ""); + static_assert (hb_is_constructible (X, Y), ""); + static_assert (!hb_is_constructible (Y, X), ""); + + static_assert (hb_is_trivially_default_constructible (X), ""); + static_assert (hb_is_trivially_default_constructible (Y), ""); + static_assert (hb_is_trivially_copy_constructible (X), ""); + static_assert (hb_is_trivially_copy_constructible (Y), ""); + static_assert (hb_is_trivially_move_constructible (X), ""); + static_assert (hb_is_trivially_move_constructible (Y), ""); + static_assert (hb_is_trivially_destructible (Y), ""); + + static_assert (hb_is_trivially_copyable (int), ""); + static_assert (hb_is_trivially_copyable (X), ""); + static_assert (hb_is_trivially_copyable (Y), ""); + + static_assert (hb_is_trivial (int), ""); + static_assert (hb_is_trivial (X), ""); + static_assert (hb_is_trivial (Y), ""); + + /* TODO Add more meaningful tests. */ + + return 0; +} diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc index 4050a664d..26931fed3 100644 --- a/src/test-ot-color.cc +++ b/src/test-ot-color.cc @@ -133,7 +133,7 @@ layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int unsigned glyph_count = hb_face_get_glyph_count (face); for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid) { - unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, NULL, NULL); + unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr); if (!num_layers) continue; @@ -169,7 +169,7 @@ layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int unsigned int palette_count = hb_ot_color_palette_get_count (face); for (unsigned int palette = 0; palette < palette_count; palette++) { - unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, NULL, NULL); + unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr); if (!num_colors) continue; @@ -271,14 +271,14 @@ main (int argc, char **argv) FILE *font_name_file = fopen ("out/.dumped_font_name", "r"); - if (font_name_file != NULL) + if (font_name_file != nullptr) { fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n"); exit (1); } font_name_file = fopen ("out/.dumped_font_name", "w"); - if (font_name_file == NULL) + if (font_name_file == nullptr) { fprintf (stderr, "./out is not accessible as a folder, create it please\n"); exit (1); diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 70a9fda85..85f2f6fd1 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -42,6 +42,7 @@ TEST_PROGS = \ test-shape \ test-subset \ test-subset-cmap \ + test-subset-drop-tables \ test-subset-glyf \ test-subset-hdmx \ test-subset-hmtx \ @@ -60,6 +61,7 @@ TEST_PROGS = \ test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la +test_subset_drop_tables_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_hmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la diff --git a/test/api/fonts/Roboto-Regular.a.retaingids.ttf b/test/api/fonts/Roboto-Regular.a.retaingids.ttf new file mode 100644 index 000000000..183b148ca Binary files /dev/null and b/test/api/fonts/Roboto-Regular.a.retaingids.ttf differ diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf index 906bdbefd..fa2a0e446 100644 Binary files a/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf and b/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf differ diff --git a/test/api/fonts/nameID.expected.ttf b/test/api/fonts/nameID.expected.ttf index ccd4b8bcd..00aecc0bb 100644 Binary files a/test/api/fonts/nameID.expected.ttf and b/test/api/fonts/nameID.expected.ttf differ diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h index 8f32aee67..25cf1e3e6 100644 --- a/test/api/hb-subset-test.h +++ b/test/api/hb-subset-test.h @@ -70,7 +70,7 @@ hb_subset_test_create_input_from_nameids (const hb_set_t *name_ids) { hb_subset_input_t *input = hb_subset_input_create_or_fail (); hb_set_t * input_name_ids = hb_subset_input_nameid_set (input); - hb_set_union (input_name_ids, name_ids); + hb_set_set (input_name_ids, name_ids); return input; } @@ -91,9 +91,9 @@ hb_subset_test_check (hb_face_t *expected, hb_tag_t table) { hb_blob_t *expected_blob, *actual_blob; - //fprintf(stderr, "comparing %c%c%c%c ", HB_UNTAG(table)); expected_blob = hb_face_reference_table (expected, table); actual_blob = hb_face_reference_table (actual, table); + fprintf(stderr, "comparing %c%c%c%c, expected %d bytes, actual %d bytes\n", HB_UNTAG(table), hb_blob_get_length(expected_blob), hb_blob_get_length (actual_blob)); hb_test_assert_blobs_equal (expected_blob, actual_blob); hb_blob_destroy (expected_blob); hb_blob_destroy (actual_blob); diff --git a/test/api/hb-test.h b/test/api/hb-test.h index 872f45c4b..b866e442a 100644 --- a/test/api/hb-test.h +++ b/test/api/hb-test.h @@ -173,6 +173,16 @@ static inline void hb_test_assert_blobs_equal (hb_blob_t *expected_blob, hb_blob const char *raw_expected = hb_blob_get_data (expected_blob, &expected_length); const char *raw_actual = hb_blob_get_data (actual_blob, &actual_length); g_assert_cmpint(expected_length, ==, actual_length); + if (memcmp (raw_expected, raw_actual, expected_length) != 0) + { + for (unsigned int i = 0; i < expected_length; i++) + { + int expected = *(raw_expected + i); + int actual = *(raw_actual + i); + if (expected != actual) fprintf(stderr, "+%u %02x != %02x\n", i, expected, actual); + else fprintf(stderr, "+%u %02x\n", i, expected); + } + } g_assert_cmpint(0, ==, memcmp(raw_expected, raw_actual, expected_length)); } diff --git a/test/api/test-aat-layout.c b/test/api/test-aat-layout.c index 1384556a8..d9dd8a3c2 100644 --- a/test/api/test-aat-layout.c +++ b/test/api/test-aat-layout.c @@ -1,5 +1,5 @@ /* - * Copyright © 2018 Google, Inc. + * Copyright © 2018 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * diff --git a/test/api/test-font.c b/test/api/test-font.c index 669019404..c6738b400 100644 --- a/test/api/test-font.c +++ b/test/api/test-font.c @@ -146,9 +146,6 @@ _test_font_nil_funcs (hb_font_t *font) glyph = 3; g_assert (!hb_font_get_glyph (font, 17, 2, &glyph)); g_assert_cmpint (glyph, ==, 0); - - x = hb_font_get_glyph_h_kerning (font, 17, 19); - g_assert_cmpint (x, ==, 0); } static void diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 7f500157e..000b0a2c5 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -629,19 +629,19 @@ test_get_glyph_assembly (void) g_assert_cmpint(parts[0].start_connector_length, ==, 800); g_assert_cmpint(parts[0].end_connector_length, ==, 384); g_assert_cmpint(parts[0].full_advance, ==, 2000); - g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(!(parts[0].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER)); g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph)); g_assert_cmpint(parts[1].glyph, ==, glyph); g_assert_cmpint(parts[1].start_connector_length, ==, 524); g_assert_cmpint(parts[1].end_connector_length, ==, 800); g_assert_cmpint(parts[1].full_advance, ==, 2000); - g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER); g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph)); g_assert_cmpint(parts[2].glyph, ==, glyph); g_assert_cmpint(parts[2].start_connector_length, ==, 316); g_assert_cmpint(parts[2].end_connector_length, ==, 454); g_assert_cmpint(parts[2].full_advance, ==, 2000); - g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(!(parts[2].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER)); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); offset = 0; @@ -662,20 +662,20 @@ test_get_glyph_assembly (void) g_assert_cmpint(parts[0].start_connector_length, ==, 365); g_assert_cmpint(parts[0].end_connector_length, ==, 158); g_assert_cmpint(parts[0].full_advance, ==, 1000); - g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(!(parts[0].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER)); g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); g_assert_cmpint(parts[1].glyph, ==, glyph); g_assert_cmpint(parts[1].glyph, ==, glyph); g_assert_cmpint(parts[1].start_connector_length, ==, 227); g_assert_cmpint(parts[1].end_connector_length, ==, 365); g_assert_cmpint(parts[1].full_advance, ==, 1000); - g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER); g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph)); g_assert_cmpint(parts[2].glyph, ==, glyph); g_assert_cmpint(parts[2].start_connector_length, ==, 54); g_assert_cmpint(parts[2].end_connector_length, ==, 158); g_assert_cmpint(parts[2].full_advance, ==, 1000); - g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(!(parts[2].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER)); g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); g_assert_cmpint(parts[3].glyph, ==, glyph); g_assert_cmpint(parts[3].glyph, ==, glyph); @@ -683,13 +683,13 @@ test_get_glyph_assembly (void) g_assert_cmpint(parts[3].start_connector_length, ==, 400); g_assert_cmpint(parts[3].end_connector_length, ==, 296); g_assert_cmpint(parts[3].full_advance, ==, 1000); - g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER); g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph)); g_assert_cmpint(parts[4].glyph, ==, glyph); g_assert_cmpint(parts[4].start_connector_length, ==, 123); g_assert_cmpint(parts[4].end_connector_length, ==, 192); g_assert_cmpint(parts[4].full_advance, ==, 1000); - g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(!(parts[4].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER)); closeFont(); diff --git a/test/api/test-shape.c b/test/api/test-shape.c index 146cf0f4a..8fbe7f70c 100644 --- a/test/api/test-shape.c +++ b/test/api/test-shape.c @@ -67,17 +67,6 @@ glyph_func (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, return FALSE; } -static hb_position_t -glyph_h_kerning_func (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t left, hb_codepoint_t right, - void *user_data HB_UNUSED) -{ - if (left == 1 && right == 2) - return -2; - - return 0; -} - static const char TesT[] = "TesT"; static void @@ -102,7 +91,6 @@ test_shape (void) ffuncs = hb_font_funcs_create (); hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL); hb_font_funcs_set_nominal_glyph_func (ffuncs, glyph_func, malloc (10), free); - hb_font_funcs_set_glyph_h_kerning_func (ffuncs, glyph_h_kerning_func, NULL, NULL); hb_font_set_funcs (font, ffuncs, NULL, NULL); hb_font_funcs_destroy (ffuncs); @@ -118,8 +106,8 @@ test_shape (void) { const hb_codepoint_t output_glyphs[] = {1, 2, 3, 1}; - const hb_position_t output_x_advances[] = {9, 5, 5, 10}; - const hb_position_t output_x_offsets[] = {0, -1, 0, 0}; + const hb_position_t output_x_advances[] = {10, 6, 5, 10}; + const hb_position_t output_x_offsets[] = {0, 0, 0, 0}; unsigned int i; g_assert_cmpint (len, ==, 4); for (i = 0; i < len; i++) { diff --git a/test/api/test-subset-drop-tables.c b/test/api/test-subset-drop-tables.c new file mode 100644 index 000000000..e23408008 --- /dev/null +++ b/test/api/test-subset-drop-tables.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2019 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "hb-test.h" +#include "hb-subset-test.h" + +/* Unit tests for hb-subset.cc drop tables functionality */ + +static void +test_subset_drop_tables (void) +{ + hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_set_add (codepoints, 97); + hb_set_add (codepoints, 99); + hb_subset_input_t *input = hb_subset_test_create_input (codepoints); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG ('h', 'd', 'm', 'x')); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG ('h', 'm', 't', 'x')); + hb_set_destroy (codepoints); + + hb_face_t* subset = hb_subset (face, input); + + hb_blob_t *hdmx = hb_face_reference_table (subset, HB_TAG ('h', 'd', 'm', 'x')); + hb_blob_t *hmtx = hb_face_reference_table (subset, HB_TAG ('h', 'm', 't', 'x')); + hb_blob_t *cmap = hb_face_reference_table (subset, HB_TAG ('c', 'm', 'a', 'p')); + g_assert (!hb_blob_get_length (hdmx)); + g_assert (!hb_blob_get_length (hmtx)); + g_assert ( hb_blob_get_length (cmap)); + hb_blob_destroy (hdmx); + hb_blob_destroy (hmtx); + hb_blob_destroy (cmap); + + hb_face_destroy (subset); + hb_subset_input_destroy (input); + hb_face_destroy (face); +} + + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_subset_drop_tables); + + return hb_test_run(); +} diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c index 4671156f9..2b330ced2 100644 --- a/test/api/test-subset-glyf.c +++ b/test/api/test-subset-glyf.c @@ -70,9 +70,9 @@ test_subset_glyf (void) face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints)); hb_set_destroy (codepoints); - hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f')); - hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a')); check_maxp_num_glyphs(face_abc_subset, 3, true); + hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a')); + hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f')); hb_face_destroy (face_abc_subset); hb_face_destroy (face_abc); @@ -137,7 +137,9 @@ test_subset_glyf_with_gsub (void) input = hb_subset_test_create_input (codepoints); hb_set_destroy (codepoints); - hb_subset_input_set_drop_layout (input, false); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'S', 'U', 'B')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'P', 'O', 'S')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'D', 'E', 'F')); face_subset = hb_subset_test_create_subset (face_fil, input); @@ -164,7 +166,9 @@ test_subset_glyf_without_gsub (void) input = hb_subset_test_create_input (codepoints); hb_set_destroy (codepoints); - hb_subset_input_set_drop_layout (input, true); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'S', 'U', 'B')); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'P', 'O', 'S')); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'D', 'E', 'F')); face_subset = hb_subset_test_create_subset (face_fil, input); @@ -190,9 +194,9 @@ test_subset_glyf_noop (void) face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints)); hb_set_destroy (codepoints); - hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','l','y','f')); - hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('l','o','c', 'a')); check_maxp_num_glyphs(face_abc_subset, 4, true); + hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('l','o','c', 'a')); + hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','l','y','f')); hb_face_destroy (face_abc_subset); hb_face_destroy (face_abc); @@ -214,9 +218,9 @@ test_subset_glyf_strip_hints_simple (void) face_abc_subset = hb_subset_test_create_subset (face_abc, input); hb_set_destroy (codepoints); + check_maxp_num_glyphs(face_abc_subset, 3, false); hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a')); hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f')); - check_maxp_num_glyphs(face_abc_subset, 3, false); hb_face_destroy (face_abc_subset); hb_face_destroy (face_abc); @@ -239,9 +243,9 @@ test_subset_glyf_strip_hints_composite (void) face_generated_subset = hb_subset_test_create_subset (face_components, input); hb_set_destroy (codepoints); - hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f')); - hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a')); check_maxp_num_glyphs(face_generated_subset, 4, false); + hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a')); + hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f')); hb_face_destroy (face_generated_subset); hb_face_destroy (face_subset); @@ -296,15 +300,39 @@ test_subset_glyf_retain_gids (void) face_abc_subset = hb_subset_test_create_subset (face_abc, input); hb_set_destroy (codepoints); - hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f')); - hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a')); check_maxp_num_glyphs(face_abc_subset, 4, true); + hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a')); + hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f')); hb_face_destroy (face_abc_subset); hb_face_destroy (face_abc); hb_face_destroy (face_ac); } +static void +test_subset_glyf_retain_gids_truncates (void) +{ + hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf"); + hb_face_t *face_a = hb_test_open_font_file ("fonts/Roboto-Regular.a.retaingids.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_face_t *face_abc_subset; + hb_set_add (codepoints, 97); + + hb_subset_input_t *input = hb_subset_test_create_input (codepoints); + hb_subset_input_set_retain_gids (input, true); + face_abc_subset = hb_subset_test_create_subset (face_abc, input); + hb_set_destroy (codepoints); + + check_maxp_num_glyphs(face_abc_subset, 2, true); + hb_subset_test_check (face_a, face_abc_subset, HB_TAG ('l','o','c', 'a')); + hb_subset_test_check (face_a, face_abc_subset, HB_TAG ('g','l','y','f')); + + hb_face_destroy (face_abc_subset); + hb_face_destroy (face_abc); + hb_face_destroy (face_a); +} + // TODO(grieger): test for long loca generation. int @@ -322,6 +350,7 @@ main (int argc, char **argv) hb_test_add (test_subset_glyf_with_gsub); hb_test_add (test_subset_glyf_without_gsub); hb_test_add (test_subset_glyf_retain_gids); + hb_test_add (test_subset_glyf_retain_gids_truncates); return hb_test_run(); } diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c index 44e579ace..7178833bc 100644 --- a/test/api/test-subset-hdmx.c +++ b/test/api/test-subset-hdmx.c @@ -91,28 +91,6 @@ test_subset_hdmx_invalid (void) hb_face_destroy (face); } -static void -test_subset_hdmx_fails_sanitize (void) -{ - hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016"); - - hb_subset_input_t *input = hb_subset_input_create_or_fail (); - hb_set_t *codepoints = hb_subset_input_unicode_set (input); - hb_face_t *subset; - - hb_set_add (codepoints, 'a'); - hb_set_add (codepoints, 'b'); - hb_set_add (codepoints, 'c'); - - subset = hb_subset (face, input); - g_assert (subset); - g_assert (subset == hb_face_get_empty ()); - - hb_subset_input_destroy (input); - hb_face_destroy (subset); - hb_face_destroy (face); -} - static void test_subset_hdmx_noop (void) { @@ -140,7 +118,6 @@ main (int argc, char **argv) hb_test_add (test_subset_hdmx_simple_subset); hb_test_add (test_subset_hdmx_multiple_device_records); hb_test_add (test_subset_hdmx_invalid); - hb_test_add (test_subset_hdmx_fails_sanitize); hb_test_add (test_subset_hdmx_noop); return hb_test_run(); diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c index 6195bb286..0587c6e7f 100644 --- a/test/api/test-unicode.c +++ b/test/api/test-unicode.c @@ -755,6 +755,10 @@ test_unicode_normalization (gconstpointer user_data) g_assert (hb_unicode_compose (uf, 0xCE20, 0x11B8, &ab) && ab == 0xCE31); g_assert (hb_unicode_compose (uf, 0x110E, 0x1173, &ab) && ab == 0xCE20); + g_assert (!hb_unicode_compose (uf, 0xAC00, 0x11A7, &ab)); + g_assert (hb_unicode_compose (uf, 0xAC00, 0x11A8, &ab) && ab == 0xAC01); + g_assert (!hb_unicode_compose (uf, 0xAC01, 0x11A8, &ab)); + /* Test decompose() */ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5702671124791296 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5702671124791296 new file mode 100644 index 000000000..9ecc7f16b Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5702671124791296 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-6252118652092416 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-6252118652092416 new file mode 100644 index 000000000..e2dd6a389 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-6252118652092416 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5077547978588160 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5077547978588160 new file mode 100644 index 000000000..37bb00955 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5077547978588160 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5634197349203968 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5634197349203968 new file mode 100644 index 000000000..39e8bd942 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5634197349203968 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5676773460672512 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5676773460672512 new file mode 100644 index 000000000..4fc920bf5 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5676773460672512 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696825891225600 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696825891225600 new file mode 100644 index 000000000..30515a4c3 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696825891225600 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5761434614497280 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5761434614497280 new file mode 100644 index 000000000..0060ade57 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5761434614497280 differ diff --git a/test/fuzzing/hb-shape-fuzzer.cc b/test/fuzzing/hb-shape-fuzzer.cc index 5723db90c..64a6b12df 100644 --- a/test/fuzzing/hb-shape-fuzzer.cc +++ b/test/fuzzing/hb-shape-fuzzer.cc @@ -10,7 +10,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { hb_blob_t *blob = hb_blob_create ((const char *)data, size, - HB_MEMORY_MODE_READONLY, NULL, NULL); + HB_MEMORY_MODE_READONLY, nullptr, nullptr); hb_face_t *face = hb_face_create (blob, 0); hb_font_t *font = hb_font_create (face); hb_ot_font_set_funcs (font); @@ -21,7 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) hb_buffer_t *buffer = hb_buffer_create (); hb_buffer_add_utf8 (buffer, text, -1, 0, -1); hb_buffer_guess_segment_properties (buffer); - hb_shape (font, buffer, NULL, 0); + hb_shape (font, buffer, nullptr, 0); hb_buffer_destroy (buffer); } @@ -34,7 +34,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) hb_buffer_t *buffer = hb_buffer_create (); hb_buffer_add_utf32 (buffer, text32, sizeof (text32) / sizeof (text32[0]), 0, -1); hb_buffer_guess_segment_properties (buffer); - hb_shape (font, buffer, NULL, 0); + hb_shape (font, buffer, nullptr, 0); hb_buffer_destroy (buffer); /* Misc calls on face. */ diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc index 56ffd2271..73c95b2a6 100644 --- a/test/fuzzing/hb-subset-fuzzer.cc +++ b/test/fuzzing/hb-subset-fuzzer.cc @@ -16,10 +16,16 @@ trySubset (hb_face_t *face, { hb_subset_input_t *input = hb_subset_input_create_or_fail (); hb_subset_input_set_drop_hints (input, drop_hints); - hb_subset_input_set_drop_layout (input, drop_layout); hb_subset_input_set_retain_gids (input, retain_gids); hb_set_t *codepoints = hb_subset_input_unicode_set (input); + if (!drop_layout) + { + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'S', 'U', 'B')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'P', 'O', 'S')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'D', 'E', 'F')); + } + for (int i = 0; i < text_length; i++) { hb_set_add (codepoints, text[i]); @@ -47,7 +53,7 @@ trySubset (hb_face_t *face, extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { hb_blob_t *blob = hb_blob_create ((const char *)data, size, - HB_MEMORY_MODE_READONLY, NULL, NULL); + HB_MEMORY_MODE_READONLY, nullptr, nullptr); hb_face_t *face = hb_face_create (blob, 0); /* Just test this API here quickly. */ diff --git a/test/fuzzing/main.cc b/test/fuzzing/main.cc index f15247cdb..5318f64ea 100644 --- a/test/fuzzing/main.cc +++ b/test/fuzzing/main.cc @@ -4,8 +4,10 @@ #include #include -int main(int argc, char **argv) { +int main (int argc, char **argv) +{ hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + unsigned int len; const char *font_data = hb_blob_get_data (blob, &len); if (len == 0) @@ -14,10 +16,13 @@ int main(int argc, char **argv) { exit (1); } - for (int i = 1; i < argc; i++) { + for (int i = 1; i < argc; i++) + { printf ("%s\n", argv[i]); - LLVMFuzzerTestOneInput((const uint8_t *) font_data, len); + LLVMFuzzerTestOneInput ((const uint8_t *) font_data, len); } hb_blob_destroy (blob); + + return 0; } diff --git a/test/shaping/data/in-house/fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf b/test/shaping/data/in-house/fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf new file mode 100644 index 000000000..945d69834 Binary files /dev/null and b/test/shaping/data/in-house/fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf differ diff --git a/test/shaping/data/in-house/tests/use-syllable.tests b/test/shaping/data/in-house/tests/use-syllable.tests index 6a247ed0c..905600891 100644 --- a/test/shaping/data/in-house/tests/use-syllable.tests +++ b/test/shaping/data/in-house/tests/use-syllable.tests @@ -10,3 +10,7 @@ ../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+11044,U+11046:[brm_KA=0+754|brm_vowelOO=0@-647,0+0|brm_virama=0@-524,0+0] ../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+1103C:[brm_KA=0+754|brm_vowelU=0@-403,0+0] ../fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf::U+111C8,U+111C9,U+111C9:[u111C8=0+500|u111C9=0@-500,0+0|u111C9=0@-500,0+0] +../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A5A,U+1A63:[uni1A3D=0+250|uni1A5A=0+0|uni1A63=0+250] +../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A60,U+1A3D,U+1A63,U+1A60,U+1A3D,U+1A59:[uni1A3D=0+250|uni1A60=0+0|uni1A3D=2+250|uni1A63=2+250|uni1A60=2+0|uni1A3D=5+250|uni1A59=5+0] +../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A60,U+1A3D,U+1A63,U+1A60,U+1A3D,U+1A5A:[uni1A3D=0+250|uni1A60=0+0|uni1A3D=2+250|uni1A63=2+250|uni1A60=2+0|uni1A3D=5+250|uni25CC=5+250|uni1A5A=5+0] +../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A60,U+1A3D,U+1A63,U+1A60,U+1A3D,U+1A60:[uni1A3D=0+250|uni1A60=0+0|uni1A3D=2+250|uni1A63=2+250|uni1A60=2+0|uni1A3D=5+250|uni1A60=5+0] diff --git a/test/shaping/record-test.sh b/test/shaping/record-test.sh index 4ab74f0f9..7f24354c1 100755 --- a/test/shaping/record-test.sh +++ b/test/shaping/record-test.sh @@ -2,6 +2,17 @@ dir=`mktemp -d` +if which sha1sum 2>/dev/null >/dev/null; then + SHA1SUM=sha1sum +elif which shasum 2>/dev/null >/dev/null; then + SHA1SUM='shasum -a 1' +elif which digest 2>/dev/null >/dev/null; then + SHA1SUM='digest -a sha1' +else + echo "'sha1sum' not found" + exit 2 +fi + out=/dev/stdout if test "x$1" == 'x-o'; then shift @@ -90,7 +101,7 @@ if ! test "x$glyphs" = "x$glyphs_subset"; then glyphs=$glyphs_subset fi -sha1sum=`sha1sum "$dir/font.subset.ttf" | cut -d' ' -f1` +sha1sum=`$SHA1SUM "$dir/font.subset.ttf" | cut -d' ' -f1` subset="data/in-house/fonts/$sha1sum.ttf" mv "$dir/font.subset.ttf" "$subset" diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index 067712055..3439588ae 100644 --- a/test/subset/data/Makefile.am +++ b/test/subset/data/Makefile.am @@ -10,6 +10,7 @@ EXTRA_DIST += \ expected/basics \ expected/full-font \ expected/japanese \ + expected/layout \ fonts \ profiles \ $(NULL) diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources index dd1bcfe7a..75913fd9f 100644 --- a/test/subset/data/Makefile.sources +++ b/test/subset/data/Makefile.sources @@ -2,6 +2,7 @@ TESTS = \ tests/basics.tests \ tests/full-font.tests \ tests/japanese.tests \ + tests/layout.tests \ $(NULL) XFAIL_TESTS = \ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf new file mode 100644 index 000000000..efe5bcb4c Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf new file mode 100644 index 000000000..8e1224178 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf new file mode 100644 index 000000000..bd802a57e Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf new file mode 100644 index 000000000..9fbebb5d4 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf new file mode 100644 index 000000000..73917418a Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf new file mode 100644 index 000000000..05d83d8f9 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf new file mode 100644 index 000000000..f47887e94 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf new file mode 100644 index 000000000..bfa9267b9 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf new file mode 100644 index 000000000..8c121581a Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf new file mode 100644 index 000000000..6a47c39d6 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf new file mode 100644 index 000000000..36a4b9a45 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf new file mode 100644 index 000000000..251794c25 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf new file mode 100644 index 000000000..9e65c8385 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf new file mode 100644 index 000000000..ada1649af Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf new file mode 100644 index 000000000..6b0dc6c3d Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf new file mode 100644 index 000000000..90e49bef6 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf new file mode 100644 index 000000000..5277d1508 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf new file mode 100644 index 000000000..de06660d0 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf new file mode 100644 index 000000000..effad7b68 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf new file mode 100644 index 000000000..21c8205cb Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf new file mode 100644 index 000000000..3c0f4cd5b Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf new file mode 100644 index 000000000..a5ce9e05d Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf new file mode 100644 index 000000000..1b843357d Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf new file mode 100644 index 000000000..97eaa26ad Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf new file mode 100644 index 000000000..f42edb71f Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf index 1a0d5bdd0..128eae016 100644 Binary files a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf index 257184b92..2d2b65b0d 100644 Binary files a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf index d3a67eafa..a699eea0b 100644 Binary files a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf and b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf index 4ff6e338c..eb84f9c9f 100644 Binary files a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf and b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf index 1bd287d3d..f0ea3ca97 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf index 328c6ee88..7ea55a27f 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf index 4602847a1..07b9aa219 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf index ca546541b..8ce5fdbf5 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf index 0f52e66b2..a1487ff65 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf index 170c15109..9168bc869 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf index 18a9bcc4c..cf0fbf601 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf index edd389b41..8ab8294cc 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf index 65fa1daea..de475e60a 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf index 87c8f00f3..7cca4891a 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf index f381f1389..06f0c1f27 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf index f32a1fcfa..556861c95 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf index 604e14045..cf3228d23 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf index 419dfa010..1bafff123 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf index 805532868..34303e790 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf index 9a5c09a17..5177c149e 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf index f5b4ebdf4..c70b82a1b 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf index 57f9a8d5e..b14b3eb67 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf index 53109e24b..112dec704 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf index dd908c242..929c4e2d1 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf index 5422d3228..939a565a9 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf index 2caee794c..02529e3ac 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf index b428a7b12..76e5cc592 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf differ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf index ccb442822..a1178c2da 100644 Binary files a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf and b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf index 93efe6553..e8b7b375c 100644 Binary files a/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf and b/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf index d4d26d7ea..912e1fb24 100644 Binary files a/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf and b/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf index 7e271f22b..6f19df6e2 100644 Binary files a/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf and b/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf index 99b91bd31..9ea42ab09 100644 Binary files a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf and b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf index eb94906a8..4d125939c 100644 Binary files a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf and b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf index ff361baef..281b47523 100644 Binary files a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf and b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf index 33989996e..6770dacab 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf index 66b98a6d1..0c662199c 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf index 22d1bb309..4a5a6f8ab 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf index 28043592e..465ce3479 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf index 333ca516d..28f3c3717 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf index c84b20cba..1bebda7f2 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf index e757b9e34..a43998d1b 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf index e869ff1fa..34c7788b4 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf index ed4ed4c10..92ec10b57 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf differ diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf index cb502388e..b9bb53974 100644 Binary files a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf and b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,42,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,42,43.ttf new file mode 100644 index 000000000..aa007bac5 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,42,43.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,43.ttf new file mode 100644 index 000000000..f3be30c5b Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,43.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41.ttf new file mode 100644 index 000000000..44c329eb1 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.43.ttf new file mode 100644 index 000000000..b0a1ea3dc Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.43.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.CA,CB.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.CA,CB.ttf new file mode 100644 index 000000000..16ad9d515 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.CA,CB.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,42,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,42,43.ttf new file mode 100644 index 000000000..d0d9d5a28 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,42,43.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,43.ttf new file mode 100644 index 000000000..f4d881f29 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,43.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41.ttf new file mode 100644 index 000000000..9e6dd28f5 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.43.ttf new file mode 100644 index 000000000..50260c54d Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.43.ttf differ diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.CA,CB.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.CA,CB.ttf new file mode 100644 index 000000000..22d5b6198 Binary files /dev/null and b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.CA,CB.ttf differ diff --git a/test/subset/data/fonts/Comfortaa-Regular-new.ttf b/test/subset/data/fonts/Comfortaa-Regular-new.ttf new file mode 100644 index 000000000..4965fbe39 Binary files /dev/null and b/test/subset/data/fonts/Comfortaa-Regular-new.ttf differ diff --git a/test/subset/data/fonts/Roboto-Regular.smallcaps.ttf b/test/subset/data/fonts/Roboto-Regular.smallcaps.ttf new file mode 100644 index 000000000..fc58299ba Binary files /dev/null and b/test/subset/data/fonts/Roboto-Regular.smallcaps.ttf differ diff --git a/test/subset/data/profiles/keep-layout-retain-gids.txt b/test/subset/data/profiles/keep-layout-retain-gids.txt new file mode 100644 index 000000000..f4787adef --- /dev/null +++ b/test/subset/data/profiles/keep-layout-retain-gids.txt @@ -0,0 +1,2 @@ +--drop-tables-=GSUB,GPOS +--retain-gids diff --git a/test/subset/data/profiles/keep-layout.txt b/test/subset/data/profiles/keep-layout.txt new file mode 100644 index 000000000..56da0ffe3 --- /dev/null +++ b/test/subset/data/profiles/keep-layout.txt @@ -0,0 +1 @@ +--drop-tables-=GSUB,GPOS diff --git a/test/subset/data/tests/basics.tests b/test/subset/data/tests/basics.tests index 794510d87..c310722b0 100644 --- a/test/subset/data/tests/basics.tests +++ b/test/subset/data/tests/basics.tests @@ -1,5 +1,6 @@ FONTS: Roboto-Regular.abc.ttf +Comfortaa-Regular-new.ttf PROFILES: default.txt diff --git a/test/subset/data/tests/full-font.tests b/test/subset/data/tests/full-font.tests index 28ae084f0..d9519b69f 100644 --- a/test/subset/data/tests/full-font.tests +++ b/test/subset/data/tests/full-font.tests @@ -10,4 +10,3 @@ SUBSETS: abc Ǽ!A bc ×ØÙÚÞ - diff --git a/test/subset/data/tests/layout.tests b/test/subset/data/tests/layout.tests new file mode 100644 index 000000000..dd1c26ee9 --- /dev/null +++ b/test/subset/data/tests/layout.tests @@ -0,0 +1,13 @@ +FONTS: +Roboto-Regular.smallcaps.ttf + +PROFILES: +keep-layout.txt +keep-layout-retain-gids.txt + +SUBSETS: +ABC +AC +C +A +ÊË diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py index 6d11cbfe6..6c65627e3 100755 --- a/test/subset/generate-expected-outputs.py +++ b/test/subset/generate-expected-outputs.py @@ -19,14 +19,14 @@ def usage(): def generate_expected_output(input_file, unicodes, profile_flags, output_path): args = ["fonttools", "subset", input_file] - args.extend(profile_flags) args.extend(["--notdef-outline", - "--name-IDs=*", "--name-languages=*", "--name-legacy", - "--drop-tables+=DSIG,GPOS,GSUB,GDEF", + "--layout-features=*", + "--drop-tables+=DSIG,GPOS,GSUB,GDEF,gvar,avar,MVAR,HVAR", "--unicodes=%s" % unicodes, "--output-file=%s" % output_path]) + args.extend(profile_flags) check_call(args) diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py index fb4684cf1..5d221e6bb 100755 --- a/test/subset/run-tests.py +++ b/test/subset/run-tests.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Runs a subsetting test suite. Compares the results of subsetting via harfbuz +# Runs a subsetting test suite. Compares the results of subsetting via harfbuzz # to subsetting via fonttools. from __future__ import print_function, division, absolute_import @@ -16,27 +16,27 @@ import tempfile from subset_test_suite import SubsetTestSuite # https://stackoverflow.com/a/377028 -def which(program): - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) +def which (program): + def is_exe (fpath): + return os.path.isfile (fpath) and os.access (fpath, os.X_OK) - fpath, _ = os.path.split(program) + fpath, _ = os.path.split (program) if fpath: - if is_exe(program): + if is_exe (program): return program else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if is_exe(exe_file): + for path in os.environ["PATH"].split (os.pathsep): + exe_file = os.path.join (path, program) + if is_exe (exe_file): return exe_file return None -ttx = which ("ttx") +fonttools = which ("fonttools") ots_sanitize = which ("ots-sanitize") -if not ttx: - print("TTX is not present, skipping test.") +if not fonttools: + print ("fonttools is not present, skipping test.") sys.exit (77) def cmd(command): @@ -50,7 +50,7 @@ def read_binary (file_path): with open (file_path, 'rb') as f: return f.read () -def fail_test(test, cli_args, message): +def fail_test (test, cli_args, message): print ('ERROR: %s' % message) print ('Test State:') print (' test.font_path %s' % os.path.abspath (test.font_path)) @@ -61,12 +61,13 @@ def fail_test(test, cli_args, message): print (' expected_file %s' % os.path.abspath (expected_file)) return 1 -def run_test(test, should_check_ots): - out_file = os.path.join(tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ()) +def run_test (test, should_check_ots): + out_file = os.path.join (tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ()) cli_args = [hb_subset, "--font-file=" + test.font_path, "--output-file=" + out_file, - "--unicodes=%s" % test.unicodes ()] + "--unicodes=%s" % test.unicodes (), + "--drop-tables+=DSIG,GPOS,GSUB,GDEF,gvar,avar,MVAR,HVAR"] cli_args.extend (test.get_profile_flags ()) print (' '.join (cli_args)) _, return_code = cmd (cli_args) @@ -75,11 +76,11 @@ def run_test(test, should_check_ots): return fail_test (test, cli_args, "%s returned %d" % (' '.join (cli_args), return_code)) expected_ttx, return_code = run_ttx (os.path.join (test_suite.get_output_directory (), - test.get_font_name ())) + test.get_font_name ())) if return_code: return fail_test (test, cli_args, "ttx (expected) returned %d" % (return_code)) - actual_ttx, return_code = run_ttx(out_file) + actual_ttx, return_code = run_ttx (out_file) if return_code: return fail_test (test, cli_args, "ttx (actual) returned %d" % (return_code)) @@ -91,7 +92,7 @@ def run_test(test, should_check_ots): for line in unified_diff (expected_ttx.splitlines (1), actual_ttx.splitlines (1)): sys.stdout.write (line) sys.stdout.flush () - return fail_test(test, cli_args, 'ttx for expected and actual does not match.') + return fail_test (test, cli_args, 'ttx for expected and actual does not match.') if should_check_ots: print ("Checking output with ots-sanitize.") @@ -101,8 +102,8 @@ def run_test(test, should_check_ots): return 0 def run_ttx (file): - print ("ttx %s" % file) - return cmd([ttx, "-q", "-o-", file]) + print ("fonttools ttx %s" % file) + return cmd ([fonttools, "ttx", "-q", "-o-", file]) def strip_check_sum (ttx_string): return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]', @@ -123,7 +124,7 @@ def check_ots (path): return True args = sys.argv[1:] -if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.argv[1]): +if not args or sys.argv[1].find ('hb-subset') == -1 or not os.path.exists (sys.argv[1]): print ("First argument does not seem to point to usable hb-subset.") sys.exit (1) hb_subset, args = args[0], args[1:] @@ -138,7 +139,7 @@ fails = 0 for path in args: with io.open (path, mode="r", encoding="utf-8") as f: print ("Running tests in " + path) - test_suite = SubsetTestSuite (path, f.read()) + test_suite = SubsetTestSuite (path, f.read ()) for test in test_suite.tests (): fails += run_test (test, has_ots) diff --git a/util/Makefile.am b/util/Makefile.am index e24a6f3dc..5298e7732 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -50,8 +50,9 @@ bin_PROGRAMS += hb-shape hb_subset_SOURCES = $(HB_SUBSET_CLI_sources) hb_subset_LDADD = \ - $(LDADD) \ - $(top_builddir)/src/libharfbuzz-subset.la + $(top_builddir)/src/libharfbuzz-subset.la \ + $(LDADD) + bin_PROGRAMS += hb-subset hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources) diff --git a/util/Makefile.sources b/util/Makefile.sources index 6c815d26b..bcf85f562 100644 --- a/util/Makefile.sources +++ b/util/Makefile.sources @@ -32,6 +32,7 @@ HB_OT_SHAPE_CLOSURE_sources = \ HB_SUBSET_CLI_sources = \ hb-subset.cc \ options.cc \ + options-subset.cc \ options.hh \ main-font-text.hh \ $(NULL) diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc index 77ca20135..33f531b37 100644 --- a/util/hb-ot-shape-closure.cc +++ b/util/hb-ot-shape-closure.cc @@ -39,7 +39,7 @@ struct shape_closure_consumer_t : option_group_t add_options (parser); } - void add_options (struct option_parser_t *parser) + void add_options (struct option_parser_t *parser) override { GOptionEntry entries[] = { diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 682ca4c34..4b7af8e9a 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -43,7 +43,7 @@ struct subset_consumer_t const font_options_t *font_opts) { font = hb_font_reference (font_opts->get_font ()); - input = hb_subset_input_create_or_fail (); + input = hb_subset_input_reference (subset_options.input); } void consume_line (const char *text, @@ -89,12 +89,6 @@ struct subset_consumer_t void finish (const font_options_t *font_opts) { - hb_subset_input_set_drop_layout (input, !subset_options.keep_layout); - hb_subset_input_set_drop_hints (input, subset_options.drop_hints); - hb_subset_input_set_retain_gids (input, subset_options.retain_gids); - hb_subset_input_set_desubroutinize (input, subset_options.desubroutinize); - hb_set_set (hb_subset_input_nameid_set (input), subset_options.name_ids); - hb_face_t *face = hb_font_get_face (font); hb_face_t *new_face = hb_subset (face, input); diff --git a/util/options-subset.cc b/util/options-subset.cc new file mode 100644 index 000000000..b2f4db087 --- /dev/null +++ b/util/options-subset.cc @@ -0,0 +1,144 @@ +/* + * Copyright © 2019 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "options.hh" + +#include "hb-subset-input.hh" + +static gboolean +parse_nameids (const char *name, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + subset_options_t *subset_opts = (subset_options_t *) data; + hb_set_t *name_ids = subset_opts->input->name_ids; + + char last_name_char = name[strlen (name) - 1]; + + if (last_name_char != '+' && last_name_char != '-') + hb_set_clear (name_ids); + + if (0 == strcmp (arg, "*")) + { + if (last_name_char == '-') + hb_set_del_range (name_ids, 0, 0x7FFF); + else + hb_set_add_range (name_ids, 0, 0x7FFF); + return true; + } + + char *s = (char *) arg; + char *p; + + while (s && *s) + { + while (*s && strchr (", ", *s)) + s++; + if (!*s) + break; + + errno = 0; + hb_codepoint_t u = strtoul (s, &p, 10); + if (errno || s == p) + { + hb_set_destroy (name_ids); + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing nameID values at: '%s'", s); + return false; + } + + if (last_name_char != '-') + { + hb_set_add (name_ids, u); + } else { + hb_set_del (name_ids, u); + } + + s = p; + } + + return true; +} + +static gboolean +parse_drop_tables (const char *name, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + subset_options_t *subset_opts = (subset_options_t *) data; + hb_set_t *drop_tables = subset_opts->input->drop_tables; + + char last_name_char = name[strlen (name) - 1]; + + if (last_name_char != '+' && last_name_char != '-') + hb_set_clear (drop_tables); + + char *s = strtok((char *) arg, ", "); + while (s) + { + if (strlen (s) > 4) // Table tags are at most 4 bytes. + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing table tag values at: '%s'", s); + return false; + } + + hb_tag_t tag = hb_tag_from_string (s, strlen (s)); + + if (last_name_char != '-') + hb_set_add (drop_tables, tag); + else + hb_set_del (drop_tables, tag); + + s = strtok(nullptr, ", "); + } + + return true; +} + +void +subset_options_t::add_options (option_parser_t *parser) +{ + GOptionEntry entries[] = + { + {"no-hinting", 0, 0, G_OPTION_ARG_NONE, &this->input->drop_hints, "Whether to drop hints", nullptr}, + {"retain-gids", 0, 0, G_OPTION_ARG_NONE, &this->input->retain_gids, "If set don't renumber glyph ids in the subset.", nullptr}, + {"desubroutinize", 0, 0, G_OPTION_ARG_NONE, &this->input->desubroutinize, "Remove CFF/CFF2 use of subroutines", nullptr}, + {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_nameids, "Subset specified nameids", "list of int numbers"}, + {"drop-tables", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, + {"drop-tables+", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, + {"drop-tables-", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, + + {nullptr} + }; + parser->add_group (entries, + "subset", + "Subset options:", + "Options subsetting", + this); +} diff --git a/util/options.cc b/util/options.cc index a9b3fc77e..4e6ca57e7 100644 --- a/util/options.cc +++ b/util/options.cc @@ -31,6 +31,8 @@ #endif #include +#define DELIMITERS "<+>{},;&#\\xXuUnNiI\n\t\v\f\r " + static struct supported_font_funcs_t { char name[4]; void (*func) (hb_font_t *); @@ -352,7 +354,7 @@ parse_unicodes (const char *name G_GNUC_UNUSED, while (s && *s) { - while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t\v\f\r ", *s)) + while (*s && strchr (DELIMITERS, *s)) s++; if (!*s) break; @@ -970,67 +972,3 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t *buffer, serialize_glyphs (buffer, font, output_format, format_flags, gs); g_string_append_c (gs, '\n'); } - -static gboolean -parse_nameids (const char *name G_GNUC_UNUSED, - const char *arg, - gpointer data, - GError **error G_GNUC_UNUSED) -{ - subset_options_t *subset_opts = (subset_options_t *) data; - - hb_set_t *name_ids = hb_set_create (); - char *s = (char *) arg; - char *p; - - while (s && *s) - { - while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t\v\f\r ", *s)) - s++; - if (!*s) - break; - - errno = 0; - hb_codepoint_t u = strtoul (s, &p, 10); - if (errno || s == p) - { - hb_set_destroy (name_ids); - g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, - "Failed parsing nameID values at: '%s'", s); - return false; - } - - hb_set_add (name_ids, u); - - s = p; - } - - hb_set_t *prev = subset_opts->name_ids; - subset_opts->name_ids = hb_set_reference (name_ids); - hb_set_destroy (prev); - hb_set_destroy (name_ids); - - return true; -} - - -void -subset_options_t::add_options (option_parser_t *parser) -{ - GOptionEntry entries[] = - { - {"layout", 0, 0, G_OPTION_ARG_NONE, &this->keep_layout, "Keep OpenType Layout tables", nullptr}, - {"no-hinting", 0, 0, G_OPTION_ARG_NONE, &this->drop_hints, "Whether to drop hints", nullptr}, - {"retain-gids", 0, 0, G_OPTION_ARG_NONE, &this->retain_gids, "If set don't renumber glyph ids in the subset.", nullptr}, - {"desubroutinize", 0, 0, G_OPTION_ARG_NONE, &this->desubroutinize, "Remove CFF/CFF2 use of subroutines", nullptr}, - {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_nameids, "Subset specified nameids", "list of int numbers"}, - - {nullptr} - }; - parser->add_group (entries, - "subset", - "Subset options:", - "Options subsetting", - this); -} - diff --git a/util/options.hh b/util/options.hh index 2691e2269..63360ca5f 100644 --- a/util/options.hh +++ b/util/options.hh @@ -28,6 +28,7 @@ #define OPTIONS_HH #include "hb.hh" +#include "hb-subset.h" #include #include @@ -128,13 +129,13 @@ struct view_options_t : option_group_t add_options (parser); } - virtual ~view_options_t () + ~view_options_t () override { g_free (fore); g_free (back); } - void add_options (option_parser_t *parser); + void add_options (option_parser_t *parser) override; hb_bool_t annotate; char *fore; @@ -164,7 +165,7 @@ struct shape_options_t : option_group_t add_options (parser); } - virtual ~shape_options_t () + ~shape_options_t () override { g_free (direction); g_free (language); @@ -173,7 +174,7 @@ struct shape_options_t : option_group_t g_strfreev (shapers); } - void add_options (option_parser_t *parser); + void add_options (option_parser_t *parser) override; void setup_buffer (hb_buffer_t *buffer) { @@ -470,7 +471,7 @@ struct font_options_t : option_group_t add_options (parser); } - virtual ~font_options_t () + ~font_options_t () override { g_free (font_file); free (variations); @@ -478,7 +479,7 @@ struct font_options_t : option_group_t hb_font_destroy (font); } - void add_options (option_parser_t *parser); + void add_options (option_parser_t *parser) override; hb_font_t *get_font () const; @@ -520,7 +521,7 @@ struct text_options_t : option_group_t add_options (parser); } - virtual ~text_options_t () + ~text_options_t () override { g_free (text_before); g_free (text_after); @@ -532,9 +533,9 @@ struct text_options_t : option_group_t fclose (fp); } - void add_options (option_parser_t *parser); + void add_options (option_parser_t *parser) override; - void post_parse (GError **error G_GNUC_UNUSED) { + void post_parse (GError **error G_GNUC_UNUSED) override { if (text && text_file) g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, @@ -571,7 +572,7 @@ struct output_options_t : option_group_t add_options (parser); } - virtual ~output_options_t () + ~output_options_t () override { g_free (output_file); g_free (output_format); @@ -579,9 +580,9 @@ struct output_options_t : option_group_t fclose (fp); } - void add_options (option_parser_t *parser); + void add_options (option_parser_t *parser) override; - void post_parse (GError **error G_GNUC_UNUSED) + void post_parse (GError **error G_GNUC_UNUSED) override { if (output_format) explicit_output_format = true; @@ -626,7 +627,7 @@ struct format_options_t : option_group_t add_options (parser); } - void add_options (option_parser_t *parser); + void add_options (option_parser_t *parser) override; void serialize_unicode (hb_buffer_t *buffer, GString *gs); @@ -673,28 +674,18 @@ struct subset_options_t : option_group_t { subset_options_t (option_parser_t *parser) { - keep_layout = false; - drop_hints = false; - retain_gids = false; - desubroutinize = false; - name_ids = hb_set_create (); - + input = hb_subset_input_create_or_fail (); add_options (parser); } - virtual ~subset_options_t () + ~subset_options_t () override { - hb_set_destroy (name_ids); + hb_subset_input_destroy (input); } + void add_options (option_parser_t *parser) override; - void add_options (option_parser_t *parser); - - hb_bool_t keep_layout; - hb_bool_t drop_hints; - hb_bool_t retain_gids; - hb_bool_t desubroutinize; - hb_set_t *name_ids; + hb_subset_input_t *input; }; /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */