Browse Source

add harfbuzz library

Sasha Szpakowski 3 years ago
parent
commit
2d13144fcd
100 changed files with 33040 additions and 0 deletions
  1. 26 0
      libs/harfbuzz/.ci/build-win32.sh
  2. 26 0
      libs/harfbuzz/.ci/build-win64.sh
  3. 33 0
      libs/harfbuzz/.ci/deploy-docs.sh
  4. 23 0
      libs/harfbuzz/.ci/publish_release_artifact.sh
  5. 20 0
      libs/harfbuzz/.ci/win32-cross-file.txt
  6. 20 0
      libs/harfbuzz/.ci/win64-cross-file.txt
  7. 229 0
      libs/harfbuzz/.circleci/config.yml
  8. 38 0
      libs/harfbuzz/.clang-format
  9. 8 0
      libs/harfbuzz/.codecov.yml
  10. 23 0
      libs/harfbuzz/.editorconfig
  11. 6 0
      libs/harfbuzz/.github/dependabot.yml
  12. 24 0
      libs/harfbuzz/.github/workflows/cifuzz.yml
  13. 27 0
      libs/harfbuzz/.github/workflows/configs-build.yml
  14. 42 0
      libs/harfbuzz/.github/workflows/coverity-scan.yml
  15. 57 0
      libs/harfbuzz/.github/workflows/linux-ci.yml
  16. 30 0
      libs/harfbuzz/.github/workflows/macos-ci.yml
  17. 58 0
      libs/harfbuzz/.github/workflows/msvc-ci.yml
  18. 68 0
      libs/harfbuzz/.github/workflows/msys2-ci.yml
  19. 14 0
      libs/harfbuzz/AUTHORS
  20. 29 0
      libs/harfbuzz/BUILD.md
  21. 832 0
      libs/harfbuzz/CMakeLists.txt
  22. 158 0
      libs/harfbuzz/CONFIG.md
  23. 38 0
      libs/harfbuzz/COPYING
  24. 82 0
      libs/harfbuzz/Makefile.am
  25. 3019 0
      libs/harfbuzz/NEWS
  26. 1 0
      libs/harfbuzz/README
  27. 99 0
      libs/harfbuzz/README.md
  28. 58 0
      libs/harfbuzz/README.mingw.md
  29. 31 0
      libs/harfbuzz/README.python.md
  30. 37 0
      libs/harfbuzz/RELEASING.md
  31. 47 0
      libs/harfbuzz/TESTING.md
  32. 7 0
      libs/harfbuzz/THANKS
  33. 48 0
      libs/harfbuzz/autogen.sh
  34. 486 0
      libs/harfbuzz/configure.ac
  35. BIN
      libs/harfbuzz/docs/HarfBuzz.png
  36. 2 0
      libs/harfbuzz/docs/HarfBuzz.svg
  37. 123 0
      libs/harfbuzz/docs/Makefile.am
  38. 259 0
      libs/harfbuzz/docs/features.dot
  39. 213 0
      libs/harfbuzz/docs/harfbuzz-docs.xml
  40. 0 0
      libs/harfbuzz/docs/harfbuzz-overrides.txt
  41. 794 0
      libs/harfbuzz/docs/harfbuzz-sections.txt
  42. 66 0
      libs/harfbuzz/docs/meson.build
  43. 294 0
      libs/harfbuzz/docs/repacker.md
  44. 178 0
      libs/harfbuzz/docs/serializer.md
  45. 412 0
      libs/harfbuzz/docs/usermanual-buffers-language-script-and-direction.xml
  46. 697 0
      libs/harfbuzz/docs/usermanual-clusters.xml
  47. 467 0
      libs/harfbuzz/docs/usermanual-fonts-and-faces.xml
  48. 312 0
      libs/harfbuzz/docs/usermanual-getting-started.xml
  49. 14 0
      libs/harfbuzz/docs/usermanual-glyph-information.xml
  50. 349 0
      libs/harfbuzz/docs/usermanual-install-harfbuzz.xml
  51. 603 0
      libs/harfbuzz/docs/usermanual-integration.xml
  52. 266 0
      libs/harfbuzz/docs/usermanual-object-model.xml
  53. 336 0
      libs/harfbuzz/docs/usermanual-opentype-features.xml
  54. 368 0
      libs/harfbuzz/docs/usermanual-shaping-concepts.xml
  55. 218 0
      libs/harfbuzz/docs/usermanual-utilities.xml
  56. 441 0
      libs/harfbuzz/docs/usermanual-what-is-harfbuzz.xml
  57. 1 0
      libs/harfbuzz/docs/version.xml.in
  58. 401 0
      libs/harfbuzz/git.mk
  59. 24 0
      libs/harfbuzz/harfbuzz.doap
  60. 74 0
      libs/harfbuzz/m4/ax_check_link_flag.m4
  61. 264 0
      libs/harfbuzz/m4/ax_code_coverage.m4
  62. 982 0
      libs/harfbuzz/m4/ax_cxx_compile_stdcxx.m4
  63. 485 0
      libs/harfbuzz/m4/ax_pthread.m4
  64. 394 0
      libs/harfbuzz/meson.build
  65. 42 0
      libs/harfbuzz/meson_options.txt
  66. 30 0
      libs/harfbuzz/mingw-configure.sh
  67. 23 0
      libs/harfbuzz/perf/Makefile.am
  68. 54 0
      libs/harfbuzz/perf/README.md
  69. 245 0
      libs/harfbuzz/perf/benchmark-font.cc
  70. 68 0
      libs/harfbuzz/perf/benchmark-map.cc
  71. 44 0
      libs/harfbuzz/perf/benchmark-ot.cc
  72. 151 0
      libs/harfbuzz/perf/benchmark-set.cc
  73. 172 0
      libs/harfbuzz/perf/benchmark-shape.cc
  74. 221 0
      libs/harfbuzz/perf/benchmark-subset.cc
  75. BIN
      libs/harfbuzz/perf/fonts/Amiri-Regular.ttf
  76. BIN
      libs/harfbuzz/perf/fonts/NotoNastaliqUrdu-Regular.ttf
  77. BIN
      libs/harfbuzz/perf/fonts/Roboto-Regular.ttf
  78. 62 0
      libs/harfbuzz/perf/meson.build
  79. 25 0
      libs/harfbuzz/perf/run.sh
  80. 1893 0
      libs/harfbuzz/perf/texts/en-thelittleprince.txt
  81. 12391 0
      libs/harfbuzz/perf/texts/en-words.txt
  82. 133 0
      libs/harfbuzz/perf/texts/fa-thelittleprince.txt
  83. 21 0
      libs/harfbuzz/replace-enum-strings.cmake
  84. 250 0
      libs/harfbuzz/src/ArabicPUASimplified.txt
  85. 295 0
      libs/harfbuzz/src/ArabicPUATraditional.txt
  86. 522 0
      libs/harfbuzz/src/Makefile.am
  87. 375 0
      libs/harfbuzz/src/Makefile.sources
  88. 338 0
      libs/harfbuzz/src/OT/Layout/Common/Coverage.hh
  89. 126 0
      libs/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
  90. 233 0
      libs/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
  91. 85 0
      libs/harfbuzz/src/OT/Layout/Common/RangeRecord.hh
  92. 83 0
      libs/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
  93. 46 0
      libs/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh
  94. 58 0
      libs/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh
  95. 100 0
      libs/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh
  96. 77 0
      libs/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh
  97. 14 0
      libs/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh
  98. 33 0
      libs/harfbuzz/src/OT/Layout/GPOS/Common.hh
  99. 14 0
      libs/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh
  100. 35 0
      libs/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh

+ 26 - 0
libs/harfbuzz/.ci/build-win32.sh

@@ -0,0 +1,26 @@
+#!/bin/bash
+set -e
+
+meson 	--cross-file=.ci/win32-cross-file.txt \
+	--wrap-mode=forcefallback \
+	-Dtests=disabled \
+	-Dcairo=enabled \
+	-Dcairo:fontconfig=disabled \
+	-Dglib=enabled \
+	-Dfreetype=enabled \
+	-Dgdi=enabled \
+	-Ddirectwrite=enabled \
+	-Dcairo=enabled \
+	win32build \
+	$@
+
+ninja -Cwin32build -j3 # building with all the cores won't work fine with CricleCI for some reason
+
+rm -rf win32build/harfbuzz-win32
+mkdir win32build/harfbuzz-win32
+cp win32build/util/hb-*.exe win32build/harfbuzz-win32
+find win32build -name '*.dll' -exec cp {} win32build/harfbuzz-win32 \;
+i686-w64-mingw32-strip win32build/harfbuzz-win32/*.{dll,exe}
+rm -f harfbuzz-win32.zip
+(cd win32build && zip -r ../harfbuzz-win32.zip harfbuzz-win32)
+echo "harfbuzz-win32.zip is ready."

+ 26 - 0
libs/harfbuzz/.ci/build-win64.sh

@@ -0,0 +1,26 @@
+#!/bin/bash
+set -e
+
+meson 	--cross-file=.ci/win64-cross-file.txt \
+	--wrap-mode=forcefallback \
+	-Dtests=disabled \
+	-Dcairo=enabled \
+	-Dcairo:fontconfig=disabled \
+	-Dglib=enabled \
+	-Dfreetype=enabled \
+	-Dgdi=enabled \
+	-Ddirectwrite=enabled \
+	-Dcairo=enabled \
+	win64build \
+	$@
+
+ninja -Cwin64build -j3 # building with all the cores won't work fine with CricleCI for some reason
+
+rm -rf win64build/harfbuzz-win64
+mkdir win64build/harfbuzz-win64
+cp win64build/util/hb-*.exe win64build/harfbuzz-win64
+find win64build -name '*.dll' -exec cp {} win64build/harfbuzz-win64 \;
+x86_64-w64-mingw32-strip win64build/harfbuzz-win64/*.{dll,exe}
+rm -f harfbuzz-win64.zip
+(cd win64build && zip -r ../harfbuzz-win64.zip harfbuzz-win64)
+echo "harfbuzz-win64.zip is ready."

+ 33 - 0
libs/harfbuzz/.ci/deploy-docs.sh

@@ -0,0 +1,33 @@
+#!/bin/bash
+
+set -x
+set -o errexit -o nounset
+
+DOCSDIR=build-docs
+REVISION=$(git rev-parse --short HEAD)
+
+rm -rf $DOCSDIR || exit
+mkdir $DOCSDIR
+cd $DOCSDIR
+
+cp ../build/docs/html/* .
+#cp ../build/docs/CNAME .
+
+git init
+git branch -m main
+git config user.name "CI"
+git config user.email "[email protected]"
+set +x
+echo "git remote add upstream \"https://\[email protected]/harfbuzz/harfbuzz.github.io.git\""
+git remote add upstream "https://[email protected]/harfbuzz/harfbuzz.github.io.git"
+set -x
+git fetch upstream
+git reset upstream/main
+
+touch .
+git add -A .
+
+if [[ $(git status -s) ]]; then
+  git commit -m "Rebuild docs for https://github.com/harfbuzz/harfbuzz/commit/$REVISION"
+  git push -q upstream HEAD:main
+fi

+ 23 - 0
libs/harfbuzz/.ci/publish_release_artifact.sh

@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+if [[ -z $GITHUB_TOKEN ]]; then
+	echo "No GITHUB_TOKEN secret found, artifact publishing skipped"
+	exit
+fi
+
+if ! hash ghr 2> /dev/null; then
+	_GHR_VER=v0.14.0
+	_GHR=ghr_${_GHR_VER}_linux_amd64
+	mkdir -p $HOME/.local/bin
+	curl -sfL https://github.com/tcnksm/ghr/releases/download/$_GHR_VER/$_GHR.tar.gz |
+		tar xz -C $HOME/.local/bin --strip-components=1 $_GHR/ghr
+fi
+
+ghr -replace \
+	-u $CIRCLE_PROJECT_USERNAME \
+	-r $CIRCLE_PROJECT_REPONAME \
+	$CIRCLE_TAG \
+	$1

+ 20 - 0
libs/harfbuzz/.ci/win32-cross-file.txt

@@ -0,0 +1,20 @@
+[host_machine]
+system = 'windows'
+cpu_family = 'x86'
+cpu = 'i686'
+endian = 'little'
+
+[properties]
+c_args = []
+c_link_args = ['-static-libgcc', '-Wl,-Bstatic', '-lpthread']
+cpp_args = []
+cpp_link_args = ['-static-libgcc', '-static-libstdc++', '-Wl,-Bstatic', '-lpthread']
+
+[binaries]
+c = 'i686-w64-mingw32-gcc'
+cpp = 'i686-w64-mingw32-g++'
+ar = 'i686-w64-mingw32-ar'
+ld = 'i686-w64-mingw32-ld'
+objcopy = 'i686-w64-mingw32-objcopy'
+strip = 'i686-w64-mingw32-strip'
+windres = 'i686-w64-mingw32-windres'

+ 20 - 0
libs/harfbuzz/.ci/win64-cross-file.txt

@@ -0,0 +1,20 @@
+[host_machine]
+system = 'windows'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
+
+[properties]
+c_args = []
+c_link_args = ['-static-libgcc', '-Wl,-Bstatic', '-lpthread']
+cpp_args = []
+cpp_link_args = ['-static-libgcc', '-static-libstdc++', '-Wl,-Bstatic', '-lpthread']
+
+[binaries]
+c = 'x86_64-w64-mingw32-gcc'
+cpp = 'x86_64-w64-mingw32-g++'
+ar = 'x86_64-w64-mingw32-ar'
+ld = 'x86_64-w64-mingw32-ld'
+objcopy = 'x86_64-w64-mingw32-objcopy'
+strip = 'x86_64-w64-mingw32-strip'
+windres = 'x86_64-w64-mingw32-windres'

+ 229 - 0
libs/harfbuzz/.circleci/config.yml

@@ -0,0 +1,229 @@
+version: 2.1
+
+executors:
+  win32-executor:
+    docker:
+      - image: cimg/base:edge-20.04
+  win64-executor:
+    docker:
+      - image: cimg/base:edge-20.04
+  autotools-executor:
+    docker:
+      - image: cimg/base:edge-20.04
+
+jobs:
+
+  macos-aat-fonts:
+    macos:
+      xcode: "12.5.1"
+    steps:
+      - checkout
+      - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection gtk-doc ninja
+      - run: pip3 install meson --upgrade
+      - run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled
+      - run: meson compile -Cbuild
+      - run: meson test -Cbuild --print-errorlogs
+      - store_artifacts:
+          path: build/meson-logs/
+
+  # will be dropped with autotools removal
+  distcheck:
+    executor: autotools-executor
+    steps:
+      - checkout
+      - run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y git ninja-build binutils libtool autoconf automake make gcc g++ pkg-config ragel gtk-doc-tools gobject-introspection libfreetype6-dev libglib2.0-dev libgirepository1.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip
+      - run: pip3 install fonttools meson --upgrade
+      - run: ./autogen.sh
+      - run: make -j2 distcheck
+      - run: rm harfbuzz-* && make distdir
+      - run: cd harfbuzz-* && meson build && ninja -j2 -Cbuild test
+      - run: make dist
+      - persist_to_workspace:
+          root: .
+          paths: harfbuzz-*.tar.xz
+
+  publish-dist:
+    executor: autotools-executor
+    steps:
+      - checkout
+      - attach_workspace:
+          at: .
+      - run: |
+          .ci/publish_release_artifact.sh harfbuzz-$CIRCLE_TAG.tar.xz
+
+  fedora-valgrind:
+    docker:
+      - image: fedora:36
+    steps:
+      - checkout
+      - run: dnf install -y pkg-config ragel valgrind gcc gcc-c++ meson git glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python python-pip || true
+      - run: meson build --buildtype=debugoptimized
+      - run: ninja -Cbuild -j9
+      # TOOD: increase timeouts and remove --no-suite=slow
+      - run: RUN_VALGRIND=1 meson test -Cbuild --no-suite=slow --wrap='valgrind --leak-check=full --error-exitcode=1' --print-errorlogs --num-processes=$(($(nproc)/2 + 1))
+
+  alpine:
+    docker:
+      - image: alpine
+    steps:
+      - checkout
+      - run: apk update && apk add ragel gcc g++ glib-dev freetype-dev cairo-dev git py3-pip ninja
+      - run: pip3 install meson==0.56.0
+      - run: meson build --buildtype=minsize
+      - run: ninja -Cbuild -j9
+      - run: meson test -Cbuild --print-errorlogs
+
+  archlinux:
+    docker:
+      - image: archlinux/base
+    steps:
+      - checkout
+      - run: pacman --noconfirm -Syu freetype2 meson git clang cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python python-pip base-devel gtk-doc
+      - run: pip install flake8 fonttools
+      - run: flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
+      - run: meson build -Dgraphite=enabled -Dauto_features=enabled -Dexperimental_api=true
+      - run: meson compile -Cbuild -j9
+      - run: meson test -Cbuild --print-errorlogs
+      - run: meson dist -Cbuild
+      - run: clang -c src/harfbuzz.cc -DHB_NO_MT
+      - run: clang -c src/hb-*.cc -DHB_NO_MT -DHB_TINY -DHB_NO_OT_FONT
+
+  asan-ubsan:
+    docker:
+      - image: ubuntu:20.04
+    steps:
+      - checkout
+      - run: apt update || true
+      - run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
+      - run: pip3 install meson==0.56.0
+      - run: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
+      - run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
+
+  tsan:
+    docker:
+      - image: ubuntu:20.04
+    steps:
+      - checkout
+      - run: apt update || true
+      - run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
+      - run: pip3 install meson==0.56.0
+      - run: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
+      - run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
+
+  msan:
+    docker:
+      - image: ubuntu:20.04
+    steps:
+      - checkout
+      - run: apt update || true
+      - run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
+      - run: pip3 install meson==0.56.0
+      # msan, needs --force-fallback-for=glib,freetype2 also which doesn't work yet but runs fuzzer cases at least
+      - run: CC=clang CXX=clang++ meson build --default-library=static -Db_sanitize=memory --buildtype=debugoptimized --wrap-mode=nodownload -Dauto_features=disabled -Dtests=enabled -Dexperimental_api=true
+      - run: ninja -Cbuild -j8 && meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
+
+  clang-cxx2a:
+    docker:
+      - image: ubuntu:20.04
+    steps:
+      - checkout
+      - run: apt update || true
+      - run: DEBIAN_FRONTEND=noninteractive apt install -y clang lld git binutils
+      - run: clang -c src/harfbuzz-subset.cc -DHB_NO_MT -Werror -std=c++2a
+
+  crossbuild-win32:
+    executor: win32-executor
+    steps:
+      - checkout
+      - run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-i686 zip
+      - run: pip3 install meson==0.56.0 --upgrade
+      - run: .ci/build-win32.sh
+      - store_artifacts:
+          path: harfbuzz-win32.zip
+      - persist_to_workspace:
+          root: .
+          paths: harfbuzz-win32.zip
+
+  publish-win32:
+    executor: win32-executor
+    steps:
+      - checkout
+      - attach_workspace:
+          at: .
+      - run: |
+          mv harfbuzz-win32{,-$CIRCLE_TAG}.zip
+          .ci/publish_release_artifact.sh harfbuzz-win32-$CIRCLE_TAG.zip
+
+  crossbuild-win64:
+    executor: win64-executor
+    steps:
+      - checkout
+      - run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-x86-64 zip
+      - run: pip3 install meson==0.56.0 --upgrade
+      - run: bash .ci/build-win64.sh
+      - store_artifacts:
+          path: harfbuzz-win64.zip
+      - persist_to_workspace:
+          root: .
+          paths: harfbuzz-win64.zip
+
+  publish-win64:
+    executor: win64-executor
+    steps:
+      - checkout
+      - attach_workspace:
+          at: .
+      - run: |
+          mv harfbuzz-win64{,-$CIRCLE_TAG}.zip
+          .ci/publish_release_artifact.sh harfbuzz-win64-$CIRCLE_TAG.zip
+
+
+workflows:
+  version: 2
+
+  build:
+    jobs:
+      - macos-aat-fonts
+      - distcheck:
+          filters: # must have filter or won't work as a dependency
+            tags:
+              only: /.*/
+      - publish-dist:
+          requires:
+            - distcheck
+          filters:
+            tags:
+              only: /^\d+\.\d+\.\d+$/
+            branches:
+              ignore: /.*/
+      - fedora-valgrind
+      - alpine
+     #- archlinux
+      - asan-ubsan
+      - tsan
+      - msan
+      - clang-cxx2a
+      - crossbuild-win32:
+          filters: # must have filter or won't work as a dependency
+            tags:
+              only: /.*/
+      - crossbuild-win64:
+          filters: # must have filter or won't work as a dependency
+            tags:
+              only: /.*/
+      - publish-win32:
+          requires:
+            - crossbuild-win32
+          filters:
+            tags:
+              only: /^\d+\.\d+\.\d+$/
+            branches:
+              ignore: /.*/
+      - publish-win64:
+          requires:
+            - crossbuild-win64
+          filters:
+            tags:
+              only: /^\d+\.\d+\.\d+$/
+            branches:
+              ignore: /.*/

+ 38 - 0
libs/harfbuzz/.clang-format

@@ -0,0 +1,38 @@
+# The following tries to match the current code style, is imperfect for now
+# but good for new codes be added
+
+IndentWidth: 2
+TabWidth: 8
+UseTab: Always
+SpaceBeforeParens: Always
+AllowShortLoopsOnASingleLine: true
+BreakBeforeBraces: Custom
+BraceWrapping:
+  AfterEnum: true
+  AfterStruct: false
+  SplitEmptyFunction: false
+  AfterClass: true
+  AfterControlStatement: true
+  AfterEnum: false
+  AfterFunction: true
+  AfterNamespace: false
+  AfterStruct: true
+  AfterUnion: true
+  BeforeElse: true
+AlwaysBreakTemplateDeclarations: true
+AlignTrailingComments: true
+AlignEscapedNewlines: Left
+AllowShortBlocksOnASingleLine: true
+SpaceAfterCStyleCast: true
+AlwaysBreakAfterDefinitionReturnType: TopLevel
+BinPackParameters: false
+AllowShortFunctionsOnASingleLine: Inline
+AccessModifierOffset: 0
+AlignTrailingComments: true
+AllowShortIfStatementsOnASingleLine: true
+AlignAfterOpenBracket: Align
+AlignOperands: true
+AllowShortCaseLabelsOnASingleLine: true
+
+# We like to have this only for function parameters and structs fields, not always
+# AlignConsecutiveDeclarations: true

+ 8 - 0
libs/harfbuzz/.codecov.yml

@@ -0,0 +1,8 @@
+comment: off
+
+coverage:
+  status:
+    project:
+      default:
+        threshold: 1%
+    patch: off

+ 23 - 0
libs/harfbuzz/.editorconfig

@@ -0,0 +1,23 @@
+root = true
+
+[*]
+charset = utf-8
+trim_trailing_whitespace = true
+end_of_line = lf
+insert_final_newline = true
+
+[*.{c,cc,h,hh,rl}]
+tab_width = 8
+indent_size = 2
+indent_style = tab # should be space
+
+[*.{py,sh}]
+indent_style = tab
+
+[{Makefile.am,Makefile.sources,configure.ac}]
+tab_width = 8
+
+[{meson.build,meson_options.txt}]
+tab_width = 8
+indent_style = space
+indent_size = 2

+ 6 - 0
libs/harfbuzz/.github/dependabot.yml

@@ -0,0 +1,6 @@
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "weekly"

+ 24 - 0
libs/harfbuzz/.github/workflows/cifuzz.yml

@@ -0,0 +1,24 @@
+name: CIFuzz
+on: [pull_request]
+jobs:
+  Fuzzing:
+    runs-on: ubuntu-latest
+    steps:
+    - name: Build Fuzzers
+      id: build
+      uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
+      with:
+        oss-fuzz-project-name: 'harfbuzz'
+        dry-run: false
+    - name: Run Fuzzers
+      uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
+      with:
+        oss-fuzz-project-name: 'harfbuzz'
+        fuzz-seconds: 600
+        dry-run: false
+    - name: Upload Crash
+      uses: actions/upload-artifact@v3
+      if: failure() && steps.build.outcome == 'success'
+      with:
+        name: artifacts
+        path: ./out/artifacts

+ 27 - 0
libs/harfbuzz/.github/workflows/configs-build.yml

@@ -0,0 +1,27 @@
+name: configs-ci
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+permissions:
+  contents: read
+
+jobs:
+  build:
+    runs-on: ubuntu-18.04
+
+    steps:
+    - uses: actions/checkout@v3
+    - name: install dependencies
+      run: sudo apt-get install gcc
+    - name: HB_DISABLE_DEPRECATED
+      run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_DISABLE_DEPRECATED
+    - name: HB_MINI
+      run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_MINI
+    - name: HB_LEAN
+      run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_LEAN
+    - name: HB_TINY
+      run: g++ -std=c++11 -c src/harfbuzz.cc -DHB_TINY

+ 42 - 0
libs/harfbuzz/.github/workflows/coverity-scan.yml

@@ -0,0 +1,42 @@
+name: coverity-scan
+
+on:
+  schedule:
+    - cron: '0 10 * * *' # Daily at 10:00 UTC
+
+permissions:
+  contents: read
+
+jobs:
+  latest:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+
+      - run: sudo apt-get install gcc clang wget git curl pkg-config libfreetype6-dev libglib2.0-dev libicu-dev libgraphite2-dev
+
+      - name: Download Coverity
+        run: |
+          wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=HarfBuzz" -O cov-analysis-linux64.tar.gz
+          mkdir cov-analysis-linux64
+          tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
+        env:
+          TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
+
+      # ideally we should've used meson and ninja here but it complains about coverage or something
+      - run: cov-analysis-linux64/bin/cov-build --dir cov-int clang src/hb-*.cc -DHAVE_FREETYPE -DHAVE_GRAPHITE2 -DHAVE_GLIB -DHAVE_ICU `pkg-config --cflags freetype2 graphite2 glib-2.0 icu-uc` -DHAVE_ROUNDF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H -DHAVE_GETPAGESIZE -DHB_EXPERIMENTAL_API -c
+
+      - run: tar czvf harfbuzz.tgz cov-int
+
+      - name: submit to coverity
+        run: |
+          curl \
+            --form project=HarfBuzz \
+            --form token=$TOKEN \
+            --form [email protected] \
+            --form [email protected] \
+            --form version=trunk \
+            --form description="`git rev-parse --short HEAD`" \
+            https://scan.coverity.com/builds?project=HarfBuzz
+        env:
+          TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}

+ 57 - 0
libs/harfbuzz/.github/workflows/linux-ci.yml

@@ -0,0 +1,57 @@
+name: linux-ci
+
+on:
+  push:
+    branches: [ main ]
+    tags: ["*.*.*"]
+  pull_request:
+    branches: [ main ]
+
+permissions:
+  contents: read
+
+jobs:
+  build:
+    runs-on: ubuntu-18.04
+
+    steps:
+    - uses: actions/checkout@v3
+    - name: install dependencies
+      run: sudo apt-get update && sudo apt-get install pkg-config gcc gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-setuptools ninja-build gobject-introspection libgirepository1.0-dev
+    - run: sudo pip3 install fonttools meson==0.56.0 gcovr==5.0
+    - name: run
+      run: meson build -Db_coverage=true --auto-features=enabled -Dgraphite=enabled -Dchafa=disabled -Dragel_subproject=true -Doptimization=2
+    - name: ci
+      run: meson test --print-errorlogs -Cbuild
+
+    - name: generate documentations
+      run: ninja -Cbuild harfbuzz-doc
+    - name: deploy documentations
+      if: github.ref_type == 'tag'
+      run: .ci/deploy-docs.sh
+      env:
+        GH_TOKEN: ${{ secrets.GH_TOKEN }}
+        REVISION: ${{ github.sha }}
+
+    # waiting for https://github.com/rhysd/github-action-benchmark/issues/36 to happen
+    # - name: benchmark
+    #   run: build/perf/perf --benchmark_format=json > perf/result.json
+    # - name: store benchmark result
+    #   uses: rhysd/github-action-benchmark@b2ee598
+    #   if: github.event_name != 'pull_request'
+    #   with:
+    #     name: C++ Benchmark
+    #     tool: 'googlecpp'
+    #     output-file-path: perf/result.json
+    #     gh-pages-branch: gh-pages
+    #     github-token: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
+    #     auto-push: true
+    #     alert-threshold: '150%'
+    #     comment-on-alert: true
+    #     fail-on-alert: true
+
+    - name: cov
+      run: ninja -Cbuild coverage-xml
+    - uses: codecov/codecov-action@v3
+      with:
+        file: build/meson-logs/coverage.xml

+ 30 - 0
libs/harfbuzz/.github/workflows/macos-ci.yml

@@ -0,0 +1,30 @@
+name: macos-ci
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+permissions:
+  contents: read
+
+jobs:
+  build:
+    runs-on: macos-latest
+
+    steps:
+    - uses: actions/checkout@v3
+    - name: install dependencies
+      run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config freetype glib glib-utils cairo icu4c graphite2 gobject-introspection gtk-doc ninja
+    - run: pip3 install fonttools meson==0.56.0 gcovr==5.0
+    - name: run
+      run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Db_coverage=true -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled -Doptimization=2
+    - name: ci
+      run: meson test --print-errorlogs -Cbuild
+
+    - name: cov
+      run: ninja -Cbuild coverage-xml
+    - uses: codecov/codecov-action@v3
+      with:
+        file: build/meson-logs/coverage.xml

+ 58 - 0
libs/harfbuzz/.github/workflows/msvc-ci.yml

@@ -0,0 +1,58 @@
+name: msvc
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+permissions:
+  contents: read
+
+jobs:
+  msvc:
+    runs-on: ${{ matrix.os }}
+
+    strategy:
+      matrix:
+        os: [windows-2019, windows-latest]
+        include:
+          - name: msvc-2019-x86
+            os: windows-2019
+            ARCH: x86
+          - name: msvc-2019-amd64
+            os: windows-latest
+            ARCH: amd64
+    name: ${{ matrix.name }}
+
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v4
+        with:
+          python-version: '3.x'
+      - uses: ilammy/msvc-dev-cmd@v1
+        with:
+          arch : ${{ matrix.ARCH }}
+      - name: Upgrade pip
+        run: |
+          python -m pip install -U pip
+      - name: Install Dependencies
+        run: |
+          pip install --upgrade meson ninja fonttools
+      - name: Build
+        run: |
+          # This dir contains a pkg-config which meson will happily use and later fail, so remove it
+          $env:path = ($env:path.Split(';') | Where-Object { $_ -ne 'C:\Strawberry\perl\bin' }) -join ';'
+
+          meson setup build `
+            --wrap-mode=default `
+            --buildtype=release `
+            -Dglib=enabled `
+            -Dfreetype=enabled `
+            -Dgdi=enabled `
+            -Ddirectwrite=enabled
+
+          meson compile -C build
+      - name: Test
+        run: |
+          meson test --print-errorlogs --suite=harfbuzz -C build

+ 68 - 0
libs/harfbuzz/.github/workflows/msys2-ci.yml

@@ -0,0 +1,68 @@
+name: msys2
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+permissions:
+  contents: read
+
+jobs:
+  msys2:
+    runs-on: windows-latest
+
+    strategy:
+      matrix:
+        include:
+          - MSYSTEM: MINGW32
+            MSYS2_ARCH: i686
+          - MSYSTEM: MINGW64
+            MSYS2_ARCH: x86_64
+    name: ${{ matrix.MSYSTEM }}
+
+    defaults:
+      run:
+        shell: msys2 {0}
+    steps:
+      - uses: actions/checkout@v3
+      - uses: msys2/setup-msys2@v2
+        with:
+          msystem: ${{ matrix.MSYSTEM }}
+          update: true
+          install: >-
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-graphite2
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-python
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
+            mingw-w64-${{ matrix.MSYS2_ARCH }}-ragel
+      - name: Install Python Dependencies
+        run: |
+          pip install --upgrade fonttools
+      - name: Build
+        run: |
+          meson build \
+            --wrap-mode=nodownload \
+            --auto-features=enabled \
+            -Ddirectwrite=enabled \
+            -Dgdi=enabled \
+            -Dgraphite=enabled \
+            -Dchafa=disabled
+          ninja -C build
+      - name: Test
+        run: |
+          meson test \
+            --print-errorlogs \
+            --suite=harfbuzz \
+            -C build

+ 14 - 0
libs/harfbuzz/AUTHORS

@@ -0,0 +1,14 @@
+Behdad Esfahbod
+David Corbett
+David Turner
+Ebrahim Byagowi
+Garret Rieger
+Jonathan Kew
+Khaled Hosny
+Lars Knoll
+Martin Hosken
+Owen Taylor
+Roderick Sheeter
+Roozbeh Pournader
+Simon Hausmann
+Werner Lemberg

+ 29 - 0
libs/harfbuzz/BUILD.md

@@ -0,0 +1,29 @@
+On Linux, install the development packages for FreeType, Cairo, and GLib. For
+example, on Ubuntu / Debian, you would do:
+
+$ sudo apt-get install meson pkg-config ragel gtk-doc-tools gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
+
+whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
+
+$ sudo dnf install meson pkgconfig gtk-doc gcc gcc-c++ freetype-devel glib2-devel cairo-devel
+
+and on ArchLinux and Manjaro:
+
+$ sudo pacman -Suy meson pkg-config ragel gcc freetype2 glib2 cairo
+
+then use meson to build the project like `meson build && meson test -Cbuild`.
+
+On macOS, `brew install pkg-config ragel gtk-doc freetype glib cairo meson`
+then use meson like above.
+
+On Windows, meson can build the project like above if a working MSVC's cl.exe
+(`vcvarsall.bat`) or gcc/clang is already on your path, and if you use
+something like `meson build --wrap-mode=default` it fetches and compiles most
+of the dependencies also.  It is recommended to install CMake either manually
+or via the Visual Studio installer when building with MSVC, using meson.
+
+Our CI configurations is also a good source of learning how to build HarfBuzz.
+
+There is also amalgam source provided with HarfBuzz which reduces whole process
+of building HarfBuzz like `g++ src/harfbuzz.cc -fno-exceptions` but there is
+not guarantee provided with buildability and reliability of features you get.

+ 832 - 0
libs/harfbuzz/CMakeLists.txt

@@ -0,0 +1,832 @@
+cmake_minimum_required(VERSION 3.12)
+project(harfbuzz)
+
+message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build systems to it, please consider using it as we might remove our cmake port soon.")
+
+## Limit framework build to Xcode generator
+if (BUILD_FRAMEWORK)
+  # for a framework build on macOS, use:
+  # cmake -DBUILD_FRAMEWORK=ON -Bbuild -H. -GXcode && cmake --build build
+  if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
+    message(FATAL_ERROR
+      "You should use Xcode generator with BUILD_FRAMEWORK enabled")
+  endif ()
+  set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
+  set (CMAKE_MACOSX_RPATH ON)
+  set (BUILD_SHARED_LIBS ON)
+endif ()
+
+
+## Disallow in-source builds, as CMake generated make files can collide with autotools ones
+if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
+  message(FATAL_ERROR
+    "
+In-source builds are not permitted!  Make a separate folder for"
+    " building, e.g.,"
+    "
+  mkdir build; cd build; cmake .."
+    "
+Before that, remove the files created by this failed run with"
+    "
+  rm -rf CMakeCache.txt CMakeFiles")
+endif ()
+
+
+## HarfBuzz build configurations
+option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF)
+option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF)
+option(HB_HAVE_GLIB "Enable glib unicode functions" OFF)
+option(HB_HAVE_ICU "Enable icu unicode functions" OFF)
+if (TARGET freetype)
+  set (HB_HAVE_FREETYPE ON)
+  add_definitions(-DHAVE_FREETYPE=1)
+endif ()
+if (APPLE)
+  option(HB_HAVE_CORETEXT "Enable CoreText shaper backend on macOS" ON)
+  set (CMAKE_MACOSX_RPATH ON)
+endif ()
+if (WIN32)
+  option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF)
+  option(HB_HAVE_GDI "Enable GDI integration helpers on Windows" OFF)
+  option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF)
+endif ()
+option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF)
+if (HB_BUILD_UTILS)
+  set (HB_HAVE_GLIB ON)
+  set (HB_HAVE_FREETYPE ON)
+endif ()
+
+option(HB_BUILD_SUBSET "Build harfbuzz-subset" ON)
+
+option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF)
+if (HB_HAVE_GOBJECT)
+  set (HB_HAVE_GLIB ON)
+endif ()
+
+option(HB_HAVE_INTROSPECTION "Enable building introspection (.gir/.typelib) files" OFF)
+if (HB_HAVE_INTROSPECTION)
+  set (HB_HAVE_GOBJECT ON)
+  set (HB_HAVE_GLIB ON)
+endif ()
+
+include_directories(AFTER
+  ${PROJECT_SOURCE_DIR}/src
+  ${PROJECT_BINARY_DIR}/src
+)
+
+# We need PYTHON_EXECUTABLE to be set for running the tests...
+include (FindPythonInterp)
+
+## Functions and headers
+include (CheckFunctionExists)
+include (CheckIncludeFile)
+include (CheckIncludeFiles)
+macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools
+  foreach (func_name ${ARGN})
+    string(TOUPPER ${func_name} definition_to_add)
+    check_function_exists(${func_name} HAVE_${definition_to_add})
+    if (${HAVE_${definition_to_add}})
+      add_definitions(-DHAVE_${definition_to_add})
+    endif ()
+  endforeach ()
+endmacro ()
+if (UNIX)
+  list(APPEND CMAKE_REQUIRED_LIBRARIES m)
+endif ()
+check_funcs(atexit mprotect sysconf getpagesize mmap isatty)
+check_include_file(unistd.h HAVE_UNISTD_H)
+if (${HAVE_UNISTD_H})
+  add_definitions(-DHAVE_UNISTD_H)
+endif ()
+check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
+if (${HAVE_SYS_MMAN_H})
+  add_definitions(-DHAVE_SYS_MMAN_H)
+endif ()
+check_include_file(stdbool.h HAVE_STDBOOL_H)
+if (${HAVE_STDBOOL_H})
+  add_definitions(-DHAVE_STDBOOL_H)
+endif ()
+
+# These will be used while making pkg-config .pc files
+set(PC_REQUIRES_PRIV "")
+set(PC_LIBS_PRIV "")
+
+if (NOT MSVC)
+  set(THREADS_PREFER_PTHREAD_FLAG ON)
+  find_package(Threads)
+  if (CMAKE_USE_PTHREADS_INIT)
+    add_definitions("-DHAVE_PTHREAD")
+    list(APPEND THIRD_PARTY_LIBS Threads::Threads)
+    list(APPEND PC_LIBS_PRIV -pthread)
+  endif ()
+endif ()
+
+if (MSVC)
+  add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
+endif ()
+
+
+## Detect if we are running inside a distribution or regular repository folder
+# if (EXISTS "${PROJECT_SOURCE_DIR}/ChangeLog")
+#   # perhaps we are on dist directory
+#   set (IN_HB_DIST TRUE)
+#   #set (HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h")
+# endif ()
+
+
+## Extract variables from Makefile files
+function (extract_make_variable variable makefile_source)
+  string(REGEX MATCH "${variable} = ([^$]+)\\$" temp "${makefile_source}")
+  string(REGEX MATCHALL "[^ \n\t\\]+" listVar "${CMAKE_MATCH_1}")
+  set (${variable} ${listVar} PARENT_SCOPE)
+endfunction ()
+
+# https://stackoverflow.com/a/27630120
+function (add_prefix_to_list var prefix)
+  set (listVar "")
+  foreach (f ${${var}})
+    list(APPEND listVar "${prefix}${f}")
+  endforeach ()
+  set (${var} "${listVar}" PARENT_SCOPE)
+endfunction ()
+
+file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES)
+file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES)
+
+extract_make_variable(HB_BASE_headers ${SRCSOURCES})
+add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/")
+
+extract_make_variable(HB_SUBSET_sources ${SRCSOURCES})
+add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/")
+
+extract_make_variable(HB_SUBSET_headers ${SRCSOURCES})
+add_prefix_to_list(HB_SUBSET_headers "${PROJECT_SOURCE_DIR}/src/")
+
+extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES})
+#if (IN_HB_DIST)
+  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
+#else ()
+#  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
+#endif ()
+
+extract_make_variable(HB_VIEW_sources ${UTILSOURCES})
+add_prefix_to_list(HB_VIEW_sources "${PROJECT_SOURCE_DIR}/util/")
+extract_make_variable(HB_SHAPE_sources ${UTILSOURCES})
+add_prefix_to_list(HB_SHAPE_sources "${PROJECT_SOURCE_DIR}/util/")
+extract_make_variable(HB_SUBSET_CLI_sources ${UTILSOURCES})
+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/")
+
+
+file(READ configure.ac CONFIGUREAC)
+string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC})
+set (HB_VERSION ${CMAKE_MATCH_1})
+set (HB_VERSION_MAJOR ${CMAKE_MATCH_2})
+set (HB_VERSION_MINOR ${CMAKE_MATCH_3})
+set (HB_VERSION_MICRO ${CMAKE_MATCH_4})
+
+## Define sources and headers of the project
+set (project_sources ${PROJECT_SOURCE_DIR}/src/harfbuzz.cc) # use amalgam source
+set (subset_project_sources ${HB_SUBSET_sources})
+set (project_extra_sources)
+set (project_headers ${HB_BASE_headers})
+set (subset_project_headers ${HB_SUBSET_headers})
+
+## Find and include needed header folders and libraries
+if (HB_HAVE_FREETYPE AND NOT TARGET freetype)
+  include (FindFreetype)
+  if (NOT FREETYPE_FOUND)
+    message(FATAL_ERROR "HB_HAVE_FREETYPE was set, but we failed to find it. Maybe add a CMAKE_PREFIX_PATH= to your Freetype2 install prefix")
+  endif ()
+
+  list(APPEND THIRD_PARTY_LIBS ${FREETYPE_LIBRARIES})
+  include_directories(AFTER ${FREETYPE_INCLUDE_DIRS})
+  add_definitions(-DHAVE_FREETYPE=1)
+
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h)
+
+  # So check_funcs can find its headers
+  set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${FREETYPE_INCLUDE_DIRS})
+  set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${FREETYPE_LIBRARIES})
+
+  check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
+endif ()
+
+if (HB_HAVE_FREETYPE)
+  list(APPEND PC_REQUIRES_PRIV "freetype2 >= 12.0.6")
+endif ()
+
+if (HB_HAVE_GRAPHITE2)
+  add_definitions(-DHAVE_GRAPHITE2)
+
+  find_path(GRAPHITE2_INCLUDE_DIR graphite2/Font.h)
+  find_library(GRAPHITE2_LIBRARY graphite2)
+
+  include_directories(${GRAPHITE2_INCLUDE_DIR})
+
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h)
+
+  list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY})
+
+  list(APPEND PC_REQUIRES_PRIV "graphite2 >= 1.2.0")
+
+  mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY)
+endif ()
+
+if (HB_HAVE_GLIB)
+  add_definitions(-DHAVE_GLIB)
+
+  # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindGLIB.cmake
+  find_package(PkgConfig)
+  pkg_check_modules(PC_GLIB QUIET glib-2.0)
+
+  find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
+  find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include)
+  find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
+
+  include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR})
+
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h)
+
+  list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES})
+
+  list(APPEND PC_REQUIRES_PRIV "glib-2.0 >= 2.19.1")
+
+  mark_as_advanced(GLIB_LIBRARIES GLIBCONFIG_INCLUDE_DIR GLIB_INCLUDE_DIR)
+endif ()
+
+if (HB_HAVE_ICU)
+  add_definitions(-DHAVE_ICU)
+
+  # https://github.com/WebKit/webkit/blob/fdd7733f2f30eab7fe096a9791f98c60f62f49c0/Source/cmake/FindICU.cmake
+  find_package(PkgConfig)
+  pkg_check_modules(PC_ICU QUIET icu-uc)
+
+  find_path(ICU_INCLUDE_DIR NAMES unicode/utypes.h HINTS ${PC_ICU_INCLUDE_DIRS} ${PC_ICU_INCLUDEDIR})
+  find_library(ICU_LIBRARY NAMES libicuuc cygicuuc cygicuuc32 icuuc HINTS ${PC_ICU_LIBRARY_DIRS} ${PC_ICU_LIBDIR})
+
+  include_directories(${ICU_INCLUDE_DIR})
+
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
+
+  list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY})
+
+  mark_as_advanced(ICU_INCLUDE_DIR ICU_LIBRARY)
+endif ()
+
+if (APPLE AND HB_HAVE_CORETEXT)
+  # Apple Advanced Typography
+  add_definitions(-DHAVE_CORETEXT)
+
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
+
+  if (HB_IOS)
+    find_library(COREFOUNDATION CoreFoundation)
+    if (COREFOUNDATION)
+      list(APPEND THIRD_PARTY_LIBS ${COREFOUNDATION})
+      list(APPEND PC_LIBS_PRIV "-framework CoreFoundation")
+    endif ()
+    mark_as_advanced(COREFOUNDATION)
+
+    find_library(CORETEXT CoreText)
+    if (CORETEXT)
+      list(APPEND THIRD_PARTY_LIBS ${CORETEXT})
+      list(APPEND PC_LIBS_PRIV "-framework CoreText")
+    endif ()
+    mark_as_advanced(CORETEXT)
+
+    find_library(COREGRAPHICS CoreGraphics)
+    if (COREGRAPHICS)
+      list(APPEND THIRD_PARTY_LIBS ${COREGRAPHICS})
+      list(APPEND PC_LIBS_PRIV "-framework CoreGraphics")
+    endif ()
+    mark_as_advanced(COREGRAPHICS)
+  else ()
+    find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
+    if (APPLICATION_SERVICES_FRAMEWORK)
+      list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
+      list(APPEND PC_LIBS_PRIV "-framework ApplicationServices")
+    endif ()
+
+    mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
+  endif ()
+endif ()
+
+if (WIN32 AND HB_HAVE_GDI)
+  add_definitions(-DHAVE_GDI)
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h)
+  list(APPEND THIRD_PARTY_LIBS gdi32)
+  list(APPEND PC_LIBS_PRIV -lgdi32)
+endif ()
+
+if (WIN32 AND HB_HAVE_UNISCRIBE)
+  add_definitions(-DHAVE_UNISCRIBE)
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
+  list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
+  list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4)
+endif ()
+
+if (WIN32 AND HB_HAVE_DIRECTWRITE)
+  if (CMAKE_VERSION VERSION_GREATER 3.12)
+    check_include_files("windows.h;dwrite_1.h" HAVE_DWRITE_1_H LANGUAGE CXX)
+  else ()
+    check_include_files("windows.h;dwrite_1.h" HAVE_DWRITE_1_H)
+  endif ()
+  if (NOT HAVE_DWRITE_1_H)
+    message(FATAL_ERROR "DirectWrite was enabled explicitly, but required header is missing")
+  endif ()
+  add_definitions(-DHAVE_DIRECTWRITE)
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
+endif ()
+
+if (HB_HAVE_GOBJECT)
+  add_definitions(-DHAVE_GOBJECT)
+  include (FindPerl)
+
+  # Use the hints from glib-2.0.pc to find glib-mkenums
+  find_package(PkgConfig)
+  pkg_check_modules(PC_GLIB QUIET glib-2.0)
+  find_program(GLIB_MKENUMS glib-mkenums
+    HINTS ${PC_glib_mkenums}
+  )
+  set (GLIB_MKENUMS_CMD)
+
+  if (WIN32 AND NOT MINGW)
+    # In Visual Studio builds, shebang lines are not supported
+    # in the standard cmd.exe shell that we use, so we need to
+    # first determine whether glib-mkenums is a Python or PERL
+    # script
+    execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}" --version
+      RESULT_VARIABLE GLIB_MKENUMS_PYTHON
+      OUTPUT_QUIET ERROR_QUIET
+    )
+    if (GLIB_MKENUMS_PYTHON EQUAL 0)
+      message("${GLIB_MKENUMS} is a Python script.")
+      set (GLIB_MKENUMS_CMD "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}")
+    else ()
+      execute_process(COMMAND "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}" --version
+        RESULT_VARIABLE GLIB_MKENUMS_PERL
+        OUTPUT_QUIET ERROR_QUIET
+      )
+      if (GLIB_MKENUMS_PERL EQUAL 0)
+        message("${GLIB_MKENUMS} is a PERL script.")
+        set (GLIB_MKENUMS_CMD "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}")
+      endif ()
+      if (NOT GLIB_MKENUMS_PERL EQUAL 0 AND NOT GLIB_MKENUMS_PYTHON EQUAL 0)
+        message(FATAL_ERROR "Unable to determine type of glib-mkenums script")
+      endif ()
+    endif ()
+  else ()
+    set (GLIB_MKENUMS_CMD "${GLIB_MKENUMS}")
+  endif ()
+  if (NOT GLIB_MKENUMS_CMD)
+    message(FATAL_ERROR "HB_HAVE_GOBJECT was set, but we failed to find glib-mkenums, which is required")
+  endif ()
+
+  pkg_check_modules(PC_GOBJECT QUIET gobject-2.0)
+
+  find_library(GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
+  find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
+
+  include_directories(${GOBJECTCONFIG_INCLUDE_DIR} ${GOBJECT_INCLUDE_DIR})
+  mark_as_advanced(GOBJECT_LIBRARIES GOBJECT_INCLUDE_DIR)
+
+  list(APPEND hb_gobject_sources ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.cc)
+  list(APPEND hb_gobject_gen_sources
+    ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
+  )
+  list(APPEND hb_gobject_structs_headers
+    ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.h
+  )
+  list(APPEND hb_gobject_headers
+    ${PROJECT_SOURCE_DIR}/src/hb-gobject.h
+    ${hb_gobject_structs_headers}
+  )
+  list(APPEND hb_gobject_gen_headers
+    ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
+  )
+
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
+    COMMAND ${GLIB_MKENUMS_CMD}
+      --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
+      --identifier-prefix hb_
+      --symbol-prefix hb_gobject
+      ${hb_gobject_structs_headers}
+      ${project_headers}
+      > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp
+    COMMAND "${CMAKE_COMMAND}"
+      "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp"
+      "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h"
+      -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
+    DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
+      ${hb_gobject_header}
+      ${project_headers}
+  )
+
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
+    COMMAND ${GLIB_MKENUMS_CMD}
+      --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
+      --identifier-prefix hb_
+      --symbol-prefix hb_gobject
+      ${hb_gobject_header}
+      ${project_headers}
+      > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp
+    COMMAND "${CMAKE_COMMAND}"
+      "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp"
+      "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc"
+      -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
+    DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
+      ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
+      ${hb_gobject_header}
+      ${project_headers}
+  )
+endif ()
+
+
+## Define harfbuzz library
+add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
+target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
+target_include_directories(harfbuzz PUBLIC
+                           "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
+                           "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz>")
+if (HB_HAVE_FREETYPE AND TARGET freetype)
+  target_link_libraries(harfbuzz freetype)
+endif ()
+
+
+## Define harfbuzz-icu library
+if (HB_HAVE_ICU)
+  add_library(harfbuzz-icu ${PROJECT_SOURCE_DIR}/src/hb-icu.cc ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
+  add_dependencies(harfbuzz-icu harfbuzz)
+  target_link_libraries(harfbuzz-icu harfbuzz ${THIRD_PARTY_LIBS})
+
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(harfbuzz harfbuzz-icu PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
+  endif ()
+endif ()
+
+
+## Define harfbuzz-subset library
+if (HB_BUILD_SUBSET)
+  add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-subset.h)
+  add_dependencies(harfbuzz-subset harfbuzz)
+  target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
+
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(harfbuzz harfbuzz-subset PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
+  endif ()
+endif ()
+
+if (UNIX OR MINGW)
+  # Make symbols link locally
+  include (CheckCXXCompilerFlag)
+  CHECK_CXX_COMPILER_FLAG(-Bsymbolic-functions CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
+  if (CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
+    link_libraries(-Bsymbolic-functions)
+  endif ()
+
+  # As of CMake 3.0.0, the compiler id for Apple-provided Clang is now "AppleClang";
+  # thus we use MATCHES instead of STREQUAL to include either regular Clang or AppleClang
+  if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    # Make sure we don't link to libstdc++
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
+    set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
+    set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
+    set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
+    if (HB_BUILD_SUBSET)
+      set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C)
+    endif ()
+
+    # No threadsafe statics as we do it ourselves
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics")
+  endif ()
+
+  CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+  if (COMPILER_SUPPORTS_CXX11)
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+  else()
+    message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
+  endif()
+endif ()
+
+
+## Define harfbuzz-gobject library
+if (HB_HAVE_GOBJECT)
+  add_library(harfbuzz-gobject
+    ${hb_gobject_sources}
+    ${hb_gobject_gen_sources}
+    ${hb_gobject_headers}
+    ${hb_gobject_gen_headers}
+  )
+  include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src)
+  add_dependencies(harfbuzz-gobject harfbuzz)
+  target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS})
+
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(harfbuzz-gobject PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
+  endif ()
+endif ()
+
+if (BUILD_SHARED_LIBS AND WIN32 AND NOT MINGW)
+  add_definitions("-DHB_DLL_EXPORT")
+endif ()
+
+# On Windows, g-ir-scanner requires a DLL build in order for it to work
+if (WIN32)
+  if (NOT BUILD_SHARED_LIBS)
+    message("Building introspection files on Windows requires BUILD_SHARED_LIBS to be enabled.")
+    set (HB_HAVE_INTROSPECTION OFF)
+  endif ()
+endif ()
+
+if (HB_HAVE_INTROSPECTION)
+  find_package(PkgConfig)
+  pkg_check_modules(PC_GI QUIET gobject-introspection-1.0)
+
+  find_program(G_IR_SCANNER g-ir-scanner
+    HINTS ${PC_g_ir_scanner}
+  )
+
+  find_program(G_IR_COMPILER g-ir-compiler
+    HINTS ${PC_g_ir_compiler}
+  )
+
+  if (WIN32 AND NOT MINGW)
+    # Note that since we already enable HB_HAVE_GOBJECT
+    # we would already have PYTHON_EXECUTABLE handy
+    set (G_IR_SCANNER_CMD "${PYTHON_EXECUTABLE}" "${G_IR_SCANNER}")
+  else ()
+    set (G_IR_SCANNER_CMD "${G_IR_SCANNER}")
+  endif ()
+
+  # We need to account for the varying output directories
+  # when we build using Visual Studio projects
+  if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
+    set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
+  else ()
+    set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
+  endif ()
+
+  # Get the CFlags that we used to build HarfBuzz/HarfBuzz-GObject
+  set (hb_defines_cflags "")
+  foreach (hb_cflag ${hb_cflags})
+    list(APPEND hb_defines_cflags "-D${hb_cflag}")
+  endforeach (hb_cflag)
+
+  # Get the other dependent libraries we used to build HarfBuzz/HarfBuzz-GObject
+  set (extra_libs "")
+  foreach (extra_lib ${THIRD_PARTY_LIBS})
+    # We don't want the .lib extension here...
+    string(REPLACE ".lib" "" extra_lib_stripped "${extra_lib}")
+    list(APPEND extra_libs "--extra-library=${extra_lib_stripped}")
+  endforeach ()
+
+  set (introspected_sources)
+  foreach (f
+    ${project_headers}
+    ${project_sources}
+    ${hb_gobject_gen_sources}
+    ${hb_gobject_gen_headers}
+    ${hb_gobject_sources}
+    ${hb_gobject_headers}
+  )
+    if (WIN32)
+      # Nasty issue: We need to make drive letters lower case,
+      # otherwise g-ir-scanner won't like it and give us a bunch
+      # of invalid items and unresolved types...
+      STRING(SUBSTRING "${f}" 0 1 drive)
+      STRING(SUBSTRING "${f}" 1 -1 path)
+      if (drive MATCHES "[A-Z]")
+        STRING(TOLOWER ${drive} drive_lower)
+        list(APPEND introspected_sources "${drive_lower}${path}")
+      else ()
+        list(APPEND introspected_sources "${f}")
+      endif ()
+    else ()
+      list(APPEND introspected_sources "${f}")
+    endif ()
+  endforeach ()
+
+  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list)
+  foreach (s ${introspected_sources})
+    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list "${s}\n")
+  endforeach ()
+
+  # Finally, build the introspection files...
+  add_custom_command(
+    TARGET harfbuzz-gobject
+    POST_BUILD
+    COMMAND ${G_IR_SCANNER_CMD}
+      --warn-all --no-libtool --verbose
+      --namespace=HarfBuzz
+      --nsversion=0.0
+      --symbol-prefix=hb
+      --symbol-prefix=hb_gobject
+      --identifier-prefix=hb_
+      --include GObject-2.0
+      --pkg-export=harfbuzz-gobject
+      --c-include=hb-gobject.h
+      --cflags-begin
+      -I${PROJECT_SOURCE_DIR}/src
+      -I${PROJECT_BINARY_DIR}/src
+      ${hb_includedir_cflags}
+      ${hb_defines_cflags}
+      -DHB_H
+      -DHB_H_IN
+      -DHB_OT_H
+      -DHB_OT_H_IN
+      -DHB_AAT_H
+      -DHB_AAT_H_IN
+      -DHB_GOBJECT_H
+      -DHB_GOBJECT_H_IN
+      -DHB_EXTERN=
+      --cflags-end
+      --library=harfbuzz-gobject
+      --library=harfbuzz
+      -L${hb_libpath}
+      ${extra_libs}
+      --filelist ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list
+      -o ${hb_libpath}/HarfBuzz-0.0.gir
+    DEPENDS harfbuzz-gobject harfbuzz ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list
+  )
+
+  add_custom_command(
+    TARGET harfbuzz-gobject
+    POST_BUILD
+    COMMAND "${G_IR_COMPILER}"
+      --verbose --debug
+      --includedir ${CMAKE_CURRENT_BINARY_DIR}
+      ${hb_libpath}/HarfBuzz-0.0.gir
+      -o ${hb_libpath}/HarfBuzz-0.0.typelib
+    DEPENDS ${hb_libpath}/HarfBuzz-0.0.gir harfbuzz-gobject
+  )
+endif ()
+
+
+## Additional framework build configs
+if (BUILD_FRAMEWORK)
+  set (CMAKE_MACOSX_RPATH ON)
+  set_target_properties(harfbuzz PROPERTIES
+    FRAMEWORK TRUE
+    PUBLIC_HEADER "${project_headers}"
+    XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
+  )
+  set (MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz")
+  set (MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}")
+  set (MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}")
+endif ()
+
+
+## Additional harfbuzz build artifacts
+if (HB_BUILD_UTILS)
+  # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindCairo.cmake
+  find_package(PkgConfig)
+  pkg_check_modules(PC_CAIRO QUIET cairo)
+
+  find_path(CAIRO_INCLUDE_DIRS NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo)
+  find_library(CAIRO_LIBRARIESNAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS})
+
+  add_definitions("-DPACKAGE_NAME=\"HarfBuzz\"")
+  add_definitions("-DPACKAGE_VERSION=\"${HB_VERSION}\"")
+  include_directories(${CAIRO_INCLUDE_DIRS})
+
+  add_executable(hb-view ${HB_VIEW_sources})
+  target_link_libraries(hb-view harfbuzz ${CAIRO_LIBRARIESNAMES})
+
+  add_executable(hb-shape ${HB_SHAPE_sources})
+  target_link_libraries(hb-shape harfbuzz)
+
+  add_executable(hb-subset ${HB_SUBSET_CLI_sources})
+  target_link_libraries(hb-subset harfbuzz harfbuzz-subset)
+
+  add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources})
+  target_link_libraries(hb-ot-shape-closure harfbuzz)
+
+  mark_as_advanced(CAIRO_INCLUDE_DIRS CAIRO_LIBRARIESNAMES)
+endif ()
+
+## Install
+include (GNUInstallDirs)
+
+if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
+  install(FILES ${project_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz)
+  if (HB_HAVE_GOBJECT)
+    install(FILES ${hb_gobject_headers} ${hb_gobject_gen_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz)
+  endif ()
+endif ()
+
+# get these variables in the required format
+list(REMOVE_DUPLICATES PC_REQUIRES_PRIV)
+string(REPLACE ";" ", " PC_REQUIRES_PRIV "${PC_REQUIRES_PRIV}")
+list(REMOVE_DUPLICATES PC_LIBS_PRIV)
+string(REPLACE ";" " " PC_LIBS_PRIV "${PC_LIBS_PRIV}")
+
+# Macro to write pkg-config .pc configuration files
+macro ( make_pkgconfig_pc_file name )
+  file(READ "${PROJECT_SOURCE_DIR}/src/${name}.pc.in" FSTR)
+
+  string(REPLACE "%prefix%" "${CMAKE_INSTALL_PREFIX}" FSTR ${FSTR})
+  string(REPLACE "%exec_prefix%" "\${prefix}" FSTR ${FSTR})
+
+  if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
+    string(REPLACE "%includedir%" "${CMAKE_INSTALL_INCLUDEDIR}" FSTR ${FSTR})
+  else ()
+    string(REPLACE "%includedir%" "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" FSTR ${FSTR})
+  endif ()
+
+  if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
+    string(REPLACE "%libdir%" "${CMAKE_INSTALL_LIBDIR}" FSTR ${FSTR})
+  else ()
+    string(REPLACE "%libdir%" "\${prefix}/${CMAKE_INSTALL_LIBDIR}" FSTR ${FSTR})
+  endif ()  
+
+  string(REPLACE "%VERSION%" "${HB_VERSION}" FSTR ${FSTR})
+  string(REPLACE "%requires_private%" "${PC_REQUIRES_PRIV}" FSTR ${FSTR})
+  string(REPLACE "%libs_private%" "${PC_LIBS_PRIV}" FSTR ${FSTR})
+
+  file(WRITE "${PROJECT_BINARY_DIR}/${name}.pc" ${FSTR})
+
+  install(
+    FILES "${PROJECT_BINARY_DIR}/${name}.pc"
+    DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
+    COMPONENT pkgconfig
+  )
+endmacro ( make_pkgconfig_pc_file )
+
+if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
+  install(TARGETS harfbuzz
+    EXPORT harfbuzzConfig
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    FRAMEWORK DESTINATION Library/Frameworks
+  )
+  make_pkgconfig_pc_file("harfbuzz")
+  install(EXPORT harfbuzzConfig
+      NAMESPACE harfbuzz::
+      DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
+  )
+  if (HB_HAVE_ICU)
+    install(TARGETS harfbuzz-icu
+      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+      FRAMEWORK DESTINATION Library/Frameworks
+    )
+    make_pkgconfig_pc_file("harfbuzz-icu")
+  endif ()
+  if (HB_BUILD_SUBSET)
+    install(TARGETS harfbuzz-subset
+      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    )
+    make_pkgconfig_pc_file("harfbuzz-subset")
+  endif ()
+  if (HB_BUILD_UTILS)
+    if (WIN32 AND BUILD_SHARED_LIBS)
+      install(TARGETS harfbuzz-subset
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+      )
+    endif ()
+    install(TARGETS hb-view
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+    install(TARGETS hb-subset
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+
+    install(TARGETS hb-shape
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+
+    install(TARGETS hb-ot-shape-closure
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+  endif ()
+  if (HB_HAVE_GOBJECT)
+    install(TARGETS harfbuzz-gobject
+      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+    make_pkgconfig_pc_file("harfbuzz-gobject")
+    if (HB_HAVE_INTROSPECTION)
+      if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
+        set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
+      else ()
+        set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
+      endif ()
+
+      install(FILES "${hb_libpath}/HarfBuzz-0.0.gir"
+        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gir-1.0
+      )
+
+      install(FILES "${hb_libpath}/HarfBuzz-0.0.typelib"
+        DESTINATION ${CMAKE_INSTALL_LIBDIR}/girepository-1.0
+      )
+    endif ()
+  endif ()
+endif ()

+ 158 - 0
libs/harfbuzz/CONFIG.md

@@ -0,0 +1,158 @@
+# Configuring HarfBuzz
+
+Most of the time you will not need any custom configuration.  The configuration
+options provided by `meson` should be enough.  In particular, if you just want
+HarfBuzz library plus hb-shape / hb-view utilities, make sure FreeType and Cairo
+are available and found during configuration.
+
+If you are building for distribution, you should more carefully consider whether
+you need Glib, ICU, Graphite2, as well as CoreText / Uniscribe / DWrite.  Make
+sure the relevant ones are enabled.
+
+If you are building for custom environment (embedded, downloadable app, etc)
+where you mostly just want to call `hb_shape()` and the binary size of the
+resulting library is very important to you, the rest of this file guides you
+through your options to disable features you may not need, in exchange for
+binary size savings.
+
+## Compiler Options
+
+Make sure you build with your compiler's "optimize for size" option.  On `gcc`
+this is `-Os`, and can be enabled by passing `CXXFLAGS=-Os`.  On clang there
+is an even more extreme flag, `-Oz`.  Meson also provides `--buildtype=minsize`
+for more convenience.
+
+HarfBuzz heavily uses inline functions and the optimize-size flag can make the
+library smaller by 20% or more.  Moreover, sometimes, based on the target CPU,
+the optimize-size builds perform *faster* as well, thanks to lower code
+footprint and caching effects.  So, definitely try that even if size is not
+extremely tight but you have a huge application.  For example, Chrome does
+that.  Note that this configuration also automatically enables certain internal
+optimizations.  Search for `HB_OPTIMIZE_SIZE` for details, if you are using
+other compilers, or continue reading.
+
+Another compiler option to consider is "link-time optimization", also known as
+'lto'.  To enable that, feel free to use `-Db_lto=true` of meson.
+This, also, can have a huge impact on the final size, 20% or more.
+
+Finally, if you are making a static library build or otherwise linking the
+library into your app, make sure your linker removes unused functions.  This
+can be tricky and differ from environment to environment, but you definitely
+want to make sure this happens.  Otherwise, every unused public function will
+be adding unneeded bytes to your binary.  The following pointers might come
+handy:
+
+ * https://lwn.net/Articles/741494/ (all of the four-part series)
+ * https://elinux.org/images/2/2d/ELC2010-gc-sections_Denys_Vlasenko.pdf
+
+Combining the above three build options should already shrink your library a lot.
+The rest of this file shows you ways to shrink the library even further at the
+expense of removing functionality (that may not be needed).  The remaining
+options are all enabled by defining pre-processor macros, which can be done
+via `CXXFLAGS` or `CPPFLAGS` similarly.
+
+
+## Unicode-functions
+
+Access to Unicode data can be configured at compile time as well as run-time.
+By default, HarfBuzz ships with its own compact subset of properties from
+Unicode Character Database that it needs.  This is a highly-optimized
+implementation that depending on compile settings (optimize-size or not)
+takes around ~40kb or ~60kb.  Using this implementation (default) is highly
+recommended, as HarfBuzz always ships with data from latest version of Unicode.
+This implementation can be disabled by defining `HB_NO_UCD`.
+
+For example, if you are enabling ICU as a built-in option, or GLib, those
+can provide Unicode data as well, so defining `HB_NO_UCD` might save you
+space without reducing functionality (to the extent that the Unicode version
+of those implementations is recent.)
+
+If, however, you provide your own Unicode data to HarfBuzz at run-time by
+calling `hb_buffer_set_unicode_funcs` on every buffer you create, and you do
+not rely on `hb_unicode_funcs_get_default()` results, you can disable the
+internal implementation by defining both `HB_NO_UCD` and `HB_NO_UNICODE_FUNCS`.
+The latter is needed to guard against accidentally building a library without
+any default Unicode implementations.
+
+
+## Font-functions
+
+Access to certain font functionalities can also be configured at run-time.  By
+default, HarfBuzz uses an efficient internal implementation of OpenType
+functionality for this.  This internal implementation is called `hb-ot-font`.
+All newly-created `hb_font_t` objects by default use `hb-ot-font`.  Using this
+is highly recommended, and is what fonts use by default when they are created.
+
+Most embedded uses will probably use HarfBuzz with FreeType using `hb-ft.h`.
+In that case, or if you otherwise provide those functions by calling
+`hb_font_set_funcs()` on every font you create, you can disable `hb-ot-font`
+without loss of functionality by defining `HB_NO_OT_FONT`.
+
+
+## Shapers
+
+Most HarfBuzz clients use it for the main shaper, called "ot".  However, it
+is legitimate to want to compile HarfBuzz with only another backend, eg.
+CoreText, for example for an iOS app.  For that, you want `HB_NO_OT_SHAPE`.
+If you are going down that route, check if you want `HB_NO_OT`.
+
+This is very rarely what you need.  Make sure you understand exactly what you
+are doing.
+
+Defining `HB_NO_FALLBACK_SHAPE` however is pretty harmless.  That removes the
+(unused) "fallback" shaper.  This is defined by the `HB_TINY` profile already
+(more below).
+
+
+## Thread-safety
+
+By default HarfBuzz builds as a thread-safe library.  The exception is that
+the `HB_TINY` predefined configuration (more below) disables thread-safety.
+
+If you do *not* need thread-safety in the library (eg. you always call into
+HarfBuzz from the same thread), you can disable thread-safety by defining
+`HB_NO_MT`.  As noted already, this is enabled by `HB_TINY`.
+
+
+## Pre-defined configurations
+
+The [`hb-config.hh`](src/hb-config.hh) internal header supports three
+pre-defined configurations as well grouping of various configuration options.
+The pre-defined configurations are:
+
+  * `HB_MINI`: Disables shaping of AAT as well as legacy fonts.  Ie. it produces
+    a capable OpenType shaper only.
+
+  * `HB_LEAN`: Disables various non-shaping functionality in the library, as well
+    as esoteric or rarely-used shaping features.  See the definition for details.
+
+  * `HB_TINY`: Enables both `HB_MINI` and `HB_LEAN` configurations, as well as
+    disabling thread-safety and debugging, and use even more size-optimized data
+    tables.
+
+
+## Tailoring configuration
+
+Most of the time, one of the pre-defined configuration is exactly what one needs.
+Sometimes, however, the pre-defined configuration cuts out features that might
+be desired in the library.  Unfortunately there is no quick way to undo those
+configurations from the command-line.
+
+However, configuration can still be overridden from a file.  To do that, add your
+override instructions (mostly `undef` instructions) to a header file and define
+the macro `HB_CONFIG_OVERRIDE_H` to the string containing to that header file's
+name.  HarfBuzz will then include that file at the appropriate place during
+configuration.
+
+Up until HarfBuzz 3.1.2 the the configuration override header file's name was
+fixed and called `config-override.h`, and was activated by defining the macro
+`HAVE_CONFIG_OVERRIDE_H`.  That still works.
+
+
+## Notes
+
+Note that the config option `HB_NO_CFF`, which is enabled by `HB_LEAN` and
+`HB_TINY` does *not* mean that the resulting library won't work with CFF fonts.
+The library can shape valid CFF fonts just fine, with or without this option.
+This option disables (among other things) the code to calculate glyph extents
+for CFF fonts, which many clients might not need.

+ 38 - 0
libs/harfbuzz/COPYING

@@ -0,0 +1,38 @@
+HarfBuzz is licensed under the so-called "Old MIT" license.  Details follow.
+For parts of HarfBuzz that are licensed under different licenses see individual
+files names COPYING in subdirectories where applicable.
+
+Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020  Google, Inc.
+Copyright © 2018,2019,2020  Ebrahim Byagowi
+Copyright © 2019,2020  Facebook, Inc.
+Copyright © 2012  Mozilla Foundation
+Copyright © 2011  Codethink Limited
+Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
+Copyright © 2009  Keith Stribley
+Copyright © 2009  Martin Hosken and SIL International
+Copyright © 2007  Chris Wilson
+Copyright © 2005,2006,2020,2021  Behdad Esfahbod
+Copyright © 2005  David Turner
+Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
+Copyright © 1998-2004  David Turner and Werner Lemberg
+
+For full copyright notices consult the individual files in the package.
+
+
+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.

+ 82 - 0
libs/harfbuzz/Makefile.am

@@ -0,0 +1,82 @@
+# Process this file with automake to produce Makefile.in
+
+NULL =
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = src util test perf docs
+
+EXTRA_DIST = \
+	autogen.sh \
+	harfbuzz.doap \
+	README.md \
+	README.python.md \
+	BUILD.md \
+	CONFIG.md \
+	RELEASING.md \
+	TESTING.md \
+	CMakeLists.txt \
+	replace-enum-strings.cmake \
+	meson.build \
+	meson_options.txt \
+	subprojects/cairo.wrap \
+	subprojects/freetype2.wrap \
+	subprojects/glib.wrap \
+	subprojects/google-benchmark.wrap \
+	subprojects/ragel.wrap \
+	subprojects/packagefiles/ragel/meson.build \
+	mingw-configure.sh \
+	$(NULL)
+
+MAINTAINERCLEANFILES = \
+	$(GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL) \
+	$(GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL) \
+	$(GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN) \
+	$(srcdir)/INSTALL \
+	$(srcdir)/ChangeLog \
+	$(srcdir)/gtk-doc.make \
+	$(srcdir)/m4/gtk-doc.m4 \
+	$(NULL)
+
+
+#
+# ChangeLog generation
+#
+CHANGELOG_RANGE =
+ChangeLog: $(srcdir)/ChangeLog
+$(srcdir)/ChangeLog:
+	$(AM_V_GEN) if test -d "$(top_srcdir)/.git"; then \
+	  (GIT_DIR=$(top_srcdir)/.git \
+	   $(GIT) log $(CHANGELOG_RANGE) --stat) > [email protected] \
+	  && mv -f [email protected] "$(srcdir)/ChangeLog" \
+	  || ($(RM) [email protected]; \
+	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
+	      (test -f $@ || echo git-log is required to generate this file >> "$(srcdir)/$@")); \
+	else \
+	  test -f $@ || \
+	  (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
+	  echo A git checkout and git-log is required to generate this file >> "$(srcdir)/$@"); \
+	fi
+.PHONY: ChangeLog $(srcdir)/ChangeLog
+
+
+#
+# Release engineering
+#
+
+DISTCHECK_CONFIGURE_FLAGS = \
+	--enable-gtk-doc \
+	--disable-doc-cross-references \
+	--with-gobject \
+	--enable-introspection \
+	$(NULL)
+
+# TAR_OPTIONS is not set as env var for 'make dist'.  How to fix that?
+TAR_OPTIONS = --owner=0 --group=0
+
+dist-hook: dist-clear-sticky-bits
+# Clean up any sticky bits we may inherit from parent dir
+dist-clear-sticky-bits:
+	chmod -R a-s $(distdir)
+
+-include $(top_srcdir)/git.mk

+ 3019 - 0
libs/harfbuzz/NEWS

@@ -0,0 +1,3019 @@
+Overview of changes leading to 5.3.1
+Wednesday, October 19, 2022
+====================================
+- Subsetter repacker fixes. (Garret Rieger)
+- Adjust Grapheme clusters for Katakana voiced sound marks. (Behdad Esfahbod)
+- New “hb-subset” option “--preprocess-face”. (Garret Rieger)
+
+
+Overview of changes leading to 5.3.0
+Saturday, October 8, 2022
+"Women, Life, Freedom" #MahsaAmini
+====================================
+- Don’t add glyphs from dropped MATH or COLR tables to the subset glyphs.
+  (Khaled Hosny)
+- Map “rlig” to appropriate AAT feature selectors. (Jonathan Kew)
+- Update USE data files to latest version. (David Corbett)
+- Check “CBDT” extents first before outline tables, to help with fonts that
+  also include an empty “glyf” table. (Khaled Hosny)
+- More work towards variable font instancing in the subsetter. (Qunxin Liu)
+- Subsetter repacker improvements. (Garret Rieger)
+- New API:
++hb_ot_layout_lookup_get_optical_bound()
++hb_face_builder_sort_tables()
+
+
+Overview of changes leading to 5.2.0
+Saturday, September 17, 2022
+====================================
+- Fix regressions in hb-ft font functions for FT_Face’s with transformation
+  matrix. (Behdad Esfahbod)
+- The experimental hb-repacker API now supports splitting several GPOS subtable
+  types when needed. (Garret Rieger)
+- The HarfBuzz extensions to OpenType font format are now opt-in behind
+  build-time flags. (Behdad Esfahbod)
+- The experimental hb-subset variable fonts instantiation API can now
+  instantiate more font tables and arbitrary axis locations. (Qunxin Liu)
+- Unicode 15 support. (David Corbett)
+- Various documentation improvements. (Behdad Esfahbod, Matthias Clasen)
+- The hb-view command line tool now detects WezTerm inline images support.
+  (Wez Furlong)
+- Fix FreeType and ICU dependency lookup with meson. (Xavier Claessens)
+
+- New API:
++HB_SCRIPT_KAWI
++HB_SCRIPT_NAG_MUNDARI
+
+
+Overview of changes leading to 5.1.0
+Sunday, July 31, 2022
+====================================
+- More extensive buffer tracing messages. (Behdad Esfahbod)
+- Fix hb-ft regression in bitmap fonts rendering. (Behdad Esfahbod)
+- Support extension promotion of lookups in hb-subset-repacker. (Garret Rieger)
+- A new HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL for scripts that use elongation
+  (e.g. Arabic) to signify where it is safe to insert tatweel glyph without
+  interrupting shaping. (Behdad Esfahbod)
+- Add “--safe-to-insert-tatweel” to “hb-shape” tool. (Behdad Esfahbod)
+
+- New API
++HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
++HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL
+
+
+Overview of changes leading to 5.0.1
+Saturday, July 23, 2022
+====================================
+- Fix version 2 “avar” table with hb-ft. (Behdad Esfahbod)
+
+
+Overview of changes leading to 5.0.0
+Saturday, July 23, 2022
+====================================
+- Support fonts with more than 65535 glyphs in “GDEF”, “GSUB”, and “GPOS”
+  tables. This is part of https://github.com/be-fonts/boring-expansion-spec to
+  extend OpenType in a backward-compatible way.
+  (Behdad Esfahbod, Garret Rieger)
+- Complete support for more than 65535 glyphs in “glyf” table that started in
+  4.0.0 release. Part of boring-expansion-spec. (Behdad Esfahbod)
+- Support version 2 of “avar” table. Part of boring-expansion-spec.
+  (Behdad Esfahbod)
+- Fix mark attachment on multiple substitutions in some cases.
+  (Behdad Esfahbod)
+- Fix application of “calt”, “rclt”, and “ccmp” features to better match
+  Uniscribe behaviour with some Arabic fonts. (Behdad Esfahbod)
+- Improvement to interaction between multiple cursive attachments.
+  (Behdad Esfahbod)
+- Improve multiple mark interactions in Hebrew. (Behdad Esfahbod)
+- Implement language-specific forms in AAT shaping. (Behdad Esfahbod)
+- Fix variation of “VORG” table. (Behdad Esfahbod)
+- Support for specific script tags to be retained in the subsetter, and add
+  “--layout-scripts” option to “hb-subset” tool. (Garret Rieger)
+- Accept space as delimiter for --features/--variations in command line tools.
+- Improve subsetting of “COLR” table. (Qunxin Liu)
+- Improved fuzzing coverage for ot-math API. (Frédéric Wang)
+- Fix “kern” table version 2 (AAT) sanitization on 32-bit systems.
+  (Behdad Esfahbod)
+- Allow negative glyph advances from “graphite2” shaper. (Stephan Bergmann)
+- Implement loading (color) bitmap fonts with hb-ft. (Behdad Esfahbod)
+- Fix regression in hb-ft when changing font size. (Behdad Esfahbod)
+- Fix build on GCC < 7. (Kleis Auke Wolthuizen)
+- Dynamically load dwrite.dll on windows if “directwrite” shaper is enabled.
+  (Luca Bacci)
+- Provide a single-file harfbuzz-subset.cc file for easier alternate building
+  of hb-subset library, similar to harfbuzz.cc. (Khaled Hosny)
+
+- New API
++HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG
++hb_language_matches()
+
+
+Overview of changes leading to 4.4.1
+Wednesday, June 29, 2022
+====================================
+- Fix test failure with some compilers.
+- Fix Telugu and Kannada kerning regression.
+
+
+Overview of changes leading to 4.4.0
+Monday, June 27, 2022
+====================================
+- Caching of variable fonts shaping, in particular when using HarfBuzz’s own
+  font loading functions (ot). Bringing performance of variable shaping in par
+  with non-variable fonts shaping. (Behdad Esfahbod)
+- Caching of format 2 “Contextual Substitution” and “Chained Contexts
+  Substitution” lookups. Resulting in up to 20% speedup of lookup-heavy fonts
+  like Gulzar or Noto Nastaliq Urdu. (Behdad Esfahbod)
+- Improved ANSI output from hb-view. (Behdad Esfahbod)
+- Support for shaping legacy, pre-OpenType Windows 3.1-era, Arabic fonts that
+  relied on a fixed PUA encoding. (Khaled Hosny, Behdad Esfahbod)
+- Sinhala script is now shaped by the USE shaper instead of “indic” one.
+  (Behdad Esfahbod, David Corbett)
+- Thai shaper improvements. (David Corbett)
+- hb-ot-name API supports approximate BCP-47 language matching, for example
+  asking for “en_US” in a font that has only “en” names will return them.
+  (Behdad Esfahbod)
+- Optimized TrueType glyph shape loading. (Behdad Esfahbod)
+- Fix subsetting of HarfBuzz faces created via hb_face_create_for_tables().
+  (Garret Rieger)
+- Add 32 bit var store support to the subsetter. (Garret Rieger)
+
+- New API
++HB_BUFFER_FLAG_DEFINED
++HB_BUFFER_SERIALIZE_FLAG_DEFINED
++hb_font_changed()
++hb_font_get_serial()
++hb_ft_hb_font_changed()
++hb_set_hash()
++hb_map_copy()
++hb_map_hash()
+
+
+Overview of changes leading to 4.3.0
+Friday, May 20, 2022
+====================================
+- Major speed up in loading and subsetting fonts, especially in
+  handling CFF table. Subsetting some fonts is now 3 times faster.
+  (Behdad Esfahbod, Garret Rieger)
+- Speed up blending CFF2 table. (Behdad Esfahbod)
+- Speed up hb_ot_tags_from_language(). (Behdad Esfahbod, David Corbett)
+- Fix USE classification of U+10A38 to fix multiple marks on single Kharoshthi
+  base. (David Corbett)
+- Fix parsing of empty CFF Index. (Behdad Esfahbod)
+- Fix subsetting CPAL table with partial palette overlaps. (Garret Rieger)
+
+- New API
++hb_map_is_equal() (Behdad Esfahbod)
+
+
+Overview of changes leading to 4.2.1
+Sunday, April 24, 2022
+====================================
+- Make sure hb_blob_create_from_file_or_fail() always returns nullptr in case
+  of failure and not empty blob sometimes. (Khaled Hosny)
+- Add --passthrough-tables option to hb-subset. (Cosimo Lupo)
+- Reinstate a pause after basic features in Khmer shaper, fixing a regression
+  introduced in previous release. (Behdad Esfahbod)
+- Better handling of Regional_Indicator when shaped with RTL-native scripts,
+  reverting earlier fix that caused regressions in AAT shaping. (Behdad Esfahbod)
+
+
+Overview of changes leading to 4.2.0
+Wednesday, March 30, 2022
+====================================
+- Source code reorganization, splitting large hb-ot-layout files into smaller,
+  per-subtable ones under OT/Layout/*. Code for more tables will follow suit in
+  later releases. (Garret Rieger, Behdad Esfahbod)
+- Revert Indic shaper change in previous release that broke some fonts and
+  instead make per-syllable restriction of “GSUB” application limited to
+  script-specific Indic features, while applying them and discretionary
+  features in one go. (Behdad Esfahbod)
+- Fix decoding of private in gvar table. (Behdad Esfahbod)
+- Fix handling of contextual lookups that delete too many glyphs. (Behdad Esfahbod)
+- Make “morx” deleted glyphs don’t block “GPOS” application. (Behdad Esfahbod)
+- Various build fixes. (Chun-wei Fan, Khaled Hosny)
+
+- New API
++hb_set_next_many() (Andrew John)
+
+
+Overview of changes leading to 4.1.0
+Wednesday, March 23, 2022
+====================================
+- Various OSS-Fuzz fixes. (Behdad Esfahbod)
+- Make fallback vertical-origin match FreeType’s. (Behdad Esfahbod)
+- Treat visible viramas like dependent vowels in USE shaper. (David Corbett)
+- Apply presentation forms features and discretionary features in one go in
+  Indic shaper, which seems to match Uniscribe and CoreText behaviour.
+  (Behdad Esfahbod, David Corbett)
+- Various bug fixes.
+
+- New API
++hb_set_add_sorted_array() (Andrew John)
+
+
+Overview of changes leading to 4.0.1
+Friday, March 11, 2022
+====================================
+- Update OpenType to AAT mappings for “hist” and “vrtr” features.
+  (Florian Pircher)
+- Update IANA Language Subtag Registry to 2022-03-02. (David Corbett)
+- Update USE shaper to allow any non-numeric tail in a symbol cluster, and
+  remove obsolete data overrides. (David Corbett)
+- Fix handling of baseline variations to return correctly scaled values.
+  (Matthias Clasen)
+- A new experimental hb_subset_repack_or_fail() to repack an array of objects,
+  eliminating offset overflows. The API is not available unless HarfBuzz is
+  built with experimental APIs enabled. (Qunxin Liu)
+
+- New experimental API
++hb_link_t
++hb_object_t
++hb_subset_repack_or_fail()
+
+
+Overview of changes leading to 4.0.0
+Tuesday, March 1, 2022
+====================================
+- New public API to create subset plan and gather information on things like
+  glyph mappings in the final subset. The plan can then be passed on to perform
+  the subsetting operation. (Garret Rieger)
+- Draw API for extracting glyph shapes have been extended and finalized and is
+  no longer an experimental API. The draw API supports glyf, CFF and CFF2
+  glyph outlines tables, and applies variation settings set on the font as well
+  as synthetic slant. The new public API is not backward compatible with the
+  previous, non-public, experimental API. (Behdad Esfahbod)
+- The hb-view tool will use HarfBuzz draw API to render the glyphs instead of
+  cairo-ft when compiled with Cairo 1.17.5 or newer, setting HB_DRAW
+  environment variable to 1 or 0 will force using or not use the draw API,
+  respectively. (Behdad Esfahbod)
+- The hb-shape and hb-view tools now default to using HarfBuzz’s own font
+  loading functions (ot) instead of FreeType ones (ft). They also have a new
+  option, --font-slant, to apply synthetic slant to the font. (Behdad Esfahbod)
+- HarfBuzz now supports more than 65535 (the OpenType limit) glyph shapes and
+  metrics. See https://github.com/be-fonts/boring-expansion-spec/issues/6 and
+  https://github.com/be-fonts/boring-expansion-spec/issues/7 for details.
+  (Behdad Esfahbod)
+- New API to get the dominant horizontal baseline tag for a given script.
+  (Behdad Esfahbod)
+- New API to get the baseline positions from the font, and synthesize missing
+  ones. As well as new API to get font metrics and synthesize missing ones.
+  (Matthias Clasen)
+- Improvements to finding dependencies on Windows when building with Visual
+  Studio. (Chun-wei Fan)
+- New buffer flag, HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT, that must be set
+  during shaping for HB_GLYPH_FLAG_UNSAFE_TO_CONCAT flag to be reliably
+  produced. This is to limit the performance hit of producing this flag to when
+  it is actually needed. (Behdad Esfahbod)
+- Documentation improvements. (Matthias Clasen)
+
+- New API
+ - General:
+   +HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT
+   +hb_var_num_t
+
+ - Draw:
+   +hb_draw_funcs_t
+   +hb_draw_funcs_create()
+   +hb_draw_funcs_reference()
+   +hb_draw_funcs_destroy()
+   +hb_draw_funcs_is_immutable()
+   +hb_draw_funcs_make_immutable()
+   +hb_draw_move_to_func_t
+   +hb_draw_funcs_set_move_to_func()
+   +hb_draw_line_to_func_t
+   +hb_draw_funcs_set_line_to_func()
+   +hb_draw_quadratic_to_func_t
+   +hb_draw_funcs_set_quadratic_to_func()
+   +hb_draw_cubic_to_func_t
+   +hb_draw_funcs_set_cubic_to_func()
+   +hb_draw_close_path_func_t
+   +hb_draw_funcs_set_close_path_func()
+   +hb_draw_state_t
+   +HB_DRAW_STATE_DEFAULT
+   +hb_draw_move_to()
+   +hb_draw_line_to()
+   +hb_draw_quadratic_to()
+   +hb_draw_cubic_to()
+   +hb_draw_close_path()
+   +hb_font_get_glyph_shape_func_t
+   +hb_font_funcs_set_glyph_shape_func()
+   +hb_font_get_glyph_shape()
+
+ - OpenType layout
+   +HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL
+   +HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL
+   +hb_ot_layout_get_horizontal_baseline_tag_for_script()
+   +hb_ot_layout_get_baseline_with_fallback()
+
+ - Metrics:
+   +hb_ot_metrics_get_position_with_fallback()
+
+ - Subset:
+   +hb_subset_plan_t
+   +hb_subset_plan_create_or_fail()
+   +hb_subset_plan_reference()
+   +hb_subset_plan_destroy()
+   +hb_subset_plan_set_user_data()
+   +hb_subset_plan_get_user_data()
+   +hb_subset_plan_execute_or_fail()
+   +hb_subset_plan_unicode_to_old_glyph_mapping()
+   +hb_subset_plan_new_to_old_glyph_mapping()
+   +hb_subset_plan_old_to_new_glyph_mapping()
+
+
+Overview of changes leading to 3.4.0
+Sunday, February 13, 2022
+====================================
+- Perform sanity checks on shaping results is now part of “harfbuzz” library
+  and can be enabled by setting the buffer flag HB_BUFFER_FLAG_VERIFY.
+  (Behdad Esfahbod)
+- Arabic Mark Transient Reordering Algorithm have been updated to revision 6.
+  (Khaled Hosny)
+- ISO 15924 code for mathematical notation, ‘Zmth’, now maps to the OpenType
+  ‘math’ tag. (Alexis King)
+- It is now possible to get at once all math kerning values for a given glyph
+  at a given corner. (Alexis King)
+- Fix locale_t portability issues on systems the typedef’s it to a void
+  pointer. (Behdad Esfahbod)
+
+- New API:
++HB_BUFFER_FLAG_VERIFY
++HB_OT_TAG_MATH_SCRIPT
++HB_SCRIPT_MATH
++hb_ot_math_kern_entry_t
++hb_ot_math_get_glyph_kernings()
+
+- Deprecated API
++HB_OT_MATH_SCRIPT
+
+
+Overview of changes leading to 3.3.2
+Sunday, February 6, 2022
+====================================
+- Revert splitting of pair positioning values introduced in 3.3.0 as it proved
+  problematic. (Behdad Esfahbod)
+
+
+Overview of changes leading to 3.3.1
+Monday, January 31, 2022
+====================================
+- Fix heap-use-after-free in harfbuzz-subset introduced in previous release.
+  (Garret Rieger)
+
+
+Overview of changes leading to 3.3.0
+Monday, January 31, 2022
+====================================
+- Improved documentation. (Matthias Clasen)
+- Internal code cleanup, using C++ standard library more. (Behdad Esfahbod)
+- The low 16-bits of face index will be used by hb_face_create() to select a
+  face inside a font collection file format, while the high 16-bits will be
+  used by hb_font_create() to load the named instance. (Behdad Esfahbod)
+- Glyph positions and other font metrics now apply synthetic slant set by
+  hb_font_set_synthetic_slant(), for improved positioning for synthetically
+  slanted fonts. (Behdad Esfahbod)
+- Fixed unintentional locale dependency in hb_variation_to_string() for decimal
+  point representation. (Matthias Clasen)
+- When applying pair positioning (kerning) the positioning value is split
+  between the two sides of the pair for improved cursor positioning between
+  such pairs. (Behdad Esfahbod)
+- Introduced new HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, to be used in conjunction
+  with HB_GLYPH_FLAG_UNSAFE_TO_BREAK for optimizing re-shaping during line
+  breaking. Check the documentation for further details. (Behdad Esfahbod)
+- Improved handling of macrolanguages when mapping BCP 47 codes to OpenType
+  tags. (David Corbett)
+
+- New API:
++HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
++hb_segment_properties_overlay()
++hb_buffer_create_similar()
++hb_font_set_synthetic_slant()
++hb_font_get_synthetic_slant()
++hb_font_get_var_coords_design()
+
+
+Overview of changes leading to 3.2.0
+Friday, November 26, 2021
+====================================
+“harfbuzz” library improvements:
+- Fixed shaping of Apple Color Emoji flags in right-to-left context. (Behdad Esfahbod)
+- Fixed positioning of CFF fonts in HB_TINY profile. (Behdad Esfahbod)
+- OpenType 1.9 language tags update. (David Corbett)
+- Add HB_NO_VERTICAL config option.
+- Add HB_CONFIG_OVERRIDE_H for easier configuration. (Behdad Esfahbod)
+
+“harfbuzz-subset” library improvements:
+- Improved packing of cmap, loca, and Ligature tables. (Garret Rieger)
+- Significantly improved overflow-resolution strategy in the repacker. (Garret Rieger)
+
+
+Overview of changes leading to 3.1.2
+Friday, November 26, 2021
+====================================
+- hb-shape / hb-view: revert treating text on the commandline as single
+  paragraph (was introduced in 3.0.0); add new --single-par to do that.
+  (Behdad Esfahbod)
+- Subsetter bug fixes. (Garret Rieger, Qunxin Liu, Behdad Esfahbod)
+
+
+Overview of changes leading to 3.1.1
+Wednesday, November 8, 2021
+====================================
+- Work around GCC cast-align error/warning on some platforms. (Behdad Esfahbod)
+- Documentation improvements. (Matthias Clasen)
+
+
+Overview of changes leading to 3.1.0
+Wednesday, November 3, 2021
+====================================
+- Better offset-overflow handling in the subsetter library. (Garret Rieger)
+- Improved Unicode 14 properties in the USE shaper, and various other USE
+  shaper fixes. (David Corbett)
+- MATH and COLR v1 tables subsetting support, and various other subsetter fixes.
+  (Qunxin Liu)
+- Support for Pwo Karen / Ason Chin medial la. (Simon Cozens)
+- Apply GPOS positioning when substituting with morx table, if kerx is missing.
+  (Behdad Esfahbod)
+- Apply calt and clig features across syllable boundaries in Indic shaper.
+  (Behdad Esfahbod)
+- meson option for enabling Graphite 2 has been renamed to graphite2.
+- Build and documentation fixes.
+
+- New API:
++hb_buffer_set_not_found_glyph()
++hb_buffer_get_not_found_glyph()
+
+
+Overview of changes leading to 3.0.0
+Friday, September 17, 2021
+====================================
+- Unicode 14.0 support (David Corbett).
+- The hb-subset API and the harfbuzz-subset library's ABI are now declared
+  stable. The harfbuzz-subset library would not have been possible without the
+  work of Garret Rieger and Qunxin Liu from Google Fonts, and the earlier work
+  of Michiharu Ariza from Adobe.
+- The hb-style API is now stable and no longer experimental.
+
+- New API:
++hb_style_tag_t
++hb_style_get_value()
++hb_subset_input_t
++hb_subset_flags_t
++hb_subset_sets_t
++hb_subset_input_create_or_fail()
++hb_subset_input_reference()
++hb_subset_input_destroy()
++hb_subset_input_set_user_data()
++hb_subset_input_get_user_data()
++hb_subset_input_unicode_set()
++hb_subset_input_glyph_set()
++hb_subset_input_set()
++hb_subset_input_get_flags()
++hb_subset_input_set_flags()
++hb_subset_or_fail()
+
+- Removed old unstable harfbuzz-subset API:
+-hb_subset_input_nameid_set()
+-hb_subset_input_namelangid_set()
+-hb_subset_input_layout_features_set()
+-hb_subset_input_no_subset_tables_set()
+-hb_subset_input_drop_tables_set()
+-hb_subset_input_set_drop_hints()
+-hb_subset_input_get_drop_hints()
+-hb_subset_input_set_desubroutinize()
+-hb_subset_input_get_desubroutinize()
+-hb_subset_input_set_retain_gids()
+-hb_subset_input_get_retain_gids()
+-hb_subset_input_set_name_legacy()
+-hb_subset_input_get_name_legacy()
+-hb_subset_input_set_overlaps_flag()
+-hb_subset_input_get_overlaps_flag()
+-hb_subset_input_set_notdef_outline()
+-hb_subset_input_get_notdef_outline()
+-hb_subset_input_set_no_prune_unicode_ranges()
+-hb_subset_input_get_no_prune_unicode_ranges()
+-hb_subset()
+
+
+Overview of changes leading to 2.9.1
+Tuesday, September 7, 2021
+====================================
+- Final subset API is in place and if no issues are discovered, it will be the
+  stable subset API of HarfBuzz 3.0.0. Old API is kept to ease transition, but
+  will be removed in 3.0.0.
+- Various fuzzer-found bug fixes.
+- hb_buffer_append() now handles the pre- and post-context which previously
+  were left unchanged in the destination buffer.
+- hb-view / hb-shape now accept following new arguments:
+  o --unicodes-before/after: takes a list of hex numbers that represent Unicode
+    codepoints.
+- Undeprecated API:
+  hb_set_invert()
+
+
+Overview of changes leading to 2.9.0
+Wednesday, August 18, 2021
+History Repeats Itself (Afghanistan)
+====================================
+- Subsetter API is being stabilized, with the first stable API to happen in
+  3.0.0 release (https://github.com/harfbuzz/harfbuzz/issues/3078).
+- Support multiple variation axes with same tag, aka HOI.
+- The “coretext” testing shaper now passes font variations to CoreText.
+- hb-shape/hb-view does not break line at new lines unless text is read from
+  file.
+- hb-view and hb-subset has a --batch now, similar to hb-shape.
+- The --batch mode now uses ; as argument separator instead of : used previously.
+- The --batch in hb-shape does not expect 0th argument anymore. That is, the
+  lines read are interpreted as argv[1:], instead of argv[0:].
+- The --batch option has been undocumented. We are ready to document it; send
+  feedback if you find it useful.
+- hb-subset got arguments revamps. Added much-requested --gids-file, --glyphs,
+  --glyphs-file, --unicodes-file, supporting ranges in --unicodes.
+- Various bug fixes.
+
+
+Overview of changes leading to 2.8.2
+Tuesday, July 8, 2021
+====================================
+- Shaping LTR digits for RTL scripts now makes the native direction of the
+  digits LTR, applying shaping and positioning rules on the same glyph order as
+  Uniscribe. (Jonathan Kew, Khaled Hosny).
+- Subsetting COLR v1 and CPAL tables is now supported. (Garret Rieger, Qunxin Liu)
+- Various fixes and improvements to the subsetter. (Garret Rieger, Qunxin Liu, Behdad)
+- When applying morx table, mark glyph widths should not be zeroed. (Jonathan Kew)
+- GPOS is preferred over kerx, if GSUB was applied. (Behdad)
+- Regional_Indicator pairs are grouped together when clustering. (Behdad)
+- New API:
++hb_blob_create_or_fail()
++hb_blob_create_from_file_or_fail()
++hb_set_copy()
+
+
+Overview of changes leading to 2.8.1
+Tuesday, May 4, 2021
+====================================
+- Subsetter now fully supports GSUB/GPOS/GDEF tables (including variations); as
+  such, layout tables are retained by subsetter by default. (Garret Rieger, Qunxin Liu)
+- Build scripts no longer check for FontConfig as HarfBuzz does not use it.
+- hb-view supports iTerm2 and kitty inline image protocols (Khaled Hosny),
+  it can also use Chafa for terminal graphics if available (Hans Petter Jansson).
+
+Overview of changes leading to 2.8.0
+Tuesday, March 16, 2021
+====================================
+- Shape joining scripts other than Arabic/Syriac using the Universal Shaping Engine.
+  Previously these were shaped using the generalized Arabic shaper. (David Corbett)
+- Fix regression in shaping of U+0B55 ORIYA SIGN OVERLINE. (David Corbett)
+- Update language tags. (David Corbett)
+- Variations: reduce error: do not round each interpolated delta. (Just van Rossum) 
+- Documentation improvements. (Khaled Hosny, Nathan Willis)
+- Subsetter improvements: subsets most, if not all, lookup types now. (Garret Rieger, Qunxin Liu)
+- Fuzzer-found fixes and other improvements when memory failures happen. (Behdad)
+- Removed most atomic implementations now that we have C++11 atomic impl. (Behdad)
+- General codebase upkeep; using more C++11 features: constexpr constructors, etc. (Behdad)
+
+
+Overview of changes leading to 2.7.4
+Sunday, December 27, 2020
+====================================
+- Fix missing --enable-introspection configure option from previous release
+  tarball.
+- Documentation updates.
+
+
+Overview of changes leading to 2.7.3
+Wednesday, December 23, 2020
+====================================
+- Update USE shaper to 2020-08-13 specification, and other improvements.
+- Don’t disable liga feature in myanmar shaper, to match Uniscribe.
+- Improvements to language and script tags handling.
+- Update language system tag registry to OpenType 1.8.4
+- Support for serializing and deserializing Unicode buffers. Serialized buffers
+  are now delimited with `<>` or `[]` based on whether it is a Unicode or
+  glyphs buffer.
+- Increase buffer work limits to handle fonts with many complex lookups.
+- Handle more shaping operations in trace output.
+- Memory access fixes.
+- More OOM fixes.
+- Improved documentation.
+- Build system improvements.
+- New API:
++hb_buffer_has_positions()
++hb_buffer_serialize()
++hb_buffer_serialize_unicode()
++hb_buffer_deserialize_unicode()
+
+
+Overview of changes leading to 2.7.2
+Saturday, August 29, 2020
+====================================
+- Fix a regression in the previous release that caused a crash with Kaithi.
+- More OOM fixes.
+
+
+Overview of changes leading to 2.7.1
+Thursday, August 13, 2020
+====================================
+- ot-funcs now handles variable empty glyphs better when hvar/vvar isn't present.
+- Reverted a GDEF processing regression.
+- A couple of fixes to handle OOM better.
+
+
+Overview of changes leading to 2.7.0
+Saturday, July 25, 2020
+====================================
+- Use an implementation for round that always rounds up, some minor fluctuations
+  are expected on var font specially when hb-ot callback is used.
+- Fix an AAT's `kerx` issue on broken rendering of Devanagari Sangam MN.
+- Remove AAT's `lcar` table support from _get_ligature_carets API, not even much
+  use on macOS installed fonts (only two files).  GDEF support is the recommended
+  one and expected to work properly after issues fixed two releases ago.
+- Minor memory fixes to handle OOM better specially in hb-ft.
+- Minor .so files versioning scheme change and remove stable/unstable scheme
+  differences, was never used in practice (always default to stable scheme).
+- We are now suggesting careful packaging of the library using meson,
+  https://github.com/harfbuzz/harfbuzz/wiki/Notes-on-migration-to-meson
+  for more information.
+- Distribution package URL is changed, either use GitHub generated tarballs,
+  `https://github.com/harfbuzz/harfbuzz/archive/$pkgver.tar.gz`
+  or, even more preferably use commit hash of the release and git checkouts like,
+  `git+https://github.com/harfbuzz/harfbuzz#commit=$commit`
+
+
+Overview of changes leading to 2.6.8
+Monday, June 22, 2020
+====================================
+- New API to fetch glyph alternates from GSUB table.
+- hb-coretext build fix for macOS < 10.10.
+- Meson build fixes, cmake port removal is postponed but please prepare for
+  it and give us feedback.
+  Autotools is still our main build system however please consider
+  experimenting with meson also for packaging the library.
+- New API:
++hb_ot_layout_lookup_get_glyph_alternates()
+
+
+Overview of changes leading to 2.6.7
+Wednesday, June 3, 2020
+====================================
+- Update to Unicode 13.0.0.
+- Fix hb_ot_layout_get_ligature_carets for fonts without lcar table, it was
+  completely broken for all the other fonts since 2.1.2.
+- As a part of our migration to meson, this release will be the last one
+  to provide cmake port files but autotools still is our main build system.
+  There is a possibility that the next version or the after be released
+  using meson.
+
+
+Overview of changes leading to 2.6.6
+Tuesday, May 12, 2020
+====================================
+- A fix in AAT kerning for Geeza Pro.
+- Better support for resource fork fonts on macOS.
+
+
+Overview of changes leading to 2.6.5
+Friday, April 17, 2020
+====================================
+- Add experimental meson build system.  Autotools is still the primary
+  and supported build system.
+- AAT is now always preferred for horizontal scripts when both AAT and OT
+  layout tables exist at the same time.
+- Subsetter improvements.
+- New API:
++hb_ft_font_lock_face()
++hb_ft_font_unlock_face()
+
+
+Overview of changes leading to 2.6.4
+Monday, October 29, 2019
+====================================
+- Small bug fix.
+- Build fixes.
+
+
+Overview of changes leading to 2.6.3
+Monday, October 28, 2019
+====================================
+- Misc small fixes, mostly to build-related issues.
+- New API:
++hb_font_get_nominal_glyphs()
+
+
+Overview of changes leading to 2.6.2
+Monday, September 30, 2019
+====================================
+- Misc small fixes, mostly to build-related issues.
+
+
+Overview of changes leading to 2.6.1
+Thursday, August 22, 2019
+====================================
+- Fix regression with hb_font_create_sub_font scaling introduced in 2.6.0.
+- Change interpretation of font PTEM size / CoreText font size handling.
+  See https://github.com/harfbuzz/harfbuzz/pull/1484
+- hb-ot-font: Prefer symbol cmap subtable if present.
+- Apply 'dist'/'abvm'/'blwm' features to all scripts.
+- Drop experimental DirectWrite API.
+
+
+Overview of changes leading to 2.6.0
+Tuesday, August 13, 2019
+====================================
+- New OpenType metrics, baseline, and metadata table access APIs.
+- New API to set font variations to a named-instance.
+- New hb-gdi.h header and API for creating hb_face_t from HFONT.
+- Amalgam: Provide a single-file harfbuzz.cc file for easier alternate building.
+- More size-reduction configurable options, enabled by HB_TINY.
+- New API:
++hb_font_set_var_named_instance()
++hb_gdi_face_create()
++hb_ot_layout_baseline_tag_t
++hb_ot_layout_get_baseline()
++hb_ot_meta_tag_t
++hb_ot_meta_get_entry_tags()
++hb_ot_meta_reference_entry()
++hb_ot_metrics_tag_t
++hb_ot_metrics_get_position()
++hb_ot_metrics_get_variation()
++hb_ot_metrics_get_x_variation()
++hb_ot_metrics_get_y_variation()
+
+
+Overview of changes leading to 2.5.3
+Wednesday, June 26, 2019
+====================================
+- Fix UCD script data for Unicode 10+ scripts.  This was broken since 2.5.0.
+- More optimizations for HB_TINY.
+
+
+Overview of changes leading to 2.5.2
+Thursday, June 20, 2019
+====================================
+- More hb-config.hh facilities to shrink library size, namely when built as
+  HB_TINY.
+- New documentation of custom configurations in CONFIG.md.
+- Fix build on gcc 4.8.  That's supported again.
+- Universal Shaping Engine improvements thanks to David Corbett.
+- API Changes: Undeprecate some horizontal-kerning API and re-enable in hb-ft,
+  such that Type1 fonts will continue kerning.
+
+
+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 Database 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
+====================================
+- Unicode 12.
+- Misc fixes.
+- Subsetter improvements.
+- New API:
+HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE
+hb_directwrite_face_create()
+
+
+Overview of changes leading to 2.3.1
+Wednesday, January 30, 2019
+====================================
+- AAT bug fixes.
+- Misc internal housekeeping cleanup.
+
+
+Overview of changes leading to 2.3.0
+Thursday, December 20, 2018
+====================================
+- Fix regression on big-endian architectures.  Ouch!
+- Misc bug and build fixes.
+- Fix subsetting of simple GSUB/GDEF.
+- Merge CFF / CFF2 support contributed by Adobe.  This mostly involves
+  the subsetter, but also get_glyph_extents on CFF fonts.
+
+New API in hb-aat.h:
++hb_aat_layout_has_substitution()
++hb_aat_layout_has_positioning()
++hb_aat_layout_has_tracking()
+
+
+Overview of changes leading to 2.2.0
+Thursday, November 29, 2018
+====================================
+- Misc shaping bug fixes.
+- Add font variations named-instance API.
+- Deprecate font variations axis enumeration API and add replacement.
+- AAT shaping improvements:
+  o Fixed 'kern' table Format 2 implementation.
+  o Implement 'feat' table API for feature detection.
+  o Blacklist 'GSUB' table of fonts from 'MUTF' foundry that also have 'morx'.
+
+New API:
++hb_aat_layout_feature_type_t
++hb_aat_layout_feature_selector_t
++hb_aat_layout_get_feature_types()
++hb_aat_layout_feature_type_get_name_id
++hb_aat_layout_feature_selector_info_t
++HB_AAT_LAYOUT_NO_SELECTOR_INDEX
++hb_aat_layout_feature_type_get_selector_infos()
++hb_ot_var_axis_flags_t
++hb_ot_var_axis_info_t
++hb_ot_var_get_axis_infos()
++hb_ot_var_find_axis_info()
++hb_ot_var_get_named_instance_count()
++hb_ot_var_named_instance_get_subfamily_name_id()
++hb_ot_var_named_instance_get_postscript_name_id()
++hb_ot_var_named_instance_get_design_coords()
+
+Deprecated API:
++HB_OT_VAR_NO_AXIS_INDEX
++hb_ot_var_axis_t
++hb_ot_var_get_axes()
++hb_ot_var_find_axis()
+
+
+Overview of changes leading to 2.1.3
+Friday, November 16, 2018
+====================================
+- Fix AAT 'mort' shaping, which was broken in 2.1.2
+
+
+Overview of changes leading to 2.1.2
+Friday, November 16, 2018
+====================================
+- Various internal changes.
+- AAT shaping improvements:
+  o Implement kern table Format 1 state-machine-based kerning.
+  o Implement cross-stream kerning (cursive positioning, etc).
+  o Ignore emptyish GSUB tables (zero scripts) if morx present.
+  o Don't apply GPOS if morx is being applied.  Matches Apple.
+
+
+-Overview of changes leading to 2.1.1
+Monday, November 5, 2018
+====================================
+- AAT improvements:
+  o Implement 'mort' table.
+  o Implement 'kern' subtables Format 1 and Format 3.
+
+
+Overview of changes leading to 2.1.0
+Tuesday, October 30, 2018
+====================================
+- AAT shaping improvements:
+  o Allow user controlling AAT features, for whole buffer only currently.
+  o Several 'morx' fixes.
+  o Implement tuple-kerns in 'kerx'; Fixes kerning with Apple default
+    San Francisco fonts.
+- Support for color fonts:
+  o COLR/CPAL API to fetch color layers.
+  o SVG table to fetch SVG documents.
+  o CBDT/sbix API to fetch PNG images.
+- New 'name' table API.
+- hb-ot-font now uses 'VORG' table to correctly position CFF glyphs
+  in vertical layout.
+- Various fuzzer-found bug fixes.
+
+Changed API:
+
+A type and a macro added in 2.0.0 were renamed:
+
+hb_name_id_t -> hb_ot_name_id_t
+HB_NAME_ID_INVALID -> HB_OT_NAME_ID_INVALID
+
+New API:
+
++hb_color_t
++HB_COLOR
++hb_color_get_alpha()
++hb_color_get_red()
++hb_color_get_green()
++hb_color_get_blue()
++hb_ot_color_has_palettes()
++hb_ot_color_palette_get_count()
++hb_ot_color_palette_get_name_id()
++hb_ot_color_palette_color_get_name_id()
++hb_ot_color_palette_flags_t
++hb_ot_color_palette_get_flags()
++hb_ot_color_palette_get_colors()
++hb_ot_color_has_layers()
++hb_ot_color_layer_t
++hb_ot_color_glyph_get_layers()
++hb_ot_color_has_svg()
++hb_ot_color_glyph_reference_svg()
++hb_ot_color_has_png()
++hb_ot_color_glyph_reference_png()
+
++hb_ot_name_id_t
++HB_OT_NAME_ID_INVALID
++HB_OT_NAME_ID_COPYRIGHT
++HB_OT_NAME_ID_FONT_FAMILY
++HB_OT_NAME_ID_FONT_SUBFAMILY
++HB_OT_NAME_ID_UNIQUE_ID
++HB_OT_NAME_ID_FULL_NAME
++HB_OT_NAME_ID_VERSION_STRING
++HB_OT_NAME_ID_POSTSCRIPT_NAME
++HB_OT_NAME_ID_TRADEMARK
++HB_OT_NAME_ID_MANUFACTURER
++HB_OT_NAME_ID_DESIGNER
++HB_OT_NAME_ID_DESCRIPTION
++HB_OT_NAME_ID_VENDOR_URL
++HB_OT_NAME_ID_DESIGNER_URL
++HB_OT_NAME_ID_LICENSE
++HB_OT_NAME_ID_LICENSE_URL
++HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY
++HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY
++HB_OT_NAME_ID_MAC_FULL_NAME
++HB_OT_NAME_ID_SAMPLE_TEXT
++HB_OT_NAME_ID_CID_FINDFONT_NAME
++HB_OT_NAME_ID_WWS_FAMILY
++HB_OT_NAME_ID_WWS_SUBFAMILY
++HB_OT_NAME_ID_LIGHT_BACKGROUND
++HB_OT_NAME_ID_DARK_BACKGROUND
++HB_OT_NAME_ID_VARIATIONS_PS_PREFIX
++hb_ot_name_entry_t
++hb_ot_name_list_names()
++hb_ot_name_get_utf8()
++hb_ot_name_get_utf16()
++hb_ot_name_get_utf32()
+
+
+Overview of changes leading to 2.0.2
+Saturday, October 20, 2018
+====================================
+- Fix two minor memory access issues in AAT tables.
+
+
+Overview of changes leading to 2.0.1
+Friday, October 19, 2018
+====================================
+- Fix hb-version.h reported release version that went wrong (1.8.0)
+  with previous release.
+- Fix extrapolation in 'trak' table.
+- Fix hb-font infinite-recursion issue with some font funcs and
+  subclassed fonts.
+- Implement variation-kerning format in kerx table, although without
+  variation.
+- Fix return value of hb_map_is_empty().
+
+
+Overview of changes leading to 2.0.0
+Thursday, October 18, 2018
+====================================
+- Added AAT shaping support (morx/kerx/trak).
+  Automatically used if GSUB/GPOS are not available respectively.
+  Set HB_OPTIONS=aat env var to have morx/kerx preferred over
+  GSUB/GPOS.
+- Apply TrueType kern table internally, instead of relying on
+  hb_font_t callbacks.
+- Khmer shaper significantly rewritten to better match Uniscribe.
+- Indic3 tags ('dev3', etc) are passed to USE shaper.
+- .dfont Mac font containers implemented.
+- Script- and language-mapping revamped to better use BCP 47.
+- Misc USE and Indic fixes.
+- Misc everything fixes.
+- Too many things to list.  Biggest release since 0.9.1, with
+  over 500 commits in just over 5 weeks!  Didn't intend it to
+  be a big release.  Just happened to become.
+- hb-ft now locks underlying FT_Face during use.
+
+API changes:
+
+- Newly-created hb_font_t's now have our internal "hb-ot-font"
+  callbacks set on them, so they should work out of the box
+  without any callbacks set.  If callbacks are set, everything
+  is back to what it was before, the fallback callbacks are
+  null.  If you to get the internal implementation modified,
+  sub_font it.
+
+- New hb_font_funcs_set_nominal_glyphs_func() allows speeding
+  up character to glyph mapping.
+
+New API:
++HB_FEATURE_GLOBAL_START
++HB_FEATURE_GLOBAL_END
++hb_buffer_set_invisible_glyph()
++hb_buffer_get_invisible_glyph()
++hb_font_funcs_set_nominal_glyphs_func()
++hb_ot_layout_table_select_script()
++hb_ot_layout_script_select_language()
++hb_ot_layout_feature_get_name_ids()
++hb_ot_layout_feature_get_characters()
++hb_name_id_t
++HB_NAME_ID_INVALID
++HB_OT_MAX_TAGS_PER_SCRIPT
++hb_ot_tags_from_script_and_language()
++hb_ot_tags_to_script_and_language()
+
+Deprecated API:
+-hb_font_funcs_set_glyph_func()
+-hb_unicode_eastasian_width_func_t
+-hb_unicode_funcs_set_eastasian_width_func()
+-hb_unicode_eastasian_width()
+-hb_unicode_decompose_compatibility_func_t
+-HB_UNICODE_MAX_DECOMPOSITION_LEN
+-hb_unicode_funcs_set_decompose_compatibility_func()
+-hb_unicode_decompose_compatibility()
+-hb_font_funcs_set_glyph_h_kerning_func()
+-hb_font_funcs_set_glyph_v_kerning_func()
+-hb_font_get_glyph_h_kerning()
+-hb_font_get_glyph_v_kerning()
+-hb_font_get_glyph_kerning_for_direction()
+-hb_ot_layout_table_choose_script()
+-hb_ot_layout_script_find_language()
+-hb_ot_tags_from_script()
+-hb_ot_tag_from_language()
+
+
+Overview of changes leading to 1.9.0
+Monday, September 10, 2018
+====================================
+- Added 'cmap' API to hb_face_t.
+- Face-builder API.
+- hb-ot-font re-creation should be much leaner now, as the
+  font tables it uses are cached on hb_face_t now.
+- Internal source header file name changes:
+  hb-*-private.hh is renamed to hb-*.hh.
+
+New API:
++HB_UNICODE_MAX
++hb_face_collect_unicodes()
++hb_face_collect_variation_selectors()
++hb_face_collect_variation_unicodes()
++hb_face_builder_create()
++hb_face_builder_add_table()
+
+
+Overview of changes leading to 1.8.8
+Tuesday, August 14, 2018
+====================================
+- Fix hb-icu crash on architectures where compare_exchange_weak() can
+  fail falsely.  This bug was introduced in 1.8.4.
+  https://bugs.chromium.org/p/chromium/issues/detail?id=873568
+- More internal refactoring of atomic operations and singletons.
+- API changes:
+  The following functions do NOT reference their return value before
+  returning:
+  * hb_unicode_funcs_get_default()
+  * hb_glib_get_unicode_funcs()
+  * hb_icu_get_unicode_funcs()
+  This is consistent with their naming ("get", instead of "reference")
+  as well as how they are used in the wild (ie. no one calls destroy()
+  on their return value.)
+
+
+Overview of changes leading to 1.8.7
+Wednesday, August 8, 2018
+====================================
+- Fix assertion failure with GDEF-blacklisted fonts.
+
+
+Overview of changes leading to 1.8.6
+Tuesday, August 7, 2018
+====================================
+- Internal code shuffling.
+- New API to speed up getting advance widths for implementations
+  that have heavy overhead in get_h_advance callback:
++hb_font_funcs_set_glyph_h_advances_func
++hb_font_funcs_set_glyph_v_advances_func
++hb_font_get_glyph_advances_for_direction
++hb_font_get_glyph_h_advances
++hb_font_get_glyph_h_advances_func_t
++hb_font_get_glyph_v_advances
++hb_font_get_glyph_v_advances_func_t
+
+
+Overview of changes leading to 1.8.5
+Wednesday, August 1, 2018
+====================================
+- Major Khmer shaper improvements to better match Microsoft.
+- Indic bug fixes.
+- Internal improvements to atomic operations.
+
+
+Overview of changes leading to 1.8.4
+Tuesday, July 17, 2018
+====================================
+- Fix build on non-C++11.
+- Use C++-style GCC atomics and C++11 atomics.
+
+
+Overview of changes leading to 1.8.3
+Wednesday, July 11, 2018
+====================================
+- A couple of Indic / USE bug fixes.
+- Disable vectorization, as it was causing unaligned access bus error on
+  certain 32bit architectures.
+
+
+Overview of changes leading to 1.8.2
+Tuesday, July 3, 2018
+====================================
+- Fix infinite loop in Khmer shaper.
+- Improve hb_blob_create_from_file() for streams.
+
+
+Overview of changes leading to 1.8.1
+Tuesday, June 12, 2018
+====================================
+- Fix hb-version.h file generation; last two releases went out with wrong ones.
+- Add correctness bug in hb_set_t operations, introduced in 1.7.7.
+- Remove HB_SUBSET_BUILTIN build option.  Not necessary.
+
+
+Overview of changes leading to 1.8.0
+Tuesday, June 5, 2018
+====================================
+- Update to Unicode 11.0.0.
+
+
+Overview of changes leading to 1.7.7
+Tuesday, June 5, 2018
+====================================
+- Lots of internal changes, but not yet exposed externally.
+- All HarfBuzz objects are significantly smaller in size now.
+- Sinhala: Position repha on top of post-consonant, not base.
+  This better matches Windows 10 behavior, which was changed
+  from previous Windows versions.
+- New build options:
+  o New cpp macro HB_NO_ATEXIT
+  o New cpp macro HB_SUBSET_BUILTIN
+- Significant libharfbuzz-subset changes. API subject to change.
+- New API in libharfbuzz:
+
++hb_blob_create_from_file()
++hb_face_count()
+
+A hashmap implementation:
++hb-map.h
++HB_MAP_VALUE_INVALID
++hb_map_t
++hb_map_create()
++hb_map_get_empty()
++hb_map_reference()
++hb_map_destroy()
++hb_map_set_user_data()
++hb_map_get_user_data()
++hb_map_allocation_successful()
++hb_map_clear()
++hb_map_is_empty()
++hb_map_get_population()
++hb_map_set()
++hb_map_get()
++hb_map_del()
++hb_map_has()
+
+
+Overview of changes leading to 1.7.6
+Wednesday, March 7, 2018
+====================================
+
+- Fix to hb_set_t binary operations. Ouch.
+- New experimental harfbuzz-subset library. All of hb-subset.h
+  is experimental right now and API WILL change.
+
+- New API:
+hb_blob_copy_writable_or_fail()
+HB_OT_TAG_BASE
+hb_set_previous()
+hb_set_previous_range()
+
+
+Overview of changes leading to 1.7.5
+Tuesday, January 30, 2018
+====================================
+
+- Separate Khmer shaper from Indic.
+- First stab at AAT morx. Not hooked up.
+- Misc bug fixes.
+
+
+Overview of changes leading to 1.7.4
+Wednesday, December 20, 2017
+====================================
+
+- Fix collect_glyphs() regression caused by hb_set_t changes.
+
+
+Overview of changes leading to 1.7.3
+Monday, December 18, 2017
+====================================
+
+- hb_set_t performance tuning and optimizations.
+- Speed up collect_glyphs() and reject garbage data.
+- In hb_coretext_font_create() set font point-size (ptem).
+- Misc fixes.
+
+
+Overview of changes leading to 1.7.2
+Monday, December 4, 2017
+====================================
+
+- Optimize hb_set_add_range().
+- Misc fixes.
+- New API:
+hb_coretext_font_create()
+
+
+Overview of changes leading to 1.7.1
+Tuesday, November 14, 2017
+====================================
+
+- Fix atexit object destruction regression.
+- Fix minor integer-overflow.
+
+
+Overview of changes leading to 1.7.0
+Monday, November 13, 2017
+====================================
+
+- Minor Indic fixes.
+- Implement kerning and glyph names in hb-ot-font.
+- Various DSO optimization re .data and .bss sizes.
+- Make C++11 optional; build fixes.
+- Mark all other backends "unsafe-to-break".
+- Graphite fix.
+
+
+Overview of changes leading to 1.6.3
+Thursday, October 26th, 2017
+====================================
+
+- Fix hb_set_t some more.  Should be solid now.
+- Implement get_glyph_name() for hb-ot-font.
+- Misc fixes.
+
+
+Overview of changes leading to 1.6.2
+Monday, October 23nd, 2017
+====================================
+
+- Yesterday's release had a bad crasher; don't use it.  That's what
+  happens when one works on Sunday...
+  https://github.com/harfbuzz/harfbuzz/issues/578
+- Build fixes for FreeBSD and Chrome Android.
+
+
+Overview of changes leading to 1.6.1
+Sunday, October 22nd, 2017
+====================================
+
+- Don't skip over COMBINING GRAPHEME JOINER when ligating, etc.
+  To be refined: https://github.com/harfbuzz/harfbuzz/issues/554
+- Faster hb_set_t implementation.
+- Don't use deprecated ICU API.
+- Fix undefined-behavior in Myanmar shaper, introduced in 1.6.0
+- Deprecated API:
+  hb_set_invert()
+
+
+Overview of changes leading to 1.6.0
+Friday, October the 13th, 2017
+====================================
+
+- Update to Unicode 10.
+
+- Various Indic and Universal Shaping Engine fixes as a result of
+  HarfBuzz Hackfest with Jonathan Kew at Web Engines Hackfest at
+  the Igalia offices in A Coruña, Spain.  Thanks Igalia for having
+  us!
+
+- Implement Unicode Arabic Mark Ordering Algorithm UTR#53.
+
+- Implement optical sizing / tracking in CoreText backend, using
+  new API hb_font_set_ptem().
+
+- Allow notifying hb_font_t that underlying FT_Face changed sizing,
+  using new API hb_ft_font_changed().
+
+- More Graphite backend RTL fixes.
+
+- Fix caching of variable font shaping plans.
+
+- hb-view / hb-shape now accept following new arguments:
+
+  o --unicodes: takes a list of hex numbers that represent Unicode
+    codepoints.
+
+New API:
++hb_face_get_table_tags()
++hb_font_set_ptem()
++hb_font_get_ptem()
++hb_ft_font_changed()
+
+
+Overview of changes leading to 1.5.1
+Tuesday, September 5, 2017
+====================================
+
+- Fix "unsafe-to-break" in fallback shaping and other corner cases.
+  All our tests pass with --verify now, meaning unsafe-to-break API
+  works as expected.
+- Add --unicodes to hb-view / hb-shape.
+- [indic] Treat Consonant_With_Stacker as consonant.  This will need
+  further tweaking.
+- hb_buffer_diff() tweaks.
+
+
+Overview of changes leading to 1.5.0
+Wednesday, August 23, 2017
+====================================
+
+- Misc new API, for appending a buffer to another, and for comparing
+  contents of two buffers for types of differences.
+
+- New "unsafe-to-break" API.  Can be used to speed up reshaping
+  in line-breaking situations.  Essentially, after shaping, it returns
+  positions in the input string (some of the cluster boundaries) that
+  are "safe to break" in that if the text is segmented at that position
+  and two sides reshaped and concatenated, the shaping result is
+  exactly the same as shaping the text in one piece.
+
+  hb-view and hb-shape and hb-shape now take --verify, which verifies
+  the above property.
+
+  Some corner cases of the implementation are still not quite working.
+  Those will be fixed in subsequent releases.
+
+- New API:
+
+hb_buffer_append()
+
+hb_glyph_flags_t
+HB_GLYPH_FLAG_UNSAFE_TO_BREAK
+HB_GLYPH_FLAG_DEFINED
+hb_glyph_info_get_glyph_flags()
+
+HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS
+
+hb_buffer_diff_flags_t
+HB_BUFFER_DIFF_FLAG_EQUAL
+HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH
+HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH
+HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT
+HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
+HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH
+HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH
+HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH
+HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH
+hb_buffer_diff
+
+
+Overview of changes leading to 1.4.8
+Tuesday, August 8, 2017
+====================================
+
+- Major fix to avar table handling.
+- Rename hb-shape --show-message to --trace.
+- Build fixes.
+
+
+Overview of changes leading to 1.4.7
+Tuesday, July 18, 2017
+====================================
+
+- Multiple Indic, Tibetan, and Cham fixes.
+- CoreText: Allow disabling kerning.
+- Adjust Arabic feature order again.
+- Misc build fixes.
+
+
+Overview of changes leading to 1.4.6
+Sunday, April 23, 2017
+====================================
+
+- Graphite2: Fix RTL positioning issue.
+- Backlist GDEF of more versions of Padauk and Tahoma.
+- New, experimental, cmake alternative build system.
+
+
+Overview of changes leading to 1.4.5
+Friday, March 10, 2017
+====================================
+
+- Revert "Fix Context lookup application when moving back after a glyph..."
+  This introduced memory access problems.  To be fixed properly soon.
+
+
+Overview of changes leading to 1.4.4
+Sunday, March 5, 2017
+====================================
+
+- Fix Context lookup application when moving back after a glyph deletion.
+- Fix buffer-overrun in Bengali.
+
+
+Overview of changes leading to 1.4.3
+Saturday, February 25, 2017
+====================================
+
+- Route Adlam script to Arabic shaper.
+- Misc fixes.
+- New API:
+  hb_font_set_face()
+- Deprecate API:
+  hb_graphite2_font_get_gr_font()
+
+
+Overview of changes leading to 1.4.2
+Monday, January 23, 2017
+====================================
+
+- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR.
+- hb-shape and hb-view now accept --variations.
+- New API:
+
+hb_variation_t
+hb_variation_from_string()
+hb_variation_to_string()
+
+hb_font_set_variations()
+hb_font_set_var_coords_design()
+hb_font_get_var_coords_normalized()
+
+hb-ot-var.h:
+hb_ot_var_axis_t
+hb_ot_var_has_data()
+hb_ot_var_get_axis_count()
+hb_ot_var_get_axes()
+hb_ot_var_find_axis()
+hb_ot_var_normalize_variations()
+hb_ot_var_normalize_coords()
+
+- MVAR to be implemented later.  Access to named instances to be
+  implemented later as well.
+
+- Misc fixes.
+
+
+Overview of changes leading to 1.4.1
+Thursday, January 5, 2017
+====================================
+
+- Always build and use UCDN for Unicode data by default.
+  Reduces dependence on version of Unicode data in glib,
+  specially in the Windows bundles we are shipping, which
+  have very old glib.
+
+
+Overview of changes leading to 1.4.0
+Thursday, January 5, 2017
+====================================
+
+- Merged "OpenType GX" branch which adds core of support for
+  OpenType 1.8 Font Variations.  To that extent, the relevant
+  new API is:
+
+New API:
+hb_font_set_var_coords_normalized()
+
+  with supporting API:
+
+New API:
+HB_OT_LAYOUT_NO_VARIATIONS_INDEX
+hb_ot_layout_table_find_feature_variations()
+hb_ot_layout_feature_with_variations_get_lookups()
+hb_shape_plan_create2()
+hb_shape_plan_create_cached2()
+
+  Currently variations in GSUB/GPOS/GDEF are fully supported,
+  and no other tables are supported.  In particular, fvar/avar
+  are NOT supported, hence the hb_font_set_var_coords_normalized()
+  taking normalized coordinates.  API to take design coordinates
+  will be added in the future.
+
+  HVAR/VVAR/MVAR support will also be added to hb-ot-font in the
+  future.
+
+- Fix regression in GDEF glyph class processing.
+- Add decompositions for Chakma, Limbu, and Balinese in USE shaper.
+- Misc fixes.
+
+
+Overview of changes leading to 1.3.4
+Monday, December 5, 2016
+====================================
+
+- Fix vertical glyph origin in hb-ot-font.
+- Implement CBDT/CBLC color font glyph extents in hb-ot-font.
+
+
+Overview of changes leading to 1.3.3
+Wednesday, September 28, 2016
+====================================
+
+- Implement parsing of OpenType MATH table.
+New API:
+HB_OT_TAG_MATH
+HB_OT_MATH_SCRIPT
+hb_ot_math_constant_t
+hb_ot_math_kern_t
+hb_ot_math_glyph_variant_t
+hb_ot_math_glyph_part_flags_t
+hb_ot_math_glyph_part_t
+hb_ot_math_has_data
+hb_ot_math_get_constant
+hb_ot_math_get_glyph_italics_correction
+hb_ot_math_get_glyph_top_accent_attachment
+hb_ot_math_get_glyph_kerning
+hb_ot_math_is_glyph_extended_shape
+hb_ot_math_get_glyph_variants
+hb_ot_math_get_min_connector_overlap
+hb_ot_math_get_glyph_assembly
+
+
+Overview of changes leading to 1.3.2
+Wednesday, September 27, 2016
+====================================
+
+- Fix build of hb-coretext on older OS X versions.
+
+
+Overview of changes leading to 1.3.1
+Wednesday, September 7, 2016
+====================================
+
+- Blacklist bad GDEF of more fonts (Padauk).
+- More CoreText backend crash fixes with OS X 10.9.5.
+- Misc fixes.
+
+
+Overview of changes leading to 1.3.0
+Thursday, July 21, 2016
+====================================
+
+- Update to Unicode 9.0.0
+- Move Javanese from Indic shaper to Universal Shaping Engine.
+- Allow MultipleSubst to delete a glyph (matching Windows engine).
+- Update Universal Shaping Engine to latest draft from Microsoft.
+- DirectWrite backend improvements.  Note: this backend is for testing ONLY.
+- CoreText backend improvements with unreachable fonts.
+- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font.
+- Blacklist bad GDEF of more fonts (Tahoma & others).
+- Misc fixes.
+
+
+Overview of changes leading to 1.2.7
+Monday, May 2, 2016
+====================================
+
+- Blacklist another version of Times New Roman (Bold) Italic from Windows 7.
+- Fix Mongolian Free Variation Selectors shaping with certain fonts.
+- Fix Tibetan shorthand contractions shaping.
+- Improved list of language tag mappings.
+- Unbreak build on Windows CE.
+- Make 'glyf' table loading lazy in hb-ot-font.
+
+
+Overview of changes leading to 1.2.6
+Friday, April 8, 2016
+====================================
+
+- Blacklist GDEF table of another set of Times New Roman (Bold) Italic.
+- DirectWrite backend improvements.  Note: DirectWrite backend is
+  exclusively for our internal testing and should NOT be used in any
+  production system whatsoever.
+
+
+Overview of changes leading to 1.2.5
+Monday, April 4, 2016
+====================================
+
+- Fix GDEF mark-filtering-set, which was broken in 1.2.3.
+
+
+Overview of changes leading to 1.2.4
+Thursday, March 17, 2016
+====================================
+
+- Synthesize GDEF glyph class for any glyph that does not have one in GDEF.
+  I really hope we don't discover broken fonts that shape badly with this
+  change.
+- Misc build and other minor fixes.
+- API changes:
+  - Added HB_NDEBUG.  It's fine for production systems to define this to
+    disable high-overhead debugging checks.  However, I also reduced the
+    overhead of those checks, so it's a non-issue right now.  You can
+    forget it.  Just not defining anything at all is fine.
+
+
+Overview of changes leading to 1.2.3
+Thursday, February 25, 2016
+====================================
+
+- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic,
+  due to bug in glyph class of ASCII double-quote character.  This should
+  address "regression" introduced in 1.2.0 when we switched mark zeroing
+  in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
+  This fourth release in a week should finally stabilize things...
+
+- hb-ot-font's get_glyph() implementation saw some optimizations.  Though,
+  might be really hard to measure in real-world situations.
+
+- Also, two rather small API changes:
+
+We now disable some time-consuming internal bookkeeping if built with NDEBUG
+defined.  This is a first time that we use NDEBUG to disable debug code.  If
+there exist production systems that do NOT want to enable NDEBUG, please let
+me know and I'll add HB_NDEBUG.
+
+Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph()
+
+New API:
+- hb_font_get_nominal_glyph_func_t
+- hb_font_get_variation_glyph_func_t
+- hb_font_funcs_set_nominal_glyph_func()
+- hb_font_funcs_set_variation_glyph_func()
+- hb_font_get_nominal_glyph()
+- hb_font_get_variation_glyph()
+
+Deprecated API:
+- hb_font_get_glyph_func_t
+- hb_font_funcs_set_glyph_func()
+
+Clients that implement their own font-funcs are encouraged to replace
+their get_glyph() implementation with a get_nominal_glyph() and
+get_variation_glyph() pair.  The variation version can assume that
+variation_selector argument is not zero.  Old (deprecated) functions
+will continue working indefinitely using internal gymnastics; it is
+just more efficient to use the new functions.
+
+
+Overview of changes leading to 1.2.2
+Wednesday, February 24, 2016
+====================================
+
+- Fix regression with mark positioning with fonts that have
+  non-zero mark advances.  This was introduced in 1.2.0 while
+  trying to make mark and cursive attachments to work together.
+  I have partially reverted that, so this version is much more
+  like what we had before.  All clients who updated to 1.2.0
+  should update to this version.
+
+
+Overview of changes leading to 1.2.1
+Tuesday, February 23, 2016
+====================================
+
+- CoreText: Fix bug with wrong scale if font scale was changed later.
+  https://github.com/libass/libass/issues/212
+- CoreText: Drastically speed up font initialization.
+- CoreText: Fix tiny leak.
+- Group ZWJ/ZWNJ with previous syllable under cluster-level=0.
+  https://github.com/harfbuzz/harfbuzz/issues/217
+- Add test/shaping/README.md about how to add tests to the suite.
+
+
+Overview of changes leading to 1.2.0
+Friday, February 19, 2016
+====================================
+
+- Fix various issues (hangs mostly) in case of memory allocation failure.
+- Change mark zeroing types of most shapers from BY_UNICODE_LATE to
+  BY_GDEF_LATE.  This seems to be what Uniscribe does.
+- Change mark zeroing of USE shaper from NONE to BY_GDEF_EARLY.  That's
+  what Windows does.
+- Allow GPOS cursive connection on marks, and fix the interaction with
+  mark attachment.  This work resulted in some changes to how mark
+  attachments work.  See:
+  https://github.com/harfbuzz/harfbuzz/issues/211
+  https://github.com/harfbuzz/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
+- Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
+- Add nmake-based build system for Windows.
+- Minor speedup.
+- Misc. improvements.
+
+
+Overview of changes leading to 1.1.3
+Monday, January 11, 2016
+====================================
+
+- Ported Indic shaper to Unicode 8.0 data.
+- Universal Shaping Engine fixes.
+- Speed up CoreText shaper when font fallback happens in CoreText.
+- Documentation improvements, thanks to Khaled Hosny.
+- Very rough directwrite shaper for testing, thanks to Ebrahim Byagowi.
+- Misc bug fixes.
+- New API:
+
+  * Font extents:
+      hb_font_extents_t
+      hb_font_get_font_extents_func_t
+      hb_font_get_font_h_extents_func_t
+      hb_font_get_font_v_extents_func_t
+      hb_font_funcs_set_font_h_extents_func
+      hb_font_funcs_set_font_v_extents_func
+      hb_font_get_h_extents
+      hb_font_get_v_extents
+      hb_font_get_extents_for_direction
+
+  * Buffer message (aka debug):
+      hb_buffer_message_func_t
+      hb_buffer_set_message_func()
+    Actual message protocol to be fleshed out later.
+
+
+Overview of changes leading to 1.1.2
+Wednesday, November 26, 2015
+====================================
+
+- Fix badly-broken fallback shaper that affected terminology.
+  https://github.com/harfbuzz/harfbuzz/issues/187
+- Fix y_scaling in Graphite shaper.
+- API changes:
+  * An unset glyph_h_origin() function in font-funcs now (sensibly)
+    implies horizontal origin at 0,0.  Ie, the nil callback returns
+    true instead of false.  As such, implementations that have a
+    glyph_h_origin() that simply returns true, can remove that function
+    with HarfBuzz >= 1.1.2.  This results in a tiny speedup.
+
+
+Overview of changes leading to 1.1.1
+Wednesday, November 24, 2015
+====================================
+
+- Build fixes, specially for hb-coretext.
+
+
+Overview of changes leading to 1.1.0
+Wednesday, November 18, 2015
+====================================
+
+- Implement 'stch' stretch feature for Syriac Abbreviation Mark.
+  https://github.com/harfbuzz/harfbuzz/issues/141
+- Disable use of decompose_compatibility() callback.
+- Implement "shaping" of various Unicode space characters, even
+  if the font does not support them.
+  https://github.com/harfbuzz/harfbuzz/issues/153
+- If font does not support U+2011 NO-BREAK HYPHEN, fallback to
+  U+2010 HYPHEN.
+- Changes resulting from libFuzzer continuous fuzzing:
+  * Reject font tables that need more than 8 edits,
+  * Bound buffer growth during shaping to 32x,
+  * Fix assertions and other issues at OOM / buffer max-growth.
+- Misc fixes and optimizations.
+- API changes:
+  * All fonts created with hb_font_create() now inherit from
+    (ie. have parent) hb_font_get_empty().
+
+
+Overview of changes leading to 1.0.6
+Thursday, October 15, 2015
+====================================
+
+- Reduce max nesting level in OT lookups from 8 to 6.
+  Should not affect any real font as far as I know.
+- Fix memory access issue in ot-font.
+- Revert default load-flags of fonts created using hb_ft_font_create()
+  back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING.  This was changed in
+  last release (1.0.5), but caused major issues, so revert.
+  https://github.com/harfbuzz/harfbuzz/issues/143
+
+
+Overview of changes leading to 1.0.5
+Tuesday, October 13, 2015
+====================================
+
+- Fix multiple memory access bugs discovered using libFuzzer.
+  https://github.com/harfbuzz/harfbuzz/issues/139
+  Everyone should upgrade to this version as soon as possible.
+  We now have continuous fuzzing set up, to avoid issues like
+  these creeping in again.
+- Misc fixes.
+
+- New API:
+  * hb_font_set_parent().
+  * hb_ft_font_[sg]et_load_flags()
+    The default flags for fonts created using hb_ft_font_create()
+    has changed to default to FT_LOAD_DEFAULT now.  Previously it
+    was defaulting to FT_LOAD_DFEAULT|FT_LOAD_NO_HINTING.
+
+- API changes:
+  * Fonts now default to units-per-EM as their scale, instead of 0.
+  * hb_font_create_sub_font() does NOT make parent font immutable
+    anymore.  hb_font_make_immutable() does.
+
+
+Overview of changes leading to 1.0.4
+Wednesday, September 30, 2015
+====================================
+
+- Fix minor out-of-bounds read error.
+
+
+Overview of changes leading to 1.0.3
+Tuesday, September 1, 2015
+====================================
+
+- Start of user documentation, from Simon Cozens!
+- Implement glyph_extents() for TrueType fonts in hb-ot-font.
+- Improve GPOS cursive attachments with conflicting lookups.
+- More fixes for cluster-level = 1.
+- Uniscribe positioning fix.
+
+
+Overview of changes leading to 1.0.2
+Wednesday, August 19, 2015
+====================================
+
+- Fix shaping with cluster-level > 0.
+- Fix Uniscribe backend font-size scaling.
+- Declare dependencies in harfbuzz.pc.
+  FreeType is not declared though, to avoid bugs in pkg-config
+  0.26 with recursive dependencies.
+- Slightly improved debug infrastructure.  More to come later.
+- Misc build fixes.
+
+
+Overview of changes leading to 1.0.1
+Monday, July 27, 2015
+====================================
+
+- Fix out-of-bounds access in USE shaper.
+
+
+Overview of changes leading to 1.0.0
+Sunday, July 26, 2015
+====================================
+
+- Implement Universal Shaping Engine:
+  https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
+  http://blogs.windows.com/bloggingwindows/2015/02/23/windows-shapes-the-worlds-languages/
+- Bump version to 1.0.0.  The soname was NOT bumped.
+
+
+Overview of changes leading to 0.9.42
+Thursday, July 26, 2015
+=====================================
+
+- New API to allow for retrieving finer-grained cluster
+  mappings if the client desires to handle them.  Default
+  behavior is unchanged.
+- Fix cluster merging when removing default-ignorables.
+- Update to Unicode 8.0
+- hb-graphite2 fixes.
+- Misc fixes.
+- Removed HB_NO_MERGE_CLUSTERS hack.
+- New API:
+  hb_buffer_cluster_level_t enum
+  hb_buffer_get_cluster_level()
+  hb_buffer_set_cluster_level()
+  hb-shape / hb-view --cluster-level
+
+
+Overview of changes leading to 0.9.41
+Thursday, June 18, 2015
+=====================================
+
+- Fix hb-coretext with trailing whitespace in right-to-left.
+- New API: hb_buffer_reverse_range().
+- Allow implementing atomic ops in config.h.
+- Fix hb_language_t in language bindings.
+- Misc fixes.
+
+
+Overview of changes leading to 0.9.40
+Friday, March 20, 2015
+=====================================
+
+- Another hb-coretext crasher fix.  Ouch!
+- Happy Norouz!
+
+
+Overview of changes leading to 0.9.39
+Wednesday, March 4, 2015
+=====================================
+
+- Critical hb-coretext fixes.
+- Optimizations and refactoring; no functional change
+  expected.
+- Misc build fixes.
+
+
+Overview of changes leading to 0.9.38
+Friday, January 23, 2015
+=====================================
+
+- Fix minor out-of-bounds access in Indic shaper.
+- Change New Tai Lue shaping engine from South-East Asian to default,
+  reflecting change in Unicode encoding model.
+- Add hb-shape --font-size.  Can take up to two numbers for separate
+  x / y size.
+- Fix CoreText and FreeType scale issues with negative scales.
+- Reject blobs larger than 2GB.  This might break some icu-le-hb clients
+  that need security fixes.  See:
+  http://www.icu-project.org/trac/ticket/11450
+- Avoid accessing font tables during face destruction, in casce rogue
+  clients released face data already.
+- Fix up gobject-introspection a bit.  Python bindings kinda working.
+  See README.python.
+- Misc fixes.
+- API additions:
+  hb_ft_face_create_referenced()
+  hb_ft_font_create_referenced()
+
+
+Overview of changes leading to 0.9.37
+Wednesday, December 17, 2014
+=====================================
+
+- Fix out-of-bounds access in Context lookup format 3.
+- Indic: Allow ZWJ/ZWNJ before syllable modifiers.
+
+
+Overview of changes leading to 0.9.36
+Thursday, November 20, 2014
+=====================================
+
+- First time that three months went by without a release since
+  0.9.2 was released on August 10, 2012!
+- Fix performance bug in hb_ot_collect_glyphs():
+  https://bugzilla.mozilla.org/show_bug.cgi?id=1090869
+- Add basic vertical-text support to hb-ot-font.
+- Misc build fixes.
+
+
+Overview of changes leading to 0.9.35
+Saturday, August 13, 2014
+=====================================
+
+- Fix major shape-plan caching bug when more than one shaper were
+  provided to hb_shape_full() (as exercised by XeTeX).
+  http://www.mail-archive.com/[email protected]/msg1246370.html
+- Fix Arabic fallback shaping regression.  This was broken in 0.9.32.
+- Major hb-coretext fixes.  That backend is complete now, including
+  respecing buffer direction and language, down to vertical writing.
+- Build fixes for Windows CE.  Should build fine now.
+- Misc fixes:
+  Use atexit() only if it's safe to call from shared library
+  https://bugs.freedesktop.org/show_bug.cgi?id=82246
+  Mandaic had errors in its Unicode Joining_Type
+  https://bugs.freedesktop.org/show_bug.cgi?id=82306
+- API changes:
+
+  * hb_buffer_clear_contents() does not reset buffer flags now.
+
+    After 763e5466c0a03a7c27020e1e2598e488612529a7, one doesn't
+    need to set flags for different pieces of text.  The flags now
+    are something the client sets up once, depending on how it
+    actually uses the buffer.  As such, don't clear it in
+    clear_contents().
+
+    I don't expect any changes to be needed to any existing client.
+
+
+Overview of changes leading to 0.9.34
+Saturday, August 2, 2014
+=====================================
+
+- hb_feature_from_string() now accepts CSS font-feature-settings format.
+- As a result, hb-shape / hb-view --features also accept CSS-style strings.
+  Eg, "'liga' off" is accepted now.
+- Add old-spec Myanmar shaper:
+  https://bugs.freedesktop.org/show_bug.cgi?id=81775
+- Don't apply 'calt' in Hangul shaper.
+- Fix mark advance zeroing for Hebrew shaper:
+  https://bugs.freedesktop.org/show_bug.cgi?id=76767
+- Implement Windows-1256 custom Arabic shaping.  Only built on Windows,
+  and requires help from get_glyph().  Used by Firefox.
+  https://bugzilla.mozilla.org/show_bug.cgi?id=1045139
+- Disable 'liga' in vertical text.
+- Build fixes.
+- API changes:
+
+  * Make HB_BUFFER_FLAG_BOT/EOT easier to use.
+
+    Previously, we expected users to provide BOT/EOT flags when the
+    text *segment* was at paragraph boundaries.  This meant that for
+    clients that provide full paragraph to HarfBuzz (eg. Pango), they
+    had code like this:
+
+      hb_buffer_set_flags (hb_buffer,
+                           (item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) |
+                           (item_offset + item_length == paragraph_length ?
+                            HB_BUFFER_FLAG_EOT : 0));
+
+      hb_buffer_add_utf8 (hb_buffer,
+                          paragraph_text, paragraph_length,
+                          item_offset, item_length);
+
+    After this change such clients can simply say:
+
+      hb_buffer_set_flags (hb_buffer,
+                           HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
+
+      hb_buffer_add_utf8 (hb_buffer,
+                          paragraph_text, paragraph_length,
+                          item_offset, item_length);
+
+    Ie, HarfBuzz itself checks whether the segment is at the beginning/end
+    of the paragraph.  Clients that only pass item-at-a-time to HarfBuzz
+    continue not setting any flags whatsoever.
+
+    Another way to put it is: if there's pre-context text in the buffer,
+    HarfBuzz ignores the BOT flag.  If there's post-context, it ignores
+    EOT flag.
+
+
+Overview of changes leading to 0.9.33
+Tuesday, July 22, 2014
+=====================================
+
+- Turn off ARabic 'cswh' feature that was accidentally turned on.
+- Add HB_TAG_MAX_SIGNED.
+- Make hb_face_make_immutable() really make face immutable!
+- Windows build fixes.
+
+
+Overview of changes leading to 0.9.32
+Thursday, July 17, 2014
+=====================================
+
+- Apply Arabic shaping features in spec order exactly.
+- Another fix for Mongolian free variation selectors.
+- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt'
+  together.
+- Minor adjustment to U+FFFD logic.
+- Fix hb-coretext build.
+
+
+Overview of changes leading to 0.9.31
+Wednesday, July 16, 2014
+=====================================
+
+- Only accept valid UTF-8/16/32; we missed many cases before.
+- Better shaping of invalid UTF-8/16/32.  Falls back to
+  U+FFFD REPLACEMENT CHARACTER now.
+- With all changes in this release, the buffer will contain fully
+  valid Unicode after hb_buffer_add_utf8/16/32 no matter how
+  broken the input is.  This can be overridden though.  See below.
+- Fix Mongolian Variation Selectors for fonts without GDEF.
+- Fix minor invalid buffer access.
+- Accept zh-Hant and zh-Hans language tags.  hb_ot_tag_to_language()
+  now uses these instead of private tags.
+- Build fixes.
+- New API:
+  * hb_buffer_add_codepoints().  This does what hb_buffer_add_utf32()
+    used to do, ie. no validity check on the input at all.  add_utf32
+    now replaces invalid Unicode codepoints with the replacement
+    character (see below).
+  * hb_buffer_set_replacement_codepoint()
+  * hb_buffer_get_replacement_codepoint()
+    Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when
+    we detected broken input, we replaced that with (hb_codepoint_t)-1.
+    This has changed to use U+FFFD now, but can be changed using these
+    new API.
+
+
+Overview of changes leading to 0.9.30
+Wednesday, July 9, 2014
+=====================================
+
+- Update to Unicode 7.0.0:
+  * New scripts Manichaean and Psalter Pahlavi are shaped using
+    Arabic shaper.
+  * All the other new scripts to through the generic shaper for
+    now.
+- Minor Indic improvements.
+- Fix graphite2 backend cluster mapping [crasher!]
+- API changes:
+  * New HB_SCRIPT_* values for Unicode 7.0 scripts.
+  * New function hb_ot_layout_language_get_required_feature().
+- Build fixes.
+
+
+Overview of changes leading to 0.9.29
+Thursday, May 29, 2014
+=====================================
+
+- Implement cmap in hb-ot-font.h.  No variation-selectors yet.
+- Myanmar: Allow MedialYa+Asat.
+- Various Indic fixes:
+  * Support most characters in Extended Devanagary and Vedic
+    Unicode blocks.
+  * Allow digits and a some punctuation as consonant placeholders.
+- Build fixes.
+
+
+Overview of changes leading to 0.9.28
+Monday, April 28, 2014
+=====================================
+
+- Unbreak old-spec Indic shaping. (bug 76705)
+- Fix shaping of U+17DD and U+0FC6.
+- Add HB_NO_MERGE_CLUSTERS build option.  NOT to be enabled by default
+  for shipping libraries.  It's an option for further experimentation
+  right now.  When we are sure how to do it properly, we will add
+  public run-time API for the functionality.
+- Build fixes.
+
+
+Overview of changes leading to 0.9.27
+Tuesday, March 18, 2014
+=====================================
+
+- Don't use "register" storage class specifier
+- Wrap definition of free_langs() with HAVE_ATEXIT
+- Add coretext_aat shaper and hb_coretext_face_create() constructor
+- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks
+- Add Myanmar test case from OpenType Myanmar spec
+- Only do fallback Hebrew composition if no GPOS 'mark' available
+- Allow bootstrapping without gtk-doc
+- Use AM_MISSING_PROG for ragel and git
+- Typo in ucdn's Makefile.am
+- Improve MemoryBarrier() implementation
+
+
+Overview of changes leading to 0.9.26
+Thursday, January 30, 2014
+=====================================
+
+- Misc fixes.
+- Fix application of 'rtlm' feature.
+- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH.
+- New header: hb-ot-shape.h
+- Uniscribe: fix scratch-buffer accounting.
+- Reorder Tai Tham SAKOT to after tone-marks.
+- Add Hangul shaper.
+- New files:
+  hb-ot-shape-complex-hangul.cc
+  hb-ot-shape-complex-hebrew.cc
+  hb-ot-shape-complex-tibetan.cc
+- Disable 'cswh' feature in Arabic shaper.
+- Coretext: better handle surrogate pairs.
+- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE.
+
+
+Overview of changes leading to 0.9.25
+Wednesday, December 4, 2013
+=====================================
+
+- Myanmar shaper improvements.
+- Avoid font fallback in CoreText backend.
+- Additional OpenType language tag mappiongs.
+- More aggressive shape-plan caching.
+- Build with / require automake 1.13.
+- Build with libtool 2.4.2.418 alpha to support ppc64le.
+
+
+Overview of changes leading to 0.9.24
+Tuesday, November 13, 2013
+=====================================
+
+- Misc compiler warning fixes with clang.
+- No functional changes.
+
+
+Overview of changes leading to 0.9.23
+Monday, October 28, 2013
+=====================================
+
+- "Udupi HarfBuzz Hackfest", Paris, October 14..18 2013.
+- Fix (Chain)Context recursion with non-monotone lookup positions.
+- Misc Indic bug fixes.
+- New Javanese / Buginese shaping, similar to Windows 8.1.
+
+
+Overview of changes leading to 0.9.22
+Thursday, October 3, 2013
+=====================================
+
+- Fix use-after-end-of-scope in hb_language_from_string().
+- Fix hiding of default_ignorables if font doesn't have space glyph.
+- Protect against out-of-range lookup indices.
+
+- API Changes:
+
+  * Added hb_ot_layout_table_get_lookup_count()
+
+
+Overview of changes leading to 0.9.21
+Monday, September 16, 2013
+=====================================
+
+- Rename gobject-introspection library name from harfbuzz to HarfBuzz.
+- Remove (long disabled) hb-old and hb-icu-le test shapers.
+- Misc gtk-doc and gobject-introspection annotations.
+- Misc fixes.
+- API changes:
+
+  * Add HB_SET_VALUE_INVALID
+
+Overview of changes leading to 0.9.20
+Thursday, August 29, 2013
+=====================================
+
+General:
+- Misc substitute_closure() fixes.
+- Build fixes.
+
+Documentation:
+- gtk-doc boilerplate integrated.  Docs are built now, but
+  contain no contents.  By next release hopefully we have
+  some content in.  Enable using --enable-gtk-doc.
+
+GObject and Introspection:
+- Added harfbuzz-gobject library (hb-gobject.h) that has type
+  bindings for all HarfBuzz objects and enums.  Enable using
+  --with-gobject.
+- Added gobject-introspection boilerplate.  Nothing useful
+  right now.  Work in progress.  Gets enabled automatically if
+  --with-gobject is used.  Override with --disable-introspection.
+
+OpenType shaper:
+- Apply 'mark' in Myanmar shaper.
+- Don't apply 'dlig' by default.
+
+Uniscribe shaper:
+- Support user features.
+- Fix loading of fonts that are also installed on the system.
+- Fix shaping of Arabic Presentation Forms.
+- Fix build with wide chars.
+
+CoreText shaper:
+- Support user features.
+
+Source changes:
+- hb_face_t code moved to hb-face.h / hb-face.cc.
+- Added hb-deprecated.h.
+
+API changes:
+- Added HB_DISABLE_DEPRECATED.
+- Deprecated HB_SCRIPT_CANADIAN_ABORIGINAL; replaced by
+  HB_SCRIPT_CANADIAN_SYLLABICS.
+- Deprecated HB_BUFFER_FLAGS_DEFAULT; replaced by
+  HB_BUFFER_FLAG_DEFAULT.
+- Deprecated HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; replaced by
+  HB_BUFFER_SERIALIZE_FLAG_DEFAULT.
+
+
+Overview of changes leading to 0.9.19
+Tuesday, July 16, 2013
+=====================================
+
+- Build fixes.
+- Better handling of multiple variation selectors in a row.
+- Pass on variation selector to GSUB if not consumed by cmap.
+- Fix undefined memory access.
+- Add Javanese config to Indic shaper.
+- Misc bug fixes.
+
+Overview of changes leading to 0.9.18
+Tuesday, May 28, 2013
+=====================================
+
+New build system:
+
+- All unneeded code is all disabled by default,
+
+- Uniscribe and CoreText shapers can be enabled with their --with options,
+
+- icu_le and old shapers cannot be enabled for now,
+
+- glib, freetype, and cairo will be detected automatically.
+  They can be force on/off'ed with their --with options,
+
+- icu and graphite2 are default off, can be enabled with their --with
+  options,
+
+Moreover, ICU support is now build into a separate library:
+libharfbuzz-icu.so, and a new harfbuzz-icu.pc is shipped for it.
+Distros can enable ICU now without every application on earth
+getting linked to via libharfbuzz.so.
+
+For distros I recommend that they make sure they are building --with-glib
+--with-freetype --with-cairo, --with-icu, and optionally --with-graphite2;
+And package harfbuzz and harfbuzz-icu separately.
+
+
+Overview of changes leading to 0.9.17
+Monday, May 20, 2013
+=====================================
+
+- Build fixes.
+- Fix bug in hb_set_get_min().
+- Fix regression with Arabic mark positioning / width-zeroing.
+
+Overview of changes leading to 0.9.16
+Friday, April 19, 2013
+=====================================
+
+- Major speedup in OpenType lookup processing.  With the Amiri
+  Arabic font, this release is over 3x faster than previous
+  release.  All scripts / languages should see this speedup.
+
+- New --num-iterations option for hb-shape / hb-view; useful for
+  profiling.
+
+Overview of changes leading to 0.9.15
+Friday, April 05, 2013
+=====================================
+
+- Build fixes.
+- Fix crasher in graphite2 shaper.
+- Fix Arabic mark width zeroing regression.
+- Don't compose Hangul jamo into Unicode syllables.
+
+
+Overview of changes leading to 0.9.14
+Thursday, March 21, 2013
+=====================================
+
+- Build fixes.
+- Fix time-consuming sanitize with malicious fonts.
+- Implement hb_buffer_deserialize_glyphs() for both json and text.
+- Do not ignore Hangul filler characters.
+- Indic fixes:
+  * Fix Malayalam pre-base reordering interaction with post-forms.
+  * Further adjust ZWJ handling.  Should fix known regressions from
+    0.9.13.
+
+
+Overview of changes leading to 0.9.13
+Thursday, February 25, 2013
+=====================================
+
+- Build fixes.
+- Ngapi HarfBuzz Hackfest in London (February 2013):
+  * Fixed all known Indic bugs,
+  * New Win8-style Myanmar shaper,
+  * New South-East Asian shaper for Tai Tham, Cham, and New Tai Lue,
+  * Smartly ignore Default_Ignorable characters (joiners, etc) wheb
+    matching GSUB/GPOS lookups,
+  * Fix 'Phags-Pa U+A872 shaping,
+  * Fix partial disabling of default-on features,
+  * Allow disabling of TrueType kerning.
+- Fix possible crasher with broken fonts with overlapping tables.
+- Removed generated files from git again.  So, one needs ragel to
+  bootstrap from the git tree.
+
+API changes:
+- hb_shape() and related APIs now abort if buffer direction is
+  HB_DIRECTION_INVALID.  Previously, hb_shape() was calling
+  hb_buffer_guess_segment_properties() on the buffer before
+  shaping.  The heuristics in that function are fragile.  If the
+  user really wants the old behvaior, they can call that function
+  right before calling hb_shape() to get the old behavior.
+- hb_blob_create_sub_blob() always creates sub-blob with
+  HB_MEMORY_MODE_READONLY.  See comments for the reason.
+
+
+Overview of changes leading to 0.9.12
+Thursday, January 18, 2013
+=====================================
+
+- Build fixes for Sun compiler.
+- Minor bug fix.
+
+Overview of changes leading to 0.9.11
+Thursday, January 10, 2013
+=====================================
+
+- Build fixes.
+- Fix GPOS mark attachment with null Anchor offsets.
+- [Indic] Fix old-spec reordering of viramas if sequence ends in one.
+- Fix multi-threaded shaper data creation crash.
+- Add atomic ops for Solaris.
+
+API changes:
+- Rename hb_buffer_clear() to hb_buffer_clear_contents().
+
+
+Overview of changes leading to 0.9.10
+Thursday, January 3, 2013
+=====================================
+
+- [Indic] Fixed rendering of Malayalam dot-reph
+- Updated OT language tags.
+- Updated graphite2 backend.
+- Improved hb_ot_layout_get_size_params() logic.
+- Improve hb-shape/hb-view help output.
+- Fixed hb-set.h implementation to not crash.
+- Fixed various issues with hb_ot_layout_collect_lookups().
+- Various build fixes.
+
+New API:
+
+hb_graphite2_face_get_gr_face()
+hb_graphite2_font_get_gr_font()
+hb_coretext_face_get_cg_font()
+
+Modified API:
+
+hb_ot_layout_get_size_params()
+
+
+Overview of changes leading to 0.9.9
+Wednesday, December 5, 2012
+====================================
+
+- Fix build on Windows.
+- Minor improvements.
+
+
+Overview of changes leading to 0.9.8
+Tuesday, December 4, 2012
+====================================
+
+
+- Actually implement hb_shape_plan_get_shaper ().
+- Make UCDB data tables const.
+- Lots of internal refactoring in OTLayout tables.
+- Flesh out hb_ot_layout_lookup_collect_glyphs().
+
+New API:
+
+hb_ot_layout_collect_lookups()
+hb_ot_layout_get_size_params()
+
+
+Overview of changes leading to 0.9.7
+Sunday, November 21, 2012
+====================================
+
+
+HarfBuzz "All-You-Can-Eat-Sushi" (aka Vancouver) Hackfest and follow-on fixes.
+
+- Fix Arabic contextual joining using pre-context text.
+- Fix Sinhala "split matra" mess.
+- Fix Khmer shaping with broken fonts.
+- Implement Thai "PUA" shaping for old fonts.
+- Do NOT route Kharoshthi script through the Indic shaper.
+- Disable fallback positioning for Indic and Thai shapers.
+- Misc fixes.
+
+
+hb-shape / hb-view changes:
+
+- Add --text-before and --text-after
+- Add --bot / --eot / --preserve-default-ignorables
+- hb-shape --output-format=json
+
+
+New API:
+
+hb_buffer_clear()
+
+hb_buffer_flags_t
+
+HB_BUFFER_FLAGS_DEFAULT
+HB_BUFFER_FLAG_BOT
+HB_BUFFER_FLAG_EOT
+HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES
+
+hb_buffer_set_flags()
+hb_buffer_get_flags()
+
+HB_BUFFER_SERIALIZE_FLAGS
+hb_buffer_serialize_glyphs()
+hb_buffer_deserialize_glyphs()
+hb_buffer_serialize_list_formats()
+
+hb_set_add_range()
+hb_set_del_range()
+hb_set_get_population()
+hb_set_next_range()
+
+hb_face_[sg]et_glyph_count()
+
+hb_segment_properties_t
+HB_SEGMENT_PROPERTIES_DEFAULT
+hb_segment_properties_equal()
+hb_segment_properties_hash()
+
+hb_buffer_set_segment_properties()
+hb_buffer_get_segment_properties()
+
+hb_ot_layout_glyph_class_t
+hb_ot_layout_get_glyph_class()
+hb_ot_layout_get_glyphs_in_class()
+
+hb_shape_plan_t
+hb_shape_plan_create()
+hb_shape_plan_create_cached()
+hb_shape_plan_get_empty()
+hb_shape_plan_reference()
+hb_shape_plan_destroy()
+hb_shape_plan_set_user_data()
+hb_shape_plan_get_user_data()
+hb_shape_plan_execute()
+hb_shape_plan_get_shaper()
+
+hb_ot_shape_plan_collect_lookups()
+
+
+API changes:
+
+- Remove "mask" parameter from hb_buffer_add().
+- Rename hb_ot_layout_would_substitute_lookup() and hb_ot_layout_substitute_closure_lookup().
+- hb-set.h API const correction.
+- Renamed hb_set_min/max() to hb_set_get_min/max().
+- Rename hb_ot_layout_feature_get_lookup_indexes() to hb_ot_layout_feature_get_lookups().
+- Rename hb_buffer_guess_properties() to hb_buffer_guess_segment_properties().
+
+
+
+Overview of changes leading to 0.9.6
+Sunday, November 13, 2012
+====================================
+
+- Don't clear pre-context text if no new context is provided.
+- Fix ReverseChainingSubstLookup, which was totally borked.
+- Adjust output format of hb-shape a bit.
+- Include config.h.in in-tree.  Makes it easier for alternate build systems.
+- Fix hb_buffer_set_length(buffer, 0) invalid memory allocation.
+- Use ICU LayoutEngine's C API instead of C++.  Avoids much headache.
+- Drop glyphs for all of Unicode Default_Ignorable characters.
+- Misc build fixes.
+
+Arabic shaper:
+- Enable 'dlig' and 'mset' features in Arabic shaper.
+- Implement 'Phags-pa shaping, improve Mongolian.
+
+Indic shaper:
+- Decompose Sinhala split matras the way old HarfBuzz / Pango did.
+- Initial support for Consonant Medials.
+- Start adding new-style Myanmar shaping.
+- Make reph and 'pref' logic introspect the font.
+- Route Meetei-Mayek through the Indic shaper.
+- Don't apply 'liga' in Indic shaper.
+- Improve Malayalam pre-base reordering Ra interaction with Chillus.
+
+
+
+Overview of changes leading to 0.9.5
+Sunday, October 14, 2012
+====================================
+
+- Synthetic-GSUB Arabic fallback shaping.
+
+- Misc Indic improvements.
+
+- Add build system support for pthread.
+
+- Imported UCDN for in-tree Unicode callbacks implementation.
+
+- Context-aware Arabic joining.
+
+- Misc other fixes.
+
+- New API:
+
+  hb_feature_to/from-string()
+  hb_buffer_[sg]et_content_type()
+
+
+
+Overview of changes leading to 0.9.4
+Tuesday, Sep 03, 2012
+====================================
+
+- Indic improvements with old-spec Malayalam.
+
+- Better fallback glyph positioning, specially with Thai / Lao marks.
+
+- Implement dotted-circle insertion.
+
+- Better Arabic fallback shaping / ligation.
+
+- Added ICU LayoutEngine backend for testing.  Call it by the 'icu_le' name.
+
+- Misc fixes.
+
+
+
+Overview of changes leading to 0.9.3
+Friday, Aug 18, 2012
+====================================
+
+- Fixed fallback mark positioning for left-to-right text.
+
+- Improve mark positioning for the remaining combining classes.
+
+- Unbreak Thai and fallback Arabic shaping.
+
+- Port Arabic shaper to shape-plan caching.
+
+- Use new ICU normalizer functions.
+
+
+
+Overview of changes leading to 0.9.2
+Friday, Aug 10, 2012
+====================================
+
+- Over a thousand commits!  This is the first major release of HarfBuzz.
+
+- HarfBuzz is feature-complete now!  It should be in par, or better, than
+  both Pango's shapers and old HarfBuzz / Qt shapers.
+
+- New Indic shaper, supporting main Indic scripts, Sinhala, and Khmer.
+
+- Improved Arabic shaper, with fallback Arabic shaping, supporting Arabic,
+  Sinhala, N'ko, Mongolian, and Mandaic.
+
+- New Thai / Lao shaper.
+
+- Tibetan / Hangul support in the generic shaper.
+
+- Synthetic GDEF support for fonts without a GDEF table.
+
+- Fallback mark positioning for fonts without a GPOS table.
+
+- Unicode normalization shaping heuristic during glyph mapping.
+
+- New experimental Graphite2 backend.
+
+- New Uniscribe backend (primarily for testing).
+
+- New CoreText backend (primarily for testing).
+
+- Major optimization and speedup.
+
+- Test suites and testing infrastructure (work in progress).
+
+- Greatly improved hb-view cmdline tool.
+
+- hb-shape cmdline tool.
+
+- Unicode 6.1 support.
+
+Summary of API changes:
+
+o Changed API:
+
+  - Users are expected to only include main header files now (ie. hb.h,
+    hb-glib.h, hb-ft.h, ...)
+
+  - All struct tag names had their initial underscore removed.
+    Ie. "struct _hb_buffer_t" is "struct hb_buffer_t" now.
+
+  - All set_user_data() functions now take a "replace" boolean parameter.
+
+  - hb_buffer_create() takes zero arguments now.
+    Use hb_buffer_pre_allocate() to pre-allocate.
+
+  - hb_buffer_add_utf*() now accept -1 for length parameters,
+    meaning "nul-terminated".
+
+  - hb_direction_t enum values changed.
+
+  - All *_from_string() APIs now take a length parameter to allow for
+    non-nul-terminated strings. A -1 length means "nul-terminated".
+
+  - Typedef for hb_language_t changed.
+
+  - hb_get_table_func_t renamed to hb_reference_table_func_t.
+
+  - hb_ot_layout_table_choose_script()
+
+  - Various renames in hb-unicode.h.
+
+o New API:
+
+  - hb_buffer_guess_properties()
+    Automatically called by hb_shape().
+
+  - hb_buffer_normalize_glyphs()
+
+  - hb_tag_from_string()
+
+  - hb-coretext.h
+
+  - hb-uniscribe.h
+
+  - hb_face_reference_blob()
+  - hb_face_[sg]et_index()
+  - hb_face_set_upem()
+
+  - hb_font_get_glyph_name_func_t
+    hb_font_get_glyph_from_name_func_t
+    hb_font_funcs_set_glyph_name_func()
+    hb_font_funcs_set_glyph_from_name_func()
+    hb_font_get_glyph_name()
+    hb_font_get_glyph_from_name()
+    hb_font_glyph_to_string()
+    hb_font_glyph_from_string()
+
+  - hb_font_set_funcs_data()
+
+  - hb_ft_font_set_funcs()
+  - hb_ft_font_get_face()
+
+  - hb-gobject.h (work in progress)
+
+  - hb_ot_shape_glyphs_closure()
+    hb_ot_layout_substitute_closure_lookup()
+
+  - hb-set.h
+
+  - hb_shape_full()
+
+  - hb_unicode_combining_class_t
+
+  - hb_unicode_compose_func_t
+    hb_unicode_decompose_func_t
+    hb_unicode_decompose_compatibility_func_t
+    hb_unicode_funcs_set_compose_func()
+    hb_unicode_funcs_set_decompose_func()
+    hb_unicode_funcs_set_decompose_compatibility_func()
+    hb_unicode_compose()
+    hb_unicode_decompose()
+    hb_unicode_decompose_compatibility()
+
+o Removed API:
+
+  - hb_ft_get_font_funcs()
+
+  - hb_ot_layout_substitute_start()
+    hb_ot_layout_substitute_lookup()
+    hb_ot_layout_substitute_finish()
+    hb_ot_layout_position_start()
+    hb_ot_layout_position_lookup()
+    hb_ot_layout_position_finish()
+
+
+
+Overview of changes leading to 0.6.0
+Friday, May 27, 2011
+====================================
+
+- Vertical text support in GPOS
+- Almost all API entries have unit tests now, under test/
+- All thread-safety issues are fixed
+
+Summary of API changes follows.
+
+
+* Simple Types API:
+
+  o New API:
+    HB_LANGUAGE_INVALID
+    hb_language_get_default()
+    hb_direction_to_string()
+    hb_direction_from_string()
+    hb_script_get_horizontal_direction()
+    HB_UNTAG()
+
+  o Renamed API:
+    hb_category_t renamed to hb_unicode_general_category_t
+
+  o Changed API:
+    hb_language_t is a typed pointers now
+
+  o Removed API:
+    HB_TAG_STR()
+
+
+* Use ISO 15924 tags for hb_script_t:
+
+  o New API:
+    hb_script_from_iso15924_tag()
+    hb_script_to_iso15924_tag()
+    hb_script_from_string()
+
+  o Changed API:
+    HB_SCRIPT_* enum members changed value.
+
+
+* Buffer API streamlined:
+
+  o New API:
+    hb_buffer_reset()
+    hb_buffer_set_length()
+    hb_buffer_allocation_successful()
+
+  o Renamed API:
+    hb_buffer_ensure() renamed to hb_buffer_pre_allocate()
+    hb_buffer_add_glyph() renamed to hb_buffer_add()
+
+  o Removed API:
+    hb_buffer_clear()
+    hb_buffer_clear_positions()
+
+  o Changed API:
+    hb_buffer_get_glyph_infos() takes an out length parameter now
+    hb_buffer_get_glyph_positions() takes an out length parameter now
+
+
+* Blob API streamlined:
+
+  o New API:
+    hb_blob_get_data()
+    hb_blob_get_data_writable()
+
+  o Renamed API:
+    hb_blob_create_empty() renamed to hb_blob_get_empty()
+
+  o Removed API:
+    hb_blob_lock()
+    hb_blob_unlock()
+    hb_blob_is_writable()
+    hb_blob_try_writable()
+
+  o Changed API:
+    hb_blob_create() takes user_data before destroy now
+
+
+* Unicode functions API:
+
+  o Unicode function vectors can subclass other unicode function vectors now.
+    Unimplemented callbacks in the subclass automatically chainup to the parent.
+
+  o All hb_unicode_funcs_t callbacks take a user_data now.  Their setters
+    take a user_data and its respective destroy callback.
+
+  o New API:
+    hb_unicode_funcs_get_empty()
+    hb_unicode_funcs_get_default()
+    hb_unicode_funcs_get_parent()
+
+  o Changed API:
+    hb_unicode_funcs_create() now takes a parent_funcs.
+
+  o Removed func getter functions:
+    hb_unicode_funcs_get_mirroring_func()
+    hb_unicode_funcs_get_general_category_func()
+    hb_unicode_funcs_get_script_func()
+    hb_unicode_funcs_get_combining_class_func()
+    hb_unicode_funcs_get_eastasian_width_func()
+
+
+* Face API:
+
+  o Renamed API:
+    hb_face_get_table() renamed to hb_face_reference_table()
+    hb_face_create_for_data() renamed to hb_face_create()
+
+  o Changed API:
+    hb_face_create_for_tables() takes user_data before destroy now
+    hb_face_reference_table() returns empty blob instead of NULL
+    hb_get_table_func_t accepts the face as first parameter now
+
+* Font API:
+
+  o Fonts can subclass other fonts now.  Unimplemented callbacks in the
+    subclass automatically chainup to the parent.  When chaining up,
+    scale is adjusted if the parent font has a different scale.
+
+  o All hb_font_funcs_t callbacks take a user_data now.  Their setters
+    take a user_data and its respective destroy callback.
+
+  o New API:
+    hb_font_get_parent()
+    hb_font_funcs_get_empty()
+    hb_font_create_sub_font()
+
+  o Removed API:
+    hb_font_funcs_copy()
+    hb_font_unset_funcs()
+
+  o Removed func getter functions:
+    hb_font_funcs_get_glyph_func()
+    hb_font_funcs_get_glyph_advance_func()
+    hb_font_funcs_get_glyph_extents_func()
+    hb_font_funcs_get_contour_point_func()
+    hb_font_funcs_get_kerning_func()
+
+  o Changed API:
+    hb_font_create() takes a face and references it now
+    hb_font_set_funcs() takes user_data before destroy now
+    hb_font_set_scale() accepts signed integers now
+    hb_font_get_contour_point_func_t now takes glyph first, then point_index
+    hb_font_get_glyph_func_t returns a success boolean now
+
+
+* Changed object model:
+
+  o All object types have a _get_empty() now:
+    hb_blob_get_empty()
+    hb_buffer_get_empty()
+    hb_face_get_empty()
+    hb_font_get_empty()
+    hb_font_funcs_get_empty()
+    hb_unicode_funcs_get_empty()
+
+  o Added _set_user_data() and _get_user_data() for all object types:
+    hb_blob_get_user_data()
+    hb_blob_set_user_data()
+    hb_buffer_get_user_data()
+    hb_buffer_set_user_data()
+    hb_face_get_user_data()
+    hb_face_set_user_data()
+    hb_font_funcs_get_user_data()
+    hb_font_funcs_set_user_data()
+    hb_font_get_user_data()
+    hb_font_set_user_data()
+    hb_unicode_funcs_get_user_data()
+    hb_unicode_funcs_set_user_data()
+
+  o Removed the _get_reference_count() from all object types:
+    hb_blob_get_reference_count()
+    hb_buffer_get_reference_count()
+    hb_face_get_reference_count()
+    hb_font_funcs_get_reference_count()
+    hb_font_get_reference_count()
+    hb_unicode_funcs_get_reference_count()
+
+  o Added _make_immutable() and _is_immutable() for all object types except for buffer:
+    hb_blob_make_immutable()
+    hb_blob_is_immutable()
+    hb_face_make_immutable()
+    hb_face_is_immutable()
+
+
+* Changed API for vertical text support
+
+  o The following callbacks where removed:
+    hb_font_get_glyph_advance_func_t
+    hb_font_get_kerning_func_t
+
+  o The following new callbacks added instead:
+    hb_font_get_glyph_h_advance_func_t
+    hb_font_get_glyph_v_advance_func_t
+    hb_font_get_glyph_h_origin_func_t
+    hb_font_get_glyph_v_origin_func_t
+    hb_font_get_glyph_h_kerning_func_t
+    hb_font_get_glyph_v_kerning_func_t
+
+  o The following API removed as such:
+    hb_font_funcs_set_glyph_advance_func()
+    hb_font_funcs_set_kerning_func()
+    hb_font_get_glyph_advance()
+    hb_font_get_kerning()
+
+  o New API added instead:
+    hb_font_funcs_set_glyph_h_advance_func()
+    hb_font_funcs_set_glyph_v_advance_func()
+    hb_font_funcs_set_glyph_h_origin_func()
+    hb_font_funcs_set_glyph_v_origin_func()
+    hb_font_funcs_set_glyph_h_kerning_func()
+    hb_font_funcs_set_glyph_v_kerning_func()
+    hb_font_get_glyph_h_advance()
+    hb_font_get_glyph_v_advance()
+    hb_font_get_glyph_h_origin()
+    hb_font_get_glyph_v_origin()
+    hb_font_get_glyph_h_kerning()
+    hb_font_get_glyph_v_kerning()
+
+  o The following higher-leve API added for convenience:
+    hb_font_get_glyph_advance_for_direction()
+    hb_font_get_glyph_origin_for_direction()
+    hb_font_add_glyph_origin_for_direction()
+    hb_font_subtract_glyph_origin_for_direction()
+    hb_font_get_glyph_kerning_for_direction()
+    hb_font_get_glyph_extents_for_origin()
+    hb_font_get_glyph_contour_point_for_origin()
+
+
+* OpenType Layout API:
+
+  o New API:
+    hb_ot_layout_position_start()
+    hb_ot_layout_substitute_start()
+    hb_ot_layout_substitute_finish()
+
+
+* Glue code:
+
+  o New API:
+    hb_glib_script_to_script()
+    hb_glib_script_from_script()
+    hb_icu_script_to_script()
+    hb_icu_script_from_script()
+
+
+* Version API added:
+
+  o New API:
+    HB_VERSION_MAJOR
+    HB_VERSION_MINOR
+    HB_VERSION_MICRO
+    HB_VERSION_STRING
+    HB_VERSION_CHECK()
+    hb_version()
+    hb_version_string()
+    hb_version_check()
+
+

+ 1 - 0
libs/harfbuzz/README

@@ -0,0 +1 @@
+README.md

+ 99 - 0
libs/harfbuzz/README.md

@@ -0,0 +1,99 @@
+[![Linux CI Status](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
+[![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
+[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/harfbuzz.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/15166/badge.svg)](https://scan.coverity.com/projects/harfbuzz)
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=harfbuzz/harfbuzz&amp;utm_campaign=Badge_Grade)
+[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
+[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
+
+# HarfBuzz
+
+HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also
+[Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome,
+ChromeOS, Firefox, GNOME, GTK+, KDE, LibreOffice, OpenJDK, PlayStation, Qt,
+XeTeX, and other places.
+
+For bug reports, mailing list, and other information please visit:
+
+  http://harfbuzz.org/
+
+For license information, see [COPYING](COPYING).
+
+## Documentation
+
+For user manual as well as API documentation, check: https://harfbuzz.github.io
+
+## Download
+
+For tarball releases of HarfBuzz, look [here][3]. At the same place you
+will also find Win32/Win64 binary bundles that include libharfbuzz DLL,
+hb-view.exe, hb-shape.exe, and all dependencies.
+
+The canonical source tree is available on [github][4].
+
+The API that comes with `hb.h` will not change incompatibly. Other, peripheral,
+headers are more likely to go through minor modifications, but again, we do our
+best to never change API in an incompatible way. We will never break the ABI.
+
+If you are not sure whether Pango or HarfBuzz is right for you, read [Pango vs
+HarfBuzz][5].
+
+## Development
+
+For build information, see [BUILD.md](BUILD.md).
+
+For custom configurations, see [CONFIG.md](CONFIG.md).
+
+For testing and profiling, see [TESTING.md](TESTING.md).
+
+To get a better idea of where HarfBuzz stands in the text rendering stack you
+may want to read [State of Text Rendering][6], though, that document is many
+years old. Here are a few presentation slides about HarfBuzz at the
+Internationalization and Unicode Conference over the years:
+
+*   November 2014, [Unicode, OpenType, and HarfBuzz: Closing the Circle][7],
+*   October 2012, [HarfBuzz, The Free and Open Text Shaping Engine][8],
+*   October 2009, [HarfBuzz: the Free and Open Shaping Engine][9].
+
+Both development and user support discussion around HarfBuzz happens on the
+[github][4].
+
+To report bugs or submit patches please use [github][4] issues and
+pull-requests.
+
+For a comparison of old vs new HarfBuzz memory consumption see [this][10].
+
+<!--See past and upcoming [HarfBuzz Hackfests](https://freedesktop.org/wiki/Software/HarfBuzz/Hackfests/)!-->
+
+## Name
+
+HarfBuzz (حرف‌باز) is my Persian translation of “[OpenType][1]”,
+transliterated using the Latin script. It sports a second meaning, but that
+ain’t translatable.
+
+> Background: Originally there was this font format called TrueType. People and
+> companies started calling their type engines all things ending in Type:
+> FreeType, CoolType, ClearType, etc. And then came OpenType, which is the
+> successor of TrueType. So, for my OpenType implementation, I decided to stick
+> with the concept but use the Persian translation. Which is fitting given that
+> Persian is written in the Arabic script, and OpenType is an extension of
+> TrueType that adds support for complex script rendering, and HarfBuzz is an
+> implementation of OpenType complex text shaping.
+
+<details>
+  <summary>Packaging status of HarfBuzz</summary>
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)
+
+</details>
+
+[1]: https://docs.microsoft.com/en-us/typography/opentype/spec/
+[2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
+[3]: https://github.com/harfbuzz/harfbuzz/releases
+[4]: https://github.com/harfbuzz/harfbuzz
+[5]: http://mces.blogspot.com/2009/11/pango-vs-harfbuzz.html
+[6]: http://behdad.org/text/
+[7]: https://goo.gl/FSIQuC
+[8]: https://goo.gl/2wSRu
+[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf
+[10]: https://goo.gl/woyty

+ 58 - 0
libs/harfbuzz/README.mingw.md

@@ -0,0 +1,58 @@
+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:
+
+You want to follow the 32bit instructions. The 64bit equivalents are included
+for reference.
+
+1. Install Wine.
+   - Fedora: `dnf install wine`.
+
+2. Install `mingw-w64` compiler.
+   - Fedora, 32bit: `dnf install mingw32-gcc-c++`
+   - Fedora, 64bit: `dnf install mingw64-gcc-c++`
+   - Debian: `apt install g++-mingw-w64`
+   - Mac: `brew install mingw-w64`
+
+3. If you have drank the `meson` koolaid, look at `.ci/build-win32.sh` to see how to
+   invoke `meson` now, or just run that script.  Otherwise, here's how to use the
+   old trusty autotools instead:
+
+   a) Install dependencies.
+      - Fedora, 32bit: `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype`
+      - Fedora, 64bit: `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype`
+
+   b) Configure:
+     - `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild`
+     - 32bit: `../mingw-configure.sh i686`
+     - 64bit: `../mingw-configure.sh x86_64`
+
+   c) Build as usual:
+     - make
+
+   d) Configure your wine to find system mingw libraries. See:
+      https://fedoraproject.org/wiki/MinGW/Configure_wine
+
+Now you can use `hb-shape` by `(cd win32build/util && wine hb-shape.exe)`
+but if you like to shape with the Microsoft Uniscribe:
+
+4. 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,
+
+5. `WINEDLLOVERRIDES="usp10=n" wine 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)
+
+When you have built that, you can test HarfBuzz's native shaper against Uniscribe
+following these instructions:
+
+  https://github.com/harfbuzz/harfbuzz/issues/3671

+ 31 - 0
libs/harfbuzz/README.python.md

@@ -0,0 +1,31 @@
+To enable HarfBuzz bindings for Python among other languages, make sure
+you have latest version of gobject-introspection available.  On Ubuntu,
+you can install that this way:
+
+```bash
+sudo apt-get install libgirepository1.0-dev
+```
+
+And then run `meson setup` and make sure that `Introspection` is reported
+enabled in output.
+
+Compile and install.
+
+Make sure you have the installation lib dir in `LD_LIBRARY_PATH`, as needed
+for the linker to find the library.
+
+Then make sure you also have `GI_TYPELIB_PATH` pointing to the resulting
+`$prefix/lib/girepository-*` directory.
+
+Make sure you have pygobject installed.  Then check that the following
+import works in your Python interpreter:
+
+```python
+from gi.repository import HarfBuzz
+```
+
+If it does, you are ready to call HarfBuzz from Python!  Congratulations.
+See [`src/sample.py`](src/sample.py).
+
+The Python API will change.  Let us know on the mailing list if you are
+using it, and send lots of feedback.

+ 37 - 0
libs/harfbuzz/RELEASING.md

@@ -0,0 +1,37 @@
+# HarfBuzz release walk-through checklist:
+
+- [ ] Open gitk and review changes since last release.
+
+	- [ ] Print all public API changes:
+        `git diff $(git describe | sed 's/-.*//').. src/*.h`
+
+    - [ ]  Document them in NEWS.
+        All API and API semantic changes should be clearly marked as API additions, API changes, or API deletions.
+
+    - [ ] Document deprecations.
+        Ensure all new API / deprecations are in listed correctly in docs/harfbuzz-sections.txt.
+        If release added new API, add entry for new API index at the end of docs/harfbuzz-docs.xml.
+
+     If there's a backward-incompatible API change (including deletions for API used anywhere), that's a release blocker.
+     Do NOT release.
+
+- [ ] Based on severity of changes, decide whether it's a minor or micro release number bump.
+
+- [ ] Search for REPLACEME on the repository and replace it with the chosen version for the release.
+
+- [ ] Make sure you have correct date and new version at the top of NEWS file.
+
+- [ ] Bump version in line 3 of meson.build and configure.ac.
+
+- [ ] Do a `meson test -Cbuild` so it both checks the tests and updates hb-version.h (use `git diff` to see if is really updated).
+
+- [ ] Commit NEWS, meson.build, configure.ac, and src/hb-version.h, as well as any REPLACEME changes you made.
+        The commit message is simply the release number, e. g. "1.4.7"
+
+- [ ] Do a `meson dist -Cbuild` that runs the tests against the latest committed changes.
+   If doesn't pass, something fishy is going on, reset the repo and start over.
+
+- [ ] Tag the release and sign it: e.g. `git tag -s 1.4.7 -m 1.4.7`.
+	  Enter your GPG password.
+
+- [ ] Push the commit and tag out: `git push --follow-tags`.

+ 47 - 0
libs/harfbuzz/TESTING.md

@@ -0,0 +1,47 @@
+## Build and Test
+
+```shell
+meson build
+ninja -Cbuild
+meson test -Cbuild
+```
+
+### Debug with GDB
+
+```shell
+meson test -Cbuild --gdb testname
+```
+
+## Build and Run
+
+Depending on what area you are working in change or add `HB_DEBUG_<whatever>`.
+Values defined in `hb-debug.hh`.
+
+```shell
+CPPFLAGS='-DHB_DEBUG_SUBSET=100' meson setup build --reconfigure
+meson test -C build
+```
+
+### Run tests with asan
+
+```shell
+meson setup build -Db_sanitize=address --reconfigure
+meson compile -C build
+meson test -C build
+```
+
+### Enable Debug Logging
+
+```shell
+CPPFLAGS=-DHB_DEBUG_SUBSET=100 meson build --reconfigure
+ninja -C build
+```
+
+## Test with the Fuzzer
+
+FOr fuzzing, see `test/fuzzing/README.md`.
+
+## Profiling
+
+For profiling, see `perf/README.md`.
+

+ 7 - 0
libs/harfbuzz/THANKS

@@ -0,0 +1,7 @@
+Bradley Grainger
+Kenichi Ishibashi
+Ivan Kuckir <https://photopea.com/>
+Ryan Lortie
+Jeff Muizelaar
+suzuki toshiya
+Philip Withnall

+ 48 - 0
libs/harfbuzz/autogen.sh

@@ -0,0 +1,48 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+
+olddir=`pwd`
+cd $srcdir
+
+#printf "checking for ragel... "
+#which ragel || {
+#	echo "You need to install ragel... See http://www.complang.org/ragel/"
+#	exit 1
+#}
+
+printf "checking for pkg-config... "
+which pkg-config || {
+	echo "*** No pkg-config found, please install it ***"
+	exit 1
+}
+
+printf "checking for libtoolize... "
+which glibtoolize || which libtoolize || {
+	echo "*** No libtoolize (libtool) found, please install it ***"
+	exit 1
+}
+printf "checking for gtkdocize... "
+if which gtkdocize ; then
+	gtkdocize --copy || exit 1
+else
+	echo "*** No gtkdocize (gtk-doc) found, skipping documentation ***"
+	echo "EXTRA_DIST = " > gtk-doc.make
+fi
+
+printf "checking for autoreconf... "
+which autoreconf || {
+	echo "*** No autoreconf (autoconf) found, please install it ***"
+	exit 1
+}
+
+echo "running autoreconf --force --install --verbose"
+autoreconf --force --install --verbose || exit $?
+
+cd $olddir
+test -n "$NOCONFIGURE" || {
+	echo "running configure $@"
+	"$srcdir/configure" "$@"
+}

+ 486 - 0
libs/harfbuzz/configure.ac

@@ -0,0 +1,486 @@
+AC_PREREQ([2.64])
+AC_INIT([HarfBuzz],
+        [5.3.1],
+        [https://github.com/harfbuzz/harfbuzz/issues/new],
+        [harfbuzz],
+        [http://harfbuzz.org/])
+
+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-xz no-dist-gzip -Wall no-define color-tests -Wno-portability])
+AM_SILENT_RULES([yes])
+AX_CODE_COVERAGE
+
+# Initialize libtool
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+LT_PREREQ([2.2])
+LT_INIT([disable-static])
+
+# Check for programs
+AC_PROG_CC
+AC_PROG_CC_C99
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AX_CXX_COMPILE_STDCXX(11)
+AC_SYS_LARGEFILE
+PKG_PROG_PKG_CONFIG([0.28])
+AM_MISSING_PROG([RAGEL], [ragel])
+AM_MISSING_PROG([GIT], [git])
+
+# Version
+m4_define(hb_version_triplet,m4_split(AC_PACKAGE_VERSION,[[.]]))
+m4_define(hb_version_major,m4_argn(1,hb_version_triplet))
+m4_define(hb_version_minor,m4_argn(2,hb_version_triplet))
+m4_define(hb_version_micro,m4_argn(3,hb_version_triplet))
+HB_VERSION_MAJOR=hb_version_major
+HB_VERSION_MINOR=hb_version_minor
+HB_VERSION_MICRO=hb_version_micro
+HB_VERSION=AC_PACKAGE_VERSION
+AC_SUBST(HB_VERSION_MAJOR)
+AC_SUBST(HB_VERSION_MINOR)
+AC_SUBST(HB_VERSION_MICRO)
+AC_SUBST(HB_VERSION)
+
+# Libtool version
+m4_define([hb_version_int],
+	  m4_eval(hb_version_major*10000 + hb_version_minor*100 + hb_version_micro))
+HB_LIBTOOL_VERSION_INFO=hb_version_int:0:hb_version_int
+AC_SUBST(HB_LIBTOOL_VERSION_INFO)
+
+AC_ARG_WITH([libstdc++],
+	[AS_HELP_STRING([--with-libstdc++=@<:@yes/no@:>@],
+			[Allow linking with libstdc++ @<:@default=no@:>@])],
+	[with_libstdcxx=$withval],
+	[with_libstdcxx=no])
+AM_CONDITIONAL(WITH_LIBSTDCXX, [test "x$with_libstdcxx" = "xyes"])
+
+# Documentation
+have_gtk_doc=false
+m4_ifdef([GTK_DOC_CHECK], [
+GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
+	if test "x$enable_gtk_doc" = xyes; then
+		have_gtk_doc=true
+	fi
+], [
+	AM_CONDITIONAL([ENABLE_GTK_DOC], false)
+])
+
+# Functions and headers
+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale uselocale)
+AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h xlocale.h)
+
+# Compiler flags
+AC_CANONICAL_HOST
+AC_CHECK_ALIGNOF([struct{char;}])
+if test "x$GCC" = "xyes"; then
+
+	# Make symbols link locally
+	AX_CHECK_LINK_FLAG([[-Bsymbolic-functions]], [LDFLAGS="$LDFLAGS -Bsymbolic-functions"])
+
+	# Make it possible to not link to libstdc++
+	# No threadsafe statics in C++ as we do it ourselves.
+	# We don't use these features, so it's safe to disable them
+	# even in the cases where we DO link to libstdc++.
+	# Put -fno-rtti before $CXXFLAGS such that users can re-enable it
+	# by overriding CXXFLAGS.
+	CXXFLAGS="-fno-rtti $CXXFLAGS -fno-exceptions -fno-threadsafe-statics"
+
+	case "$host" in
+		*-*-mingw*)
+		;;
+		*)
+			# Hide inline methods
+			CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden"
+		;;
+	esac
+
+	case "$host" in
+		arm-*-*)
+			if test "x$ac_cv_alignof_struct_char__" != x1; then
+				# Request byte alignment
+				CXXFLAGS="$CXXFLAGS -mstructure-size-boundary=8"
+			fi
+		;;
+	esac
+fi
+
+AM_CONDITIONAL(HAVE_GCC, test "x$GCC" = "xyes")
+
+hb_os_win32=no
+AC_MSG_CHECKING([for native Win32])
+case "$host" in
+  *-*-mingw*)
+    hb_os_win32=yes
+    ;;
+esac
+AC_MSG_RESULT([$hb_os_win32])
+AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes")
+
+have_pthread=false
+AX_PTHREAD([have_pthread=true])
+if $have_pthread; then
+	AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
+fi
+AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
+
+dnl ==========================================================================
+
+AC_ARG_WITH(glib,
+	[AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@],
+			[Use glib @<:@default=auto@:>@])],,
+	[with_glib=auto])
+have_glib=false
+GLIB_DEPS="glib-2.0 >= 2.19.1"
+AC_SUBST(GLIB_DEPS)
+if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
+	PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :)
+fi
+if test "x$with_glib" = "xyes" -a "x$have_glib" != "xtrue"; then
+	AC_MSG_ERROR([glib support requested but glib-2.0 not found])
+fi
+if $have_glib; then
+	AC_DEFINE(HAVE_GLIB, 1, [Have glib2 library])
+fi
+AM_CONDITIONAL(HAVE_GLIB, $have_glib)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(gobject,
+	[AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@],
+			[Use gobject @<:@default=no@:>@])],,
+	[with_gobject=no])
+have_gobject=false
+if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then
+	PKG_CHECK_MODULES(GOBJECT, gobject-2.0 glib-2.0, have_gobject=true, :)
+fi
+if test "x$with_gobject" = "xyes" -a "x$have_gobject" != "xtrue"; then
+	AC_MSG_ERROR([gobject support requested but gobject-2.0 / glib-2.0 not found])
+fi
+if $have_gobject; then
+	AC_DEFINE(HAVE_GOBJECT, 1, [Have gobject2 library])
+	GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
+	AC_SUBST(GLIB_MKENUMS)
+fi
+AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject)
+AC_SUBST(have_gobject)
+
+dnl ===========================================================================
+
+
+dnl ===========================================================================
+# Gobject-Introspection
+have_introspection=false
+m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [
+	if $have_gobject; then
+		GOBJECT_INTROSPECTION_CHECK([1.34.0])
+		if test "x$found_introspection" = xyes; then
+			have_introspection=true
+		fi
+	else
+		AM_CONDITIONAL([HAVE_INTROSPECTION], false)
+	fi
+], [
+	AM_CONDITIONAL([HAVE_INTROSPECTION], false)
+])
+
+dnl ==========================================================================
+
+AC_ARG_WITH(cairo,
+	[AS_HELP_STRING([--with-cairo=@<:@yes/no/auto@:>@],
+			[Use cairo @<:@default=auto@:>@])],,
+	[with_cairo=auto])
+have_cairo=false
+if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
+	PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
+	save_libs=$LIBS
+	LIBS="$LIBS $CAIRO_LIBS"
+	AC_CHECK_FUNCS(cairo_user_font_face_set_render_color_glyph_func)
+	LIBS=$save_libs
+fi
+if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
+	AC_MSG_ERROR([cairo support requested but not found])
+fi
+if $have_cairo; then
+	AC_DEFINE(HAVE_CAIRO, 1, [Have cairo graphics library])
+fi
+AM_CONDITIONAL(HAVE_CAIRO, $have_cairo)
+
+have_cairo_ft=false
+if $have_cairo; then
+	PKG_CHECK_MODULES(CAIRO_FT, cairo-ft, have_cairo_ft=true, :)
+fi
+if $have_cairo_ft; then
+	AC_DEFINE(HAVE_CAIRO_FT, 1, [Have cairo-ft support in cairo graphics library])
+fi
+AM_CONDITIONAL(HAVE_CAIRO_FT, $have_cairo_ft)
+
+dnl ==========================================================================
+
+AC_ARG_WITH(chafa,
+	[AS_HELP_STRING([--with-chafa=@<:@yes/no/auto@:>@],
+			[Use chafa @<:@default=auto@:>@])],,
+	[with_chafa=auto])
+have_chafa=false
+if test "x$with_chafa" = "xyes" -o "x$with_chafa" = "xauto"; then
+	PKG_CHECK_MODULES(CHAFA, chafa >= 1.6.0, have_chafa=true, :)
+fi
+if test "x$with_chafa" = "xyes" -a "x$have_chafa" != "xtrue"; then
+	AC_MSG_ERROR([chafa support requested but not found])
+fi
+if $have_chafa; then
+	AC_DEFINE(HAVE_CHAFA, 1, [Have chafa terminal graphics library])
+fi
+AM_CONDITIONAL(HAVE_CHAFA, $have_chafa)
+
+dnl ==========================================================================
+
+AC_ARG_WITH(icu,
+	[AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@],
+			[Use ICU @<:@default=auto@:>@])],,
+	[with_icu=auto])
+have_icu=false
+if test "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" -o "x$with_icu" = "xauto"; then
+	PKG_CHECK_MODULES(ICU, icu-uc, have_icu=true, :)
+fi
+if test \( "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" \) -a "x$have_icu" != "xtrue"; then
+	AC_MSG_ERROR([icu support requested but icu-uc not found])
+fi
+
+if $have_icu; then
+	CXXFLAGS="$CXXFLAGS `$PKG_CONFIG --variable=CXXFLAGS icu-uc`"
+	AC_DEFINE(HAVE_ICU, 1, [Have ICU library])
+	if test "x$with_icu" = "xbuiltin"; then
+		AC_DEFINE(HAVE_ICU_BUILTIN, 1, [Use hb-icu Unicode callbacks])
+	fi
+fi
+AM_CONDITIONAL(HAVE_ICU, $have_icu)
+AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
+
+dnl ===========================================================================
+
+AC_ARG_WITH(graphite2,
+	[AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@],
+			[Use the graphite2 library @<:@default=no@:>@])],,
+	[with_graphite2=no])
+have_graphite2=false
+GRAPHITE2_DEPS="graphite2 >= 1.2.0"
+AC_SUBST(GRAPHITE2_DEPS)
+if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
+	PKG_CHECK_MODULES(GRAPHITE2, $GRAPHITE2_DEPS, have_graphite2=true, :)
+	if test "x$have_graphite2" != "xtrue"; then
+                # If pkg-config is not available, graphite2 can still be there
+		ac_save_CFLAGS="$CFLAGS"
+		ac_save_CPPFLAGS="$CPPFLAGS"
+		CFLAGS="$CFLAGS $GRAPHITE2_CFLAGS"
+		CPPFLAGS="$CPPFLAGS $GRAPHITE2_CFLAGS"
+		AC_CHECK_HEADER(graphite2/Segment.h, have_graphite2=true, :)
+		CPPFLAGS="$ac_save_CPPFLAGS"
+		CFLAGS="$ac_save_CFLAGS"
+	fi
+fi
+if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then
+	AC_MSG_ERROR([graphite2 support requested but libgraphite2 not found])
+fi
+if $have_graphite2; then
+	AC_DEFINE(HAVE_GRAPHITE2, 1, [Have Graphite2 library])
+fi
+AM_CONDITIONAL(HAVE_GRAPHITE2, $have_graphite2)
+
+dnl ==========================================================================
+
+AC_ARG_WITH(freetype,
+	[AS_HELP_STRING([--with-freetype=@<:@yes/no/auto@:>@],
+			[Use the FreeType library @<:@default=auto@:>@])],,
+	[with_freetype=auto])
+have_freetype=false
+FREETYPE_DEPS="freetype2 >= 12.0.6"
+AC_SUBST(FREETYPE_DEPS)
+if test "x$with_freetype" = "xyes" -o "x$with_freetype" = "xauto"; then
+	# See freetype/docs/VERSION.DLL; 12.0.6 means freetype-2.4.2
+	PKG_CHECK_MODULES(FREETYPE, $FREETYPE_DEPS, have_freetype=true, :)
+fi
+if test "x$with_freetype" = "xyes" -a "x$have_freetype" != "xtrue"; then
+	AC_MSG_ERROR([FreeType support requested but libfreetype2 not found])
+fi
+if $have_freetype; then
+	AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
+	save_libs=$LIBS
+	LIBS="$LIBS $FREETYPE_LIBS"
+	AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var FT_Get_Transform)
+	LIBS=$save_libs
+fi
+AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(uniscribe,
+	[AS_HELP_STRING([--with-uniscribe=@<:@yes/no/auto@:>@],
+			[Use the Uniscribe library @<:@default=no@:>@])],,
+	[with_uniscribe=no])
+have_uniscribe=false
+if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then
+	AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true)
+fi
+if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then
+	AC_MSG_ERROR([uniscribe support requested but not found])
+fi
+if $have_uniscribe; then
+	UNISCRIBE_CFLAGS=
+	UNISCRIBE_LIBS="-lusp10 -lgdi32 -lrpcrt4"
+	AC_SUBST(UNISCRIBE_CFLAGS)
+	AC_SUBST(UNISCRIBE_LIBS)
+	AC_DEFINE(HAVE_UNISCRIBE, 1, [Have Uniscribe library])
+fi
+AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(gdi,
+	[AS_HELP_STRING([--with-gdi=@<:@yes/no/auto@:>@],
+			[Provide GDI integration helpers @<:@default=no@:>@])],,
+	[with_gdi=no])
+have_gdi=false
+if test "x$with_gdi" = "xyes" -o "x$with_gdi" = "xauto"; then
+	AC_CHECK_HEADERS(windows.h, have_gdi=true)
+fi
+if test "x$with_gdi" = "xyes" -a "x$have_gdi" != "xtrue"; then
+	AC_MSG_ERROR([gdi support requested but not found])
+fi
+if $have_gdi; then
+	GDI_CFLAGS=
+	GDI_LIBS="-lgdi32"
+	AC_SUBST(GDI_CFLAGS)
+	AC_SUBST(GDI_LIBS)
+	AC_DEFINE(HAVE_GDI, 1, [Have GDI library])
+fi
+AM_CONDITIONAL(HAVE_GDI, $have_gdi)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(directwrite,
+	[AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@],
+			[Use the DirectWrite library (experimental) @<:@default=no@:>@])],,
+	[with_directwrite=no])
+have_directwrite=false
+AC_LANG_PUSH([C++])
+if test "x$with_directwrite" = "xyes" -o "x$with_directwrite" = "xauto"; then
+	AC_CHECK_HEADERS(dwrite_1.h, have_directwrite=true)
+fi
+AC_LANG_POP([C++])
+if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then
+	AC_MSG_ERROR([directwrite support requested but not found])
+fi
+if $have_directwrite; then
+	AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library])
+fi
+AM_CONDITIONAL(HAVE_DIRECTWRITE, $have_directwrite)
+
+dnl ===========================================================================
+
+AC_ARG_WITH(coretext,
+	[AS_HELP_STRING([--with-coretext=@<:@yes/no/auto@:>@],
+			[Use CoreText @<:@default=no@:>@])],,
+	[with_coretext=no])
+have_coretext=false
+if test "x$with_coretext" = "xyes" -o "x$with_coretext" = "xauto"; then
+	AC_CHECK_TYPE(CTFontRef, have_coretext=true,, [#include <ApplicationServices/ApplicationServices.h>])
+
+	if $have_coretext; then
+		CORETEXT_CFLAGS=
+		CORETEXT_LIBS="-framework ApplicationServices"
+		AC_SUBST(CORETEXT_CFLAGS)
+		AC_SUBST(CORETEXT_LIBS)
+	else
+		# On iOS CoreText and CoreGraphics are stand-alone frameworks
+		if test "x$have_coretext" != "xtrue"; then
+			# Check for a different symbol to avoid getting cached result.
+			AC_CHECK_TYPE(CTRunRef, have_coretext=true,, [#include <CoreText/CoreText.h>])
+		fi
+
+		if $have_coretext; then
+			CORETEXT_CFLAGS=
+			CORETEXT_LIBS="-framework CoreText -framework CoreGraphics -framework CoreFoundation"
+			AC_SUBST(CORETEXT_CFLAGS)
+			AC_SUBST(CORETEXT_LIBS)
+		fi
+	fi
+fi
+if test "x$with_coretext" = "xyes" -a "x$have_coretext" != "xtrue"; then
+	AC_MSG_ERROR([CoreText support requested but libcoretext not found])
+fi
+if $have_coretext; then
+	AC_DEFINE(HAVE_CORETEXT, 1, [Have Core Text backend])
+fi
+AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext)
+
+dnl ===========================================================================
+
+AC_CONFIG_FILES([
+Makefile
+src/Makefile
+src/harfbuzz-config.cmake
+util/Makefile
+test/Makefile
+test/api/Makefile
+test/fuzzing/Makefile
+test/shape/Makefile
+test/shape/data/Makefile
+test/shape/data/aots/Makefile
+test/shape/data/in-house/Makefile
+test/shape/data/text-rendering-tests/Makefile
+test/subset/Makefile
+test/subset/data/Makefile
+test/subset/data/repack_tests/Makefile
+test/threads/Makefile
+perf/Makefile
+docs/Makefile
+docs/version.xml
+])
+
+AC_OUTPUT
+
+echo
+echo "C++ compiler version:"
+$CXX --version
+echo
+
+AC_MSG_NOTICE([
+
+Autotools is no longer our supported build system for building the library
+for *nix distributions, please migrate to meson.
+
+])
+
+
+AC_MSG_NOTICE([
+
+Build configuration:
+
+Unicode callbacks (you want at least one):
+	Builtin			true
+	Glib:			${have_glib}
+	ICU:			${have_icu}
+
+Font callbacks (the more the merrier):
+	FreeType:		${have_freetype}
+
+Tools used for command-line utilities:
+	Cairo:			${have_cairo}
+	Chafa:			${have_chafa}
+
+Additional shapers:
+	Graphite2:		${have_graphite2}
+
+Platform shapers (not normally needed):
+	CoreText:		${have_coretext}
+	DirectWrite:		${have_directwrite}
+	GDI:			${have_gdi}
+	Uniscribe:		${have_uniscribe}
+
+Other features:
+	Documentation:		${enable_gtk_doc}
+	GObject bindings:	${have_gobject}
+	Introspection:		${have_introspection}
+])

BIN
libs/harfbuzz/docs/HarfBuzz.png


File diff suppressed because it is too large
+ 2 - 0
libs/harfbuzz/docs/HarfBuzz.svg


+ 123 - 0
libs/harfbuzz/docs/Makefile.am

@@ -0,0 +1,123 @@
+# Process this file with automake to produce Makefile.in
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# This is a blank Makefile.am for using gtk-doc.
+# Copy this to your project's API docs directory and modify the variables to
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
+# of using the various options.
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=harfbuzz
+
+# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
+#DOC_MODULE_VERSION=$(HB_VERSION_MAJOR)
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
+
+# Directories containing the source code.
+# gtk-doc will search all .c and .h files beneath these paths
+# for inline comments documenting functions and macros.
+# e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk
+DOC_SOURCE_DIR=$(top_srcdir)/src $(top_builddir)/src
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS=
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS=--rebuild-types --deprecated-guards="HB_DISABLE_DEPRECATED" \
+	--ignore-decorators='HB_EXTERN|HB_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 './*/*.h' | sed 's@^.*/@@'`
+IGNORE_HFILES+=hb-gobject.h hb-gobject-enums.h hb-gobject-structs.h
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
+MKDB_OPTIONS=--source-suffixes=h,cc --xml-mode --output-format=xml --ignore-files="$(IGNORE_HFILES)"
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkhtml
+MKHTML_OPTIONS=
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS=
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB=$(top_srcdir)/src/hb.h $(top_srcdir)/src/hb-*.h
+CFILE_GLOB=$(top_srcdir)/src/hb-*.cc
+
+# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
+# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES=  \
+	HarfBuzz.png \
+	HarfBuzz.svg
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+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-opentype-features.xml \
+	usermanual-clusters.xml \
+	usermanual-utilities.xml \
+	usermanual-integration.xml \
+	version.xml
+
+# SGML files where gtk-doc abbreviations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files=
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+GTKDOC_CFLAGS=
+GTKDOC_LIBS=$(top_builddir)/src/libharfbuzz.la
+if HAVE_GOBJECT
+GTKDOC_LIBS+=$(top_builddir)/src/libharfbuzz-gobject.la
+endif
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+include $(top_srcdir)/gtk-doc.make
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST += version.xml.in meson.build
+
+# Files not to distribute
+# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
+# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
+#DISTCLEANFILES +=
+
+# Comment this out if you don't want 'make check' to test you doc status
+# and run some sanity checks
+if ENABLE_GTK_DOC
+TESTS_ENVIRONMENT = cd $(srcdir) && \
+  DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
+  SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
+#TESTS = $(GTKDOC_CHECK)
+endif
+
+-include $(top_srcdir)/git.mk

+ 259 - 0
libs/harfbuzz/docs/features.dot

@@ -0,0 +1,259 @@
+digraph {
+  graph [outputorder=edgefirst];
+	node [shape="record", fontname="Noto Sans Mono SemiBold", fontsize=15];
+	edge [fontname="Verdana", fontsize=12,labeldistance=7.5 ];
+	fontname="Verdana";
+  ranksep=0.02; nodesep=0.5;
+
+subgraph {
+	ranksep="0.02 equally";
+	preprocessing[style=filled,fillcolor="lightgreen",fontname="Verdana",label="Glyph pre-processing"];
+	orthographic[style=filled,fillcolor="lightblue",fontname="Verdana",label="Orthographic Unit Shaping"];
+	reordering[style=filled, fillcolor="lightcoral",fontname="Verdana",label="Reordering group (USE)"];
+	topographic[style=filled,fillcolor="lightgoldenrod",fontname="Verdana",label="Topographical Features‡"];
+	typographic[style=filled,fillcolor="lightpink",fontname="Verdana",label="Typographic Presentation"];
+	positioning[style=filled,fillcolor="lightsalmon",fontname="Verdana",label="Positioning"];
+	preprocessing->reordering->orthographic->topographic->typographic->positioning;
+}
+
+	decision1 [shape="diamond", label="Script\ndirection?",fontname="Verdana"];
+	rvrn->decision1;
+
+	ltrfeatures [label="{ltra|ltrm}", fillcolor="lightgreen",style="filled"];
+	{
+	rtlfeatures [label="{rtla|rtlm¹}", fillcolor="lightgreen",style="filled"];
+	}
+	{
+		rank=same;
+		fracfeatures [label="frac²|numr³|dnom⁴", fillcolor="lightpink",style="filled"];
+		fracnotes [fontname="Verdana",shape=plaintext,label=<<table border="0" cellborder="0" cellspacing="0">
+			<tr><td align="left">¹ rtlm is scoped to characters with a Unicode mirroring property</td></tr>
+			<tr><td align="left">² frac is scoped to numr + the slash + dnom</td></tr>
+			<tr><td align="left">³ numr is scoped to all decimal numbers before a U+2044 FRACTION SLASH.</td></tr>
+			<tr><td align="left">⁴ dnom is scoped to all decimal numbers after a U+2044 FRACTION SLASH.</td></tr>
+	</table>
+		>];
+
+	}
+	rand [fillcolor="lightpink",style="filled"];
+
+	decision1 -> ltrfeatures [label="Left-to-right"];
+	decision1 -> rtlfeatures [label="Right-to-left"];
+
+	decision1 -> fracfeatures [label="Other"];
+
+	ltrfeatures -> fracfeatures;
+	rtlfeatures -> fracfeatures;
+	fracfeatures->rand;
+
+	decision2 [shape="diamond", label="Script?",fontname="Verdana"];
+
+{rank=same; HARF [label="{Harf|HARF}"]; notes;}
+	rand -> trak -> HARF -> decision2;
+
+	commonfeatures [shape=none,label=<<table border="0" cellspacing="0">
+                    <tr>
+                    	<td border="1" bgcolor="lightsalmon">abvm</td>
+                    	<td border="1" bgcolor="lightsalmon">blwm</td>
+                    	<td border="1" bgcolor="lightgreen">ccmp</td>
+                    	<td border="1" bgcolor="lightgreen">locl</td>
+                    	<td border="1" bgcolor="lightsalmon">mark</td>
+                    	<td border="1" bgcolor="lightsalmon">mkmk</td>
+                    	<td border="1" bgcolor="lightpink">rlig</td>
+                    </tr>
+                </table>>
+    ];
+
+	decision3 [shape="diamond", label="Script\ndirection?",fontname="Verdana"];
+
+	BUZZ  [label="{Buzz|BUZZ}"];
+	BUZZ -> commonfeatures -> decision3;
+
+	horizontalfeatures [
+	shape=none,label=<<table border="0" cellspacing="0">
+                    <tr><td border="1" bgcolor="lightpink">calt <font face="Verdana">(not Hangul)</font></td></tr>
+                    <tr><td border="1" bgcolor="lightpink">clig <font face="Verdana">(not Khmer)</font></td></tr>
+                    <tr><td border="1" bgcolor="lightsalmon">curs</td></tr>
+                    <tr><td border="1" bgcolor="lightsalmon">dist</td></tr>
+                    <tr><td border="1" bgcolor="lightsalmon">kern</td></tr>
+                    <tr><td border="1" bgcolor="lightpink">liga <font face="Verdana">(not Khmer)</font></td></tr>
+                    <tr><td border="1" bgcolor="lightpink">rclt</td></tr>
+                </table>>
+                ];
+	vert [label="vert",style=filled,fillcolor="lightpink"];
+
+	decision3 -> horizontalfeatures [label="Horizontal"];
+	decision3 -> vert [label="Vertical"];
+
+	discretionary [label="User-selected\ndiscretionary\nfeatures",fontname="Verdana"];
+
+	horizontalfeatures -> discretionary;
+	vert -> discretionary;
+
+	decision2->stch;
+
+	BUZZ;
+
+subgraph shapers {
+	subgraph cluster_arabic {
+		bgcolor="lightyellow"
+		label="Arabic, Syriac";
+	stch [ style="filled", fillcolor="lightgreen",label="stch"];
+	ccmplocl [ style="filled", label="ccmp|locl", fillcolor="lightgreen"];
+	arabicfeatures [label="isol|fina|fin2|fin3|medi|med2|init", style="filled", fillcolor="lightgoldenrod"];
+	arabicfeatures2 [label="rclt|calt", style="filled",fillcolor="lightpink"];
+rlig[style="filled",fillcolor="lightpink"];
+mset [fillcolor="lightpink",style="filled"]
+	stch->ccmplocl->arabicfeatures->rlig->arabicfeatures2->mset;
+	}
+	mset->BUZZ:n;
+
+	subgraph cluster_hangul {
+		bgcolor="lightyellow"
+		label="Hangul";
+		hangulfeatures [label="ljmo|vjmo|tjmo", style="filled",fillcolor="lightgoldenrod"]
+	}
+	  hangulfeatures->BUZZ:n;
+
+	subgraph cluster_indic {
+		label="Indic";
+		bgcolor="lightyellow"
+		// Preprocessing
+		loclccmpindic [label="locl†|ccmp†",style=filled,fillcolor="lightgreen"];
+		node[style=filled,fillcolor="lightgreen"];
+		nukt [label="nukt†"];
+		akhn [label="akhn†"];
+		loclccmpindic->indic_reorder_1->nukt->akhn;
+		indic_reorder_1[label="Initial reordering", fontname="Verdana",fillcolor="lightgrey",shape=ellipse,style=filled]
+
+		// Orthographic
+		node[style=filled,fillcolor="lightblue"]
+		rphf [label="rphf⁵"];
+		rkpf [label="rkpf†"];
+		pref [label="pref⁶"];
+		blwf [label="blwf⁷"];
+		abvf [label="abvf⁸"];
+		half [label="half⁹"];
+		pstf [label="pstf⁸"];
+		vatu [label="vatu†"];
+		cjct [label="cjct†"];
+		akhn ->rphf -> rkpf -> pref -> blwf -> abvf -> half -> pstf -> vatu -> cjct;
+		// Typographic presentation
+		indic_typographic[style=filled,fillcolor="lightpink",label="init|pres|abvs|blws|psts|haln"]
+		indic_reorder_2[label="Final reordering",fillcolor="lightgrey",fontname="Verdana", shape=ellipse,style=filled]
+		cjct->indic_reorder_2->indic_typographic;
+
+	notes2 [fontname="Verdana",shape=plaintext,style="",label=<<table border="0" cellborder="0" cellspacing="0">
+<tr><td align="right">⁵ rphf is scoped to pre-base ra+halant sequences</td></tr>
+<tr><td align="right">⁶ pref is scoped to the two glyphs after the base; outputs are reordered</td></tr>
+<tr><td align="right">⁷ blwf is usually scoped to the whole syllable, except in Telugu and Kannada where it is post-base</td></tr>
+<tr><td align="right">⁸ abvf and pstf are scoped to post-base</td></tr>
+<tr><td align="right">⁹ half is scoped to pre-base</td></tr>
+</table>
+>];
+		indic_typographic -> notes2 [style=invis];
+	}
+
+
+	subgraph cluster_khmer {
+		label="Khmer";
+		bgcolor="lightyellow"
+
+		khmerbasic [style=filled,fillcolor="lightgreen",label="locl†|ccmp†|pref†|bwlf†|abvf†|pstf†|cfar†"]
+		khmerother [style=filled,fillcolor="lightpink",label="pres|abvs|blws|psts"]
+		khmerbasic -> khmerother -> khmerclig;
+				khmerclig [label="clig",style=filled,fillcolor="lightpink"];
+	}
+
+	subgraph cluster_myanmar {
+		label="Myanmar";
+		bgcolor="lightyellow"
+		loclccmpmyanmar [label="locl†|ccmp†",style=filled,fillcolor="lightgreen"];
+		rphfmymr [label="rphf†",style=filled,fillcolor="lightblue"]
+		prefmymr [label="pref†",style=filled,fillcolor="lightblue"]
+		blwfmymr [label="blwf†",style=filled,fillcolor="lightblue"]
+		pstfmymr [label="pstf†",style=filled,fillcolor="lightblue"]
+		myanmarother [label="pres|abvs|blws|psts",style=filled,fillcolor="lightpink"];
+		reorder_myanmar[label="Reordering", shape=ellipse,style=filled,fontname="Verdana"]
+		loclccmpmyanmar -> reorder_myanmar-> rphfmymr -> prefmymr -> blwfmymr -> pstfmymr -> myanmarother;
+	}
+
+	subgraph cluster_use {
+		label="Universal Shaping Engine"
+		bgcolor="lightyellow"
+		use_preprocessing [style=filled, label="locl†|ccmp†|nukt†|akhn†", fillcolor="lightgreen"];
+		// Reoredering
+		rphfuse [label="rphf¹⁰", style=filled, fillcolor="lightcoral"];
+		prefuse [label="pref¹¹", style=filled, fillcolor="lightcoral"];
+		// Orthographic
+		orthographicuse [label="rkrf†|abvf†|blwf†|half†|pstf†|vatu†|cjct†", style="filled", fillcolor="lightblue"];
+		topographicaluse [label="isol|init|medi|fina", style="filled", fillcolor="lightgoldenrod"];
+		typographicaluse [label="abvs|blws|haln|pres|psts", style="filled", fillcolor="lightpink"];
+		reorder_use[label="Reordering", shape=ellipse,style=filled,fontname="Verdana"]
+		use_preprocessing -> rphfuse -> prefuse->orthographicuse ->reorder_use -> topographicaluse -> typographicaluse;
+			notes3 [fontname="Verdana",shape=plaintext,label=<<table border="0" cellborder="0" cellspacing="0">
+		<tr><td align="left">¹⁰ Outputs are reordered as category R</td></tr>
+		<tr><td align="left">¹¹ Outputs are reordered to before base</td></tr>
+		</table>
+		>];
+		typographicaluse -> notes3 [style=invis];
+	}
+
+}
+
+	indic_typographic->BUZZ:n;
+	typographicaluse->BUZZ:n;
+	khmerclig -> BUZZ:n;
+	myanmarother -> BUZZ:n;
+
+
+	decision2->hangulfeatures;
+	decision2->loclccmpindic;
+	decision2->khmerbasic;
+	decision2->loclccmpmyanmar;
+	decision2->use_preprocessing;
+	decision2->BUZZ [label="  Hebrew, Thai,\n  Lao, other"];
+
+notes [fontname="Verdana",shape=box,label=<<table border="0" cellborder="0" cellspacing="0">
+	<tr><td align="left">
+<b>Indic</b> scripts are: Bengali, Devanagari,
+ Gujarati, Gurmukhi, Kannada,
+ Malayalam, Oriya, Tamil,
+ Telugu
+</td></tr>
+
+	<tr><td align="left">
+<b>USE</b> scripts are:
+ Adlam, Ahom, Balinese, Batak, Bhaiksuki, Brahmi, Buginese,
+ Buhid, Chakma, Cham, Chorasmian, Dives Akuru, Dogra, Duployan,
+</td></tr>
+	<tr><td align="left">
+Egyptian hieroglyphs, Elymaic, Grantha, Gunjala Ggondi, Hanifi Rohingya,
+ Hanunoo, Javanese, Kaithi, Kayah li, Kharoshthi, Khojki,
+</td></tr>
+	<tr><td align="left">
+Khudawadi, Lepcha, Limbu, Mahajani, Makasar, Mandaic, Manichaean,
+ Marchen, Masaram Gondi, Medefaidrin, Meetei Mayek, Miao, Modi,
+</td></tr>
+	<tr><td align="left">
+Mongolian, Multani, Nandinagari, Newa, Nko, Nyiakeng Puachue Hmong,
+ Old Sogdian, Pahawh Hmong, Phags Pa, Psalter Pahlavi, Rejang,
+</td></tr>
+	<tr><td align="left">
+Saurashtra, Sharada, Siddham, Sinhala, Sogdian, Soyombo, Sundanese,
+ Syloti Nagri, Tagalog, Tagbanwa, Tai Le, Tai Tham, Tai Viet,
+</td></tr>
+	<tr><td align="left">
+Takri, Tibetan, Tifinagh, Tirhuta, Wancho, Zanabazar square,
+</td></tr>
+
+</table>>]
+
+
+	footnote[fontname="Verdana",label=<<table border="0" cellborder="0" cellspacing="0">
+		<tr><td align="left">† Feature is scoped to each syllable</td></tr>
+		<tr><td align="left">‡ All topographic features are scoped based on topographic position</td></tr>
+		</table>>];
+	notes3->footnote[style=invis];
+
+}

+ 213 - 0
libs/harfbuzz/docs/harfbuzz-docs.xml

@@ -0,0 +1,213 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<book id="index">
+  <bookinfo>
+    <title>HarfBuzz Manual</title>
+    <abstract>
+      <title>HarfBuzz</title>
+      <graphic fileref="HarfBuzz.png" format="PNG" align="center"/>
+      <para>
+        HarfBuzz is a text shaping library. Using the HarfBuzz library allows
+	programs to convert a sequence of Unicode input into
+	properly formatted and positioned glyph output&mdash;for any writing
+	system and language.
+      </para>
+
+      <para>
+	The canonical source-code tree is available at
+        <ulink url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>.
+	See <xref linkend="download" endterm="download.title"/> for
+	release tarballs.
+      </para>
+    </abstract>
+  </bookinfo>
+
+  <part id="user-manual">
+    <title>User's manual</title>
+      <xi:include href="usermanual-what-is-harfbuzz.xml"/>
+      <xi:include href="usermanual-install-harfbuzz.xml"/>
+      <xi:include href="usermanual-getting-started.xml"/>
+      <xi:include href="usermanual-shaping-concepts.xml"/>
+      <xi:include href="usermanual-object-model.xml"/>
+      <xi:include href="usermanual-buffers-language-script-and-direction.xml"/>
+      <xi:include href="usermanual-fonts-and-faces.xml"/>
+      <xi:include href="usermanual-opentype-features.xml"/>
+      <xi:include href="usermanual-clusters.xml"/>
+      <xi:include href="usermanual-utilities.xml"/>
+      <xi:include href="usermanual-integration.xml"/>
+  </part>
+
+  <part id="reference-manual">
+    <partinfo>
+      <releaseinfo>
+        This document is for HarfBuzz &version;.
+        <!--The latest version of this documentation can be found on-line at
+        <ulink role="online-location" url="http://[SERVER]/libharfbuzz/index.html">http://[SERVER]/libharfbuzz/</ulink>.-->
+      </releaseinfo>
+    </partinfo>
+
+    <title>Reference manual</title>
+      <chapter id="core-api">
+        <title>Core API</title>
+        <xi:include href="xml/hb-blob.xml"/>
+        <xi:include href="xml/hb-buffer.xml"/>
+        <xi:include href="xml/hb-common.xml"/>
+        <xi:include href="xml/hb-draw.xml"/>
+        <xi:include href="xml/hb-deprecated.xml"/>
+        <xi:include href="xml/hb-face.xml"/>
+        <xi:include href="xml/hb-font.xml"/>
+        <xi:include href="xml/hb-map.xml"/>
+        <xi:include href="xml/hb-set.xml"/>
+        <xi:include href="xml/hb-shape-plan.xml"/>
+        <xi:include href="xml/hb-shape.xml"/>
+        <xi:include href="xml/hb-unicode.xml"/>
+        <xi:include href="xml/hb-version.xml"/>
+      </chapter>
+
+      <chapter id="opentype-api">
+        <title>OpenType API</title>
+        <xi:include href="xml/hb-ot-color.xml"/>
+        <xi:include href="xml/hb-ot-font.xml"/>
+        <xi:include href="xml/hb-ot-layout.xml"/>
+        <xi:include href="xml/hb-ot-math.xml"/>
+        <xi:include href="xml/hb-ot-meta.xml"/>
+        <xi:include href="xml/hb-ot-metrics.xml"/>
+        <xi:include href="xml/hb-ot-name.xml"/>
+        <xi:include href="xml/hb-ot-shape.xml"/>
+        <xi:include href="xml/hb-ot-var.xml"/>
+      </chapter>
+
+      <chapter id="apple-advanced-typography-api">
+        <title>Apple Advanced Typography API</title>
+        <xi:include href="xml/hb-aat-layout.xml"/>
+      </chapter>
+
+      <chapter id="integration-api">
+        <title>Integration API</title>
+        <xi:include href="xml/hb-coretext.xml"/>
+        <xi:include href="xml/hb-ft.xml"/>
+        <xi:include href="xml/hb-glib.xml"/>
+        <xi:include href="xml/hb-graphite2.xml"/>
+        <xi:include href="xml/hb-icu.xml"/>
+        <xi:include href="xml/hb-uniscribe.xml"/>
+        <xi:include href="xml/hb-gdi.xml"/>
+        <xi:include href="xml/hb-directwrite.xml"/>
+      </chapter>
+
+      <chapter id="style-api">
+        <title>Style API</title>
+        <xi:include href="xml/hb-style.xml"/>
+      </chapter>
+
+      <chapter id="subset-api">
+        <title>Subset API</title>
+        <xi:include href="xml/hb-subset.xml"/>
+      </chapter>
+
+
+      <!--chapter id="object-tree">
+        <title>Object Hierarchy</title>
+         <xi:include href="xml/tree_index.sgml"/>
+      </chapter-->
+
+      <index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include></index>
+      <index id="deprecated-api-index" role="deprecated"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
+
+      <index id="api-index-5-3-0" role="5.3.0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-5-0-0" role="5.0.0"><title>Index of new symbols in 5.0.0</title><xi:include href="xml/api-index-5.0.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-4-4-0" role="4.4.0"><title>Index of new symbols in 4.4.0</title><xi:include href="xml/api-index-4.4.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-4-3-0" role="4.3.0"><title>Index of new symbols in 4.3.0</title><xi:include href="xml/api-index-4.3.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-4-2-0" role="4.2.0"><title>Index of new symbols in 4.2.0</title><xi:include href="xml/api-index-4.2.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-4-1-0" role="4.1.0"><title>Index of new symbols in 4.1.0</title><xi:include href="xml/api-index-4.1.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-4-0-0" role="4.0.0"><title>Index of new symbols in 4.0.0</title><xi:include href="xml/api-index-4.0.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-3-4-0" role="3.4.0"><title>Index of new symbols in 3.4.0</title><xi:include href="xml/api-index-3.4.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-3-3-0" role="3.3.0"><title>Index of new symbols in 3.3.0</title><xi:include href="xml/api-index-3.3.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-3-1-0" role="3.1.0"><title>Index of new symbols in 3.1.0</title><xi:include href="xml/api-index-3.1.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-3-0-0" role="3.0.0"><title>Index of new symbols in 3.0.0</title><xi:include href="xml/api-index-3.0.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-9-1" role="2.9.1"><title>Index of new symbols in 2.9.1</title><xi:include href="xml/api-index-2.9.1.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-9-0" role="2.9.0"><title>Index of new symbols in 2.9.0</title><xi:include href="xml/api-index-2.9.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-8-2" role="2.8.2"><title>Index of new symbols in 2.8.2</title><xi:include href="xml/api-index-2.8.2.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-7-3" role="2.7.3"><title>Index of new symbols in 2.7.3</title><xi:include href="xml/api-index-2.7.3.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-6-8" role="2.6.8"><title>Index of new symbols in 2.6.8</title><xi:include href="xml/api-index-2.6.8.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-6-5" role="2.6.5"><title>Index of new symbols in 2.6.5</title><xi:include href="xml/api-index-2.6.5.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-6-3" role="2.6.3"><title>Index of new symbols in 2.6.3</title><xi:include href="xml/api-index-2.6.3.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-6-0" role="2.6.0"><title>Index of new symbols in 2.6.0</title><xi:include href="xml/api-index-2.6.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-5-0" role="2.5.0"><title>Index of new symbols in 2.5.0</title><xi:include href="xml/api-index-2.5.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-4-0" role="2.4.0"><title>Index of new symbols in 2.4.0</title><xi:include href="xml/api-index-2.4.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-3-0" role="2.3.0"><title>Index of new symbols in 2.3.0</title><xi:include href="xml/api-index-2.3.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-2-0" role="2.2.0"><title>Index of new symbols in 2.2.0</title><xi:include href="xml/api-index-2.2.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-1-0" role="2.1.0"><title>Index of new symbols in 2.1.0</title><xi:include href="xml/api-index-2.1.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-2-0-0" role="2.0.0"><title>Index of new symbols in 2.0.0</title><xi:include href="xml/api-index-2.0.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-9-0" role="1.9.0"><title>Index of new symbols in 1.9.0</title><xi:include href="xml/api-index-1.9.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-8-6" role="1.8.6"><title>Index of new symbols in 1.8.6</title><xi:include href="xml/api-index-1.8.6.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-8-5" role="1.8.5"><title>Index of new symbols in 1.8.5</title><xi:include href="xml/api-index-1.8.5.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-8-1" role="1.8.1"><title>Index of new symbols in 1.8.1</title><xi:include href="xml/api-index-1.8.1.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-8-0" role="1.8.0"><title>Index of new symbols in 1.8.0</title><xi:include href="xml/api-index-1.8.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-7-7" role="1.7.7"><title>Index of new symbols in 1.7.7</title><xi:include href="xml/api-index-1.7.7.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-7-2" role="1.7.2"><title>Index of new symbols in 1.7.2</title><xi:include href="xml/api-index-1.7.2.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-6-0" role="1.6.0"><title>Index of new symbols in 1.6.0</title><xi:include href="xml/api-index-1.6.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-5-0" role="1.5.0"><title>Index of new symbols in 1.5.0</title><xi:include href="xml/api-index-1.5.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-4-3" role="1.4.3"><title>Index of new symbols in 1.4.3</title><xi:include href="xml/api-index-1.4.3.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-4-2" role="1.4.2"><title>Index of new symbols in 1.4.2</title><xi:include href="xml/api-index-1.4.2.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-4-0" role="1.4.0"><title>Index of new symbols in 1.4.0</title><xi:include href="xml/api-index-1.4.0.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-3-3" role="1.3.3"><title>Index of new symbols in 1.3.3</title><xi:include href="xml/api-index-1.3.3.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-2-3" role="1.2.3"><title>Index of new symbols in 1.2.3</title><xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-1-3" role="1.1.3"><title>Index of new symbols in 1.1.3</title><xi:include href="xml/api-index-1.1.3.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-1-2" role="1.1.2"><title>Index of new symbols in 1.1.2</title><xi:include href="xml/api-index-1.1.2.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-1-0-5" role="1.0.5"><title>Index of new symbols in 1.0.5</title><xi:include href="xml/api-index-1.0.5.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-42" role="0.9.42"><title>Index of new symbols in 0.9.42</title><xi:include href="xml/api-index-0.9.42.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-41" role="0.9.41"><title>Index of new symbols in 0.9.41</title><xi:include href="xml/api-index-0.9.41.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-39" role="0.9.39"><title>Index of new symbols in 0.9.39</title><xi:include href="xml/api-index-0.9.39.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-38" role="0.9.38"><title>Index of new symbols in 0.9.38</title><xi:include href="xml/api-index-0.9.38.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-33" role="0.9.33"><title>Index of new symbols in 0.9.33</title><xi:include href="xml/api-index-0.9.33.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-31" role="0.9.31"><title>Index of new symbols in 0.9.31</title><xi:include href="xml/api-index-0.9.31.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-30" role="0.9.30"><title>Index of new symbols in 0.9.30</title><xi:include href="xml/api-index-0.9.30.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-28" role="0.9.28"><title>Index of new symbols in 0.9.28</title><xi:include href="xml/api-index-0.9.28.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-26" role="0.9.26"><title>Index of new symbols in 0.9.26</title><xi:include href="xml/api-index-0.9.26.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-22" role="0.9.22"><title>Index of new symbols in 0.9.22</title><xi:include href="xml/api-index-0.9.22.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-21" role="0.9.21"><title>Index of new symbols in 0.9.21</title><xi:include href="xml/api-index-0.9.21.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-20" role="0.9.20"><title>Index of new symbols in 0.9.20</title><xi:include href="xml/api-index-0.9.20.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-11" role="0.9.11"><title>Index of new symbols in 0.9.11</title><xi:include href="xml/api-index-0.9.11.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-10" role="0.9.10"><title>Index of new symbols in 0.9.10</title><xi:include href="xml/api-index-0.9.10.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-8" role="0.9.8"><title>Index of new symbols in 0.9.8</title><xi:include href="xml/api-index-0.9.8.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-7" role="0.9.7"><title>Index of new symbols in 0.9.7</title><xi:include href="xml/api-index-0.9.7.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-5" role="0.9.5"><title>Index of new symbols in 0.9.5</title><xi:include href="xml/api-index-0.9.5.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-9-2" role="0.9.2"><title>Index of new symbols in 0.9.2</title><xi:include href="xml/api-index-0.9.2.xml"><xi:fallback /></xi:include></index>
+      <index id="api-index-0-6-0" role="0.6.0"><title>Index of new symbols in 0.6.0</title><xi:include href="xml/api-index-0.6.0.xml"><xi:fallback /></xi:include></index>
+
+      <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+  </part>
+
+  <note>
+    <para>
+      The current HarfBuzz codebase is versioned 2.x.x and is stable
+      and under active maintenance. This is what is used in latest
+      versions of Firefox, GNOME, ChromeOS, Chrome, LibreOffice,
+      XeTeX, Android, and KDE, among other places.
+    </para>
+    <para>
+      Prior to 2012, the original HarfBuzz codebase (which, these days, is
+      referred to as <emphasis>harfbuzz-old</emphasis>) was derived from code
+      in <ulink url="http://freetype.org/">FreeType</ulink>,
+      <ulink url="http://pango.org/">Pango</ulink>, and
+      <ulink url="http://qt-project.org/">Qt</ulink>.
+      It is <emphasis>not</emphasis> actively developed or  maintained, and is
+      extremely buggy. All users of harfbuzz-old are encouraged to switch over
+      to the new HarfBuzz as soon as possible.
+    </para>
+    <para>
+      To make this distinction clearer in discussions, the current HarfBuzz
+      codebase is sometimes referred to as <emphasis>harfbuzz-ng</emphasis>.
+    </para>
+    <para>
+      For reference purposes, the harfbuzz-old source tree is archived
+      <ulink url="http://cgit.freedesktop.org/harfbuzz.old/">here</ulink>.
+      There are no release tarballs of harfbuzz-old whatsoever.
+    </para>
+  </note>
+
+</book>

+ 0 - 0
libs/harfbuzz/docs/harfbuzz-overrides.txt


+ 794 - 0
libs/harfbuzz/docs/harfbuzz-sections.txt

@@ -0,0 +1,794 @@
+<SUBSECTION Private>
+HB_H_IN
+HB_OT_H_IN
+HB_AAT_H_IN
+</SECTION>
+
+<SECTION>
+<FILE>hb-aat-layout</FILE>
+HB_AAT_LAYOUT_NO_SELECTOR_INDEX
+hb_aat_layout_feature_type_t
+hb_aat_layout_feature_selector_t
+hb_aat_layout_feature_selector_info_t
+hb_aat_layout_feature_type_get_name_id
+hb_aat_layout_feature_type_get_selector_infos
+hb_aat_layout_get_feature_types
+hb_aat_layout_has_positioning
+hb_aat_layout_has_substitution
+hb_aat_layout_has_tracking
+</SECTION>
+
+<SECTION>
+<FILE>hb-blob</FILE>
+hb_blob_create
+hb_blob_create_or_fail
+hb_blob_create_from_file
+hb_blob_create_from_file_or_fail
+hb_blob_create_sub_blob
+hb_blob_copy_writable_or_fail
+hb_blob_destroy
+hb_blob_get_data
+hb_blob_get_data_writable
+hb_blob_get_empty
+hb_blob_get_length
+hb_blob_get_user_data
+hb_blob_is_immutable
+hb_blob_make_immutable
+hb_blob_reference
+hb_blob_set_user_data
+hb_blob_t
+hb_memory_mode_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-buffer</FILE>
+HB_SEGMENT_PROPERTIES_DEFAULT
+HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
+hb_buffer_create
+hb_buffer_create_similar
+hb_buffer_reference
+hb_buffer_get_empty
+hb_buffer_destroy
+hb_buffer_reset
+hb_buffer_clear_contents
+hb_buffer_pre_allocate
+hb_buffer_allocation_successful
+hb_buffer_add
+hb_buffer_add_codepoints
+hb_buffer_add_utf32
+hb_buffer_add_utf16
+hb_buffer_add_utf8
+hb_buffer_add_latin1
+hb_buffer_append
+hb_buffer_set_content_type
+hb_buffer_get_content_type
+hb_buffer_set_direction
+hb_buffer_get_direction
+hb_buffer_set_script
+hb_buffer_get_script
+hb_buffer_set_language
+hb_buffer_get_language
+hb_buffer_set_flags
+hb_buffer_get_flags
+hb_buffer_set_cluster_level
+hb_buffer_get_cluster_level
+hb_buffer_set_length
+hb_buffer_get_length
+hb_buffer_set_segment_properties
+hb_buffer_get_segment_properties
+hb_buffer_guess_segment_properties
+hb_buffer_set_unicode_funcs
+hb_buffer_get_unicode_funcs
+hb_buffer_set_user_data
+hb_buffer_get_user_data
+hb_buffer_get_glyph_infos
+hb_buffer_get_glyph_positions
+hb_buffer_has_positions
+hb_buffer_get_invisible_glyph
+hb_buffer_set_invisible_glyph
+hb_buffer_get_not_found_glyph
+hb_buffer_set_not_found_glyph
+hb_buffer_set_replacement_codepoint
+hb_buffer_get_replacement_codepoint
+hb_buffer_normalize_glyphs
+hb_buffer_reverse
+hb_buffer_reverse_range
+hb_buffer_reverse_clusters
+hb_buffer_serialize
+hb_buffer_serialize_glyphs
+hb_buffer_deserialize_glyphs
+hb_buffer_serialize_unicode
+hb_buffer_deserialize_unicode
+hb_buffer_serialize_format_from_string
+hb_buffer_serialize_format_to_string
+hb_buffer_serialize_list_formats
+hb_segment_properties_equal
+hb_segment_properties_hash
+hb_segment_properties_overlay
+hb_buffer_diff
+hb_buffer_set_message_func
+hb_buffer_t
+hb_glyph_info_get_glyph_flags
+hb_glyph_info_t
+hb_glyph_flags_t
+hb_glyph_position_t
+hb_buffer_content_type_t
+hb_buffer_flags_t
+hb_buffer_cluster_level_t
+hb_segment_properties_t
+hb_buffer_serialize_format_t
+hb_buffer_serialize_flags_t
+hb_buffer_diff_flags_t
+hb_buffer_message_func_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-common</FILE>
+hb_tag_from_string
+hb_tag_to_string
+hb_direction_from_string
+hb_direction_to_string
+hb_script_from_iso15924_tag
+hb_script_from_string
+hb_script_to_iso15924_tag
+hb_script_get_horizontal_direction
+hb_language_from_string
+hb_language_to_string
+hb_language_get_default
+hb_language_matches
+hb_feature_from_string
+hb_feature_to_string
+hb_variation_from_string
+hb_variation_to_string
+hb_bool_t
+hb_codepoint_t
+hb_destroy_func_t
+hb_direction_t
+hb_language_t
+hb_feature_t
+hb_variation_t
+hb_mask_t
+hb_position_t
+hb_tag_t
+hb_script_t
+hb_user_data_key_t
+HB_TAG
+HB_TAG_NONE
+HB_TAG_MAX
+HB_TAG_MAX_SIGNED
+HB_UNTAG
+HB_DIRECTION_REVERSE
+HB_DIRECTION_IS_BACKWARD
+HB_DIRECTION_IS_FORWARD
+HB_DIRECTION_IS_HORIZONTAL
+HB_DIRECTION_IS_VALID
+HB_DIRECTION_IS_VERTICAL
+HB_LANGUAGE_INVALID
+HB_FEATURE_GLOBAL_END
+HB_FEATURE_GLOBAL_START
+<SUBSECTION Private>
+HB_BEGIN_DECLS
+HB_END_DECLS
+hb_var_int_t
+hb_var_num_t
+int16_t
+int32_t
+int64_t
+int8_t
+uint16_t
+uint32_t
+uint64_t
+uint8_t
+<SUBSECTION Private>
+HB_EXTERN
+HB_DEPRECATED
+HB_DEPRECATED_FOR
+</SECTION>
+
+<SECTION>
+<FILE>hb-draw</FILE>
+hb_draw_funcs_t
+hb_draw_funcs_create
+hb_draw_funcs_destroy
+hb_draw_funcs_reference
+hb_draw_funcs_is_immutable
+hb_draw_funcs_make_immutable
+hb_draw_move_to_func_t
+hb_draw_funcs_set_move_to_func
+hb_draw_line_to_func_t
+hb_draw_funcs_set_line_to_func
+hb_draw_quadratic_to_func_t
+hb_draw_funcs_set_quadratic_to_func
+hb_draw_cubic_to_func_t
+hb_draw_funcs_set_cubic_to_func
+hb_draw_close_path_func_t
+hb_draw_funcs_set_close_path_func
+hb_draw_state_t
+HB_DRAW_STATE_DEFAULT
+hb_draw_move_to
+hb_draw_line_to
+hb_draw_quadratic_to
+hb_draw_cubic_to
+hb_draw_close_path
+</SECTION>
+
+<SECTION>
+<FILE>hb-deprecated</FILE>
+HB_BUFFER_FLAGS_DEFAULT
+HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
+HB_SCRIPT_CANADIAN_ABORIGINAL
+hb_font_funcs_set_glyph_func
+hb_font_get_glyph_func_t
+HB_MATH_GLYPH_PART_FLAG_EXTENDER
+HB_OT_MATH_SCRIPT
+hb_ot_layout_table_choose_script
+hb_ot_layout_table_find_script
+hb_ot_tag_from_language
+hb_ot_tags_from_script
+HB_OT_VAR_NO_AXIS_INDEX
+hb_ot_var_axis_t
+hb_ot_var_find_axis
+hb_ot_var_get_axes
+hb_unicode_eastasian_width_func_t
+hb_unicode_eastasian_width
+hb_unicode_funcs_set_eastasian_width_func
+HB_UNICODE_MAX_DECOMPOSITION_LEN
+hb_unicode_decompose_compatibility_func_t
+hb_unicode_decompose_compatibility
+hb_unicode_funcs_set_decompose_compatibility_func
+hb_font_funcs_set_glyph_v_kerning_func
+hb_font_get_glyph_v_kerning
+hb_font_get_glyph_v_kerning_func_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-coretext</FILE>
+HB_CORETEXT_TAG_KERX
+HB_CORETEXT_TAG_MORT
+HB_CORETEXT_TAG_MORX
+hb_coretext_face_create
+hb_coretext_font_create
+hb_coretext_face_get_cg_font
+hb_coretext_font_get_ct_font
+</SECTION>
+
+<SECTION>
+<FILE>hb-directwrite</FILE>
+hb_directwrite_face_create
+hb_directwrite_face_get_font_face
+</SECTION>
+
+<SECTION>
+<FILE>hb-face</FILE>
+hb_face_count
+hb_face_t
+hb_face_create
+hb_face_create_for_tables
+hb_face_destroy
+hb_face_get_empty
+hb_face_get_table_tags
+hb_face_get_glyph_count
+hb_face_get_index
+hb_face_get_upem
+hb_face_get_user_data
+hb_face_is_immutable
+hb_face_make_immutable
+hb_face_reference
+hb_face_reference_blob
+hb_face_reference_table
+hb_face_set_glyph_count
+hb_face_set_index
+hb_face_set_upem
+hb_face_set_user_data
+hb_face_collect_unicodes
+hb_face_collect_variation_selectors
+hb_face_collect_variation_unicodes
+hb_face_builder_create
+hb_face_builder_add_table
+hb_face_builder_sort_tables
+</SECTION>
+
+<SECTION>
+<FILE>hb-font</FILE>
+hb_font_add_glyph_origin_for_direction
+hb_font_create
+hb_font_create_sub_font
+hb_font_destroy
+hb_font_funcs_create
+hb_font_funcs_destroy
+hb_font_funcs_get_empty
+hb_font_funcs_get_user_data
+hb_font_funcs_is_immutable
+hb_font_funcs_make_immutable
+hb_font_funcs_reference
+hb_font_funcs_set_glyph_contour_point_func
+hb_font_funcs_set_glyph_extents_func
+hb_font_funcs_set_glyph_from_name_func
+hb_font_funcs_set_glyph_h_advance_func
+hb_font_funcs_set_glyph_h_advances_func
+hb_font_funcs_set_glyph_h_kerning_func
+hb_font_funcs_set_glyph_h_origin_func
+hb_font_funcs_set_glyph_name_func
+hb_font_funcs_set_glyph_shape_func
+hb_font_funcs_set_glyph_v_advance_func
+hb_font_funcs_set_glyph_v_advances_func
+hb_font_funcs_set_glyph_v_origin_func
+hb_font_funcs_set_nominal_glyph_func
+hb_font_funcs_set_nominal_glyphs_func
+hb_font_funcs_set_user_data
+hb_font_funcs_set_variation_glyph_func
+hb_font_funcs_t
+hb_font_get_empty
+hb_font_get_face
+hb_font_get_glyph
+hb_font_get_glyph_advance_for_direction
+hb_font_get_glyph_advance_func_t
+hb_font_get_glyph_advances_for_direction
+hb_font_get_glyph_advances_func_t
+hb_font_get_glyph_contour_point
+hb_font_get_glyph_contour_point_for_origin
+hb_font_get_glyph_contour_point_func_t
+hb_font_get_glyph_extents
+hb_font_get_glyph_extents_for_origin
+hb_font_get_glyph_extents_func_t
+hb_font_get_glyph_from_name
+hb_font_get_glyph_from_name_func_t
+hb_font_get_glyph_h_advance
+hb_font_get_glyph_h_advance_func_t
+hb_font_get_glyph_h_advances
+hb_font_get_glyph_h_advances_func_t
+hb_font_get_glyph_h_kerning
+hb_font_get_glyph_h_kerning_func_t
+hb_font_get_glyph_h_origin
+hb_font_get_glyph_h_origin_func_t
+hb_font_get_glyph_kerning_for_direction
+hb_font_get_glyph_kerning_func_t
+hb_font_get_glyph_name
+hb_font_get_glyph_name_func_t
+hb_font_get_glyph_origin_for_direction
+hb_font_get_glyph_origin_func_t
+hb_font_get_glyph_shape
+hb_font_get_glyph_shape_func_t
+hb_font_get_glyph_v_advance
+hb_font_get_glyph_v_advance_func_t
+hb_font_get_glyph_v_advances
+hb_font_get_glyph_v_advances_func_t
+hb_font_get_glyph_v_origin
+hb_font_get_glyph_v_origin_func_t
+hb_font_get_nominal_glyph
+hb_font_get_nominal_glyph_func_t
+hb_font_get_nominal_glyphs
+hb_font_get_nominal_glyphs_func_t
+hb_font_get_parent
+hb_font_get_ppem
+hb_font_get_ptem
+hb_font_get_scale
+hb_font_get_synthetic_slant
+hb_font_get_user_data
+hb_font_get_variation_glyph
+hb_font_get_variation_glyph_func_t
+hb_font_get_var_coords_design
+hb_font_get_var_coords_normalized
+hb_font_glyph_from_string
+hb_font_glyph_to_string
+hb_font_is_immutable
+hb_font_make_immutable
+hb_font_get_serial
+hb_font_changed
+hb_font_reference
+hb_font_set_face
+hb_font_set_funcs
+hb_font_set_funcs_data
+hb_font_set_parent
+hb_font_set_ppem
+hb_font_set_ptem
+hb_font_set_scale
+hb_font_set_synthetic_slant
+hb_font_set_user_data
+hb_font_set_variations
+hb_font_set_var_coords_design
+hb_font_set_var_coords_normalized
+hb_font_set_var_named_instance
+hb_font_subtract_glyph_origin_for_direction
+hb_font_t
+hb_reference_table_func_t
+hb_font_funcs_set_font_h_extents_func
+hb_font_funcs_set_font_v_extents_func
+hb_font_get_extents_for_direction
+hb_font_get_font_extents_func_t
+hb_font_get_font_h_extents_func_t
+hb_font_get_font_v_extents_func_t
+hb_font_get_h_extents
+hb_font_get_v_extents
+hb_font_extents_t
+hb_glyph_extents_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-ft</FILE>
+hb_ft_face_create
+hb_ft_face_create_cached
+hb_ft_face_create_referenced
+hb_ft_font_create
+hb_ft_font_create_referenced
+hb_ft_font_changed
+hb_ft_font_get_face
+hb_ft_font_lock_face
+hb_ft_font_unlock_face
+hb_ft_font_set_load_flags
+hb_ft_font_get_load_flags
+hb_ft_font_set_funcs
+hb_ft_hb_font_changed
+</SECTION>
+
+<SECTION>
+<FILE>hb-gdi</FILE>
+hb_gdi_face_create
+</SECTION>
+
+<SECTION>
+<FILE>hb-glib</FILE>
+hb_glib_get_unicode_funcs
+hb_glib_script_from_script
+hb_glib_script_to_script
+hb_glib_blob_create
+</SECTION>
+
+<SECTION>
+<FILE>hb-graphite2</FILE>
+HB_GRAPHITE2_TAG_SILF
+hb_graphite2_face_get_gr_face
+hb_graphite2_font_get_gr_font
+</SECTION>
+
+<SECTION>
+<FILE>hb-icu</FILE>
+hb_icu_get_unicode_funcs
+hb_icu_script_from_script
+hb_icu_script_to_script
+</SECTION>
+
+<SECTION>
+<FILE>hb-map</FILE>
+HB_MAP_VALUE_INVALID
+hb_map_allocation_successful
+hb_map_clear
+hb_map_copy
+hb_map_create
+hb_map_del
+hb_map_destroy
+hb_map_get
+hb_map_get_empty
+hb_map_get_population
+hb_map_is_equal
+hb_map_get_user_data
+hb_map_has
+hb_map_hash
+hb_map_is_empty
+hb_map_reference
+hb_map_set
+hb_map_set_user_data
+hb_map_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-color</FILE>
+hb_color_t
+HB_COLOR
+hb_color_get_alpha
+hb_color_get_blue
+hb_color_get_green
+hb_color_get_red
+hb_ot_color_glyph_get_layers
+hb_ot_color_glyph_reference_png
+hb_ot_color_glyph_reference_svg
+hb_ot_color_has_layers
+hb_ot_color_has_palettes
+hb_ot_color_has_png
+hb_ot_color_has_svg
+hb_ot_color_layer_t
+hb_ot_color_palette_color_get_name_id
+hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_colors
+hb_ot_color_palette_get_count
+hb_ot_color_palette_get_flags
+hb_ot_color_palette_get_name_id
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-font</FILE>
+hb_ot_font_set_funcs
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-name</FILE>
+hb_ot_name_id_t
+HB_OT_NAME_ID_INVALID
+hb_ot_name_entry_t
+hb_ot_name_list_names
+hb_ot_name_get_utf16
+hb_ot_name_get_utf32
+hb_ot_name_get_utf8
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-layout</FILE>
+HB_OT_MAX_TAGS_PER_LANGUAGE
+HB_OT_MAX_TAGS_PER_SCRIPT
+HB_OT_TAG_DEFAULT_LANGUAGE
+HB_OT_TAG_DEFAULT_SCRIPT
+hb_ot_tag_to_language
+hb_ot_tag_to_script
+hb_ot_tags_from_script_and_language
+hb_ot_tags_to_script_and_language
+HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
+HB_OT_LAYOUT_NO_FEATURE_INDEX
+HB_OT_LAYOUT_NO_SCRIPT_INDEX
+HB_OT_LAYOUT_NO_VARIATIONS_INDEX
+HB_OT_TAG_BASE
+HB_OT_TAG_GDEF
+HB_OT_TAG_GPOS
+HB_OT_TAG_GSUB
+HB_OT_TAG_JSTF
+hb_ot_layout_baseline_tag_t
+hb_ot_layout_collect_lookups
+hb_ot_layout_collect_features
+hb_ot_layout_feature_get_characters
+hb_ot_layout_feature_get_lookups
+hb_ot_layout_feature_get_name_ids
+hb_ot_layout_feature_with_variations_get_lookups
+hb_ot_layout_get_attach_points
+hb_ot_layout_get_horizontal_baseline_tag_for_script
+hb_ot_layout_get_baseline
+hb_ot_layout_get_baseline_with_fallback
+hb_ot_layout_get_glyph_class
+hb_ot_layout_get_glyphs_in_class
+hb_ot_layout_get_ligature_carets
+hb_ot_layout_get_size_params
+hb_ot_layout_glyph_class_t
+hb_ot_layout_has_glyph_classes
+hb_ot_layout_has_positioning
+hb_ot_layout_has_substitution
+hb_ot_layout_language_find_feature
+hb_ot_layout_language_get_feature_indexes
+hb_ot_layout_language_get_feature_tags
+hb_ot_layout_language_get_required_feature
+hb_ot_layout_lookup_collect_glyphs
+hb_ot_layout_lookup_get_glyph_alternates
+hb_ot_layout_lookup_get_optical_bound
+hb_ot_layout_lookup_substitute_closure
+hb_ot_layout_lookups_substitute_closure
+hb_ot_layout_lookup_would_substitute
+hb_ot_layout_script_find_language
+hb_ot_layout_script_get_language_tags
+hb_ot_layout_script_select_language
+hb_ot_layout_table_find_feature_variations
+hb_ot_layout_table_get_feature_tags
+hb_ot_layout_table_get_script_tags
+hb_ot_layout_table_get_lookup_count
+hb_ot_layout_table_select_script
+hb_ot_shape_plan_collect_lookups
+hb_ot_layout_language_get_required_feature_index
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-math</FILE>
+HB_OT_TAG_MATH
+HB_OT_TAG_MATH_SCRIPT
+hb_ot_math_constant_t
+hb_ot_math_kern_t
+hb_ot_math_kern_entry_t
+hb_ot_math_glyph_variant_t
+hb_ot_math_glyph_part_flags_t
+hb_ot_math_glyph_part_t
+hb_ot_math_has_data
+hb_ot_math_get_constant
+hb_ot_math_get_glyph_italics_correction
+hb_ot_math_get_glyph_top_accent_attachment
+hb_ot_math_get_glyph_kerning
+hb_ot_math_get_glyph_kernings
+hb_ot_math_is_glyph_extended_shape
+hb_ot_math_get_glyph_variants
+hb_ot_math_get_min_connector_overlap
+hb_ot_math_get_glyph_assembly
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-meta</FILE>
+hb_ot_meta_tag_t
+hb_ot_meta_get_entry_tags
+hb_ot_meta_reference_entry
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-metrics</FILE>
+hb_ot_metrics_tag_t
+hb_ot_metrics_get_position
+hb_ot_metrics_get_position_with_fallback
+hb_ot_metrics_get_variation
+hb_ot_metrics_get_x_variation
+hb_ot_metrics_get_y_variation
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-shape</FILE>
+hb_ot_shape_glyphs_closure
+</SECTION>
+
+<SECTION>
+<FILE>hb-ot-var</FILE>
+HB_OT_TAG_VAR_AXIS_ITALIC
+HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
+HB_OT_TAG_VAR_AXIS_SLANT
+HB_OT_TAG_VAR_AXIS_WEIGHT
+HB_OT_TAG_VAR_AXIS_WIDTH
+hb_ot_var_has_data
+hb_ot_var_axis_flags_t
+hb_ot_var_axis_info_t
+hb_ot_var_find_axis_info
+hb_ot_var_get_axis_count
+hb_ot_var_get_axis_infos
+hb_ot_var_get_named_instance_count
+hb_ot_var_named_instance_get_subfamily_name_id
+hb_ot_var_named_instance_get_postscript_name_id
+hb_ot_var_named_instance_get_design_coords
+hb_ot_var_normalize_variations
+hb_ot_var_normalize_coords
+</SECTION>
+
+<SECTION>
+<FILE>hb-set</FILE>
+HB_SET_VALUE_INVALID
+hb_set_add
+hb_set_add_range
+hb_set_add_sorted_array
+hb_set_allocation_successful
+hb_set_copy
+hb_set_clear
+hb_set_create
+hb_set_del
+hb_set_del_range
+hb_set_destroy
+hb_set_get_empty
+hb_set_get_max
+hb_set_get_min
+hb_set_get_population
+hb_set_get_user_data
+hb_set_has
+hb_set_hash
+hb_set_intersect
+hb_set_invert
+hb_set_is_empty
+hb_set_is_equal
+hb_set_is_subset
+hb_set_next
+hb_set_next_range
+hb_set_next_many
+hb_set_previous
+hb_set_previous_range
+hb_set_reference
+hb_set_set
+hb_set_set_user_data
+hb_set_subtract
+hb_set_symmetric_difference
+hb_set_t
+hb_set_union
+</SECTION>
+
+<SECTION>
+<FILE>hb-shape</FILE>
+hb_shape
+hb_shape_full
+hb_shape_list_shapers
+</SECTION>
+
+<SECTION>
+<FILE>hb-shape-plan</FILE>
+hb_shape_plan_create
+hb_shape_plan_create_cached
+hb_shape_plan_create2
+hb_shape_plan_create_cached2
+hb_shape_plan_destroy
+hb_shape_plan_execute
+hb_shape_plan_get_empty
+hb_shape_plan_get_shaper
+hb_shape_plan_get_user_data
+hb_shape_plan_reference
+hb_shape_plan_set_user_data
+hb_shape_plan_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-unicode</FILE>
+HB_UNICODE_MAX
+hb_unicode_combining_class
+hb_unicode_combining_class_func_t
+hb_unicode_combining_class_t
+hb_unicode_compose
+hb_unicode_compose_func_t
+hb_unicode_decompose
+hb_unicode_decompose_func_t
+hb_unicode_funcs_create
+hb_unicode_funcs_destroy
+hb_unicode_funcs_get_default
+hb_unicode_funcs_get_empty
+hb_unicode_funcs_get_parent
+hb_unicode_funcs_get_user_data
+hb_unicode_funcs_is_immutable
+hb_unicode_funcs_make_immutable
+hb_unicode_funcs_reference
+hb_unicode_funcs_set_combining_class_func
+hb_unicode_funcs_set_compose_func
+hb_unicode_funcs_set_decompose_func
+hb_unicode_funcs_set_general_category_func
+hb_unicode_funcs_set_mirroring_func
+hb_unicode_funcs_set_script_func
+hb_unicode_funcs_set_user_data
+hb_unicode_funcs_t
+hb_unicode_general_category
+hb_unicode_general_category_func_t
+hb_unicode_general_category_t
+hb_unicode_mirroring
+hb_unicode_mirroring_func_t
+hb_unicode_script
+hb_unicode_script_func_t
+</SECTION>
+
+<SECTION>
+<FILE>hb-uniscribe</FILE>
+hb_uniscribe_font_get_hfont
+hb_uniscribe_font_get_logfontw
+</SECTION>
+
+<SECTION>
+<FILE>hb-version</FILE>
+HB_VERSION_ATLEAST
+HB_VERSION_MAJOR
+HB_VERSION_MICRO
+HB_VERSION_MINOR
+HB_VERSION_STRING
+hb_version
+hb_version_atleast
+hb_version_string
+</SECTION>
+
+<SECTION>
+<FILE>hb-style</FILE>
+hb_style_tag_t
+hb_style_get_value
+</SECTION>
+
+<SECTION>
+<FILE>hb-subset</FILE>
+hb_subset_flags_t
+hb_subset_input_t
+hb_subset_sets_t
+hb_subset_plan_t
+hb_subset_input_create_or_fail
+hb_subset_input_reference
+hb_subset_input_destroy
+hb_subset_input_set_user_data
+hb_subset_input_get_user_data
+hb_subset_input_get_flags
+hb_subset_input_set_flags
+hb_subset_input_unicode_set
+hb_subset_input_glyph_set
+hb_subset_input_set
+hb_subset_or_fail
+hb_subset_plan_create_or_fail
+hb_subset_plan_reference
+hb_subset_plan_destroy
+hb_subset_plan_set_user_data
+hb_subset_plan_get_user_data
+hb_subset_plan_execute_or_fail
+hb_subset_plan_unicode_to_old_glyph_mapping
+hb_subset_plan_new_to_old_glyph_mapping
+hb_subset_plan_old_to_new_glyph_mapping
+<SUBSECTION Private>
+hb_link_t
+hb_object_t
+hb_subset_repack_or_fail
+hb_subset_preprocess
+hb_subset_input_pin_axis_location
+hb_subset_input_pin_axis_to_default
+</SECTION>

+ 66 - 0
libs/harfbuzz/docs/meson.build

@@ -0,0 +1,66 @@
+if build_machine.system() == 'windows'
+  message('Skipping gtk-doc while building on Windows')
+  subdir_done()
+endif
+
+if not find_program('gtkdoc-scan', required: get_option('docs')).found()
+  message('Not building documentation as gtk-doc was not found')
+  subdir_done()
+endif
+
+conf.set('HAVE_GTK_DOC', 1)
+
+gnome = import('gnome')
+
+docconf = configuration_data()
+docconf.set('HB_VERSION', meson.project_version())
+
+version_xml = configure_file(input: 'version.xml.in',
+  output: 'version.xml',
+  configuration: docconf)
+
+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-opentype-features.xml',
+  'usermanual-clusters.xml',
+  'usermanual-utilities.xml',
+  'usermanual-integration.xml',
+  version_xml,
+]
+
+html_images = [
+  'HarfBuzz.png',
+  'HarfBuzz.svg',
+]
+
+ignore_headers = [
+  'hb-gobject.h',
+  'hb-gobject-enums.h',
+  'hb-gobject-enums-tmp.h',
+  'hb-gobject-structs.h',
+]
+
+gnome.gtkdoc('harfbuzz',
+  main_sgml: 'harfbuzz-docs.xml',
+  src_dir: [meson.current_source_dir() / '..' / 'src',
+            meson.current_build_dir() / '..' / 'src',
+           ],
+  scan_args: ['--deprecated-guards=HB_DISABLE_DEPRECATED',
+              '--ignore-decorators=HB_EXTERN|HB_DEPRECATED',
+             ],
+  mkdb_args: ['--source-suffixes=h,cc',
+              '--xml-mode',
+              '--output-format=xml',
+             ],
+  content_files: content_files,
+  html_assets: html_images,
+  ignore_headers: ignore_headers,
+  dependencies: [libharfbuzz_dep],
+  install: true)

+ 294 - 0
libs/harfbuzz/docs/repacker.md

@@ -0,0 +1,294 @@
+# Introduction
+
+Several tables in the opentype format are formed internally by a graph of subtables. Parent node's
+reference their children through the use of positive offsets, which are typically 16 bits wide.
+Since offsets are always positive this forms a directed acyclic graph. For storage in the font file
+the graph must be given a topological ordering and then the subtables packed in serial according to
+that ordering. Since 16 bit offsets have a maximum value of 65,535 if the distance between a parent
+subtable and a child is more then 65,535 bytes then it's not possible for the offset to encode that
+edge.
+
+For many fonts with complex layout rules (such as Arabic) it's not unusual for the tables containing
+layout rules ([GSUB/GPOS](https://docs.microsoft.com/en-us/typography/opentype/spec/gsub)) to be
+larger than 65kb. As a result these types of fonts are susceptible to offset overflows when
+serializing to the binary font format.
+
+Offset overflows can happen for a variety of reasons and require different strategies to resolve:
+*  Simple overflows can often be resolved with a different topological ordering.
+*  If a subtable has many parents this can result in the link from furthest parent(s)
+   being at risk for overflows. In these cases it's possible to duplicate the shared subtable which
+   allows it to be placed closer to it's parent.
+*  If subtables exist which are themselves larger than 65kb it's not possible for any offsets to point
+   past them. In these cases the subtable can usually be split into two smaller subtables to allow
+   for more flexibility in the ordering.
+*  In GSUB/GPOS overflows from Lookup subtables can be resolved by changing the Lookup to an extension
+   lookup which uses a 32 bit offset instead of 16 bit offset.
+
+In general there isn't a simple solution to produce an optimal topological ordering for a given graph.
+Finding an ordering which doesn't overflow is a NP hard problem. Existing solutions use heuristics
+which attempt a combination of the above strategies to attempt to find a non-overflowing configuration.
+
+The harfbuzz subsetting library
+[includes a repacking algorithm](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh)
+which is used to resolve offset overflows that are present in the subsetted tables it produces. This
+document provides a deep dive into how the harfbuzz repacking algorithm works.
+
+Other implementations exist, such as in
+[fontTools](https://github.com/fonttools/fonttools/blob/7af43123d49c188fcef4e540fa94796b3b44e858/Lib/fontTools/ttLib/tables/otBase.py#L72), however these are not covered in this document.
+
+# Foundations
+
+There's four key pieces to the harfbuzz approach:
+
+*  Subtable Graph: a table's internal structure is abstracted out into a lightweight graph
+   representation where each subtable is a node and each offset forms an edge. The nodes only need
+   to know how many bytes the corresponding subtable occupies. This lightweight representation can
+   be easily modified to test new ordering's and strategies as the repacking algorithm iterates.
+
+*  [Topological sorting algorithm](https://en.wikipedia.org/wiki/Topological_sorting): an algorithm
+   which given a graph gives a linear sorting of the nodes such that all offsets will be positive.
+
+*  Overflow check: given a graph and a topological sorting it checks if there will be any overflows
+   in any of the offsets. If there are overflows it returns a list of (parent, child) tuples that
+   will overflow. Since the graph has information on the size of each subtable it's straightforward
+   to calculate the final position of each subtable and then check if any offsets to it will
+   overflow.
+
+*  Content Aware Preprocessing: if the overflow resolver is aware of the format of the underlying
+   tables (eg. GSUB, GPOS) then in some cases preprocessing can be done to increase the chance of
+   successfully packing the graph. For example for GSUB and GPOS we can preprocess the graph and
+   promote lookups to extension lookups (upgrades a 16 bit offset to 32 bits) or split large lookup
+   subtables into two or more pieces.
+
+*  Offset resolution strategies: given a particular occurrence of an overflow these strategies
+   modify the graph to attempt to resolve the overflow.
+
+# High Level Algorithm
+
+```
+def repack(graph):
+  graph.topological_sort()
+
+  if (graph.will_overflow())
+    preprocess(graph)
+    assign_spaces(graph)
+    graph.topological_sort()
+
+  while (overflows = graph.will_overflow()):
+    for overflow in overflows:
+      apply_offset_resolution_strategy (overflow, graph)
+    graph.topological_sort()
+```
+
+The actual code for this processing loop can be found in the function hb_resolve_overflows () of
+[hb-repacker.hh](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh).
+
+# Topological Sorting Algorithms
+
+The harfbuzz repacker uses two different algorithms for topological sorting:
+*  [Kahn's Algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm)
+*  Sorting by shortest distance
+
+Kahn's algorithm is approximately twice as fast as the shortest distance sort so that is attempted
+first (only on the first topological sort). If it fails to eliminate overflows then shortest distance
+sort will be used for all subsequent topological sorting operations.
+
+## Shortest Distance Sort
+
+This algorithm orders the nodes based on total distance to each node. Nodes with a shorter distance
+are ordered first.
+
+The "weight" of an edge is the sum of the size of the sub-table being pointed to plus 2^16 for a 16 bit
+offset and 2^32 for a 32 bit offset.
+
+The distance of a node is the sum of all weights along the shortest path from the root to that node
+plus a priority modifier (used to change where nodes are placed by moving increasing or
+decreasing the effective distance). Ties between nodes with the same distance are broken based
+on the order of the offset in the sub table bytes.
+
+The shortest distance to each node is determined using
+[Djikstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). Then the topological
+ordering is produce by applying a modified version of Kahn's algorithm that uses a priority queue
+based on the shortest distance to each node.
+
+## Optimizing the Sorting
+
+The topological sorting operation is the core of the repacker and is run on each iteration so it needs
+to be as fast as possible. There's a few things that are done to speed up subsequent sorting
+operations:
+
+*  The number of incoming edges to each node is cached. This is required by the Kahn's algorithm
+   portion of both sorts. Where possible when the graph is modified we manually update the cached
+   edge counts of affected nodes.
+
+*  The distance to each node is cached. Where possible when the graph is modified we manually update
+   the cached distances of any affected nodes.
+
+Caching these values allows the repacker to avoid recalculating them for the full graph on each
+iteration.
+
+The other important factor to speed is a fast priority queue which is a core datastructure to
+the topological sorting algorithm. Currently a basic heap based queue is used. Heap based queue's
+don't support fast priority decreases, but that can be worked around by just adding redundant entries
+to the priority queue and filtering the older ones out when poppping off entries. This is based
+on the recommendations in
+[a study of the practical performance of priority queues in Dijkstra's algorithm](https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf)
+
+## Special Handling of 32 bit Offsets
+
+If a graph contains multiple 32 bit offsets then the shortest distance sorting will be likely be
+suboptimal. For example consider the case where a graph contains two 32 bit offsets that each point
+to a subgraph which are not connected to each other. The shortest distance sort will interleave the
+subtables of the two subgraphs, potentially resulting in overflows. Since each of these subgraphs are
+independent of each other, and 32 bit offsets can point extremely long distances a better strategy is
+to pack the first subgraph in it's entirety and then have the second subgraph packed after with the 32
+bit offset pointing over the first subgraph. For example given the graph:
+
+
+```
+a--- b -- d -- f
+ \
+  \_ c -- e -- g
+```
+
+Where the links from a to b and a to c are 32 bit offsets, the shortest distance sort would be:
+
+```
+a, b, c, d, e, f, g
+
+```
+
+If nodes d and e have a combined size greater than 65kb then the offset from d to f will overflow.
+A better ordering is:
+
+```
+a, b, d, f, c, e, g
+```
+
+The ability for 32 bit offsets to point long distances is utilized to jump over the subgraph of
+b which gives the remaining 16 bit offsets a better chance of not overflowing.
+
+The above is an ideal situation where the subgraphs are disconnected from each other, in practice
+this is often not this case. So this idea can be generalized as follows:
+
+If there is a subgraph that is only reachable from one or more 32 bit offsets, then:
+*  That subgraph can be treated as an independent unit and all nodes of the subgraph packed in isolation
+   from the rest of the graph.
+*  In a table that occupies less than 4gb of space (in practice all fonts), that packed independent
+   subgraph can be placed anywhere after the parent nodes without overflowing the 32 bit offsets from
+   the parent nodes.
+
+The sorting algorithm incorporates this via a "space" modifier that can be applied to nodes in the
+graph. By default all nodes are treated as being in space zero. If a node is given a non-zero space, n,
+then the computed distance to the node will be modified by adding `n * 2^32`. This will cause that
+node and it's descendants to be packed between all nodes in space n-1 and space n+1. Resulting in a
+topological sort like:
+
+```
+| space 0 subtables | space 1 subtables | .... | space n subtables |
+```
+
+The assign_spaces() step in the high level algorithm is responsible for identifying independent
+subgraphs and assigning unique spaces to each one. More information on the space assignment can be
+found in the next section.
+
+# Graph Preprocessing
+
+For certain table types we can preprocess and modify the graph structure to reduce the occurences
+of overflows. Currently the repacker implements preprocessing only for GPOS and GSUB tables.
+
+## GSUB/GPOS Table Splitting
+
+The GSUB/GPOS preprocessor scans each lookup subtable and determines if the subtable's children are
+so large that no overflow resolution is possible (for example a single subtable that exceeds 65kb
+cannot be pointed over). When such cases are detected table splitting is invoked:
+
+* The subtable is first analyzed to determine the smallest number of split points that will allow
+  for successful offset overflow resolution.
+
+* Then the subtable in the graph representation is modified to actually perform the split at the
+  previously computed split points. At a high level splits are done by inserting new subtables
+  which contain a subset of the data of the original subtable and then shrinking the original subtable.
+
+Table splitting must be aware of the underlying format of each subtable type and thus needs custom
+code for each subtable type. Currently subtable splitting is only supported for GPOS subtable types.
+
+## GSUB/GPOS Extension Lookup Promotion
+
+In GSUB/GPOS tables lookups can be regular lookups which use 16 bit offsets to the children subtables
+or extension lookups which use 32 bit offsets to the children subtables. If the sub graph of all
+regular lookups is too large then it can be difficult to find an overflow free configuration. This
+can be remedied by promoting one or more regular lookups to extension lookups.
+
+During preprocessing the graph is scanned to determine the size of the subgraph of regular lookups.
+If the graph is found to be too big then the analysis finds a set of lookups to promote to reduce
+the subgraph size. Lastly the graph is modified to convert those lookups to extension lookups.
+
+# Offset Resolution Strategies
+
+## Space Assignment
+
+The goal of space assignment is to find connected subgraphs that are only reachable via 32 bit offsets
+and then assign each such subgraph to a unique non-zero space. The algorithm is roughly:
+
+1.  Collect the set, `S`, of nodes that are children of 32 bit offsets.
+
+2.  Do a directed traversal from each node in `S` and collect all encountered nodes into set `T`.
+    Mark all nodes in the graph that are not in `T` as being in space 0.
+
+3.  Set `next_space = 1`.
+
+4.  While set `S` is not empty:
+
+    a.  Pick a node `n` in set `S` then perform an undirected graph traversal and find the set `Q` of
+        nodes that are reachable from `n`.
+
+    b.  During traversal if a node, `m`, has a edge to a node in space 0 then `m` must be duplicated
+        to disconnect it from space 0.
+
+    d.  Remove all nodes in `Q` from `S` and assign all nodes in `Q` to `next_space`.
+
+
+    c.  Increment `next_space` by one.
+
+
+## Manual Iterative Resolutions
+
+For each overflow in each iteration the algorithm will attempt to apply offset overflow resolution
+strategies to eliminate the overflow. The type of strategy applied is dependent on the characteristics
+of the overflowing link:
+
+*  If the overflowing offset is inside a space other than space 0 and the subgraph space has more
+   than one 32 bit offset pointing into the subgraph then subdivide the space by moving subgraph
+   from one of the 32 bit offsets into a new space via the duplication of shared nodes.
+
+*  If the overflowing offset is pointing to a subtable with more than one incoming edge: duplicate
+   the node so that the overflowing offset is pointing at it's own copy of that node.
+
+*  Otherwise, attempt to move the child subtable closer to it's parent. This is accomplished by
+   raising the priority of all children of the parent. Next time the topological sort is run the
+   children will be ordered closer to the parent.
+
+# Test Cases
+
+The harfbuzz repacker has tests defined using generic graphs: https://github.com/harfbuzz/harfbuzz/blob/main/src/test-repacker.cc
+
+# Future Improvements
+
+Currently for GPOS tables the repacker implementation is sufficient to handle both subsetting and the
+general case of font compilation repacking. However for GSUB the repacker is only sufficient for
+subsetting related overflows. To enable general case repacking of GSUB, support for splitting of
+GSUB subtables will need to be added. Other table types such as COLRv1 shouldn't require table
+splitting due to the wide use of 24 bit offsets throughout the table.
+
+Beyond subtable splitting there are a couple of "nice to have" improvements, but these are not required
+to support the general case:
+
+*  Extension demotion: currently extension promotion is supported but in some cases if the non-extension
+   subgraph is underfilled then packed size can be reduced by demoting extension lookups back to regular
+   lookups.
+
+*  Currently only children nodes are moved to resolve offsets. However, in many cases moving a parent
+   node closer to it's children will have less impact on the size of other offsets. Thus the algorithm
+   should use a heuristic (based on parent and child subtable sizes) to decide if the children's
+   priority should be increased or the parent's priority decreased.

+ 178 - 0
libs/harfbuzz/docs/serializer.md

@@ -0,0 +1,178 @@
+# Introduction
+
+In hb-subset serialization is the process of writing the subsetted font
+tables out to actual bytes in the final format. All serialization works
+through an object called the serialize context
+([hb_serialize_context_t](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-serialize.hh)).
+
+Internally the serialize context holds a fixed size memory buffer. For simple
+tables the final bytes are written into the buffer sequentially to produce
+the final serialized bytes.
+
+## Simple Tables
+
+Simple tables are tables that do not use offset graphs.
+
+To write a struct into the serialization context, first you call an
+allocation method on the context which requests a writable array of bytes of
+a fixed size. If the requested array will not exceed the bounds of the fixed
+buffer the serializer will return a pointer to the next unwritten portion
+of the buffer. Then the struct is cast onto the returned pointer and values
+are written to the structs fields.
+
+Internally the serialization context ends up looking like:
+
+```
++-------+-------+-----+-------+--------------+
+| Obj 1 | Obj 2 | ... | Obj N | Unused Space |
++-------+-------+-----+-------+--------------+
+```
+
+Here Obj N, is the object currently being written.
+
+## Complex Tables
+
+Complex tables are made up of graphs of objects, where offset's are used
+to form the edges of the graphs. Each object is a continuous slice of bytes
+that contains zero or more offsets pointing to more objects.
+
+In this case the serialization buffer has a different layout:
+
+```
+|- in progress objects -|              |--- packed objects --|
++-----------+-----------+--------------+-------+-----+-------+
+|  Obj n+2  |  Obj n+1  | Unused Space | Obj n | ... | Obj 0 |
++-----------+-----------+--------------+-------+-----+-------+
+|----------------------->              <---------------------|
+```
+
+The buffer holds two stacks:
+
+1. In progress objects are held in a stack starting from the start of buffer
+   that grows towards the end of the buffer.
+
+2. Packed objects are held in a stack that starts at the end of the buffer
+   and grows towards the start of the buffer.
+
+Once the object on the top of the in progress stack is finished being written
+its bytes are popped from the in progress stack and copied to the top of
+the packed objects stack. In the example above, finalizing Obj n+1
+would result in the following state:
+
+```
++---------+--------------+---------+-------+-----+-------+
+| Obj n+2 | Unused Space | Obj n+1 | Obj n | ... | Obj 0 |
++---------+--------------+---------+-------+-----+-------+
+```
+
+Each packed object is associated with an ID, it's zero based position in the packed
+objects stack. In this example Obj 0, would have an ID of 0.
+
+During serialization offsets that link from one object to another are stored
+using object ids. The serialize context maintains a list of links between
+objects. Each link records the parent object id, the child object id, the position
+of the offset field within the parent object, and the width of the offset.
+
+Links are always added to the current in progress object and you can only link too
+objects that have been packed and thus have an ID.
+
+### Object De-duplication
+
+An important optimization in packing offset graphs is de-duplicating equivalent objects. If you
+have two or more parent objects that point to child objects that are equivalent then you only need
+to encode the child once and can have the parents point to the same child. This can significantly
+reduce the final size of a serialized graph.
+
+During packing of an inprogress object the serialization context checks if any existing packed
+objects are equivalent to the object being packed. Here equivalence means the object has the
+exact same bytes and all of it's links are equivalent. If an equivalent object is found the
+in progress object is discarded and not copied to the packed object stack. The object id of
+the equivalent object is instead returned. Thus parent objects will then link to the existing
+equivalent object.
+
+To find equivalent objects the serialization context maintains a hashmap from object to the canonical
+object id.
+
+### Link Resolution
+
+Once all objects have been packed the next step is to assign actual values to all of the offset
+fields. Prior to this point all links in the graph have been recorded using object id's. For each
+link the resolver computes the offset between the parent and child and writes the offset into
+the serialization buffer at the appropriate location.
+
+### Offset Overflow Resolution
+
+If during link resolution the resolver finds that an offsets value would exceed what can be encoded
+in that offset field link resolution is aborted and the offset overflow resolver is invoked.
+That process is documented [here](reapcker.md).
+
+
+### Example of Complex Serialization
+
+
+If we wanted to serialize the following graph:
+
+```
+a--b--d
+ \   /
+   c
+```
+
+Serializer would be called like this:
+
+```c++
+hb_serialize_context_t ctx;
+
+struct root {
+  char name;
+  Offset16To<child> child_1;
+  Offset16To<child> child_2;
+}
+
+struct child {
+  char name;
+  Offset16To<char> leaf;
+}
+
+// Object A.
+ctx->push();
+root* a = ctx->start_embed<root> ();
+ctx->extend_min (a);
+a->name = 'a';
+
+// Object B.
+ctx->push();
+child* b = ctx->start_embed<child> ();
+ctx->extend_min (b);
+b->name = 'b';
+
+// Object D.
+ctx->push();
+*ctx->allocate_size<char> (1) = 'd';
+unsigned d_id = ctx->pop_pack ();
+
+ctx->add_link (b->leaf, d_id);
+unsigned b_id = ctx->pop_pack ();
+
+// Object C
+ctx->push();
+child* c = ctx->start_embed<child> ();
+ctx->extend_min (c);
+c->name = 'c';
+
+// Object D.
+ctx->push();
+*ctx->allocate_size<char> (1) = 'd';
+d_id = ctx->pop_pack (); // Serializer will automatically de-dup this with the previous 'd'
+
+ctx->add_link (c->leaf, d_id);
+unsigned c_id = ctx->pop_pack ();
+
+// Object A's links:
+ctx->add_link (a->child_1, b_id);
+ctx->add_link (a->child_2, c_id);
+ctx->pop_pack ();
+
+ctx->end_serialize ();
+
+```

+ 412 - 0
libs/harfbuzz/docs/usermanual-buffers-language-script-and-direction.xml

@@ -0,0 +1,412 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="buffers-language-script-and-direction">
+  <title>Buffers, language, script and direction</title>
+  <para>
+    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 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.
+  </para>
+  <para>
+    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.
+  </para>
+  <section id="creating-and-destroying-buffers">
+    <title>Creating and destroying buffers</title>
+    <para>
+      As we saw in our <emphasis>Getting Started</emphasis> example, a
+      buffer is created and 
+      initialized with <function>hb_buffer_create()</function>. This
+      produces a new, empty buffer object, instantiated with some
+      default values and ready to accept your Unicode strings.
+    </para>
+    <para>
+      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 <function>hb_buffer_destroy()</function>:
+    </para>
+    <programlisting language="C">
+      hb_buffer_t *buf = hb_buffer_create();
+      ...
+      hb_buffer_destroy(buf);
+    </programlisting>
+    <para>
+      This will destroy the object and free its associated memory -
+      unless some other part of the program holds a reference to this
+      buffer. If you acquire a HarfBuzz buffer from another subsystem
+      and want to ensure that it is not garbage collected by someone
+      else destroying it, you should increase its reference count:
+    </para>
+    <programlisting language="C">
+      void somefunc(hb_buffer_t *buf) {
+      buf = hb_buffer_reference(buf);
+      ...
+    </programlisting>
+    <para>
+      And then decrease it once you're done with it:
+    </para>
+    <programlisting language="C">
+      hb_buffer_destroy(buf);
+      }
+    </programlisting>
+    <para>
+      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.
+    </para>
+    <para>
+      To throw away all the data in your buffer and start from scratch,
+      call <function>hb_buffer_reset(buf)</function>. If you want to
+      throw away the string in the buffer but keep the options, you can
+      instead call <function>hb_buffer_clear_contents(buf)</function>.
+    </para>
+  </section>
+  
+  <section id="adding-text-to-the-buffer">
+    <title>Adding text to the buffer</title>
+    <para>
+      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 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:
+      <function>hb_buffer_add_utf8()</function>,
+      <function>hb_buffer_add_utf16()</function>, and
+      <function>hb_buffer_add_utf32()</function>. Other than the
+      character encoding they accept, they function identically.
+    </para>
+    <para>
+      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:
+    </para>
+    <programlisting language="C">
+    hb_buffer_add_utf8 (hb_buffer_t *buf,
+                    const char *text,
+                    int text_length,
+                    unsigned int item_offset,
+                    int item_length)
+    </programlisting>
+    <para>
+      So, in practice, you can say:
+    </para>
+    <programlisting language="C">
+      hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
+    </programlisting>
+    <para>
+      This will append your new characters to
+      <parameter>buf</parameter>, not replace its existing
+      contents. Also, note that you can use <literal>-1</literal> in
+      place of the first instance of <function>strlen(text)</function>
+      if your text array is NULL-terminated. Similarly, you can also use
+      <literal>-1</literal> as the final argument want to add its full
+      contents.
+    </para>
+    <para>
+      Whatever start <parameter>item_offset</parameter> and
+      <parameter>item_length</parameter> you provide, HarfBuzz will also
+      attempt to grab the five characters <emphasis>before</emphasis>
+      the offset point and the five characters
+      <emphasis>after</emphasis> 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.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      The safest approach is to add all of the text available (even
+      if your text contains a mix of scripts, directions, languages
+      and fonts), then use <parameter>item_offset</parameter> and
+      <parameter>item_length</parameter> to indicate which characters you
+      want shaped (which must all have the same script, direction,
+      language and font), so that HarfBuzz has access to any context.
+    </para>
+    <para>
+      You can also add Unicode code points directly with
+      <function>hb_buffer_add_codepoints()</function>. 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.
+    </para>
+    
+  </section>
+  
+  <section id="setting-buffer-properties">
+    <title>Setting buffer properties</title>
+    <para>
+      Buffers containing input characters still need several
+      properties set before HarfBuzz can shape their text correctly.
+    </para>
+    <para>
+      Initially, all buffers are set to the
+      <literal>HB_BUFFER_CONTENT_TYPE_INVALID</literal> content
+      type. After adding text, the buffer should be set to
+      <literal>HB_BUFFER_CONTENT_TYPE_UNICODE</literal> instead, which
+      indicates that it contains un-shaped input
+      characters. After shaping, the buffer will have the
+      <literal>HB_BUFFER_CONTENT_TYPE_GLYPHS</literal> content type.
+    </para>
+    <para>
+      <function>hb_buffer_add_utf8()</function> 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
+      <function>hb_buffer_get_content_type(buffer)</function>. If
+      necessary you can set the content type with
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_content_type(buf, HB_BUFFER_CONTENT_TYPE_UNICODE);
+    </programlisting>
+    <para>
+      to prepare for shaping.
+    </para>
+    <para>
+      Buffers also need to carry information about the script,
+      language, and text direction of their contents. You can set
+      these properties individually:
+    </para>
+    <programlisting language="C">
+      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));
+    </programlisting>
+    <para>
+      However, since these properties are often repeated for
+      multiple text runs, you can also save them in a
+      <literal>hb_segment_properties_t</literal> for reuse:
+    </para>
+    <programlisting language="C">
+      hb_segment_properties_t *savedprops;
+      hb_buffer_get_segment_properties (buf, savedprops);
+      ...
+      hb_buffer_set_segment_properties (buf2, savedprops);
+    </programlisting>
+    <para>
+      HarfBuzz also provides getter functions to retrieve a buffer's
+      direction, script, and language properties individually.
+    </para>
+    <para>
+      HarfBuzz recognizes four text directions in
+      <type>hb_direction_t</type>: left-to-right
+      (<literal>HB_DIRECTION_LTR</literal>), right-to-left (<literal>HB_DIRECTION_RTL</literal>),
+      top-to-bottom (<literal>HB_DIRECTION_TTB</literal>), and
+      bottom-to-top (<literal>HB_DIRECTION_BTT</literal>).  For the
+      script property, HarfBuzz uses identifiers based on the
+      <ulink
+      url="https://unicode.org/iso15924/">ISO 15924
+      standard</ulink>. For languages, HarfBuzz uses tags based on the
+      <ulink url="https://tools.ietf.org/html/bcp47">IETF BCP 47</ulink> standard.
+    </para>
+    <para>
+      Helper functions are provided to convert character strings into
+      the necessary script and language tag types.
+    </para>
+    <para>
+      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 <literal>REPLACEMENT CHARACTER</literal> code
+      point, <literal>U+FFFD</literal> "&#xFFFD;". You can change this with
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_replacement_codepoint(buf, replacement);
+    </programlisting>
+    <para>
+      passing in the replacement Unicode code point as the
+      <parameter>replacement</parameter> parameter.
+    </para>
+    <para>
+      The invisible glyph is used to replace all output glyphs that
+      are invisible. By default, the standard space character
+      <literal>U+0020</literal> is used; you can replace this (for
+      example, when using a font that provides script-specific
+      spaces) with 
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_invisible_glyph(buf, replacement_glyph);
+    </programlisting>
+    <para>
+      Do note that in the <parameter>replacement_glyph</parameter>
+      parameter, you must provide the glyph ID of the replacement you
+      wish to use, not the Unicode code point.
+    </para>
+    <para>
+      HarfBuzz supports a few additional flags you might want to set
+      on your buffer under certain circumstances. The
+      <literal>HB_BUFFER_FLAG_BOT</literal> and
+      <literal>HB_BUFFER_FLAG_EOT</literal> 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.
+    </para>
+    <para>
+      <literal>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</literal>
+      tells HarfBuzz not to hide glyphs with the
+      <literal>Default_Ignorable</literal> 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.
+    </para>
+    <para>
+      Conversely, setting the
+      <literal>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</literal> flag
+      tells HarfBuzz to remove <literal>Default_Ignorable</literal>
+      glyphs from the output buffer entirely. Finally, setting the
+      <literal>HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE</literal>
+      flag tells HarfBuzz not to insert the dotted-circle glyph
+      (<literal>U+25CC</literal>, "&#x25CC;"), 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).
+    </para>
+  </section>
+  
+  <section id="customizing-unicode-functions">
+    <title>Customizing Unicode functions</title>
+    <para>
+      HarfBuzz requires some simple functions for accessing
+      information from the Unicode Character Database (such as the
+      <literal>General_Category</literal> (gc) and
+      <literal>Script</literal> (sc) properties) that is useful
+      for shaping, as well as some useful operations like composing and
+      decomposing code points.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      The Unicode functions are specified in a structure called
+      <literal>unicode_funcs</literal> which is attached to each
+      buffer. But even though <literal>unicode_funcs</literal> is
+      associated with a <type>hb_buffer_t</type>, 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.
+    </para>
+    <para>
+      In addition, you can mark your <literal>unicode_funcs</literal>
+      as immutable by calling
+      <function>hb_unicode_funcs_make_immutable (ufuncs)</function>.
+      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
+      <literal>unicode_funcs</literal> configuration and introducing
+      inconsistencies and errors downstream.
+    </para>
+    <para>
+      You can retrieve the Unicode-functions configuration for
+      your buffer by calling <function>hb_buffer_get_unicode_funcs()</function>:
+    </para>
+    <programlisting language="C">
+      hb_unicode_funcs_t *ufunctions;
+      ufunctions = hb_buffer_get_unicode_funcs(buf);
+    </programlisting>
+    <para>
+      The current version of <literal>unicode_funcs</literal> uses six functions:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  <function>hb_unicode_combining_class_func_t</function>:
+	  returns the Canonical Combining Class of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_general_category_func_t</function>:
+	  returns the General Category (gc) of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_mirroring_func_t</function>: returns
+	  the Mirroring Glyph code point (for bi-directional
+	  replacement) of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_script_func_t</function>: returns the
+	  Script (sc) property of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_compose_func_t</function>: returns the
+	  canonical composition of a sequence of two code points.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_decompose_func_t</function>: returns
+	  the canonical decomposition of a code point.
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      Note, however, that future HarfBuzz releases may alter this set.
+    </para>
+    <para>
+      Each Unicode function has a corresponding setter, with which you
+      can assign a callback to your replacement function. For example,
+      to replace
+      <function>hb_unicode_general_category_func_t</function>, you can call
+    </para>
+    <programlisting language="C">
+      hb_unicode_funcs_set_general_category_func (*ufuncs, func, *user_data, destroy)	    
+    </programlisting>
+    <para>
+      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
+      <literal>unicode_funcs</literal>. 
+    </para>
+  </section>
+  
+</chapter>

+ 697 - 0
libs/harfbuzz/docs/usermanual-clusters.xml

@@ -0,0 +1,697 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="clusters">
+  <title>Clusters</title>
+  <section id="clusters-and-shaping">
+    <title>Clusters and shaping</title>
+    <para>
+      In text shaping, a <emphasis>cluster</emphasis> is a sequence of
+      characters that needs to be treated as a single, indivisible
+      unit. A single letter or symbol can be a cluster of its
+      own. Other clusters correspond to longer subsequences of the
+      input code points &mdash; such as a ligature or conjunct form
+      &mdash; and require the shaper to ensure that the cluster is not
+      broken during the shaping process.
+    </para>
+    <para>
+      A cluster is distinct from a <emphasis>grapheme</emphasis>,
+      which is the smallest unit of meaning in a writing system or
+      script.
+    </para>
+    <para>
+      The definitions of the two terms are similar. However, clusters
+      are only relevant for script shaping and glyph layout. In
+      contrast, graphemes are a property of the underlying script, and
+      are of interest when client programs implement orthographic 
+      or linguistic functionality.
+    </para>
+    <para>
+      For example, two individual letters are often two separate
+      graphemes. When two letters form a ligature, however, they
+      combine into a single glyph. They are then part of the same
+      cluster and are treated as a unit by the shaping engine &mdash;
+      even though the two original, underlying letters remain separate
+      graphemes.
+    </para>
+    <para>
+      HarfBuzz is concerned with clusters, <emphasis>not</emphasis>
+      with graphemes &mdash; although client programs using HarfBuzz
+      may still care about graphemes for other reasons from time to time.
+    </para>
+    <para>
+      During the shaping process, there are several shaping operations
+      that may merge adjacent characters (for example, when two code
+      points form a ligature or a conjunct form and are replaced by a
+      single glyph) or split one character into several (for example,
+      when decomposing a code point through the
+      <literal>ccmp</literal> feature). Operations like these alter
+      clusters; HarfBuzz tracks the changes to ensure that no clusters
+      get lost or broken during shaping. 
+    </para>
+    <para>
+      HarfBuzz records cluster information independently from how
+      shaping operations affect the individual glyphs returned in an
+      output buffer. Consequently, a client program using HarfBuzz can
+      utilize the cluster information to implement features such as:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  Correctly positioning the cursor within a shaped text run,
+	  even when characters have formed ligatures, composed or
+	  decomposed, reordered, or undergone other shaping operations.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Correctly highlighting a text selection that includes some,
+	  but not all, of the characters in a word. 
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Applying text attributes (such as color or underlining) to
+	  part, but not all, of a word.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Generating output document formats (such as PDF) with
+	  embedded text that can be fully extracted.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Determining the mapping between input characters and output
+	  glyphs, such as which glyphs are ligatures.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Performing line-breaking, justification, and other
+	  line-level or paragraph-level operations that must be done
+	  after shaping is complete, but which require examining
+	  character-level properties.
+	</para>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section id="working-with-harfbuzz-clusters">
+    <title>Working with HarfBuzz clusters</title>
+    <para>
+      When you add text to a HarfBuzz buffer, each code point must be
+      assigned a <emphasis>cluster value</emphasis>.
+    </para>
+    <para>
+      This cluster value is an arbitrary number; HarfBuzz uses it only
+      to distinguish between clusters. Many client programs will use
+      the index of each code point in the input text stream as the
+      cluster value. This is for the sake of convenience; the actual
+      value does not matter.
+    </para>
+    <para>
+      Some of the shaping operations performed by HarfBuzz &mdash;
+      such as reordering, composition, decomposition, and substitution
+      &mdash; may alter the cluster values of some characters. The
+      final cluster values in the buffer at the end of the shaping
+      process will indicate to client programs which subsequences of
+      glyphs represent a cluster and, therefore, must not be
+      separated.
+    </para>
+    <para>
+      In addition, client programs can query the final cluster values
+      to discern other potentially important information about the
+      glyphs in the output buffer (such as whether or not a ligature
+      was formed).
+    </para>
+    <para>
+      For example, if the initial sequence of cluster values was:
+    </para>
+    <programlisting>
+      0,1,2,3,4
+    </programlisting>
+    <para>
+      and the final sequence of cluster values is:
+    </para>
+    <programlisting>
+      0,0,3,3
+    </programlisting>
+    <para>
+      then there are two clusters in the output buffer: the first
+      cluster includes the first two glyphs, and the second cluster
+      includes the third and fourth glyphs. It is also evident that a
+      ligature or conjunct has been formed, because there are fewer
+      glyphs in the output buffer (four) than there were code points
+      in the input buffer (five).
+    </para>
+    <para>
+      Although client programs using HarfBuzz are free to assign
+      initial cluster values in any manner they choose to, HarfBuzz
+      does offer some useful guarantees if the cluster values are
+      assigned in a monotonic (either non-decreasing or non-increasing)
+      order.
+    </para>
+    <para>
+      For buffers in the left-to-right (LTR)
+      or top-to-bottom (TTB) text flow direction,
+      HarfBuzz will preserve the monotonic property: client programs
+      are guaranteed that monotonically increasing initial cluster
+      values will be returned as monotonically increasing final
+      cluster values.
+    </para>
+    <para>
+      For buffers in the right-to-left (RTL)
+      or bottom-to-top (BTT) text flow direction,
+      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 cluster values will be
+      returned as monotonically <emphasis>decreasing</emphasis> final
+      cluster values.
+    </para>
+    <para>
+      Client programs can adjust how HarfBuzz handles clusters during
+      shaping by setting the
+      <literal>cluster_level</literal> of the
+      buffer. HarfBuzz offers three <emphasis>levels</emphasis> of
+      clustering support for this property:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para><emphasis>Level 0</emphasis> is the default and
+	reproduces the behavior of the old HarfBuzz library.
+	</para>
+	<para>
+	  The distinguishing feature of level 0 behavior is that, at
+	  the beginning of processing the buffer, all code points that
+	  are categorized as <emphasis>marks</emphasis>,
+	  <emphasis>modifier symbols</emphasis>, or
+	  <emphasis>Emoji extended pictographic</emphasis> modifiers,
+	  as well as the <emphasis>Zero Width Joiner</emphasis> and
+	  <emphasis>Zero Width Non-Joiner</emphasis> code points, are
+	  assigned the cluster value of the closest preceding code
+	  point from <emphasis>different</emphasis> category. 
+	</para>
+	<para>
+	  In essence, whenever a base character is followed by a mark
+	  character or a sequence of mark characters, those marks are
+	  reassigned to the same initial cluster value as the base
+	  character. This reassignment is referred to as
+	  "merging" the affected clusters. This behavior is based on
+	  the Grapheme Cluster Boundary specification in <ulink
+	  url="https://www.unicode.org/reports/tr29/#Regex_Definitions">Unicode
+	  Technical Report 29</ulink>.
+	</para>
+	<para>
+	  Client programs can specify level 0 behavior for a buffer by
+	  setting its <literal>cluster_level</literal> to
+	  <literal>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES</literal>. 
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>Level 1</emphasis> tweaks the old behavior
+	  slightly to produce better results. Therefore, level 1
+	  clustering is recommended for code that is not required to
+	  implement backward compatibility with the old HarfBuzz.
+	</para>
+	<para>
+	  Level 1 differs from level 0 by not merging the 
+	  clusters of marks and other modifier code points with the
+	  preceding "base" code point's cluster. By preserving the
+	  separate cluster values of these marks and modifier code
+	  points, script shapers can perform additional operations
+	  that might lead to improved results (for example, reordering
+	  a sequence of marks).
+	</para>
+	<para>
+	  Client programs can specify level 1 behavior for a buffer by
+	  setting its <literal>cluster_level</literal> to
+	  <literal>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS</literal>. 
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>Level 2</emphasis> differs significantly in how it
+	  treats cluster values. In level 2, HarfBuzz never merges
+	  clusters.
+	</para>
+	<para>
+	  This difference can be seen most clearly when HarfBuzz processes
+	  ligature substitutions and glyph decompositions. In level 0 
+	  and level 1, ligatures and glyph decomposition both involve
+	  merging clusters; in level 2, neither of these operations
+	  triggers a merge.
+	</para>
+	<para>
+	  Client programs can specify level 2 behavior for a buffer by
+	  setting its <literal>cluster_level</literal> to
+	  <literal>HB_BUFFER_CLUSTER_LEVEL_CHARACTERS</literal>. 
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      As mentioned earlier, client programs using HarfBuzz often
+      assign initial cluster values in a buffer by reusing the indices
+      of the code points in the input text. This gives a sequence of
+      cluster values that is monotonically increasing (for example,
+      0,1,2,3,4). 
+    </para>
+    <para>
+      It is not <emphasis>required</emphasis> that the cluster values
+      in a buffer be monotonically increasing. However, if the initial
+      cluster values in a buffer are monotonic and the buffer is
+      configured to use cluster level 0 or 1, then HarfBuzz
+      guarantees that the final cluster values in the shaped buffer
+      will also be monotonic. No such guarantee is made for cluster
+      level 2.
+    </para>
+    <para>
+      In levels 0 and 1, HarfBuzz implements the following conceptual
+      model for cluster values:
+    </para>
+    <itemizedlist spacing="compact">
+      <listitem>
+	<para>
+          If the sequence of input cluster values is monotonic, the
+	  sequence of cluster values will remain monotonic.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+          Each cluster value represents a single cluster.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+          Each cluster contains one or more glyphs and one or more
+          characters.
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      In practice, this model offers several benefits. Assuming that
+      the initial cluster values were monotonically increasing
+      and distinct before shaping began, then, in the final output:
+    </para>
+    <itemizedlist spacing="compact">
+      <listitem>
+	<para>
+	  All adjacent glyphs having the same final cluster
+	  value belong to the same cluster.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+          Each character belongs to the cluster that has the highest
+	  cluster value <emphasis>not larger than</emphasis> its
+	  initial cluster value.
+	</para>
+      </listitem>
+    </itemizedlist>
+  </section>
+  
+  <section id="a-clustering-example-for-levels-0-and-1">
+    <title>A clustering example for levels 0 and 1</title>
+    <para>
+      The basic shaping operations affect clusters in a predictable
+      manner when using level 0 or level 1: 
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  When two or more clusters <emphasis>merge</emphasis>, the
+	  resulting merged cluster takes as its cluster value the
+	  <emphasis>minimum</emphasis> of the incoming cluster values.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  When a cluster <emphasis>decomposes</emphasis>, all of the
+	  resulting child clusters inherit as their cluster value the
+	  cluster value of the parent cluster.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  When a character is <emphasis>reordered</emphasis>, the
+	  reordered character and all clusters that the character
+	  moves past as part of the reordering are merged into one cluster.
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      The functionality, guarantees, and benefits of level 0 and level
+      1 behavior can be seen with some examples. First, let us examine
+      what happens with cluster values when shaping involves cluster
+      merging with ligatures and decomposition.
+    </para>
+
+    <para>
+      Let's say we start with the following character sequence (top row) and
+      initial cluster values (bottom row):
+    </para>
+    <programlisting>
+      A,B,C,D,E
+      0,1,2,3,4
+    </programlisting>
+    <para>
+      During shaping, HarfBuzz maps these characters to glyphs from
+      the font. For simplicity, let us assume that each character maps
+      to the corresponding, identical-looking glyph:
+    </para>
+    <programlisting>
+      A,B,C,D,E
+      0,1,2,3,4
+    </programlisting>
+    <para>
+      Now if, for example, <literal>B</literal> and <literal>C</literal>
+      form a ligature, then the clusters to which they belong
+      &quot;merge&quot;. This merged cluster takes for its cluster
+      value the minimum of all the cluster values of the clusters that
+      went in to the ligature. In this case, we get:
+    </para>
+    <programlisting>
+      A,BC,D,E
+      0,1 ,3,4
+    </programlisting>
+    <para>
+      because 1 is the minimum of the set {1,2}, which were the
+      cluster values of <literal>B</literal> and
+      <literal>C</literal>. 
+    </para>
+    <para>
+      Next, let us say that the <literal>BC</literal> ligature glyph
+      decomposes into three components, and <literal>D</literal> also
+      decomposes into two components. Whenever a cluster decomposes,
+      its components each inherit the cluster value of their parent: 
+    </para>
+    <programlisting>
+      A,BC0,BC1,BC2,D0,D1,E
+      0,1  ,1  ,1  ,3 ,3 ,4
+    </programlisting>
+    <para>
+      Next, if <literal>BC2</literal> and <literal>D0</literal> form a
+      ligature, then their clusters (cluster values 1 and 3) merge into
+      <literal>min(1,3) = 1</literal>:
+    </para>
+    <programlisting>
+      A,BC0,BC1,BC2D0,D1,E
+      0,1  ,1  ,1    ,1 ,4
+    </programlisting>
+    <para>
+      Note that the entirety of cluster 3 merges into cluster 1, not
+      just the <literal>D0</literal> glyph. This reflects the fact
+      that the cluster <emphasis>must</emphasis> be treated as an
+      indivisible unit.
+    </para>
+    <para>
+      At this point, cluster 1 means: the character sequence
+      <literal>BCD</literal> is represented by glyphs
+      <literal>BC0,BC1,BC2D0,D1</literal> and cannot be broken down any
+      further.
+    </para>
+  </section>
+  <section id="reordering-in-levels-0-and-1">
+    <title>Reordering in levels 0 and 1</title>
+    <para>
+      Another common operation in some shapers is glyph
+      reordering. In order to maintain a monotonic cluster sequence
+      when glyph reordering takes place, HarfBuzz merges the clusters
+      of everything in the reordering sequence.
+    </para>
+    <para>
+      For example, let us again start with the character sequence (top
+      row) and initial cluster values (bottom row):
+    </para>
+    <programlisting>
+      A,B,C,D,E
+      0,1,2,3,4
+    </programlisting>
+    <para>
+      If <literal>D</literal> is reordered to the position immediately
+      before <literal>B</literal>, then HarfBuzz merges the
+      <literal>B</literal>, <literal>C</literal>, and
+      <literal>D</literal> clusters &mdash; all the clusters between
+      the final position of the reordered glyph and its original
+      position. This means that we get:
+    </para>
+    <programlisting>
+      A,D,B,C,E
+      0,1,1,1,4
+    </programlisting>
+    <para>
+      as the final cluster sequence.
+    </para>
+    <para>
+      Merging this many clusters is not ideal, but it is the only
+      sensible way for HarfBuzz to maintain the guarantee that the
+      sequence of cluster values remains monotonic and to retain the
+      true relationship between glyphs and characters.
+    </para>
+  </section>
+  <section id="the-distinction-between-levels-0-and-1">
+    <title>The distinction between levels 0 and 1</title>
+    <para>
+      The preceding examples demonstrate the main effects of using
+      cluster levels 0 and 1. The only difference between the two
+      levels is this: in level 0, at the very beginning of the shaping
+      process, HarfBuzz merges the cluster of each base character
+      with the clusters of all Unicode marks (combining or not) and
+      modifiers that follow it.
+    </para>
+    <para>
+      For example, let us start with the following character sequence
+      (top row) and accompanying initial cluster values (bottom row):
+    </para>
+    <programlisting>
+      A,acute,B
+      0,1    ,2
+    </programlisting>
+    <para>
+      The <literal>acute</literal> is a Unicode mark. If HarfBuzz is
+      using cluster level 0 on this sequence, then the
+      <literal>A</literal> and <literal>acute</literal> clusters will
+      merge, and the result will become:
+    </para>
+    <programlisting>
+      A,acute,B
+      0,0    ,2
+    </programlisting>
+    <para>
+      This merger is performed before any other script-shaping
+      steps.
+    </para>
+    <para>
+      This initial cluster merging is the default behavior of the
+      Windows shaping engine, and the old HarfBuzz codebase copied
+      that behavior to maintain compatibility. Consequently, it has
+      remained the default behavior in the new HarfBuzz codebase.
+    </para>
+    <para>
+      But this initial cluster-merging behavior makes it impossible
+      for client programs to implement some features (such as to
+      color diacritic marks differently from their base
+      characters). That is why, in level 1, HarfBuzz does not perform
+      the initial merging step.
+    </para>
+    <para>
+      For client programs that rely on HarfBuzz cluster values to
+      perform cursor positioning, level 0 is more convenient. But
+      relying on cluster boundaries for cursor positioning is wrong: cursor
+      positions should be determined based on Unicode grapheme
+      boundaries, not on shaping-cluster boundaries. As such, using
+      level 1 clustering behavior is recommended. 
+    </para>
+    <para>
+      One final facet of levels 0 and 1 is worth noting. HarfBuzz
+      currently does not allow any
+      <emphasis>multiple-substitution</emphasis> GSUB lookups to 
+      replace a glyph with zero glyphs (in other words, to delete a
+      glyph).
+    </para>
+    <para>
+      But, in some other situations, glyphs can be deleted. In
+      those cases, if the glyph being deleted is the last glyph of its
+      cluster, HarfBuzz makes sure to merge the deleted glyph's
+      cluster with a neighboring cluster.
+    </para>
+    <para>
+      This is done primarily to make sure that the starting cluster of the
+      text always has the cluster index pointing to the start of the text
+      for the run; more than one client program currently relies on this
+      guarantee.
+    </para>
+    <para>
+      Incidentally, Apple's CoreText does something different to
+      maintain the same promise: it inserts a glyph with id 65535 at
+      the beginning of the glyph string if the glyph corresponding to
+      the first character in the run was deleted. HarfBuzz might do
+      something similar in the future.
+    </para>
+  </section>
+  <section id="level-2">
+    <title>Level 2</title>
+    <para>
+      HarfBuzz's level 2 cluster behavior uses a significantly
+      different model than that of level 0 and level 1.
+    </para>
+    <para>
+      The level 2 behavior is easy to describe, but it may be
+      difficult to understand in practical terms. In brief, level 2 
+      performs no merging of clusters whatsoever.
+    </para>
+    <para>
+      This means that there is no initial base-and-mark merging step
+      (as is done in level 0), and it means that reordering moves and
+      ligature substitutions do not trigger a cluster merge.
+    </para>
+    <para>
+      Only one shaping operation directly affects clusters when using
+      level 2:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  When a cluster <emphasis>decomposes</emphasis>, all of the
+	  resulting child clusters inherit as their cluster value the
+	  cluster value of the parent cluster.
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      When glyphs do form a ligature (or when some other feature
+      substitutes multiple glyphs with one glyph) the cluster value
+      of the first glyph is retained as the cluster value for the
+      resulting ligature.
+    </para>
+    <para>
+      This occurrence sounds similar to a cluster merge, but it is
+      different. In particular, no subsequent characters &mdash;
+      including marks and modifiers &mdash; are affected. They retain
+      their previous cluster values. 
+    </para>
+    <para>
+      Level 2 cluster behavior is ultimately less complex than level 0
+      or level 1, but there are several cases for which processing
+      cluster values produced at level 2 may be tricky. 
+    </para>
+    <section id="ligatures-with-combining-marks-in-level-2">
+      <title>Ligatures with combining marks in level 2</title>
+      <para>
+	The first example of how HarfBuzz's level 2 cluster behavior
+	can be tricky is when the text to be shaped includes combining
+	marks attached to ligatures.
+      </para>
+      <para>
+	Let us start with an input sequence with the following
+	characters (top row) and initial cluster values (bottom row):
+      </para>
+      <programlisting>
+	A,acute,B,breve,C,circumflex
+	0,1    ,2,3    ,4,5
+      </programlisting>
+      <para>
+	If the sequence <literal>A,B,C</literal> forms a ligature,
+	then these are the cluster values HarfBuzz will return under
+	the various cluster levels:
+      </para>
+      <para>
+	Level 0:
+      </para>
+      <programlisting>
+	ABC,acute,breve,circumflex
+	0  ,0    ,0    ,0
+      </programlisting>
+      <para>
+	Level 1:
+      </para>
+      <programlisting>
+	ABC,acute,breve,circumflex
+	0  ,0    ,0    ,5
+      </programlisting>
+      <para>
+	Level 2:
+      </para>
+      <programlisting>
+	ABC,acute,breve,circumflex
+	0  ,1    ,3    ,5
+      </programlisting>
+      <para>
+	Making sense of the level 2 result is the hardest for a client
+	program, because there is nothing in the cluster values that
+	indicates that <literal>B</literal> and <literal>C</literal>
+	formed a ligature with <literal>A</literal>.
+      </para>
+      <para>
+	In contrast, the "merged" cluster values of the mark glyphs
+	that are seen in the level 0 and level 1 output are evidence
+	that a ligature substitution took place. 
+      </para>
+    </section>
+    <section id="reordering-in-level-2">
+      <title>Reordering in level 2</title>
+      <para>
+	Another example of how HarfBuzz's level 2 cluster behavior
+	can be tricky is when glyphs reorder. Consider an input sequence
+	with the following characters (top row) and initial cluster
+	values (bottom row):
+      </para>
+      <programlisting>
+	A,B,C,D,E
+	0,1,2,3,4
+      </programlisting>
+      <para>
+	Now imagine <literal>D</literal> moves before
+	<literal>B</literal> in a reordering operation. The cluster
+	values will then be:
+      </para>
+      <programlisting>
+	A,D,B,C,E
+	0,3,1,2,4
+      </programlisting>
+      <para>
+	Next, if <literal>D</literal> forms a ligature with
+	<literal>B</literal>, the output is:
+      </para>
+      <programlisting>
+	A,DB,C,E
+	0,3 ,2,4
+      </programlisting>
+      <para>
+	However, in a different scenario, in which the shaping rules
+	of the script instead caused <literal>A</literal> and
+	<literal>B</literal> to form a ligature
+	<emphasis>before</emphasis> the <literal>D</literal> reordered, the
+	result would be:
+      </para>
+      <programlisting>
+	AB,D,C,E
+	0 ,3,2,4   
+      </programlisting>
+      <para>
+	There is no way for a client program to differentiate between
+	these two scenarios based on the cluster values
+	alone. Consequently, client programs that use level 2 might
+	need to undertake additional work in order to manage cursor
+	positioning, text attributes, or other desired features.
+      </para>
+    </section>
+    <section id="other-considerations-in-level-2">
+      <title>Other considerations in level 2</title>
+      <para>
+	There may be other problems encountered with ligatures under
+	level 2, such as if the direction of the text is forced to
+	the opposite of its natural direction (for example, Arabic text
+	that is forced into left-to-right directionality). But,
+	generally speaking, these other scenarios are minor corner
+	cases that are too obscure for most client programs to need to
+	worry about.
+      </para>
+    </section>
+  </section>
+</chapter>

+ 467 - 0
libs/harfbuzz/docs/usermanual-fonts-and-faces.xml

@@ -0,0 +1,467 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="fonts-and-faces">
+  <title>Fonts, faces, and output</title>
+    <para>
+      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.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      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.
+    </para>
+
+  <section id="fonts-and-faces-objects">
+    <title>Font and face objects</title>
+    <para>
+      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.
+    </para>
+    <para>
+      An <type>hb_face_t</type> represents a <emphasis>face</emphasis>
+      in HarfBuzz. This data type is a wrapper around an
+      <type>hb_blob_t</type> 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
+      <literal>0</literal> as the index when you create a face:
+    </para>
+    <programlisting language="C">
+      hb_blob_t* blob = hb_blob_create_from_file(file);
+      ...
+      hb_face_t* face = hb_face_create(blob, 0);
+    </programlisting>
+    <para>
+      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.
+    </para>
+    <para>
+      In HarfBuzz, you do this by creating a <emphasis>font</emphasis>
+      object from your face.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      You can create a font object from a face object:
+    </para>
+    <programlisting language="C">
+      hb_font_t* hb_font = hb_font_create(hb_face);
+    </programlisting>
+    <para>
+      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. <function>hb_font_set_ppem(font, x_ppem,
+      y_ppem)</function> sets the pixels-per-EM value of the font. You
+      can also set the point size of the font with
+      <function>hb_font_set_ptem(font, ptem)</function>. HarfBuzz uses the
+      industry standard 72 points per inch.
+    </para>
+    <para>
+      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 <function>hb_font_set_scale(font, x_scale,
+      y_scale)</function>. 
+    </para>
+    <para>
+      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
+    </para>
+    <programlisting language="C">
+      hb_face = hb_font_get_face(hb_font);
+    </programlisting>
+    <para>
+      You can also create a font object from an existing font object
+      using the <function>hb_font_create_sub_font()</function>
+      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.
+    </para>
+    <para>
+      All face objects and font objects are lifecycle-managed by
+      HarfBuzz. After creating a face, you increase its reference
+      count with <function>hb_face_reference(face)</function> and
+      decrease it with
+      <function>hb_face_destroy(face)</function>. Likewise, you
+      increase the reference count on a font with
+      <function>hb_font_reference(font)</function> and decrease it
+      with <function>hb_font_destroy(font)</function>.
+    </para>
+    <para>
+      You can also attach user data to face objects and font objects.
+    </para>
+  </section>
+
+ <section id="fonts-and-faces-custom-functions">
+    <title>Customizing font functions</title>
+    <para>
+      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. 
+    </para>
+    <para>
+      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
+      <literal>font_funcs</literal> that serves as a vtable for the
+      font object. The virtual methods in
+      <literal>font_funcs</literal> are:
+    </para>
+    <itemizedlist>
+      <listitem>
+    <para>
+      <function>hb_font_get_font_h_extents_func_t</function>: returns
+      the extents of the font for horizontal text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_font_v_extents_func_t</function>: returns
+      the extents of the font for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_nominal_glyph_func_t</function>: returns
+      the font's nominal glyph for a given code point.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_variation_glyph_func_t</function>: returns
+      the font's glyph for a given code point when it is followed by a
+      given Variation Selector.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_nominal_glyphs_func_t</function>: returns
+      the font's nominal glyphs for a series of code points.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_advance_func_t</function>: returns
+      the advance for a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_h_advance_func_t</function>: returns
+      the advance for a glyph for horizontal text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_v_advance_func_t</function>:returns
+      the advance for a glyph for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_advances_func_t</function>: returns
+      the advances for a series of glyphs.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_h_advances_func_t</function>: returns
+      the advances for a series of glyphs for horizontal text .
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_v_advances_func_t</function>: returns
+      the advances for a series of glyphs for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_origin_func_t</function>: returns
+      the origin coordinates of a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_h_origin_func_t</function>: returns
+      the origin coordinates of a glyph for horizontal text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_v_origin_func_t</function>: returns
+      the origin coordinates of a glyph for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_extents_func_t</function>: returns
+      the extents for a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_contour_point_func_t</function>:
+      returns the coordinates of a specific contour point from a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_name_func_t</function>: returns the
+      name of a glyph (from its glyph index).
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_from_name_func_t</function>: returns
+      the glyph index that corresponds to a given glyph name.
+    </para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      You can create new font-functions by calling
+      <function>hb_font_funcs_create()</function>:
+    </para>
+    <programlisting language="C">
+      hb_font_funcs_t *ffunctions = hb_font_funcs_create ();
+      hb_font_set_funcs (font, ffunctions, font_data, destroy);
+    </programlisting>
+    <para>
+      The individual methods can each be set with their own setter
+      function, such as
+      <function>hb_font_funcs_set_nominal_glyph_func(ffunctions,
+      func, user_data, destroy)</function>.
+    </para>
+    <para>
+      Font-functions structures can be reused for multiple font
+      objects, and can be reference counted with
+      <function>hb_font_funcs_reference()</function> and
+      <function>hb_font_funcs_destroy()</function>. Just like other
+      objects in HarfBuzz, you can set user-data for each
+      font-functions structure and assign a destroy callback for
+      it.
+    </para>
+    <para>
+      You can also mark a font-functions structure as immutable,
+      with <function>hb_font_funcs_make_immutable()</function>. 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.
+    </para>
+    <para>
+      To override only some functions while using the default implementation
+      for the others, you will need to create a sub-font. By default, the
+      sub-font uses the font functions of its parent except for the functions
+      that were explicitly set. The following code will override only the
+      <function>hb_font_get_nominal_glyph_func_t</function> for the sub-font:
+    </para>
+    <programlisting language="C">
+      hb_font_t *subfont = hb_font_create_sub_font (font)
+      hb_font_funcs_t *ffunctions = hb_font_funcs_create ();
+      hb_font_funcs_set_nominal_glyph_func (ffunctions, func, user_data, destroy);
+      hb_font_set_funcs (subfont, ffunctions, font_data, destroy);
+      hb_font_funcs_destroy (ffunctions);
+    </programlisting>
+  </section>
+
+  <section id="fonts-and-faces-native-opentype">
+    <title>Font objects and HarfBuzz's native OpenType implementation</title>
+    <para>
+      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.
+    </para>
+    <para>
+      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 <literal>(0,0)</literal> 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).
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      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
+    </para>
+    <programlisting language="C">
+      hb_font_get_glyph_advance_for_direction(font, direction, extents);
+    </programlisting>
+    <para>
+      then you can provide any <type>hb_direction_t</type> as the
+      <parameter>direction</parameter> 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.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      HarfBuzz also provides functions for converting between glyph
+      names and string
+      variables. <function>hb_font_glyph_to_string(font, glyph, s,
+      size)</function> retrieves the name for the glyph ID
+      <parameter>glyph</parameter> from the font object. It generates a
+      generic name of the form <literal>gidDDD</literal> (where DDD is
+      the glyph index) if there is no name for the glyph in the
+      font. The <function>hb_font_glyph_from_string(font, s, len,
+      glyph)</function> takes an input string <parameter>s</parameter>
+      and looks for a glyph with that name in the font, returning its
+      glyph ID in the <parameter>glyph</parameter>
+      output parameter. It automatically parses
+      <literal>gidDDD</literal> and <literal>uniUUUU</literal> strings.
+    </para>
+  </section>
+
+
+  <!-- Commenting out FreeType integration section-holder for now. May move
+       to the full-blown Integration Chapter. -->
+  
+  <!--   <section id="fonts-and-faces-freetype">
+    <title>Using FreeType</title>
+    <para>
+
+    </para>
+    <para>
+      
+    </para>
+  </section> -->
+
+  <section id="fonts-and-faces-variable">
+    <title>Working with OpenType Variable Fonts</title>
+    <para>
+      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).
+    </para>
+    <para>
+      HarfBuzz manages variation settings in the
+      <type>hb_variation_t</type> data type, which holds a <property>tag</property> for the
+      variation-axis identifier tag and a <property>value</property> 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 <function>hb_ot_var_get_axis_count(face)</function> to
+      find the number of axes, then using
+      <function>hb_ot_var_get_axis_infos()</function> to collect the 
+      axis structures:
+    </para>
+    <programlisting language="C">
+      axes = hb_ot_var_get_axis_count(face);
+      ...
+      hb_ot_var_get_axis_infos(face, 0, axes, axes_array);
+    </programlisting>
+    <para>
+      For each axis returned in the array, you can can access the
+      identifier in its <property>tag</property>. HarfBuzz also has
+      tag definitions predefined for the five standard axes specified
+      in OpenType (<literal>ital</literal> for italic,
+      <literal>opsz</literal> for optical size,
+      <literal>slnt</literal> for slant, <literal>wdth</literal> for
+      width, and <literal>wght</literal> for weight). Each axis also
+      has a <property>min_value</property>, a
+      <property>default_value</property>, and a <property>max_value</property>.
+    </para>
+    <para>
+      To set your font object's variation settings, you call the
+      <function>hb_font_set_variations()</function> function with an
+      array of <type>hb_variation_t</type> 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:
+    </para>
+    <programlisting language="C">
+      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);
+    </programlisting>
+    <para>
+      That should give us a slightly condensed font ("normal" on the
+      <literal>wdth</literal> axis is 100) at a noticeably bolder
+      weight ("regular" is 400 on the <literal>wght</literal> axis).
+    </para>
+    <para>
+      In practice, though, you should always check that the value you
+      want to set on the axis is within the
+      [<property>min_value</property>,<property>max_value</property>]
+      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 <literal>wght</literal> axis will
+      not change that. 
+    </para>
+    <para>
+      Once your variation settings are specified on your font object,
+      however, shaping with a variable font is just like shaping a
+      static font.
+    </para>
+  </section>
+
+ </chapter>

+ 312 - 0
libs/harfbuzz/docs/usermanual-getting-started.xml

@@ -0,0 +1,312 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="getting-started">
+  <title>Getting started with HarfBuzz</title>
+  <section id="an-overview-of-the-harfbuzz-shaping-api">
+    <title>An overview of the HarfBuzz shaping API</title>
+    <para>
+      The core of the HarfBuzz shaping API is the function
+      <function>hb_shape()</function>. This function takes a font, a
+      buffer containing a string of Unicode codepoints and
+      (optionally) a list of font features as its input. It replaces
+      the codepoints in the buffer with the corresponding glyphs from
+      the font, correctly ordered and positioned, and with any of the
+      optional font features applied.
+    </para>
+    <para>
+      In addition to holding the pre-shaping input (the Unicode
+      codepoints that comprise the input string) and the post-shaping
+      output (the glyphs and positions), a HarfBuzz buffer has several
+      properties that affect shaping. The most important are the
+      text-flow direction (e.g., left-to-right, right-to-left,
+      top-to-bottom, or bottom-to-top), the script tag, and the
+      language tag.
+    </para>
+
+    <para>
+      For input string buffers, flags are available to denote when the
+      buffer represents the beginning or end of a paragraph, to
+      indicate whether or not to visibly render Unicode <literal>Default
+      Ignorable</literal> codepoints, and to modify the cluster-merging
+      behavior for the buffer. For shaped output buffers, the
+      individual X and Y offsets and <literal>advances</literal>
+      (the logical dimensions) of each glyph are 
+      accessible. HarfBuzz also flags glyphs as
+      <literal>UNSAFE_TO_BREAK</literal> if breaking the string at
+      that glyph (e.g., in a line-breaking or hyphenation process)
+      would require re-shaping the text.
+    </para>
+    
+    <para>
+      HarfBuzz also provides methods to compare the contents of
+      buffers, join buffers, normalize buffer contents, and handle
+      invalid codepoints, as well as to determine the state of a
+      buffer (e.g., input codepoints or output glyphs). Buffer
+      lifecycles are managed and all buffers are reference-counted.
+    </para>
+
+    <para>
+      Although the default <function>hb_shape()</function> function is
+      sufficient for most use cases, a variant is also provided that
+      lets you specify which of HarfBuzz's shapers to use on a buffer. 
+    </para>
+
+    <para>
+      HarfBuzz can read TrueType fonts, TrueType collections, OpenType
+      fonts, and OpenType collections. Functions are provided to query
+      font objects about metrics, Unicode coverage, available tables and
+      features, and variation selectors. Individual glyphs can also be
+      queried for metrics, variations, and glyph names. OpenType
+      variable fonts are supported, and HarfBuzz allows you to set
+      variation-axis coordinates on font objects.
+    </para>
+    
+    <para>
+      HarfBuzz provides glue code to integrate with various other
+      libraries, including FreeType, GObject, and CoreText. Support
+      for integrating with Uniscribe and DirectWrite is experimental
+      at present.
+    </para>
+  </section>
+
+  <section id="terminology">
+    <title>Terminology</title>
+    <para>
+      
+    </para>
+      <variablelist>
+	<?dbfo list-presentation="blocks"?> 
+	<varlistentry>
+	  <term>script</term>
+	  <listitem>
+	    <para>
+	      In text shaping, a <emphasis>script</emphasis> is a
+	      writing system: a set of symbols, rules, and conventions
+	      that is used to represent a language or multiple
+	      languages.
+	    </para>
+	    <para>
+	      In general computing lingo, the word "script" can also
+	      be used to mean an executable program (usually one
+	      written in a human-readable programming language). For
+	      the sake of clarity, HarfBuzz documents will always use
+	      more specific terminology when referring to this
+	      meaning, such as "Python script" or "shell script." In
+	      all other instances, "script" refers to a writing system.
+	    </para>
+	    <para>
+	      For developers using HarfBuzz, it is important to note
+	      the distinction between a script and a language. Most
+	      scripts are used to write a variety of different
+	      languages, and many languages may be written in more
+	      than one script.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term>shaper</term>
+	  <listitem>
+	    <para>
+	      In HarfBuzz, a <emphasis>shaper</emphasis> is a
+	      handler for a specific script-shaping model. HarfBuzz
+	      implements separate shapers for Indic, Arabic, Thai and
+	      Lao, Khmer, Myanmar, Tibetan, Hangul, Hebrew, the
+	      Universal Shaping Engine (USE), and a default shaper for
+	      scripts with no script-specific shaping model.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term>cluster</term>
+	  <listitem>
+	    <para>
+	      In text shaping, a <emphasis>cluster</emphasis> is a
+	      sequence of codepoints that must be treated as an
+	      indivisible unit. Clusters can include code-point
+	      sequences that form a ligature or base-and-mark
+	      sequences. Tracking and preserving clusters is important
+	      when shaping operations might separate or reorder
+	      code points.
+	    </para>
+	    <para>
+	      HarfBuzz provides three cluster
+	      <emphasis>levels</emphasis> that implement different
+	      approaches to the problem of preserving clusters during
+	      shaping operations.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term>grapheme</term>
+	  <listitem>
+	    <para>
+	      In linguistics, a <emphasis>grapheme</emphasis> is one
+	      of the indivisible units that make up a writing system or
+	      script. Often, graphemes are individual symbols (letters,
+	      numbers, punctuation marks, logograms, etc.) but,
+	      depending on the writing system, a particular grapheme
+	      might correspond to a sequence of several Unicode code
+	      points.
+	    </para>
+	    <para>
+	      In practice, HarfBuzz and other text-shaping engines
+	      are not generally concerned with graphemes. However, it
+	      is important for developers using HarfBuzz to recognize
+	      that there is a difference between graphemes and shaping
+	      clusters (see above). The two concepts may overlap
+	      frequently, but there is no guarantee that they will be
+	      identical.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term>syllable</term>
+	  <listitem>
+	    <para>
+	      In linguistics, a <emphasis>syllable</emphasis> is an 
+	      a sequence of sounds that makes up a building block of a
+	      particular language. Every language has its own set of
+	      rules describing what constitutes a valid syllable.
+	    </para>
+	    <para>
+	      For text-shaping purposes, the various definitions of
+	      "syllable" are important because script-specific shaping
+	      operations may be applied at the syllable level. For
+	      example, a reordering rule might specify that a vowel
+	      mark be reordered to the beginning of the syllable.
+	    </para>
+	    <para>
+	      Syllables will consist of one or more Unicode code
+	      points. The definition of a syllable for a particular
+	      writing system might correspond to how HarfBuzz
+	      identifies clusters (see above) for the same writing
+	      system. However, it is important for developers using
+	      HarfBuzz to recognize that there is a difference between
+	      syllables and shaping clusters. The two concepts may
+	      overlap frequently, but there is no guarantee that they
+	      will be identical.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    
+  </section>
+
+
+  <section id="a-simple-shaping-example">
+    <title>A simple shaping example</title>
+
+    <para>
+      Below is the simplest HarfBuzz shaping example possible.
+    </para>
+    <orderedlist numeration="arabic">
+      <listitem>
+	<para>
+          Create a buffer and put your text in it.
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting language="C">
+      #include &lt;hb.h&gt;
+
+      hb_buffer_t *buf;
+      buf = hb_buffer_create();
+      hb_buffer_add_utf8(buf, text, -1, 0, -1);
+    </programlisting>
+    <orderedlist numeration="arabic">
+      <listitem override="2">
+	<para>
+          Set the script, language and direction of the buffer.
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting language="C">
+      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));
+    </programlisting>
+    <orderedlist numeration="arabic">
+      <listitem override="3">
+	<para>
+          Create a face and a font from a font file.
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting language="C">
+      hb_blob_t *blob = hb_blob_create_from_file(filename); /* or hb_blob_create_from_file_or_fail() */
+      hb_face_t *face = hb_face_create(blob, 0);
+      hb_font_t *font = hb_font_create(face);
+    </programlisting>
+    <orderedlist numeration="arabic">
+      <listitem override="4">
+	<para>
+          Shape!
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting>
+      hb_shape(font, buf, NULL, 0);
+    </programlisting>
+    <orderedlist numeration="arabic">
+      <listitem override="5">
+	<para>
+          Get the glyph and position information.
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting language="C">
+      unsigned int glyph_count;
+      hb_glyph_info_t *glyph_info    = hb_buffer_get_glyph_infos(buf, &amp;glyph_count);
+      hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &amp;glyph_count);
+    </programlisting>
+    <orderedlist numeration="arabic">
+      <listitem override="6">
+	<para>
+          Iterate over each glyph.
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting language="C">
+      hb_position_t cursor_x = 0;
+      hb_position_t cursor_y = 0;
+      for (unsigned int i = 0; i &lt; glyph_count; i++) {
+          hb_codepoint_t glyphid  = glyph_info[i].codepoint;
+          hb_position_t x_offset  = glyph_pos[i].x_offset;
+          hb_position_t y_offset  = glyph_pos[i].y_offset;
+          hb_position_t x_advance = glyph_pos[i].x_advance;
+          hb_position_t y_advance = glyph_pos[i].y_advance;
+       /* draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset); */
+          cursor_x += x_advance;
+          cursor_y += y_advance;
+      }
+    </programlisting>
+    <orderedlist numeration="arabic">
+      <listitem override="7">
+	<para>
+          Tidy up.
+	</para>
+      </listitem>
+    </orderedlist>
+    <programlisting language="C">
+      hb_buffer_destroy(buf);
+      hb_font_destroy(font);
+      hb_face_destroy(face);
+      hb_blob_destroy(blob);
+    </programlisting>
+    
+    <para>
+      This example shows enough to get us started using HarfBuzz. In
+      the sections that follow, we will use the remainder of
+      HarfBuzz's API to refine and extend the example and improve its
+      text-shaping capabilities.
+    </para>
+  </section>
+</chapter>

+ 14 - 0
libs/harfbuzz/docs/usermanual-glyph-information.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<sect1 id="glyph-information">
+  <title>Glyph information</title>
+  <sect2 id="names-and-numbers">
+    <title>Names and numbers</title>
+    <para>
+    </para>
+  </sect2>
+</sect1>

+ 349 - 0
libs/harfbuzz/docs/usermanual-install-harfbuzz.xml

@@ -0,0 +1,349 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="install-harfbuzz">
+  <title>Installing HarfBuzz</title>
+  
+  <section id="download">
+    <title id="download.title">Downloading HarfBuzz</title>
+    <para>
+      The HarfBuzz source code is hosted at <ulink
+      url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>.
+    </para>
+    <para>
+      Tarball releases and Win32 binary bundles (which include the
+      libharfbuzz DLL, hb-view.exe, hb-shape.exe, and all
+      dependencies) of HarfBuzz can be downloaded from <ulink
+      url="https://github.com/harfbuzz/harfbuzz/releases">github.com/harfbuzz/harfbuzz/releases</ulink>.
+    </para>
+    <para>
+      Release notes are posted with each new release to provide an
+      overview of the changes. The project <ulink url="https://github.com/harfbuzz/harfbuzz/issues">tracks bug
+      reports and other issues</ulink> on GitHub. Discussion and
+      questions are welcome on <ulink
+      url="https://github.com/harfbuzz/harfbuzz/discussions">GitHub</ulink> as well.
+    </para>
+    <para>
+      The API included in the <filename
+      class='headerfile'>hb.h</filename> file will not change in a
+      compatibility-breaking way in any release. However, other,
+      peripheral headers are more likely to go through minor
+      modifications. We will do our best to never change APIs in an
+      incompatible way. We will <emphasis>never</emphasis> break the ABI. 
+    </para>
+  </section>
+  
+  <section id="building">
+    <title>Building HarfBuzz</title>
+
+    <section id="building.linux">
+      <title>Building on Linux</title>
+    <para>
+      <emphasis>(1)</emphasis> To build HarfBuzz on Linux, you must first install the
+      development packages for FreeType, Cairo, and GLib. The exact
+      commands required for this step will vary depending on
+      the Linux distribution you use.
+    </para>
+    <para>
+      For example, on an Ubuntu or Debian system, you would run:
+      <programlisting><command>sudo apt install</command> <package>gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev</package></programlisting>
+      On Fedora, RHEL, CentOS, or other Red-Hat&ndash;based systems, you would run:
+      <programlisting><command>sudo yum install</command> <package>gcc gcc-c++ freetype-devel glib2-devel cairo-devel</package></programlisting>
+
+    </para>
+    
+    <para>
+      <emphasis>(2)</emphasis> The next step depends on whether you
+      are building from the source in a downloaded release tarball or
+      from the source directly from the git repository.
+    </para>
+    <para>
+      <emphasis>(2)(a)</emphasis> If you downloaded the HarfBuzz
+      source code in a tarball, you can now extract the source.
+    </para>
+    <para>
+      From a shell in the top-level directory of the extracted source
+      code, you can run <command>meson build</command> followed by
+      <command>meson compile -C build</command> as with any other standard package.
+    </para>
+    <para>
+      This should leave you with a shared
+      library in the <filename>src/</filename> directory, and a few
+      utility programs including <command>hb-view</command> and
+      <command>hb-shape</command> under the <filename>util/</filename>
+      directory.
+    </para>
+    <para>
+      <emphasis>(2)(b)</emphasis> If you are building from the source in the HarfBuzz git
+      repository, rather than installing from a downloaded tarball
+      release, then you must install two more auxiliary tools before you 
+      can build for the first time: <package>pkg-config</package>.
+    </para>
+    <para>
+      On Ubuntu or Debian, run:
+      <programlisting><command>sudo apt-get install</command> <package>meson pkg-config gtk-doc-tools</package></programlisting>
+      On Fedora, RHEL, CentOS, run:
+      <programlisting><command>sudo yum install</command> <package>meson pkgconfig gtk-doc</package></programlisting>
+      
+    </para>
+    <para>
+      With <package>pkg-config</package> installed, you can now run
+      <command>meson build</command> then
+      <command>meson compile -C build</command> to build HarfBuzz.
+    </para>
+    </section>
+
+    
+    <section id="building.windows">
+      <title>Building on Windows</title>
+
+      <para>
+        <ulink url="https://mesonbuild.com/Getting-meson.html">Install meson</ulink>
+        and run (from the console) <command>meson build</command> (by default
+        bundled dependencies are not built, <command>--wrap-mode=default</command>
+        overrides this), then <command>meson compile -C build</command> to
+	build HarfBuzz.
+      </para>
+    </section>
+
+    
+    <section id="building.macos">
+      <title>Building on macOS</title>
+
+      <para>
+	There are two ways to build HarfBuzz on Mac systems: MacPorts
+	and Homebrew. The process is similar to the process used on a
+	Linux system.
+      </para>
+      <para>
+	<emphasis>(1)</emphasis> You must first install the
+	development packages for FreeType, Cairo, and GLib. If you are
+	using MacPorts, you should run:
+      <programlisting><command>sudo port install</command> <package>freetype glib2 cairo</package></programlisting>
+      </para>
+      <para>
+	If you are using Homebrew, you should run:
+	<programlisting><command>brew install</command> <package>freetype glib cairo</package></programlisting>
+      </para>
+      <para>
+	<emphasis>(2)</emphasis> The next step depends on whether you are building from the
+	source in a downloaded release tarball or from the source directly
+	from the git repository.
+      </para>
+      <para>
+	<emphasis>(2)(a)</emphasis> If you are installing HarfBuzz
+	from a downloaded tarball release, extract the tarball and
+	open a Terminal in the extracted source-code directory. Run:
+	<programlisting><command>meson build</command></programlisting>
+	followed by:
+	<programlisting><command>meson compile -C build</command></programlisting>
+	to build HarfBuzz.
+      </para>
+      <para>
+	<emphasis>(2)(b)</emphasis> Alternatively, if you are building
+	HarfBuzz from the source in the HarfBuzz git repository, then
+	you must install several built-time dependencies before
+	proceeding.
+      </para>
+      <para>If you are
+	using MacPorts, you should run:
+      <programlisting><command>sudo port install</command> <package>meson pkgconfig gtk-doc</package></programlisting>
+      to install the build dependencies.
+      </para>
+      <para>If you are using Homebrew, you should run:
+	<programlisting><command>brew install</command> <package>meson pkgconfig gtk-doc</package></programlisting>
+      	Finally, you can run:
+	<programlisting><command>meson build</command></programlisting>
+      </para>
+      <para>
+	<emphasis>(3)</emphasis> You can now build HarfBuzz (on either
+	a MacPorts or a Homebrew system) by running:
+	<programlisting><command>meson build</command></programlisting>
+	followed by:
+	<programlisting><command>meson compile -C build</command></programlisting>
+      </para>
+      <para>
+	This should leave you with a shared
+	library in the <filename>src/</filename> directory, and a few
+	utility programs including <command>hb-view</command> and
+	<command>hb-shape</command> under the <filename>util/</filename>
+	directory.
+      </para>      
+	
+    </section>
+
+    <section id="configuration">
+      <title>Configuration options</title>
+
+      <para>
+	The instructions in the "Building HarfBuzz" section will build
+	the source code under its default configuration. If needed,
+	the following additional configuration options are available.
+      </para>
+
+      <variablelist>
+	<?dbfo list-presentation="blocks"?>	
+	<varlistentry>
+	  <term><command>-Dglib=enabled</command></term>
+	  <listitem>
+	    <para>
+	     Use <ulink url="https://developer.gnome.org/glib/">GLib</ulink>. <emphasis>(Default = auto)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the GLib
+	      library.  The default setting is to check for the
+	      presence of GLib and, if it is found, build with
+	      GLib support. GLib is native to GNU/Linux systems but is
+	      available on other operating system as well.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dgobject=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use <ulink url="https://developer.gnome.org/gobject/stable/">GObject</ulink>. <emphasis>(Default = no)</emphasis>
+	    </para>	   
+	    <para>
+	      This option enables or disables usage of the GObject
+	      library. The default setting is to check for the
+	      presence of GObject and, if it is found, build with
+	      GObject support. GObject is native to GNU/Linux systems but is
+	      available on other operating system as well.
+	    </para> 
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dcairo=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use <ulink url="https://cairographics.org/">Cairo</ulink>. <emphasis>(Default = auto)</emphasis>
+	    </para>	   
+	    <para>
+	      This option enables or disables usage of the Cairo
+	      graphics-rendering library. The default setting is to
+	      check for the presence of Cairo and, if it is found,
+	      build with Cairo support.
+	    </para>
+	    <para>
+	      Note: Cairo is used only by the HarfBuzz
+	      command-line utilities, and not by the HarfBuzz library.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dicu=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use the <ulink url="http://site.icu-project.org/home">ICU</ulink> library. <emphasis>(Default = auto)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the
+	      <emphasis>International Components for
+	      Unicode</emphasis> (ICU) library, which provides access
+	      to Unicode Character Database (UCD) properties as well
+	      as normalization and conversion functions. The default
+	      setting is to check for the presence of ICU and, if it
+	      is found, build with ICU support.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dgraphite=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use the <ulink url="http://graphite.sil.org/">Graphite2</ulink> library. <emphasis>(Default = no)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the Graphite2
+	      library, which provides support for the Graphite shaping
+	      model. 
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dfreetype=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use the <ulink url="https://www.freetype.org/">FreeType</ulink> library. <emphasis>(Default = auto)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the FreeType
+	      font-rendering library. The default setting is to check for the
+	      presence of FreeType and, if it is found, build with
+	      FreeType support.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dgdi=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use the <ulink
+	      url="https://docs.microsoft.com/en-us/windows/desktop/intl/uniscribe">Uniscribe</ulink>
+	      library (experimental). <emphasis>(Default = no)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the Uniscribe
+	      font-rendering library. Uniscribe is available on
+	      Windows systems. Uniscribe support is used only for
+	      testing purposes and does not need to be enabled for
+	      HarfBuzz to run on Windows systems.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Ddirectwrite=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use the <ulink url="https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal">DirectWrite</ulink> library (experimental). <emphasis>(Default = no)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the DirectWrite
+	      font-rendering library. DirectWrite is available on
+	      Windows systems. DirectWrite support is used only for
+	      testing purposes and does not need to be enabled for
+	      HarfBuzz to run on Windows systems.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	
+	<varlistentry>
+	  <term><command>-Dcoretext=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use the <ulink url="https://developer.apple.com/documentation/coretext">CoreText</ulink> library. <emphasis>(Default = no)</emphasis>
+	    </para>
+	    <para>
+	      This option enables or disables usage of the CoreText
+	      library. CoreText is available on macOS and iOS systems.
+	    </para>
+	  </listitem>
+	</varlistentry>	
+
+	<varlistentry>
+	  <term><command>-Ddocs=enabled</command></term>
+	  <listitem>
+	    <para>
+	      Use <ulink url="https://github.com/GNOME/gtk-doc">GTK-Doc</ulink>. <emphasis>(Default = no)</emphasis>
+	    </para>
+	    <para>
+	      This option enables the building of the documentation.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </section>
+    
+  </section>
+</chapter>

+ 603 - 0
libs/harfbuzz/docs/usermanual-integration.xml

@@ -0,0 +1,603 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="integration">
+  <title>Platform Integration Guide</title>
+  <para>
+    HarfBuzz was first developed for use with the GNOME and GTK
+    software stack commonly found in desktop Linux
+    distributions. Nevertheless, it can be used on other operating
+    systems and platforms, from iOS and macOS to Windows. It can also
+    be used with other application frameworks and components, such as
+    Android, Qt, or application-specific widget libraries.
+  </para>
+  <para>
+    This chapter will look at how HarfBuzz fits into a typical
+    text-rendering pipeline, and will discuss the APIs available to
+    integrate HarfBuzz with contemporary Linux, Mac, and Windows
+    software. It will also show how HarfBuzz integrates with popular
+    external libraries like FreeType and International Components for
+    Unicode (ICU) and describe the HarfBuzz language bindings for
+    Python.
+  </para>
+  <para>
+    On a GNOME system, HarfBuzz is designed to tie in with several
+    other common system libraries. The most common architecture uses
+    Pango at the layer directly "above" HarfBuzz; Pango is responsible
+    for text segmentation and for ensuring that each input
+    <type>hb_buffer_t</type> passed to HarfBuzz for shaping contains
+    Unicode code points that share the same segment properties
+    (namely, direction, language, and script, but also higher-level
+    properties like the active font, font style, and so on).
+  </para>
+  <para>
+    The layer directly "below" HarfBuzz is typically FreeType, which
+    is used to rasterize glyph outlines at the necessary optical size,
+    hinting settings, and pixel resolution. FreeType provides APIs for
+    accessing font and face information, so HarfBuzz includes
+    functions to create <type>hb_face_t</type> and
+    <type>hb_font_t</type> objects directly from FreeType
+    objects. HarfBuzz can use FreeType's built-in functions for
+    <structfield>font_funcs</structfield> vtable in an <type>hb_font_t</type>.
+  </para>
+  <para>
+    FreeType's output is bitmaps of the rasterized glyphs; on a
+    typical Linux system these will then be drawn by a graphics
+    library like Cairo, but those details are beyond HarfBuzz's
+    control. On the other hand, at the top end of the stack, Pango is
+    part of the larger GNOME framework, and HarfBuzz does include APIs
+    for working with key components of GNOME's higher-level libraries
+    &mdash; most notably GLib.
+  </para>
+  <para>
+    For other operating systems or application frameworks, the
+    critical integration points are where HarfBuzz gets font and face
+    information about the font used for shaping and where HarfBuzz
+    gets Unicode data about the input-buffer code points.
+  </para>
+  <para>
+    The font and face information is necessary for text shaping
+    because HarfBuzz needs to retrieve the glyph indices for
+    particular code points, and to know the extents and advances of
+    glyphs. Note that, in an OpenType variable font, both of those
+    types of information can change with different variation-axis
+    settings.
+  </para>
+  <para>
+    The Unicode information is necessary for shaping because the
+    properties of a code point (such as its General Category (gc),
+    Canonical Combining Class (ccc), and decomposition) can directly
+    impact the shaping moves that HarfBuzz performs.
+  </para>
+  
+  <section id="integration-glib">
+    <title>GNOME integration, GLib, and GObject</title>
+    <para>
+      As mentioned in the preceding section, HarfBuzz offers
+      integration APIs to help client programs using the
+      GNOME and GTK framework commonly found in desktop Linux
+      distributions. 
+    </para>
+    <para>
+      GLib is the main utility library for GNOME applications. It
+      provides basic data types and conversions, file abstractions,
+      string manipulation, and macros, as well as facilities like
+      memory allocation and the main event loop.
+    </para>
+    <para>
+      Where text shaping is concerned, GLib provides several utilities
+      that HarfBuzz can take advantage of, including a set of
+      Unicode-data functions and a data type for script
+      information. Both are useful when working with HarfBuzz
+      buffers. To make use of them, you will need to include the
+      <filename>hb-glib.h</filename> header file.
+    </para>
+    <para>
+      GLib's <ulink
+      url="https://developer.gnome.org/glib/stable/glib-Unicode-Manipulation.html">Unicode
+      manipulation API</ulink> includes all the functionality
+      necessary to retrieve Unicode data for the
+      <structfield>unicode_funcs</structfield> structure of a HarfBuzz
+      <type>hb_buffer_t</type>. 
+    </para>
+    <para>
+      The function <function>hb_glib_get_unicode_funcs()</function>
+      sets up a <type>hb_unicode_funcs_t</type> structure configured
+      with the GLib Unicode functions and returns a pointer to it.
+    </para>
+    <para>
+      You can attach this Unicode-functions structure to your buffer,
+      and it will be ready for use with GLib:
+    </para>
+    <programlisting language="C">
+      #include &lt;hb-glib.h&gt;
+      ...
+      hb_unicode_funcs_t *glibufunctions;
+      glibufunctions = hb_glib_get_unicode_funcs();
+      hb_buffer_set_unicode_funcs(buf, glibufunctions);
+    </programlisting>
+    <para>
+      For script information, GLib uses the
+      <type>GUnicodeScript</type> type. Like HarfBuzz's own
+      <type>hb_script_t</type>, this data type is an enumeration
+      of Unicode scripts, but text segments passed in from GLib code
+      will be tagged with a <type>GUnicodeScript</type>. Therefore,
+      when setting the script property on a <type>hb_buffer_t</type>,
+      you will need to convert between the <type>GUnicodeScript</type>
+      of the input provided by GLib and HarfBuzz's
+      <type>hb_script_t</type> type.
+    </para>
+    <para>
+      The <function>hb_glib_script_to_script()</function> function
+      takes an <type>GUnicodeScript</type> script identifier as its
+      sole argument and returns the corresponding <type>hb_script_t</type>.
+      The <function>hb_glib_script_from_script()</function> does the
+      reverse, taking an <type>hb_script_t</type> and returning the
+      <type>GUnicodeScript</type> identifier for GLib.
+    </para>
+    <para>
+      Finally, GLib also provides a reference-counted object type called <ulink
+      url="https://developer.gnome.org/glib/stable/glib-Byte-Arrays.html#GBytes"><type>GBytes</type></ulink>
+      that is used for accessing raw memory segments with the benefits
+      of GLib's lifecycle management. HarfBuzz provides a
+      <function>hb_glib_blob_create()</function> function that lets
+      you create an <type>hb_blob_t</type> directly from a
+      <type>GBytes</type> object. This function takes only the
+      <type>GBytes</type> object as its input; HarfBuzz registers the
+      GLib <function>destroy</function> callback automatically.
+    </para>
+    <para>
+      The GNOME platform also features an object system called
+      GObject. For HarfBuzz, the main advantage of GObject is a
+      feature called <ulink
+      url="https://gi.readthedocs.io/en/latest/">GObject
+      Introspection</ulink>. This is a middleware facility that can be
+      used to generate language bindings for C libraries. HarfBuzz uses it
+      to build its Python bindings, which we will look at in a separate section.
+    </para>
+  </section>
+  
+  <section id="integration-freetype">
+    <title>FreeType integration</title>
+    <para>
+      FreeType is the free-software font-rendering engine included in
+      desktop Linux distributions, Android, ChromeOS, iOS, and multiple Unix
+      operating systems, and used by cross-platform programs like
+      Chrome, Java, and GhostScript. Used together, HarfBuzz can
+      perform shaping on Unicode text segments, outputting the glyph
+      IDs that FreeType should rasterize from the active font as well
+      as the positions at which those glyphs should be drawn.
+    </para>
+    <para>
+      HarfBuzz provides integration points with FreeType at the
+      face-object and font-object level and for the font-functions
+      virtual-method structure of a font object. To use the
+      FreeType-integration API, include the
+      <filename>hb-ft.h</filename> header.
+    </para>
+    <para>
+      In a typical client program, you will create your
+      <type>hb_face_t</type> face object and <type>hb_font_t</type>
+      font object from a FreeType <type>FT_Face</type>. HarfBuzz
+      provides a suite of functions for doing this.
+    </para>
+    <para>
+      In the most common case, you will want to use
+      <function>hb_ft_font_create_referenced()</function>, which
+      creates both an <type>hb_face_t</type> face object and
+      <type>hb_font_t</type> font object (linked to that face object),
+      and provides lifecycle management.
+    </para>
+    <para>
+      It is important to note,
+      though, that while HarfBuzz makes a distinction between its face and
+      font objects, FreeType's <type>FT_Face</type> does not. After
+      you create your <type>FT_Face</type>, you must set its size
+      parameter using <function>FT_Set_Char_Size()</function>, because
+      an <type>hb_font_t</type> is defined as an instance of an
+      <type>hb_face_t</type> with size specified.
+    </para>
+    <programlisting language="C">
+      #include &lt;hb-ft.h&gt;
+      ...
+      FT_New_Face(ft_library, font_path, index, &amp;face);
+      FT_Set_Char_Size(face, 0, 1000, 0, 0);
+      hb_font_t *font = hb_ft_font_create(face);
+    </programlisting>
+    <para>
+      <function>hb_ft_font_create_referenced()</function> is
+      the recommended function for creating an <type>hb_face_t</type> face
+      object. This function calls <function>FT_Reference_Face()</function>
+      before using the <type>FT_Face</type> and calls 
+      <function>FT_Done_Face()</function> when it is finished using the
+      <type>FT_Face</type>. Consequently, your client program does not need
+      to worry about destroying the <type>FT_Face</type> while HarfBuzz
+      is still using it.
+    </para>
+    <para>
+      Although <function>hb_ft_font_create_referenced()</function> is
+      the recommended function, there is another variant for client code
+      where special circumstances make it necessary. The simpler
+      version of the function is <function>hb_ft_font_create()</function>,
+      which takes an <type>FT_Face</type> and an optional destroy callback 
+      as its arguments. Because <function>hb_ft_font_create()</function> 
+      does not offer lifecycle management, however, your client code will
+      be responsible for tracking references to the <type>FT_Face</type>
+      objects and destroying them when they are no longer needed. If you
+      do not have a valid reason for doing this, use
+      <function>hb_ft_font_create_referenced()</function>. 
+    </para>
+    <para>
+      After you have created your font object from your
+      <type>FT_Face</type>, you can set or retrieve the
+      <structfield>load_flags</structfield> of the
+      <type>FT_Face</type> through the <type>hb_font_t</type>
+      object. HarfBuzz provides
+      <function>hb_ft_font_set_load_flags()</function> and
+      <function>hb_ft_font_get_load_flags()</function> for this
+      purpose. The ability to set the
+      <structfield>load_flags</structfield> through the font object
+      could be useful for enabling or disabling hinting, for example,
+      or to activate vertical layout.
+    </para>
+    <para>
+      HarfBuzz also provides a utility function called
+      <function>hb_ft_font_has_changed()</function> that you should
+      call whenever you have altered the properties of your underlying
+      <type>FT_Face</type>, as well as a
+      <function>hb_ft_get_face()</function> that you can call on an
+      <type>hb_font_t</type> font object to fetch its underlying <type>FT_Face</type>.
+    </para>
+    <para>
+      With an <type>hb_face_t</type> and <type>hb_font_t</type> both linked
+      to your <type>FT_Face</type>, you will typically also want to
+      use FreeType for the <structfield>font_funcs</structfield>
+      vtable of your <type>hb_font_t</type>. As a reminder, this
+      font-functions structure is the set of methods that HarfBuzz
+      will use to fetch important information from the font, such as
+      the advances and extents of individual glyphs. 
+    </para>
+    <para>
+      All you need to do is call
+    </para>
+    <programlisting language="C">
+      hb_ft_font_set_funcs(font);
+    </programlisting>
+    <para>
+      and HarfBuzz will use FreeType for the font-functions in
+      <literal>font</literal>. 
+    </para>
+    <para>
+      As we noted above, an <type>hb_font_t</type> is derived from an
+      <type>hb_face_t</type> with size (and, perhaps, other
+      parameters, such as variation-axis coordinates)
+      specified. Consequently, you can reuse an <type>hb_face_t</type>
+      with several <type>hb_font_t</type> objects, and HarfBuzz
+      provides functions to simplify this.
+    </para>
+    <para>
+      The <function>hb_ft_face_create_referenced()</function>
+      function creates just an <type>hb_face_t</type> from a FreeType
+      <type>FT_Face</type> and, as with
+      <function>hb_ft_font_create_referenced()</function> above,
+      provides lifecycle management for the <type>FT_Face</type>.
+    </para>
+    <para>
+      Similarly, there is an <function>hb_ft_face_create()</function>
+      function variant that does not provide the lifecycle-management
+      feature. As with the font-object case, if you use this version
+      of the function, it will be your client code's respsonsibility
+      to track usage of the <type>FT_Face</type> objects.
+    </para>
+    <para>
+      A third variant of this function is
+      <function>hb_ft_face_create_cached()</function>, which is the
+      same as <function>hb_ft_face_create()</function> except that it
+      also uses the <structfield>generic</structfield> field of the
+      <type>FT_Face</type> structure to save a pointer to the newly
+      created <type>hb_face_t</type>. Subsequently, function calls
+      that pass the same <type>FT_Face</type> will get the same
+      <type>hb_face_t</type> returned &mdash; and the
+      <type>hb_face_t</type> will be correctly reference
+      counted. Still, as with
+      <function>hb_ft_face_create()</function>, your client code must
+      track references to the <type>FT_Face</type> itself, and destroy
+      it when it is unneeded.
+    </para>
+  </section>
+  
+  <section id="integration-uniscribe">
+    <title>Uniscribe integration</title>
+    <para>
+      If your client program is running on Windows, HarfBuzz offers
+      an additional API that can help integrate with Microsoft's
+      Uniscribe engine and the Windows GDI.
+    </para>
+    <para>
+      Overall, the Uniscribe API covers a broader set of typographic
+      layout functions than HarfBuzz implements, but HarfBuzz's
+      shaping API can serve as a drop-in replacement for Uniscribe's shaping
+      functionality. In fact, one of HarfBuzz's design goals is to
+      accurately reproduce the same output for shaping a given text
+      segment that Uniscribe produces &mdash; even to the point of
+      duplicating known shaping bugs or deviations from the
+      specification &mdash; so you can be confident that your users'
+      documents with their existing fonts will not be affected adversely by
+      switching to HarfBuzz.
+    </para>
+    <para>
+      At a basic level, HarfBuzz's <function>hb_shape()</function>
+      function replaces both the <ulink url=""><function>ScriptShape()</function></ulink>
+      and <ulink
+      url="https://docs.microsoft.com/en-us/windows/desktop/api/Usp10/nf-usp10-scriptplace"><function>ScriptPlace()</function></ulink>
+      functions from Uniscribe. 
+    </para>
+    <para>
+      However, whereas <function>ScriptShape()</function> returns the
+      glyphs and clusters for a shaped sequence and
+      <function>ScriptPlace()</function> returns the advances and
+      offsets for those glyphs, <function>hb_shape()</function>
+      handles both. After <function>hb_shape()</function> shapes a
+      buffer, the output glyph IDs and cluster IDs are returned as
+      an array of <structname>hb_glyph_info_t</structname> structures, and the
+      glyph advances and offsets are returned as an array of
+      <structname>hb_glyph_position_t</structname> structures. 
+    </para>
+    <para>
+      Your client program only needs to ensure that it converts
+      correctly between HarfBuzz's low-level data types (such as
+      <type>hb_position_t</type>) and Windows's corresponding types
+      (such as <type>GOFFSET</type> and <type>ABC</type>). Be sure you
+      read the <xref linkend="buffers-language-script-and-direction"
+      /> 
+      chapter for a full explanation of how HarfBuzz input buffers are
+      used, and see <xref linkend="shaping-buffer-output" /> for the
+      details of what <function>hb_shape()</function> returns in the
+      output buffer when shaping is complete. 
+    </para>
+    <para>
+      Although <function>hb_shape()</function> itself is functionally
+      equivalent to Uniscribe's shaping routines, there are two
+      additional HarfBuzz functions you may want to use to integrate
+      the libraries in your code. Both are used to link HarfBuzz font
+      objects to the equivalent Windows structures.
+    </para>
+    <para>
+      The <function>hb_uniscribe_font_get_logfontw()</function>
+      function takes a <type>hb_font_t</type> font object and returns
+      a pointer to the <ulink
+      url="https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-logfontw"><type>LOGFONTW</type></ulink>
+      "logical font" that corresponds to it. A <type>LOGFONTW</type>
+      structure holds font-wide attributes, including metrics, size,
+      and style information.
+    </para>
+<!--      
+     <para>
+       In Uniscribe's model, the <type>SCRIPT_CACHE</type> holds the
+       device context, including the logical font that the shaping
+       functions apply.
+       https://docs.microsoft.com/en-us/windows/desktop/Intl/script-cache
+    </para>
+-->
+    <para>
+      The <function>hb_uniscribe_font_get_hfont()</function> function
+      also takes a <type>hb_font_t</type> font object, but it returns
+      an <type>HFONT</type> &mdash; a handle to the underlying logical
+      font &mdash; instead.
+    </para>
+    <para>
+      <type>LOGFONTW</type>s and <type>HFONT</type>s are both needed
+      by other Uniscribe functions.
+    </para>
+    <para>
+      As a final note, you may notice a reference to an optional
+      <literal>uniscribe</literal> shaper back-end in the <xref
+      linkend="configuration" /> section of the HarfBuzz manual. This
+      option is not a Uniscribe-integration facility.
+    </para>
+    <para>
+      Instead, it is a internal code path used in the
+      <command>hb-shape</command> command-line utility, which hands
+      shaping functionality over to Uniscribe entirely, when run on a
+      Windows system. That allows testing HarfBuzz's native output
+      against the Uniscribe engine, for tracking compatibility and
+      debugging.
+    </para>
+    <para>
+      Because this back-end is only used when testing HarfBuzz
+      functionality, it is disabled by default when building the
+      HarfBuzz binaries.
+    </para>
+  </section>
+   
+  <section id="integration-coretext">
+    <title>Core Text integration</title>
+    <para>
+      If your client program is running on macOS or iOS, HarfBuzz offers
+      an additional API that can help integrate with Apple's
+      Core Text engine and the underlying Core Graphics
+      framework. HarfBuzz does not attempt to offer the same
+      drop-in-replacement functionality for Core Text that it strives
+      for with Uniscribe on Windows, but you can still use HarfBuzz
+      to perform text shaping in native macOS and iOS applications.
+    </para>
+    <para>
+      Note, though, that if your interest is just in using fonts that
+      contain Apple Advanced Typography (AAT) features, then you do
+      not need to add Core Text integration. HarfBuzz natively
+      supports AAT features and will shape AAT fonts (on any platform)
+      automatically, without requiring additional work on your
+      part. This includes support for AAT-specific TrueType tables
+      such as <literal>mort</literal>, <literal>morx</literal>, and
+      <literal>kerx</literal>, which AAT fonts use instead of
+      <literal>GSUB</literal> and <literal>GPOS</literal>.
+    </para>
+    <para>
+      On a macOS or iOS system, the primary integration points offered
+      by HarfBuzz are for face objects and font objects. 
+    </para>
+    <para>
+      The Apple APIs offer a pair of data structures that map well to
+      HarfBuzz's face and font objects. The Core Graphics API, which
+      is slightly lower-level than Core Text, provides
+      <ulink url="https://developer.apple.com/documentation/coregraphics/cgfontref"><type>CGFontRef</type></ulink>, which enables access to typeface
+      properties, but does not include size information. Core Text's
+      <ulink url="https://developer.apple.com/documentation/coretext/ctfont-q6r"><type>CTFontRef</type></ulink> is analogous to a HarfBuzz font object,
+      with all of the properties required to render text at a specific
+      size and configuration.
+      Consequently, a HarfBuzz <type>hb_font_t</type> font object can
+      be hooked up to a Core Text <type>CTFontRef</type>, and a HarfBuzz
+      <type>hb_face_t</type> face object can be hooked up to a
+      <type>CGFontRef</type>.
+    </para>
+    <para>
+      You can create a <type>hb_face_t</type> from a
+      <type>CGFontRef</type> by using the
+      <function>hb_coretext_face_create()</function>. Subsequently,
+      you can retrieve the <type>CGFontRef</type> from a
+      <type>hb_face_t</type> with <function>hb_coretext_face_get_cg_font()</function>.
+    </para>
+    <para>
+      Likewise, you create a <type>hb_font_t</type> from a
+      <type>CTFontRef</type> by calling
+      <function>hb_coretext_font_create()</function>, and you can
+      fetch the associated <type>CTFontRef</type> from a
+      <type>hb_font_t</type> font object with
+      <function>hb_coretext_face_get_ct_font()</function>. 
+    </para>
+    <para>
+      HarfBuzz also offers a <function>hb_font_set_ptem()</function>
+      that you an use to set the nominal point size on any
+      <type>hb_font_t</type> font object. Core Text uses this value to
+      implement optical scaling. 
+    </para>
+    <para>
+      When integrating your client code with Core Text, it is
+      important to recognize that Core Text <literal>points</literal>
+      are not typographic points (standardized at 72 per inch) as the
+      term is used elsewhere in OpenType. Instead, Core Text points
+      are CSS points, which are standardized at 96 per inch.
+    </para>
+    <para>
+      HarfBuzz's font functions take this distinction into account,
+      but it can be an easy detail to miss in cross-platform
+      code. 
+    </para>
+    <para>
+      As a final note, you may notice a reference to an optional
+      <literal>coretext</literal> shaper back-end in the <xref
+      linkend="configuration" /> section of the HarfBuzz manual. This
+      option is not a Core Text-integration facility.
+    </para>
+    <para>
+      Instead, it is a internal code path used in the
+      <command>hb-shape</command> command-line utility, which hands
+      shaping functionality over to Core Text entirely, when run on a
+      macOS system. That allows testing HarfBuzz's native output
+      against the Core Text engine, for tracking compatibility and debugging.
+    </para>
+    <para>
+      Because this back-end is only used when testing HarfBuzz
+      functionality, it is disabled by default when building the
+      HarfBuzz binaries.
+    </para>
+  </section>
+  
+  <section id="integration-icu">
+    <title>ICU integration</title>
+    <para>
+      Although HarfBuzz includes its own Unicode-data functions, it
+      also provides integration APIs for using the International
+      Components for Unicode (ICU) library as a source of Unicode data
+      on any supported platform.
+    </para>
+    <para>
+      The principal integration point with ICU is the
+      <type>hb_unicode_funcs_t</type> Unicode-functions structure
+      attached to a buffer. This structure holds the virtual methods
+      used for retrieving Unicode character properties, such as
+      General Category, Script, Combining Class, decomposition
+      mappings, and mirroring information.
+    </para>
+    <para>
+      To use ICU in your client program, you need to call
+      <function>hb_icu_get_unicode_funcs()</function>, which creates a
+      Unicode-functions structure populated with the ICU function for
+      each included method. Subsequently, you can attach the
+      Unicode-functions structure to your buffer:
+    </para>
+    <programlisting language="C">
+      hb_unicode_funcs_t *icufunctions;
+      icufunctions = hb_icu_get_unicode_funcs();
+      hb_buffer_set_unicode_funcs(buf, icufunctions);
+    </programlisting>
+    <para>
+      and ICU will be used for Unicode-data access.
+    </para>
+    <para>
+      HarfBuzz also supplies a pair of functions
+      (<function>hb_icu_script_from_script()</function> and
+      <function>hb_icu_script_to_script()</function>) for converting
+      between ICU's and HarfBuzz's internal enumerations of Unicode
+      scripts. The <function>hb_icu_script_from_script()</function>
+      function converts from a HarfBuzz <type>hb_script_t</type> to an
+      ICU <type>UScriptCode</type>. The
+      <function>hb_icu_script_to_script()</function> function does the
+      reverse: converting from a <type>UScriptCode</type> identifier
+      to a <type>hb_script_t</type>.
+    </para>
+    <para>
+      By default, HarfBuzz's ICU support is built as a separate shared
+      library (<filename class="libraryfile">libharfbuzz-icu.so</filename>)
+      when compiling HarfBuzz from source. This allows client programs
+      that do not need ICU to link against HarfBuzz without unnecessarily
+      adding ICU as a dependency. You can also build HarfBuzz with ICU
+      support built directly into the main HarfBuzz shared library
+      (<filename class="libraryfile">libharfbuzz.so</filename>),
+      by specifying the <literal>--with-icu=builtin</literal>
+      compile-time option.
+    </para>
+
+  </section>
+  
+  <section id="integration-python">
+    <title>Python bindings</title>
+    <para>
+      As noted in the <xref linkend="integration-glib" /> section,
+      HarfBuzz uses a feature called <ulink
+      url="https://wiki.gnome.org/Projects/GObjectIntrospection">GObject
+      Introspection</ulink> (GI) to provide bindings for Python.
+    </para>
+    <para>
+      At compile time, the GI scanner analyzes the HarfBuzz C source
+      and builds metadata objects connecting the language bindings to
+      the C library. Your Python code can then use the HarfBuzz binary
+      through its Python interface.
+    </para>
+    <para>
+      HarfBuzz's Python bindings support Python 2 and Python 3. To use
+      them, you will need to have the <literal>pygobject</literal>
+      package installed. Then you should import
+      <literal>HarfBuzz</literal> from
+      <literal>gi.repository</literal>: 
+    </para>
+    <programlisting language="Python">
+      from gi.repository import HarfBuzz
+    </programlisting>
+    <para>
+      and you can call HarfBuzz functions from Python. Sample code can
+      be found in the <filename>sample.py</filename> script in the
+      HarfBuzz <filename>src</filename> directory.
+    </para>
+    <para>
+      Do note, however, that the Python API is subject to change
+      without advance notice. GI allows the bindings to be
+      automatically updated, which is one of its advantages, but you
+      may need to update your Python code.
+    </para>
+  </section>
+  
+</chapter>

+ 266 - 0
libs/harfbuzz/docs/usermanual-object-model.xml

@@ -0,0 +1,266 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="object-model">
+  <title>The HarfBuzz object model</title>
+  <section id="object-model-intro">
+    <title>An overview of data types in HarfBuzz</title>
+    <para>
+      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.
+    </para>
+    <para>
+      <emphasis>Value types:</emphasis> 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.
+    </para>
+    <para>
+      In HarfBuzz, several structs, like <literal>hb_glyph_info_t</literal> and
+      <literal>hb_glyph_position_t</literal>, fall into that efficiency-sensitive
+      category and are non-opaque.
+    </para>
+    <para>
+      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
+      <function>equal()</function>, and <function>hash()</function>
+      methods for such structs, allowing users of the API do
+      effectively deal with the type without having to
+      adapt their code to future changes.
+    </para>
+    <para>
+      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.
+    </para>
+  </section>
+
+  <section id="object-model-object-types">
+    <title>Objects in HarfBuzz</title>
+    <para>
+      <emphasis>Object types:</emphasis> 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.
+    </para>
+    <para>
+      In HarfBuzz, all object types provide certain
+      lifecycle-management APIs.  Objects are reference-counted, and
+      constructed with various <function>create()</function> methods, referenced via
+      <function>reference()</function> and dereferenced using
+      <function>destroy()</function>.
+    </para>
+    <para>
+      For example,
+      the <literal>hb_buffer_t</literal> object has
+      <function>hb_buffer_create()</function> as its constructor,
+      <function>hb_buffer_reference()</function> to reference, and
+      <function>hb_buffer_destroy()</function> to dereference.
+    </para>
+    <para>
+      After construction, each object's properties are accessible only
+      through the setter and getter functions described in the API
+      Reference manual.
+    </para>
+    <para>
+      Note that many object types can be marked as read-only or immutable,
+      facilitating their use in multi-threaded environments.
+    </para>
+    <para>
+      Key object types provided by HarfBuzz include:
+    </para>
+    <itemizedlist spacing="compact">
+      <listitem>
+	<para>
+	  <emphasis>blobs</emphasis>, which act as low-level wrappers around binary
+	  data. Blobs are typically used to hold the contents of a
+	  binary font file.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>faces</emphasis>, which represent typefaces from a
+	  font file, but without specific parameters (such as size) set.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>fonts</emphasis>, which represent instances of a
+	  face with all of their parameters specified.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>buffers</emphasis>, which hold Unicode code points
+	  for characters (before shaping) and the shaped glyph output
+	  (after shaping).
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>shape plans</emphasis>, 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.
+	</para>
+      </listitem>
+    </itemizedlist>
+
+  </section>
+
+
+
+  <section id="object-model-lifecycle">
+    <title>Object lifecycle management</title>
+    <para>
+      Each object type in HarfBuzz provides a
+      <function>create()</function> method. Some object types provide
+      additional variants of <function>create()</function> to handle
+      special cases or to speed up common tasks; those variants are
+      documented in the API reference. For example,
+      <function>hb_blob_create_from_file()</function> constructs a new
+      blob directly from the contents of a file.
+    </para>
+    <para>
+      All objects are created with an initial reference count of
+      <literal>1</literal>. Client programs can increase the reference
+      count on an object by calling its
+      <function>reference()</function> method. Whenever a client
+      program is finished with an object, it should call its
+      corresponding <function>destroy()</function> 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.
+    </para>
+    <para>
+      All of HarfBuzz's object-lifecycle-management APIs are
+      thread-safe (unless you compiled HarfBuzz from source with the
+      <literal>HB_NO_MT</literal> configuration flag), even when the
+      object as a whole is not thread-safe.
+      It is also permissible to <function>reference()</function> or to
+      <function>destroy()</function> the <literal>NULL</literal>
+      value.
+    </para>
+    <para>
+      Some objects are thread-safe after they have been constructed
+      and set up. The general pattern is to
+      <function>create()</function> the object, make a few
+      <function>set_*()</function> calls to set up the
+      object, and then use it without further modification.
+    </para>
+    <para>
+      To ensure that such an object is not modified, client programs
+      can explicitly mark an object as immutable. HarfBuzz provides
+      <function>make_immutable()</function> methods to mark an object
+      as immutable and <function>is_immutable()</function> 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.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      Finally, object constructors (and, indeed, as much of the
+      shaping API as possible) will never return
+      <literal>NULL</literal>.  Instead, if there is an allocation
+      error, each constructor will return an “empty” object
+      singleton.
+    </para>
+    <para>
+      These empty-object singletons are inert and safe (although
+      typically useless) to pass around.  This design choice avoids
+      having to check for <literal>NULL</literal> pointers all
+      throughout the code.
+    </para>
+    <para>
+      In addition, this “empty” object singleton can also be accessed
+      using the <function>get_empty()</function> method of the object
+      type in question.
+    </para>
+  </section>
+
+
+  <section id="object-model-user-data">
+    <title>User data</title>
+    <para>
+      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.
+    </para>
+    <para>
+      Each object type has a <function>set_user_data()</function>
+      method and a <function>get_user_data()</function> method. The
+      <function>set_user_data()</function> methods take a client-provided
+      <literal>key</literal> and a pointer,
+      <literal>user_data</literal>, pointing to the data itself. Once
+      the key-data pair has been attached to the object, the
+      <function>get_user_data()</function> method can be called with
+      the key, returning the <function>user_data</function> pointer.
+    </para>
+    <para>
+      The <function>set_user_data()</function> methods also support an
+      optional <function>destroy</function> callback. Client programs
+      can set the <function>destroy</function> callback and receive
+      notification from HarfBuzz whenever the object is destructed.
+    </para>
+    <para>
+      Finally, each <function>set_user_data()</function> method allows
+      the client program to set a <literal>replace</literal> Boolean
+      indicating whether or not the function call should replace any
+      existing <literal>user_data</literal>
+      associated with the specified key.
+    </para>
+  </section>
+
+
+
+  <section id="object-model-blobs">
+    <title>Blobs</title>
+    <para>
+      While most of HarfBuzz's object types are specific to the
+      shaping process, <emphasis>blobs</emphasis> are somewhat
+      different.
+    </para>
+    <para>
+      Blobs are an abstraction designed 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 <literal>hb_blob_t</literal> wrapper.
+    </para>
+    <para>
+      This allows you to take advantage of HarfBuzz's
+      reference-counting and <function>destroy</function>
+      callbacks. If you allocated the memory for the data using
+      <function>malloc()</function>, you would create the blob using
+    </para>
+    <programlisting language="C">
+      hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, data, free)
+    </programlisting>
+    <para>
+      That way, HarfBuzz will call <function>free()</function> 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.
+    </para>
+    <para>
+      Most of the time, blobs are read-only, facilitating their use in
+      immutable objects.
+    </para>
+  </section>
+
+</chapter>

+ 336 - 0
libs/harfbuzz/docs/usermanual-opentype-features.xml

@@ -0,0 +1,336 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="shaping-and-shape-plans">
+  <title>Shaping and shape plans</title>
+  <para>
+    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 <function>hb_shape()</function>.
+  </para>
+  <para>
+    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.
+  </para>
+  <para>
+    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.
+  </para>
+  
+  <section id="shaping-buffer-output">
+    <title>Shaping and buffer output</title>
+    <para>
+      The <function>hb_shape()</function> 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.
+    </para>
+    <para>
+      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
+      <emphasis>shaper</emphasis> to use (<literal>ot</literal> for
+      OpenType fonts, <literal>aat</literal> 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).      
+    </para>
+    <para>
+      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 <literal>morx</literal> 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
+      <literal>kerx</literal> 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 <literal>kern</literal> table, then HarfBuzz will
+      use the <literal>kern</literal> table. If there is no <literal>kerx</literal>, no GPOS, and no
+      <literal>kern</literal>, HarfBuzz will fall back to positioning marks itself.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      The algorithms
+      used for shaping 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, to the extent that is feasible and desirable. See the <ulink
+      url="https://docs.microsoft.com/en-us/typography/script-development/standard">Microsoft
+      Typography pages</ulink> for more detail.
+    </para>
+    <para>
+      In general, though, all that you need to know is that
+      <function>hb_shape()</function> returns the results of shaping
+      in the same buffer that you provided. The buffer's content type
+      will now be set to
+      <literal>HB_BUFFER_CONTENT_TYPE_GLYPHS</literal>, indicating
+      that it contains shaped output, rather than input text. You can
+      now extract the glyph information and positioning arrays:
+    </para>
+    <programlisting language="C">
+      hb_glyph_info_t *glyph_info    = hb_buffer_get_glyph_infos(buf, &amp;glyph_count);
+      hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &amp;glyph_count);
+    </programlisting>
+    <para>
+      The glyph information array holds a <type>hb_glyph_info_t</type>
+      for each output glyph, which has two fields:
+      <parameter>codepoint</parameter> and
+      <parameter>cluster</parameter>. Whereas, in the input buffer,
+      the <parameter>codepoint</parameter> field contained the Unicode
+      code point, it now contains the glyph ID of the corresponding
+      glyph in the font. The <parameter>cluster</parameter> 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.
+    </para>
+    <para>
+      The glyph positions array holds a corresponding
+      <type>hb_glyph_position_t</type> for each output glyph,
+      containing four fields: <parameter>x_advance</parameter>,
+      <parameter>y_advance</parameter>,
+      <parameter>x_offset</parameter>, and
+      <parameter>y_offset</parameter>. 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.
+    </para>
+    <para>
+      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.
+    </para>
+  </section>
+  
+  <section id="shaping-opentype-features">
+    <title>OpenType features</title>
+    <para>
+      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.
+    </para>
+    <para>
+      Some OpenType features are defined for the purpose of supporting
+      script-specific shaping, and are automatically activated, but
+      only when a buffer's script property is set to a script that the
+      feature supports.
+    </para>
+    <para>
+      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 <literal>abvm</literal>,
+      <literal>blwm</literal>, <literal>ccmp</literal>,
+      <literal>locl</literal>, <literal>mark</literal>,
+      <literal>mkmk</literal>, and <literal>rlig</literal>.
+    </para>
+    <para>
+      In addition, if the text direction is horizontal, HarfBuzz
+      also applies the <literal>calt</literal>,
+      <literal>clig</literal>, <literal>curs</literal>,
+      <literal>dist</literal>, <literal>kern</literal>,
+      <literal>liga</literal> and <literal>rclt</literal>, features.
+    </para>
+    <para>
+      Additionally, when HarfBuzz encounters a fraction slash
+      (<literal>U+2044</literal>), it looks backward and forward for decimal
+      digits (Unicode General Category = Nd), and enables features
+      <literal>numr</literal> on the sequence before the fraction slash,
+      <literal>dnom</literal> on the sequence after the fraction slash,
+      and <literal>frac</literal> on the whole sequence including the fraction
+      slash.
+    </para>
+    <para>
+      Some script-specific shaping models
+      (see <xref linkend="opentype-shaping-models" />) disable some of the
+      features listed above:
+    </para>
+    <itemizedlist>
+      <listitem>
+        <para>
+          Hangul: <literal>calt</literal>
+	</para>
+      </listitem>
+      <listitem>
+        <para>
+          Indic: <literal>liga</literal>
+	</para>
+      </listitem>
+      <listitem>
+        <para>
+          Khmer: <literal>liga</literal>
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      If the text direction is vertical, HarfBuzz applies
+      the <literal>vert</literal> feature by default.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      You can adjust the set of features that HarfBuzz applies to a
+      buffer by supplying an array of <type>hb_feature_t</type>
+      features as the third argument to
+      <function>hb_shape()</function>. For a simple case, let's just
+      enable the <literal>dlig</literal> feature, which turns on any
+      "discretionary" ligatures in the font:
+    </para>
+    <programlisting language="C">
+      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;
+    </programlisting>
+    <para>
+      <literal>HB_FEATURE_GLOBAL_END</literal> and
+      <literal>HB_FEATURE_GLOBAL_END</literal> are macros we can use
+      to indicate that the features will be applied to the entire
+      buffer. We could also have used a literal <literal>0</literal>
+      for the start and a <literal>-1</literal> to indicate the end of
+      the buffer (or have selected other start and end positions, if needed).
+    </para>
+    <para>
+      When we pass the <varname>userfeatures</varname> array to
+      <function>hb_shape()</function>, any discretionary ligature
+      substitutions from our font that match the text in our buffer
+      will get performed:
+    </para>
+    <programlisting language="C">
+      hb_shape(font, buf, userfeatures, num_features);
+    </programlisting>
+    <para>
+      Just like we enabled the <literal>dlig</literal> feature by
+      setting its <parameter>value</parameter> to
+      <literal>1</literal>, you would disable a feature by setting its
+      <parameter>value</parameter> to <literal>0</literal>. Some
+      features can take other <parameter>value</parameter> settings;
+      be sure you read the full specification of each feature tag to
+      understand what it does and how to control it.
+    </para>
+  </section>
+
+  <section id="shaping-shaper-selection">
+    <title>Shaper selection</title>
+    <para>
+      The basic version of <function>hb_shape()</function> determines
+      its shaping strategy based on examining the capabilities of the
+      font file. OpenType font tables cause HarfBuzz to try the
+      <literal>ot</literal> shaper, while AAT font tables cause HarfBuzz to try the
+      <literal>aat</literal> shaper. 
+    </para>
+    <para>
+      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 <function>hb_shape()</function> what you want it to try.
+    </para>
+    <para>
+      <function>hb_shape_full()</function> 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 <function>hb_shape_full()</function>
+    </para>
+    <programlisting language="C">
+      char *shaperprefs[3] = {"ot", "default", "aat"};
+      ...
+      hb_shape_full(font, buf, userfeatures, num_features, shaperprefs);
+    </programlisting>
+    <para>
+      to get results you are happier with.
+    </para>
+    <para>
+      You may also want to call
+      <function>hb_shape_list_shapers()</function> to get a list of
+      the shapers that were built at compile time in your copy of HarfBuzz.
+    </para>
+  </section>
+  
+  <section id="shaping-plans-and-caching">
+    <title>Plans and caching</title>
+    <para>
+      Internally, HarfBuzz uses a structure called a shape plan to
+      track its decisions about how to shape the contents of a
+      buffer. The <function>hb_shape()</function> function builds up the shape plan by
+      examining segment properties and by inspecting the contents of
+      the font.
+    </para>
+    <para>
+      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
+      <literal>DFLT</literal> tag (and sometimes other common tags)
+      if there are actually no lookups for the tag requested.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      You can create a cacheable shape plan with
+      <function>hb_shape_plan_create_cached(face, props,
+      user_features, num_user_features, shaper_list)</function>, where
+      <parameter>face</parameter> is a face object (not a font object,
+      notably), <parameter>props</parameter> is an
+      <type>hb_segment_properties_t</type>,
+      <parameter>user_features</parameter> is an array of
+      <type>hb_feature_t</type>s (with length
+      <parameter>num_user_features</parameter>), and
+      <parameter>shaper_list</parameter> is a list of shapers to try.
+    </para>
+    <para>
+      Shape plans are objects in HarfBuzz, so there are
+      reference-counting functions and user-data attachment functions
+      you can
+      use. <function>hb_shape_plan_reference(shape_plan)</function>
+      increases the reference count on a shape plan, while
+      <function>hb_shape_plan_destroy(shape_plan)</function> decreases
+      the reference count, destroying the shape plan when the last
+      reference is dropped.
+    </para>
+    <para>
+      You can attach user data to a shaper (with a key) using the
+      <function>hb_shape_plan_set_user_data(shape_plan,key,data,destroy,replace)</function>
+      function, optionally supplying a <function>destroy</function>
+      callback to use. You can then fetch the user data attached to a
+      shape plan with
+      <function>hb_shape_plan_get_user_data(shape_plan, key)</function>.
+    </para>
+  </section>
+  
+</chapter>

+ 368 - 0
libs/harfbuzz/docs/usermanual-shaping-concepts.xml

@@ -0,0 +1,368 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="shaping-concepts">
+  <title>Shaping concepts</title>
+  <section id="text-shaping-concepts">
+    <title>Text shaping</title>
+    <para>
+      Text shaping is the process of transforming a sequence of Unicode
+      codepoints that represent individual characters (letters,
+      diacritics, tone marks, numbers, symbols, etc.) into the
+      orthographically and linguistically correct two-dimensional layout
+      of glyph shapes taken from a specified font.
+    </para>
+    <para>
+      For some writing systems (or <emphasis>scripts</emphasis>) and
+      languages, the process is simple, requiring the shaper to do
+      little more than advance the horizontal position forward by the
+      correct amount for each successive glyph.
+    </para>
+    <para>
+      But, for other scripts (often unceremoniously called <emphasis>complex scripts</emphasis>), any combination of
+      several shaping operations may be required, and the rules for how
+      and when they are applied vary from script to script. HarfBuzz and
+      other shaping engines implement these rules.
+    </para>
+    <para>
+      The exact rules and necessary operations for a particular script
+      constitute a shaping <emphasis>model</emphasis>. OpenType
+      specifies a set of shaping models that covers all of
+      Unicode. Other shaping models are available, however, including
+      Graphite and Apple Advanced Typography (AAT). 
+    </para>
+  </section>
+  
+  <section id="script-specific-shaping">
+    <title>Script-specific shaping</title>
+    <para>
+      In many scripts, transforming the input
+      sequence into the final layout often requires some combination of
+      operations&mdash;such as context-dependent substitutions,
+      context-dependent mark positioning, glyph-to-glyph joining,
+      glyph reordering, or glyph stacking.
+    </para>
+    <para>
+      In some scripts, the shaping rules require that a text
+      run be divided into syllables before the operations can be
+      applied. Other scripts may apply shaping operations over
+      entire words or over the entire text run, with no subdivision
+      required.
+    </para>
+    <para>
+      Other scripts, do not require these
+      operations. However, correctly shaping a text run in
+      any script may still involve Unicode normalization,
+      ligature substitutions, mark positioning, kerning, and applying
+      other font features.
+    </para>
+  </section>
+  
+  <section id="shaping-operations">
+    <title>Shaping operations</title>
+    <para>
+      Shaping a text run involves transforming the
+      input sequence of Unicode codepoints with some combination of
+      operations that is specified in the shaping model for the
+      script.
+    </para>
+    <para>
+      The specific conditions that trigger a given operation for a
+      text run varies from script to script, as do the order that the
+      operations are performed in and which codepoints are
+      affected. However, the same general set of shaping operations is
+      common to all of the script shaping models. 
+    </para>
+    
+    <itemizedlist>
+      <listitem>
+	<para>
+	  A <emphasis>reordering</emphasis> operation moves a glyph
+	  from its original ("logical") position in the sequence to
+	  some other ("visual") position.
+	</para>
+	<para>
+	  The shaping model for a given script might involve
+	  more than one reordering step.
+	</para>
+      </listitem>
+      
+      <listitem>
+	<para>
+	  A <emphasis>joining</emphasis> operation replaces a glyph
+	  with an alternate form that is designed to connect with one
+	  or more of the adjacent glyphs in the sequence.
+	</para>
+      </listitem>
+      
+      <listitem>
+	<para>
+	  A contextual <emphasis>substitution</emphasis> operation
+	  replaces either a single glyph or a subsequence of several
+	  glyphs with an alternate glyph. This substitution is
+	  performed when the original glyph or subsequence of glyphs
+	  occurs in a specified position with respect to the
+	  surrounding sequence. For example, one substitution might be
+	  performed only when the target glyph is the first glyph in
+	  the sequence, while another substitution is performed only
+	  when a different target glyph occurs immediately after a
+	  particular string pattern.
+	</para>
+	<para>
+	  The shaping model for a given script might involve
+	  multiple contextual-substitution operations, each applying
+	  to different target glyphs and patterns, and which are
+	  performed in separate steps.
+	</para>
+      </listitem>
+      
+      <listitem>
+	<para>
+	  A contextual <emphasis>positioning</emphasis> operation
+	  moves the horizontal and/or vertical position of a
+	  glyph. This positioning move is performed when the glyph
+	  occurs in a specified position with respect to the
+	  surrounding sequence.
+	</para>
+	<para>
+	  Many contextual positioning operations are used to place
+	  <emphasis>mark</emphasis> glyphs (such as diacritics, vowel
+	  signs, and tone markers) with respect to
+	  <emphasis>base</emphasis> glyphs. However, some
+	  scripts may use contextual positioning operations to
+	  correctly place base glyphs as well, such as
+	  when the script uses <emphasis>stacking</emphasis> characters.
+	</para>
+      </listitem>
+      
+    </itemizedlist>
+  </section>
+  
+  <section id="unicode-character-categories">
+    <title>Unicode character categories</title>
+    <para>
+      Shaping models are typically specified with respect to how
+      scripts are defined in the Unicode standard.
+    </para>
+    <para>
+      Every codepoint in the Unicode Character Database (UCD) is
+      assigned a <emphasis>Unicode General Category</emphasis> (UGC),
+      which provides the most fundamental information about the
+      codepoint: whether the codepoint represents a
+      <emphasis>Letter</emphasis>, a <emphasis>Mark</emphasis>, a
+      <emphasis>Number</emphasis>, <emphasis>Punctuation</emphasis>, a
+      <emphasis>Symbol</emphasis>, a <emphasis>Separator</emphasis>,
+      or something else (<emphasis>Other</emphasis>).
+    </para>
+    <para>
+      These UGC properties are "Major" categories. Each codepoint is
+      further assigned to a "minor" category within its Major
+      category, such as "Letter, uppercase" (<literal>Lu</literal>) or
+      "Letter, modifier" (<literal>Lm</literal>).
+    </para>
+    <para>
+      Shaping models are concerned primarily with Letter and Mark
+      codepoints. The minor categories of Mark codepoints are
+      particularly important for shaping. Marks can be nonspacing
+      (<literal>Mn</literal>), spacing combining
+      (<literal>Mc</literal>), or enclosing (<literal>Me</literal>).
+    </para>
+    <para>
+      In addition to the UGC property, codepoints in the Indic and
+      Southeast Asian scripts are also assigned
+      <emphasis>Unicode Indic Syllabic Category</emphasis> (UISC) and
+      <emphasis>Unicode Indic Positional Category</emphasis> (UIPC)
+      properties that provide more detailed information needed for
+      shaping.
+    </para>
+    <para>
+      The UISC property sub-categorizes Letters and Marks according to
+      common script-shaping behaviors. For example, UISC distinguishes
+      between consonant letters, vowel letters, and vowel marks. The
+      UIPC property sub-categorizes Mark codepoints by the relative visual
+      position that they occupy (above, below, right, left, or in
+      multiple positions).
+    </para>
+    <para>
+      Some scripts require that the text run be split into
+      syllables. What constitutes a valid syllable in these
+      scripts is specified in regular expressions, formed from the
+      Letter and Mark codepoints, that take the UISC and UIPC
+      properties into account.
+    </para>
+
+  </section>
+  
+  <section id="text-runs">
+    <title>Text runs</title>
+    <para>
+      Real-world text usually contains codepoints from a mixture of
+      different Unicode scripts (including punctuation, numbers, symbols,
+      white-space characters, and other codepoints that do not belong
+      to any script). Real-world text may also be marked up with
+      formatting that changes font properties (including the font,
+      font style, and font size).
+    </para>
+    <para>
+      For shaping purposes, all real-world text streams must be first
+      segmented into runs that have a uniform set of properties. 
+    </para>
+    <para>
+      In particular, shaping models always assume that every codepoint
+      in a text run has the same <emphasis>direction</emphasis>,
+      <emphasis>script</emphasis> tag, and
+      <emphasis>language</emphasis> tag.
+    </para>
+  </section>
+  
+  <section id="opentype-shaping-models">
+    <title>OpenType shaping models</title>
+    <para>
+      OpenType provides shaping models for the following scripts:
+    </para>
+
+    <itemizedlist>
+      <listitem>
+	<para>
+	  The <emphasis>default</emphasis> shaping model handles all
+	  scripts with no script-specific shaping model, and may also be used as a fallback for
+	  handling unrecognized scripts.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Indic</emphasis> shaping model handles the Indic
+	  scripts Bengali, Devanagari, Gujarati, Gurmukhi, Kannada,
+	  Malayalam, Oriya, Tamil, and Telugu.
+	</para>
+	<para>
+	  The Indic shaping model was revised significantly in
+	  2005. To denote the change, a new set of <emphasis>script
+	  tags</emphasis> was assigned for Bengali, Devanagari,
+	  Gujarati, Gurmukhi, Kannada, Malayalam, Oriya, Tamil, and
+	  Telugu. For the sake of clarity, the term "Indic2" is
+	  sometimes used to refer to the current, revised shaping
+	  model.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Arabic</emphasis> shaping model supports
+	  Arabic, Mongolian, N'Ko, Syriac, and several other connected
+	  or cursive scripts.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Thai/Lao</emphasis> shaping model supports
+	  the Thai and Lao scripts.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Khmer</emphasis> shaping model supports the
+	  Khmer script.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Myanmar</emphasis> shaping model supports the
+	  Myanmar (or Burmese) script.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Tibetan</emphasis> shaping model supports the
+	  Tibetan script.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Hangul</emphasis> shaping model supports the
+	  Hangul script.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Hebrew</emphasis> shaping model supports the
+	  Hebrew script.
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  The <emphasis>Universal Shaping Engine</emphasis> (USE)
+	  shaping model supports scripts not covered by one of
+	  the above, script-specific shaping models, including
+	  Javanese, Balinese, Buginese, Batak, Chakma, Lepcha, Modi,
+	  Phags-pa, Tagalog, Siddham, Sundanese, Tai Le, Tai Tham, Tai
+	  Viet, and many others. 
+	</para>
+      </listitem>
+
+      <listitem>
+	<para>
+	  Text runs that do not fall under one of the above shaping
+	  models may still require processing by a shaping engine. Of
+	  particular note is <emphasis>Emoji</emphasis> shaping, which
+	  may involve variation-selector sequences and glyph
+	  substitution. Emoji shaping is handled by the default
+	  shaping model.
+	</para>
+      </listitem>
+
+    </itemizedlist>
+    
+  </section>
+  
+  <section id="graphite-shaping">
+    <title>Graphite shaping</title>
+    <para>
+      In contrast to OpenType shaping, Graphite shaping does not
+      specify a predefined set of shaping models or a set of supported
+      scripts.
+    </para>
+    <para>
+      Instead, each Graphite font contains a complete set of rules that
+      implement the required shaping model for the intended
+      script. These rules include finite-state machines to match
+      sequences of codepoints to the shaping operations to perform.
+    </para>
+    <para>
+      Graphite shaping can perform the same shaping operations used in
+      OpenType shaping, as well as other functions that have not been
+      defined for OpenType shaping.
+    </para>
+  </section>
+  
+  <section id="aat-shaping">
+    <title>AAT shaping</title>
+    <para>
+      In contrast to OpenType shaping, AAT shaping does not specify a 
+      predefined set of shaping models or a set of supported scripts.
+    </para>
+    <para>
+      Instead, each AAT font includes a complete set of rules that
+      implement the desired shaping model for the intended
+      script. These rules include finite-state machines to match glyph
+      sequences and the shaping operations to perform.
+    </para>
+    <para>
+      Notably, AAT shaping rules are expressed for glyphs in the font,
+      not for Unicode codepoints. AAT shaping can perform the same
+      shaping operations used in OpenType shaping, as well as other
+      functions that have not been defined for OpenType shaping.
+    </para>
+  </section>
+</chapter>

+ 218 - 0
libs/harfbuzz/docs/usermanual-utilities.xml

@@ -0,0 +1,218 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="utilities">
+  <title>Utilities</title>
+  <para>
+    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.
+  </para>
+  
+  <section id="utilities-command-line-tools">
+    <title>Command-line tools</title>
+    <para>
+      HarfBuzz include three command-line tools:
+      <command>hb-shape</command>, <command>hb-view</command>, and
+      <command>hb-subset</command>. They can be used to examine
+      HarfBuzz's functionality, debug font binaries, or explore the
+      various shaping models and features from a terminal.
+    </para>
+    
+    <section id="utilities-command-line-hbshape">
+      <title>hb-shape</title>
+      <para>
+	<emphasis><command>hb-shape</command></emphasis> allows you to run HarfBuzz's
+	<function>hb_shape()</function> function on an input string and
+	to examine the outcome, in human-readable form, as terminal
+	output. <command>hb-shape</command> does
+	<emphasis>not</emphasis> render the results of the shaping call
+	into rendered text (you can use <command>hb-view</command>, 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.
+      </para>
+      <para>
+	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
+      </para>
+      <programlisting>
+	<command>hb-shape</command> <optional>[OPTIONS]</optional>
+      <parameter>path/to/font/file.ttf</parameter>
+      <parameter>yourinputtext</parameter>
+      </programlisting>
+      <para>
+	The default output format is plain text (although JSON output
+	can be selected instead by specifying the option
+	<optional>--output-format=json</optional>). 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.
+      </para>
+      <para>
+	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.
+      </para>
+      <para>
+	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.
+      </para>
+      <para>
+	For a complete explanation of the options available, run
+      </para>
+      <programlisting>
+	<command>hb-shape</command> <parameter>--help</parameter>
+      </programlisting>  
+    </section>
+    
+    <section id="utilities-command-line-hbview">
+      <title>hb-view</title>
+      <para>
+	<emphasis><command>hb-view</command></emphasis> allows you to
+	see the shaped output of an input string in rendered
+	form. Like <command>hb-shape</command>,
+	<command>hb-view</command> takes a font file and a text string
+	as its arguments:
+      </para>
+      <programlisting>
+	<command>hb-view</command> <optional>[OPTIONS]</optional>
+	<parameter>path/to/font/file.ttf</parameter>
+	<parameter>yourinputtext</parameter>
+      </programlisting>
+      <para>
+	By default, <command>hb-view</command> renders the shaped
+	text in ASCII block-character images as terminal output. By
+	appending the
+	<command>--output-file=<optional>filename</optional></command>
+	switch, you can write the output to a PNG, SVG, or PDF file
+	(among other formats).
+      </para>
+      <para>
+	As with <command>hb-shape</command>, 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.
+      </para>
+      <para>
+	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 
+      </para>
+      <para>
+	In general, <command>hb-view</command> 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 <command>hb-shape</command> to figure out exactly
+	why something does not appear as expected.
+      </para>
+    </section>
+    
+    <section id="utilities-command-line-hbsubset">
+      <title>hb-subset</title>
+      <para>
+	<emphasis><command>hb-subset</command></emphasis> allows you
+	to generate a subset of a given font, with a limited set of
+	supported characters, features, and variation settings.
+      </para>
+      <para>
+	By default, you provide an input font and an input text string
+	as the arguments to <command>hb-subset</command>, and it will
+	generate a font that covers the input text exactly like the
+	input font does, but includes no other characters or features.
+      </para>
+      <programlisting>
+	<command>hb-subset</command> <optional>[OPTIONS]</optional>
+	<parameter>path/to/font/file.ttf</parameter>
+	<parameter>yourinputtext</parameter>
+      </programlisting>
+      <para>
+	For example, to create a subset of Noto Serif that just includes the
+	numerals and the lowercase Latin alphabet, you could run
+      </para>
+      <programlisting>
+	<command>hb-subset</command> <optional>[OPTIONS]</optional>
+	<parameter>NotoSerif-Regular.ttf</parameter>
+	<parameter>0123456789abcdefghijklmnopqrstuvwxyz</parameter>
+      </programlisting>
+      <para>
+	There are options available to remove hinting from the
+	subsetted font and to specify a list of variation-axis settings.
+      </para>
+    </section>
+    
+  </section>
+  
+  <section id="utilities-common-types-apis">
+    <title>Common data types and APIs</title>
+    <para>
+      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.
+    </para>
+    <para>
+      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.
+    </para>
+    <para>
+      All set elements are integers (specifically,
+      <type>hb_codepoint_t</type> 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.
+    </para>
+    <para>
+      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
+      <function>hb_set_reference()</function> and decrease it with
+      <function>hb_set_destroy()</function>. 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.
+    </para>
+    <para>
+      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 <type>hb_codepoint_t</type>
+      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.
+    </para>
+    <para>
+      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
+      <type>hb_tag_t</type> 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. 
+    </para>
+    <para>
+      Finally, HarfBuzz also includes data type for Booleans, bit
+      masks, and other simple types.
+    </para>
+  </section>
+
+</chapter>

+ 441 - 0
libs/harfbuzz/docs/usermanual-what-is-harfbuzz.xml

@@ -0,0 +1,441 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="what-is-harfbuzz">
+  <title>What is HarfBuzz?</title>
+  <para>
+    HarfBuzz is a <emphasis>text-shaping engine</emphasis>. If you
+    give HarfBuzz a font and a string containing a sequence of Unicode
+    codepoints, HarfBuzz selects and positions the corresponding
+    glyphs from the font, applying all of the necessary layout rules
+    and font features. HarfBuzz then returns the string to you in the
+    form that is correctly arranged for the language and writing
+    system. 
+  </para>
+  <para>
+    HarfBuzz can properly shape all of the world's major writing
+    systems. It runs on all major operating systems and software
+    platforms and it supports the major font formats in use
+    today.
+  </para>
+  <section id="what-is-text-shaping">
+    <title>What is text shaping?</title>
+    <para>
+      Text shaping is the process of translating a string of character
+      codes (such as Unicode codepoints) into a properly arranged
+      sequence of glyphs that can be rendered onto a screen or into
+      final output form for inclusion in a document.
+    </para>
+    <para>
+      The shaping process is dependent on the input string, the active
+      font, the script (or writing system) that the string is in, and
+      the language that the string is in.
+    </para>
+    <para>
+      Modern software systems generally only deal with strings in the
+      Unicode encoding scheme (although legacy systems and documents may
+      involve other encodings).
+    </para>
+    <para>
+      There are several font formats that a program might
+      encounter, each of which has a set of standard text-shaping
+      rules.
+    </para>
+    <para>The dominant format is <ulink
+      url="http://www.microsoft.com/typography/otspec/">OpenType</ulink>. The
+    OpenType specification defines a series of <ulink url="https://github.com/n8willis/opentype-shaping-documents">shaping models</ulink> for
+    various scripts from around the world. These shaping models depend on
+    the font incorporating certain features as
+    <emphasis>lookups</emphasis> in its <literal>GSUB</literal> 
+    and <literal>GPOS</literal> tables.
+    </para>
+    <para>
+      Alternatively, OpenType fonts can include shaping features for
+      the <ulink url="https://graphite.sil.org/">Graphite</ulink> shaping model.
+    </para>
+    <para>
+      TrueType fonts can also include OpenType shaping
+      features. Alternatively, TrueType fonts can also include <ulink url="https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html">Apple
+      Advanced Typography</ulink> (AAT) tables to implement shaping
+      support. AAT fonts are generally only found on macOS and iOS systems.
+    </para>
+    <para>
+      Text strings will usually be tagged with a script and language
+      tag that provide the context needed to perform text shaping
+      correctly.  The necessary <ulink
+      url="https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags">script</ulink> 
+      and <ulink
+      url="https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags">language</ulink>
+      tags are defined by OpenType.
+    </para>
+  </section>
+  
+  <section id="why-do-i-need-a-shaping-engine">
+    <title>Why do I need a shaping engine?</title>
+    <para>
+      Text shaping is an integral part of preparing text for
+      display. Before a Unicode sequence can be rendered, the
+      codepoints in the sequence must be mapped to the corresponding
+      glyphs provided in the font, and those glyphs must be positioned
+      correctly relative to each other. For many of the scripts
+      supported in Unicode, these steps involve script-specific layout
+      rules, including complex joining, reordering, and positioning
+      behavior. Implementing these rules is the job of the shaping engine.
+    </para>
+    <para>
+      Text shaping is a fairly low-level operation. HarfBuzz is
+      used directly by text-handling libraries like <ulink
+      url="https://www.pango.org/">Pango</ulink>, as well as by the layout
+      engines in Firefox, LibreOffice, and Chromium. Unless you are
+      <emphasis>writing</emphasis> one of these layout engines
+      yourself, you will probably not need to use HarfBuzz: normally,
+      a layout engine, toolkit, or other library will turn text into
+      glyphs for you.
+    </para>
+    <para>
+      However, if you <emphasis>are</emphasis> writing a layout engine
+      or graphics library yourself, then you will need to perform text
+      shaping, and this is where HarfBuzz can help you.
+    </para>
+    <para>
+      Here are some specific scenarios where a text-shaping engine
+      like HarfBuzz helps you:
+    </para>
+    <itemizedlist>
+      <listitem>
+        <para>
+          OpenType fonts contain a set of glyphs (that is, shapes
+	  to represent the letters, numbers, punctuation marks, and
+	  all other symbols), which are indexed by a <literal>glyph ID</literal>.
+	</para>
+	<para>
+          A particular glyph ID within the font does not necessarily
+	  correlate to a predictable Unicode codepoint. For instance,
+	  some fonts have the letter &quot;a&quot; as glyph ID 1, but
+	  many others do not. In order to retrieve the right glyph
+	  from the font to display &quot;a&quot;, you need to consult
+	  the table inside the font (the <literal>cmap</literal>
+	  table) that maps Unicode codepoints to glyph IDs. In other
+	  words, <emphasis>text shaping turns codepoints into glyph
+	  IDs</emphasis>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          Many OpenType fonts contain ligatures: combinations of
+          characters that are rendered as a single unit. For instance,
+	  it is common for the &quot;f, i&quot; letter
+	  sequence to appear in print as the single ligature glyph
+	  &quot;fi&quot;.
+	</para>
+	<para>
+	  Whether you should render an &quot;f, i&quot; sequence
+	  as <literal>fi</literal> or as &quot;fi&quot; does not
+          depend on the input text. Instead, it depends on the whether
+	  or not the font includes an &quot;fi&quot; glyph and on the
+	  level of ligature application you wish to perform. The font
+	  and the amount of ligature application used are under your
+	  control. In other words, <emphasis>text shaping involves
+	  querying the font's ligature tables and determining what
+	  substitutions should be made</emphasis>. 
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          While ligatures like &quot;fi&quot; are optional typographic
+          refinements, some languages <emphasis>require</emphasis> certain
+          substitutions to be made in order to display text correctly.
+        </para>
+	<para>
+	  For example, in Tamil, when the letter &quot;TTA&quot; (ட)
+	  letter is followed by the vowel sign &quot;U&quot; (ு), the pair
+	  must be replaced by the single glyph &quot;டு&quot;. The
+	  sequence of Unicode characters &quot;ட,ு&quot; needs to be
+	  substituted with a single &quot;டு&quot; glyph from the
+	  font.
+	</para>
+	<para>
+	  But &quot;டு&quot; does not have a Unicode codepoint. To
+	  find this glyph, you need to consult the table inside 
+	  the font (the <literal>GSUB</literal> table) that contains
+	  substitution information. In other words, <emphasis>text shaping 
+	  chooses the correct glyph for a sequence of characters
+	  provided</emphasis>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          Similarly, each Arabic character has four different variants
+	  corresponding to the different positions it might appear in
+	  within a sequence. Inside a font, there will be separate
+	  glyphs for the initial, medial, final, and isolated forms of
+	  each letter, each at a different glyph ID.
+	</para>
+	<para>
+	  Unicode only assigns one codepoint per character, so a
+	  Unicode string will not tell you which glyph variant to use
+	  for each character. To decide, you need to analyze the whole
+	  string and determine the appropriate glyph for each character
+	  based on its position. In other words, <emphasis>text
+	  shaping chooses the correct form of the letter by its
+	  position and returns the correct glyph from the font</emphasis>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          Other languages involve marks and accents that need to be
+          rendered in specific positions relative a base character. For
+          instance, the Moldovan language includes the Cyrillic letter
+          &quot;zhe&quot; (ж) with a breve accent, like so: &quot;ӂ&quot;.
+	</para>
+	<para>
+	  Some fonts will provide this character as a single
+	  zhe-with-breve glyph, but other fonts will not and, instead,
+	  will expect the rendering engine to form the character by 
+          superimposing the separate &quot;ж&quot; and &quot;˘&quot;
+	  glyphs.
+	</para>
+	<para>
+	  But exactly where you should draw the breve depends on the
+	  height and width of the preceding zhe glyph. To find the
+	  right position, you need to consult the table inside
+	  the font (the <literal>GPOS</literal> table) that contains
+	  positioning information.
+          In other words, <emphasis>text shaping tells you whether you
+	  have a precomposed glyph within your font or if you need to
+	  compose a glyph yourself out of combining marks&mdash;and,
+	  if so, where to position those marks.</emphasis>
+        </para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      If tasks like these are something that you need to do, then you
+      need a text shaping engine. You could use Uniscribe if you are
+      writing Windows software; you could use CoreText on macOS; or
+      you could use HarfBuzz.
+    </para>
+    <note>
+      <para>
+	In the rest of this manual, the text will assume that the reader
+	is that implementor of a text-layout engine.
+      </para>
+    </note>
+  </section>
+  
+
+  <section id="what-does-harfbuzz-do">
+    <title>What does HarfBuzz do?</title>
+    <para>
+      HarfBuzz provides text shaping through a cross-platform
+      C API that accepts sequences of Unicode codepoints as input. Currently,
+      the following OpenType shaping models are supported:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  Indic (covering Devanagari, Bengali, Gujarati,
+	  Gurmukhi, Kannada, Malayalam, Oriya, Tamil, and Telugu)
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Arabic (covering Arabic, N'Ko, Syriac, and Mongolian)
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Thai and Lao
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Khmer
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Myanmar
+	</para>
+      </listitem>
+      
+      <listitem>
+	<para>
+	  Tibetan
+	</para>
+      </listitem>
+      
+      <listitem>
+	<para>
+	  Hangul
+	</para>
+      </listitem>
+      
+      <listitem>
+	<para>
+	  Hebrew
+	</para>
+      </listitem>      
+      <listitem>
+	<para>
+	  The Universal Shaping Engine or <emphasis>USE</emphasis>
+	  (covering complex scripts not covered by the above shaping
+	  models)
+	</para>
+      </listitem>      
+      <listitem>
+	<para>
+	  A default shaping model for non-complex scripts
+	  (covering Latin, Cyrillic, Greek, Armenian, Georgian, Tifinagh,
+	  and many others)
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Emoji (including emoji modifier sequences, flag sequences,
+	  and ZWJ sequences)
+	</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>
+      In addition to OpenType shaping, HarfBuzz supports the latest
+      version of Graphite shaping (the "Graphite 2" model) and AAT
+      shaping.
+    </para>
+    
+    <para>
+      HarfBuzz can read and understand TrueType fonts (.ttf), TrueType
+      collections (.ttc), and OpenType fonts (.otf, including those
+      fonts that contain TrueType-style outlines and those that
+      contain PostScript CFF or CFF2 outlines).
+    </para>
+
+    <para>
+      HarfBuzz is designed and tested to run on top of the FreeType
+      font renderer. It can run on Linux, Android, Windows, macOS, and
+      iOS systems.
+    </para>
+    
+    <para>
+      In addition to its core shaping functionality, HarfBuzz provides
+      functions for accessing other font features, including optional
+      GSUB and GPOS OpenType features, as well as
+      all color-font formats (<literal>CBDT</literal>,
+      <literal>sbix</literal>, <literal>COLR/CPAL</literal>, and
+      <literal>SVG-OT</literal>) and OpenType variable fonts. HarfBuzz
+      also includes a font-subsetting feature. HarfBuzz can perform
+      some low-level math-shaping operations, although it does not
+      currently perform full shaping for mathematical typesetting.
+    </para>
+    
+    <para>
+      A suite of command-line utilities is also provided in the
+      source-code tree, designed to help users test and debug
+      HarfBuzz's features on real-world fonts and input.
+    </para>
+  </section>
+
+  <section id="what-harfbuzz-doesnt-do">
+    <title>What HarfBuzz doesn't do</title>
+    <para>
+      HarfBuzz will take a Unicode string, shape it, and give you the
+      information required to lay it out correctly on a single
+      horizontal (or vertical) line using the font provided. That is the
+      extent of HarfBuzz's responsibility.
+    </para>
+    <para>
+      It is important to note that if you are implementing a complete
+      text-layout engine you may have other responsibilities that
+      HarfBuzz will <emphasis>not</emphasis> help you with. For example:
+    </para>
+    <itemizedlist>
+      <listitem>
+        <para>
+          HarfBuzz won't help you with bidirectionality. If you want to
+          lay out text that includes a mix of Hebrew and English, you
+	  will need to ensure that each buffer provided to HarfBuzz
+	  has all of its characters in the same order and that the
+	  directionality of the buffer is set correctly. This may mean
+	  segmenting the text before it is placed into HarfBuzz buffers. In
+          other words, the user will hit the keys in the following
+          sequence:
+        </para>
+        <programlisting>
+	  A B C [space] ג ב א [space] D E F
+        </programlisting>
+        <para>
+          but will expect to see in the output:
+        </para>
+        <programlisting>
+	  ABC אבג DEF
+        </programlisting>
+        <para>
+          This reordering is called <emphasis>bidi processing</emphasis>
+          (&quot;bidi&quot; is short for bidirectional), and there's an
+          algorithm as an annex to the Unicode Standard which tells you how
+          to process a string of mixed directionality.
+          Before sending your string to HarfBuzz, you may need to apply the
+          bidi algorithm to it. Libraries such as <ulink
+	  url="http://icu-project.org/">ICU</ulink> and <ulink
+	  url="http://fribidi.org/">fribidi</ulink> can do this for you.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          HarfBuzz won't help you with text that contains different font
+          properties. For instance, if you have the string &quot;a
+          <emphasis>huge</emphasis> breakfast&quot;, and you expect
+          &quot;huge&quot; to be italic, then you will need to send three
+          strings to HarfBuzz: <literal>a</literal>, in your Roman font;
+          <literal>huge</literal> using your italic font; and
+          <literal>breakfast</literal> using your Roman font again.
+	</para>
+	<para>
+          Similarly, if you change the font, font size, script,
+	  language, or direction within your string, then you will
+	  need to shape each run independently and output them
+	  independently. HarfBuzz expects to shape a run of characters
+	  that all share the same properties.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          HarfBuzz won't help you with line breaking, hyphenation, or
+          justification. As mentioned above, HarfBuzz lays out the string
+          along a <emphasis>single line</emphasis> of, notionally,
+          infinite length. If you want to find out where the potential
+          word, sentence and line break points are in your text, you
+          could use the ICU library's break iterator functions.
+        </para>
+        <para>
+          HarfBuzz can tell you how wide a shaped piece of text is, which is
+          useful input to a justification algorithm, but it knows nothing
+          about paragraphs, lines or line lengths. Nor will it adjust the
+          space between words to fit them proportionally into a line.
+        </para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      As a layout-engine implementor, HarfBuzz will help you with the
+      interface between your text and your font, and that's something
+      that you'll need&mdash;what you then do with the glyphs that your font
+      returns is up to you. 
+    </para>
+  </section>
+    
+  <section id="why-is-it-called-harfbuzz">
+    <title>Why is it called HarfBuzz?</title>
+    <para>
+      HarfBuzz began its life as text-shaping code within the FreeType
+      project (and you will see references to the FreeType authors
+      within the source code copyright declarations), but was then
+      extracted out to its own project. This project is maintained by
+      Behdad Esfahbod, who named it HarfBuzz. Originally, it was a
+      shaping engine for OpenType fonts&mdash;&quot;HarfBuzz&quot; is
+      the Persian for &quot;open type&quot;.
+    </para>
+  </section>
+</chapter>

+ 1 - 0
libs/harfbuzz/docs/version.xml.in

@@ -0,0 +1 @@
+@HB_VERSION@

+ 401 - 0
libs/harfbuzz/git.mk

@@ -0,0 +1,401 @@
+# git.mk, a small Makefile to autogenerate .gitignore files
+# for autotools-based projects.
+#
+# Copyright 2009, Red Hat, Inc.
+# Copyright 2010,2011,2012,2013 Behdad Esfahbod
+# Written by Behdad Esfahbod
+#
+# Copying and distribution of this file, with or without modification,
+# is permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+# The latest version of this file can be downloaded from:
+GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk
+#
+# Bugs, etc, should be reported upstream at:
+#   https://github.com/behdad/git.mk
+#
+# To use in your project, import this file in your git repo's toplevel,
+# then do "make -f git.mk".  This modifies all Makefile.am files in
+# your project to -include git.mk.  Remember to add that line to new
+# Makefile.am files you create in your project, or just rerun the
+# "make -f git.mk".
+#
+# This enables automatic .gitignore generation.  If you need to ignore
+# more files, add them to the GITIGNOREFILES variable in your Makefile.am.
+# But think twice before doing that.  If a file has to be in .gitignore,
+# chances are very high that it's a generated file and should be in one
+# of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES.
+#
+# The only case that you need to manually add a file to GITIGNOREFILES is
+# when remove files in one of mostlyclean-local, clean-local, distclean-local,
+# or maintainer-clean-local make targets.
+#
+# Note that for files like editor backup, etc, there are better places to
+# ignore them.  See "man gitignore".
+#
+# If "make maintainer-clean" removes the files but they are not recognized
+# by this script (that is, if "git status" shows untracked files still), send
+# me the output of "git status" as well as your Makefile.am and Makefile for
+# the directories involved and I'll diagnose.
+#
+# For a list of toplevel files that should be in MAINTAINERCLEANFILES, see
+# Makefile.am.sample in the git.mk git repo.
+#
+# Don't EXTRA_DIST this file.  It is supposed to only live in git clones,
+# not tarballs.  It serves no useful purpose in tarballs and clutters the
+# build dir.
+#
+# This file knows how to handle autoconf, automake, libtool, gtk-doc,
+# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
+# appstream, hotdoc.
+#
+# This makefile provides the following targets:
+#
+# - all: "make all" will build all gitignore files.
+# - gitignore: makes all gitignore files in the current dir and subdirs.
+# - .gitignore: make gitignore file for the current dir.
+# - gitignore-recurse: makes all gitignore files in the subdirs.
+#
+# KNOWN ISSUES:
+#
+# - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the
+#   submodule doesn't find us.  If you have configure.{in,ac} files in
+#   subdirs, add a proxy git.mk file in those dirs that simply does:
+#   "include $(top_srcdir)/../git.mk".  Add more ..'s to your taste.
+#   And add those files to git.  See vte/gnome-pty-helper/git.mk for
+#   example.
+#
+
+
+
+###############################################################################
+# Variables user modules may want to add to toplevel MAINTAINERCLEANFILES:
+###############################################################################
+
+#
+# Most autotools-using modules should be fine including this variable in their
+# toplevel MAINTAINERCLEANFILES:
+GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
+	$(srcdir)/aclocal.m4 \
+	$(srcdir)/autoscan.log \
+	$(srcdir)/configure.scan \
+	`AUX_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_AUX_DIR:$$1' ./configure.ac); \
+	 test "x$$AUX_DIR" = "x$(srcdir)/" && AUX_DIR=$(srcdir); \
+	 for x in \
+		ar-lib \
+		compile \
+		config.guess \
+		config.rpath \
+		config.sub \
+		depcomp \
+		install-sh \
+		ltmain.sh \
+		missing \
+		mkinstalldirs \
+		test-driver \
+		ylwrap \
+	 ; do echo "$$AUX_DIR/$$x"; done` \
+	`cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_HEADERS:$$1' ./configure.ac | \
+	head -n 1 | while read f; do echo "$(srcdir)/$$f.in"; done`
+#
+# All modules should also be fine including the following variable, which
+# removes automake-generated Makefile.in files:
+GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN = \
+	`cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_FILES:$$1' ./configure.ac | \
+	while read f; do \
+	  case $$f in Makefile|*/Makefile) \
+	    test -f "$(srcdir)/$$f.am" && echo "$(srcdir)/$$f.in";; esac; \
+	done`
+#
+# Modules that use libtool and use  AC_CONFIG_MACRO_DIR() may also include this,
+# though it's harmless to include regardless.
+GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
+	`MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \
+	 if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \
+		for x in \
+			libtool.m4 \
+			ltoptions.m4 \
+			ltsugar.m4 \
+			ltversion.m4 \
+			lt~obsolete.m4 \
+		; do echo "$$MACRO_DIR/$$x"; done; \
+	 fi`
+#
+# Modules that use gettext and use  AC_CONFIG_MACRO_DIR() may also include this,
+# though it's harmless to include regardless.
+GITIGNORE_MAINTAINERCLEANFILES_M4_GETTEXT = \
+	`MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \
+	if test "x$$MACRO_DIR" != "x$(srcdir)/"; then	\
+		for x in				\
+			codeset.m4			\
+			extern-inline.m4		\
+			fcntl-o.m4			\
+			gettext.m4			\
+			glibc2.m4			\
+			glibc21.m4			\
+			iconv.m4			\
+			intdiv0.m4			\
+			intl.m4				\
+			intldir.m4			\
+			intlmacosx.m4			\
+			intmax.m4			\
+			inttypes-pri.m4			\
+			inttypes_h.m4			\
+			lcmessage.m4			\
+			lib-ld.m4			\
+			lib-link.m4			\
+			lib-prefix.m4			\
+			lock.m4				\
+			longlong.m4			\
+			nls.m4				\
+			po.m4				\
+			printf-posix.m4			\
+			progtest.m4			\
+			size_max.m4			\
+			stdint_h.m4			\
+			threadlib.m4			\
+			uintmax_t.m4			\
+			visibility.m4			\
+			wchar_t.m4			\
+			wint_t.m4			\
+			xsize.m4			\
+		; do echo "$$MACRO_DIR/$$x"; done; \
+	fi`
+
+
+
+###############################################################################
+# Default rule is to install ourselves in all Makefile.am files:
+###############################################################################
+
+git-all: git-mk-install
+
+git-mk-install:
+	@echo "Installing git makefile"
+	@any_failed=; \
+		find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while read x; do \
+		if grep 'include .*/git.mk' $$x >/dev/null; then \
+			echo "$$x already includes git.mk"; \
+		else \
+			failed=; \
+			echo "Updating $$x"; \
+			{ cat $$x; \
+			  echo ''; \
+			  echo '-include $$(top_srcdir)/git.mk'; \
+			} > $$x.tmp || failed=1; \
+			if test x$$failed = x; then \
+				mv $$x.tmp $$x || failed=1; \
+			fi; \
+			if test x$$failed = x; then : else \
+				echo "Failed updating $$x"; >&2 \
+				any_failed=1; \
+			fi; \
+	fi; done; test -z "$$any_failed"
+
+git-mk-update:
+	wget $(GIT_MK_URL) -O $(top_srcdir)/git.mk
+
+.PHONY: git-all git-mk-install git-mk-update
+
+
+
+###############################################################################
+# Actual .gitignore generation:
+###############################################################################
+
+$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk $(top_srcdir)/configure.ac
+	@echo "git.mk: Generating $@"
+	@{ \
+		if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \
+			for x in \
+				$(DOC_MODULE)-decl-list.txt \
+				$(DOC_MODULE)-decl.txt \
+				tmpl/$(DOC_MODULE)-unused.sgml \
+				"tmpl/*.bak" \
+				$(REPORT_FILES) \
+				$(DOC_MODULE).pdf \
+				xml html \
+			; do echo "/$$x"; done; \
+			FLAVOR=$$(cd $(top_srcdir); $(AUTOCONF) --trace 'GTK_DOC_CHECK:$$2' ./configure.ac); \
+			case $$FLAVOR in *no-tmpl*) echo /tmpl;; esac; \
+			if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-types"; then \
+				echo "/$(DOC_MODULE).types"; \
+			fi; \
+			if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-sections"; then \
+				echo "/$(DOC_MODULE)-sections.txt"; \
+			fi; \
+			if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+				for x in \
+					$(SETUP_FILES) \
+					$(DOC_MODULE).types \
+				; do echo "/$$x"; done; \
+			fi; \
+		fi; \
+		if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \
+			for lc in $(DOC_LINGUAS); do \
+				for x in \
+					$(if $(DOC_MODULE),$(DOC_MODULE).xml) \
+					$(DOC_PAGES) \
+					$(DOC_INCLUDES) \
+				; do echo "/$$lc/$$x"; done; \
+			done; \
+			for x in \
+				$(_DOC_OMF_ALL) \
+				$(_DOC_DSK_ALL) \
+				$(_DOC_HTML_ALL) \
+				$(_DOC_MOFILES) \
+				$(DOC_H_FILE) \
+				"*/.xml2po.mo" \
+				"*/*.omf.out" \
+			; do echo /$$x; done; \
+		fi; \
+		if test "x$(HOTDOC)" = x; then :; else \
+			$(foreach project, $(HOTDOC_PROJECTS),echo "/$(call HOTDOC_TARGET,$(project))"; \
+				echo "/$(shell $(call HOTDOC_PROJECT_COMMAND,$(project)) --get-conf-path output)" ; \
+				echo "/$(shell $(call HOTDOC_PROJECT_COMMAND,$(project)) --get-private-folder)" ; \
+			) \
+			for x in \
+				.hotdoc.d \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
+			for lc in $(HELP_LINGUAS); do \
+				for x in \
+					$(HELP_FILES) \
+					"$$lc.stamp" \
+					"$$lc.mo" \
+				; do echo "/$$lc/$$x"; done; \
+			done; \
+		fi; \
+		if test "x$(gsettings_SCHEMAS)" = x; then :; else \
+			for x in \
+				$(gsettings_SCHEMAS:.xml=.valid) \
+				$(gsettings__enum_file) \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(appdata_XML)" = x; then :; else \
+			for x in \
+				$(appdata_XML:.xml=.valid) \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(appstream_XML)" = x; then :; else \
+			for x in \
+				$(appstream_XML:.xml=.valid) \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test -f $(srcdir)/po/Makefile.in.in; then \
+			for x in \
+				ABOUT-NLS \
+				po/Makefile.in.in \
+				po/Makefile.in.in~ \
+				po/Makefile.in \
+				po/Makefile \
+				po/Makevars.template \
+				po/POTFILES \
+				po/Rules-quot \
+				po/stamp-it \
+				po/stamp-po \
+				po/.intltool-merge-cache \
+				"po/*.gmo" \
+				"po/*.header" \
+				"po/*.mo" \
+				"po/*.sed" \
+				"po/*.sin" \
+				po/$(GETTEXT_PACKAGE).pot \
+				intltool-extract.in \
+				intltool-merge.in \
+				intltool-update.in \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test -f $(srcdir)/configure; then \
+			for x in \
+				autom4te.cache \
+				configure \
+				config.h \
+				stamp-h1 \
+				libtool \
+				config.lt \
+			; do echo "/$$x"; done; \
+		fi; \
+		if test "x$(DEJATOOL)" = x; then :; else \
+			for x in \
+				$(DEJATOOL) \
+			; do echo "/$$x.sum"; echo "/$$x.log"; done; \
+			echo /site.exp; \
+		fi; \
+		if test "x$(am__dirstamp)" = x; then :; else \
+			echo "$(am__dirstamp)"; \
+		fi; \
+		if test "x$(findstring libtool,$(LTCOMPILE))" = x -a "x$(findstring libtool,$(LTCXXCOMPILE))" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
+			for x in \
+				"*.lo" \
+				".libs" "_libs" \
+			; do echo "$$x"; done; \
+		fi; \
+		for x in \
+			.gitignore \
+			$(GITIGNOREFILES) \
+			$(CLEANFILES) \
+			$(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \
+			$(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \
+			$(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \
+			so_locations \
+			$(MOSTLYCLEANFILES) \
+			$(TEST_LOGS) \
+			$(TEST_LOGS:.log=.trs) \
+			$(TEST_SUITE_LOG) \
+			$(TESTS:=.test) \
+			"*.gcda" \
+			"*.gcno" \
+			$(DISTCLEANFILES) \
+			$(am__CONFIG_DISTCLEAN_FILES) \
+			$(CONFIG_CLEAN_FILES) \
+			TAGS ID GTAGS GRTAGS GSYMS GPATH tags \
+			"*.tab.c" \
+			$(MAINTAINERCLEANFILES) \
+			$(BUILT_SOURCES) \
+			$(patsubst %.vala,%.c,$(filter %.vala,$(SOURCES))) \
+			$(filter %_vala.stamp,$(DIST_COMMON)) \
+			$(filter %.vapi,$(DIST_COMMON)) \
+			$(filter $(addprefix %,$(notdir $(patsubst %.vapi,%.h,$(filter %.vapi,$(DIST_COMMON))))),$(DIST_COMMON)) \
+			Makefile \
+			Makefile.in \
+			"*.orig" \
+			"*.rej" \
+			"*.bak" \
+			"*~" \
+			".*.sw[nop]" \
+			".dirstamp" \
+		; do echo "/$$x"; done; \
+		for x in \
+			"*.$(OBJEXT)" \
+			$(DEPDIR) \
+		; do echo "$$x"; done; \
+	} | \
+	sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \
+	sed 's@/[.]/@/@g' | \
+	LC_ALL=C sort | uniq > .gitignore.tmp && \
+	(mv .gitignore.tmp $@ || (echo "WARNING: Cannot create $@ file; skipping"; \
+				  $(RM) .gitignore.tmp));
+
+all: $(srcdir)/.gitignore gitignore-recurse-maybe
+gitignore: $(srcdir)/.gitignore gitignore-recurse
+
+gitignore-recurse-maybe:
+	@for subdir in $(DIST_SUBDIRS); do \
+	  case " $(SUBDIRS) " in \
+	    *" $$subdir "*) :;; \
+	    *) test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir");; \
+	  esac; \
+	done
+gitignore-recurse:
+	@for subdir in $(DIST_SUBDIRS); do \
+	    test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir"); \
+	done
+
+maintainer-clean: gitignore-clean
+gitignore-clean:
+	-rm -f $(srcdir)/.gitignore
+
+.PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe

+ 24 - 0
libs/harfbuzz/harfbuzz.doap

@@ -0,0 +1,24 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+         xmlns:foaf="http://xmlns.com/foaf/0.1/"
+         xmlns="http://usefulinc.com/ns/doap#">
+
+  <name xml:lang="en">harfbuzz</name>
+  <shortdesc xml:lang="en">Text shaping library</shortdesc>
+
+  <homepage
+  rdf:resource="https://github.com/harfbuzz/harfbuzz" />
+  <mailing-list
+  rdf:resource="https://github.com/harfbuzz/harfbuzz/discussions" />
+  <download-page
+  rdf:resource="https://github.com/harfbuzz/harfbuzz/releases" />
+  <bug-database
+  rdf:resource="https://github.com/harfbuzz/harfbuzz/issues" />
+
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Behdad Esfahbod</foaf:name>
+      <foaf:mbox rdf:resource="mailto:[email protected]" />
+    </foaf:Person>
+  </maintainer>
+</Project>

+ 74 - 0
libs/harfbuzz/m4/ax_check_link_flag.m4

@@ -0,0 +1,74 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the linker or gives an error.
+#   (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the linker's default flags
+#   when the check is done.  The check is thus made with the flags: "LDFLAGS
+#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to
+#   issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <[email protected]>
+#   Copyright (c) 2011 Maarten Bosmans <[email protected]>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+  ax_check_save_flags=$LDFLAGS
+  LDFLAGS="$LDFLAGS $4 $1"
+  AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  LDFLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS

+ 264 - 0
libs/harfbuzz/m4/ax_code_coverage.m4

@@ -0,0 +1,264 @@
+# ===========================================================================
+#     https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CODE_COVERAGE()
+#
+# DESCRIPTION
+#
+#   Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS,
+#   CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included
+#   in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every
+#   build target (program or library) which should be built with code
+#   coverage support. Also defines CODE_COVERAGE_RULES which should be
+#   substituted in your Makefile; and $enable_code_coverage which can be
+#   used in subsequent configure output. CODE_COVERAGE_ENABLED is defined
+#   and substituted, and corresponds to the value of the
+#   --enable-code-coverage option, which defaults to being disabled.
+#
+#   Test also for gcov program and create GCOV variable that could be
+#   substituted.
+#
+#   Note that all optimization flags in CFLAGS must be disabled when code
+#   coverage is enabled.
+#
+#   Usage example:
+#
+#   configure.ac:
+#
+#     AX_CODE_COVERAGE
+#
+#   Makefile.am:
+#
+#     @CODE_COVERAGE_RULES@
+#     my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ...
+#     my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ...
+#     my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ...
+#     my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ...
+#
+#   This results in a "check-code-coverage" rule being added to any
+#   Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module
+#   has been configured with --enable-code-coverage). Running `make
+#   check-code-coverage` in that directory will run the module's test suite
+#   (`make check`) and build a code coverage report detailing the code which
+#   was touched, then print the URI for the report.
+#
+#   In earlier versions of this macro, CODE_COVERAGE_LDFLAGS was defined
+#   instead of CODE_COVERAGE_LIBS. They are both still defined, but use of
+#   CODE_COVERAGE_LIBS is preferred for clarity; CODE_COVERAGE_LDFLAGS is
+#   deprecated. They have the same value.
+#
+#   This code was derived from Makefile.decl in GLib, originally licenced
+#   under LGPLv2.1+.
+#
+# LICENSE
+#
+#   Copyright (c) 2012, 2016 Philip Withnall
+#   Copyright (c) 2012 Xan Lopez
+#   Copyright (c) 2012 Christian Persch
+#   Copyright (c) 2012 Paolo Borelli
+#   Copyright (c) 2012 Dan Winship
+#   Copyright (c) 2015 Bastien ROUCARIES
+#
+#   This library is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Lesser General Public License as published by
+#   the Free Software Foundation; either version 2.1 of the License, or (at
+#   your option) any later version.
+#
+#   This library is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+#   General Public License for more details.
+#
+#   You should have received a copy of the GNU Lesser General Public License
+#   along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+#serial 25
+
+AC_DEFUN([AX_CODE_COVERAGE],[
+	dnl Check for --enable-code-coverage
+	AC_REQUIRE([AC_PROG_SED])
+
+	# allow to override gcov location
+	AC_ARG_WITH([gcov],
+	  [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])],
+	  [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov],
+	  [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov])
+
+	AC_MSG_CHECKING([whether to build with code coverage support])
+	AC_ARG_ENABLE([code-coverage],
+	  AS_HELP_STRING([--enable-code-coverage],
+	  [Whether to enable code coverage support]),,
+	  enable_code_coverage=no)
+
+	AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
+	AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
+	AC_MSG_RESULT($enable_code_coverage)
+
+	AS_IF([ test "$enable_code_coverage" = "yes" ], [
+		# check for gcov
+		AC_CHECK_TOOL([GCOV],
+		  [$_AX_CODE_COVERAGE_GCOV_PROG_WITH],
+		  [:])
+		AS_IF([test "X$GCOV" = "X:"],
+		  [AC_MSG_ERROR([gcov is needed to do coverage])])
+		AC_SUBST([GCOV])
+
+		dnl Check if gcc is being used
+		AS_IF([ test "$GCC" = "no" ], [
+			AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
+		])
+
+		AC_CHECK_PROG([LCOV], [lcov], [lcov])
+		AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
+
+		AS_IF([ test -z "$LCOV" ], [
+			AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed])
+		])
+
+		AS_IF([ test -z "$GENHTML" ], [
+			AC_MSG_ERROR([Could not find genhtml from the lcov package])
+		])
+
+		dnl Build the code coverage flags
+		dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility
+		CODE_COVERAGE_CPPFLAGS="-DNDEBUG"
+		CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
+		CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
+		CODE_COVERAGE_LIBS="-lgcov"
+		CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS"
+
+		AC_SUBST([CODE_COVERAGE_CPPFLAGS])
+		AC_SUBST([CODE_COVERAGE_CFLAGS])
+		AC_SUBST([CODE_COVERAGE_CXXFLAGS])
+		AC_SUBST([CODE_COVERAGE_LIBS])
+		AC_SUBST([CODE_COVERAGE_LDFLAGS])
+
+		[CODE_COVERAGE_RULES_CHECK='
+	-$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check
+	$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
+']
+		[CODE_COVERAGE_RULES_CAPTURE='
+	$(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS)
+	$(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS)
+	-@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
+	$(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
+	@echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
+']
+		[CODE_COVERAGE_RULES_CLEAN='
+clean: code-coverage-clean
+distclean: code-coverage-clean
+code-coverage-clean:
+	-$(LCOV) --directory $(top_builddir) -z
+	-rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
+	-find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete
+']
+	], [
+		[CODE_COVERAGE_RULES_CHECK='
+	@echo "Need to reconfigure with --enable-code-coverage"
+']
+		CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK"
+		CODE_COVERAGE_RULES_CLEAN=''
+	])
+
+[CODE_COVERAGE_RULES='
+# Code coverage
+#
+# Optional:
+#  - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
+#    Multiple directories may be specified, separated by whitespace.
+#    (Default: $(top_builddir))
+#  - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
+#    by lcov for code coverage. (Default:
+#    $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
+#  - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
+#    reports to be created. (Default:
+#    $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
+#  - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
+#    set to 0 to disable it and leave empty to stay with the default.
+#    (Default: empty)
+#  - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
+#    instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
+#  - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
+#    instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
+#  - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
+#  - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
+#    collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
+#  - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
+#    instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
+#  - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
+#    lcov instance. (Default: empty)
+#  - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
+#    instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
+#  - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
+#    genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
+#  - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
+#    instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
+#  - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
+#
+# The generated report will be titled using the $(PACKAGE_NAME) and
+# $(PACKAGE_VERSION). In order to add the current git hash to the title,
+# use the git-version-gen script, available online.
+
+# Optional variables
+CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
+CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
+CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
+CODE_COVERAGE_BRANCH_COVERAGE ?=
+CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
+--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
+CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
+CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)"
+CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
+CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
+CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
+CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
+CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\
+$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
+--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
+CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
+CODE_COVERAGE_IGNORE_PATTERN ?=
+
+GITIGNOREFILES ?=
+GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
+
+code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V))
+code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY))
+code_coverage_v_lcov_cap_0 = @echo "  LCOV   --capture"\
+ $(CODE_COVERAGE_OUTPUT_FILE);
+code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V))
+code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY))
+code_coverage_v_lcov_ign_0 = @echo "  LCOV   --remove /tmp/*"\
+ $(CODE_COVERAGE_IGNORE_PATTERN);
+code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V))
+code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY))
+code_coverage_v_genhtml_0 = @echo "  GEN   " $(CODE_COVERAGE_OUTPUT_DIRECTORY);
+code_coverage_quiet = $(code_coverage_quiet_$(V))
+code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
+code_coverage_quiet_0 = --quiet
+
+# sanitizes the test-name: replaces with underscores: dashes and dots
+code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1)))
+
+# Use recursive makes in order to ignore errors during check
+check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"'
+
+# Capture code coverage data
+code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"'
+
+# Hook rule executed before code-coverage-capture, overridable by the user
+code-coverage-capture-hook:
+
+'"$CODE_COVERAGE_RULES_CLEAN"'
+
+A''M_DISTCHECK_CONFIGURE_FLAGS ?=
+A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
+
+.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
+']
+
+	AC_SUBST([CODE_COVERAGE_RULES])
+	m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])])
+])

+ 982 - 0
libs/harfbuzz/m4/ax_cxx_compile_stdcxx.m4

@@ -0,0 +1,982 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the specified
+#   version of the C++ standard.  If necessary, add switches to CXX and
+#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
+#   or '14' (for the C++14 standard).
+#
+#   The second argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for an extended mode.
+#
+#   The third argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline support for the specified C++ standard is
+#   required and that the macro should error out if no mode with that
+#   support is found.  If specified 'optional', then configuration proceeds
+#   regardless, after defining HAVE_CXX${VERSION} if and only if a
+#   supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <[email protected]>
+#   Copyright (c) 2012 Zack Weinberg <[email protected]>
+#   Copyright (c) 2013 Roy Stogner <[email protected]>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <[email protected]>
+#   Copyright (c) 2015 Paul Norman <[email protected]>
+#   Copyright (c) 2015 Moritz Klammler <[email protected]>
+#   Copyright (c) 2016 Krzesimir Nowak <[email protected]>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 7
+
+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl  (serial version number 13).
+
+AX_REQUIRE_DEFINED([AC_MSG_WARN])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$2], [], [],
+        [$2], [ext], [],
+        [$2], [noext], [],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+  ax_cv_cxx_compile_cxx$1,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+    [ax_cv_cxx_compile_cxx$1=yes],
+    [ax_cv_cxx_compile_cxx$1=no])])
+  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+    ac_success=yes
+  fi
+
+  m4_if([$2], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      switch="-std=gnu++${alternative}"
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$2], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+        cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                       $cachevar,
+          [ac_save_CXX="$CXX"
+           CXX="$CXX $switch"
+           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+            [eval $cachevar=yes],
+            [eval $cachevar=no])
+           CXX="$ac_save_CXX"])
+        if eval test x\$$cachevar = xyes; then
+          CXX="$CXX $switch"
+          if test -n "$CXXCPP" ; then
+            CXXCPP="$CXXCPP $switch"
+          fi
+          ac_success=yes
+          break
+        fi
+      done
+      if test x$ac_success = xyes; then
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX$1=0
+    AC_MSG_NOTICE([No compiler with C++$1 support was found])
+  else
+    HAVE_CXX$1=1
+    AC_DEFINE(HAVE_CXX$1,1,
+              [define if the compiler supports basic C++$1 syntax])
+  fi
+  AC_SUBST(HAVE_CXX$1)
+  m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
+])
+
+
+dnl  Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+
+dnl  Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
+
+dnl  Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // https://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+]])
+
+
+dnl  Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+  namespace test_polymorphic_lambdas
+  {
+
+    int
+    test()
+    {
+      const auto lambda = [](auto&&... args){
+        const auto istiny = [](auto x){
+          return (sizeof(x) == 1UL) ? 1 : 0;
+        };
+        const int aretiny[] = { istiny(args)... };
+        return aretiny[0];
+      };
+      return lambda(1, 1L, 1.0f, '1');
+    }
+
+  }
+
+  namespace test_binary_literals
+  {
+
+    constexpr auto ivii = 0b0000000000101010;
+    static_assert(ivii == 42, "wrong value");
+
+  }
+
+  namespace test_generalized_constexpr
+  {
+
+    template < typename CharT >
+    constexpr unsigned long
+    strlen_c(const CharT *const s) noexcept
+    {
+      auto length = 0UL;
+      for (auto p = s; *p; ++p)
+        ++length;
+      return length;
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("x") == 1UL, "");
+    static_assert(strlen_c("test") == 4UL, "");
+    static_assert(strlen_c("another\0test") == 7UL, "");
+
+  }
+
+  namespace test_lambda_init_capture
+  {
+
+    int
+    test()
+    {
+      auto x = 0;
+      const auto lambda1 = [a = x](int b){ return a + b; };
+      const auto lambda2 = [a = lambda1(x)](){ return a; };
+      return lambda2();
+    }
+
+  }
+
+  namespace test_digit_separators
+  {
+
+    constexpr auto ten_million = 100'000'000;
+    static_assert(ten_million == 100000000, "");
+
+  }
+
+  namespace test_return_type_deduction
+  {
+
+    auto f(int& x) { return x; }
+    decltype(auto) g(int& x) { return x; }
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static constexpr auto value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static constexpr auto value = true;
+    };
+
+    int
+    test()
+    {
+      auto x = 0;
+      static_assert(is_same<int, decltype(f(x))>::value, "");
+      static_assert(is_same<int&, decltype(g(x))>::value, "");
+      return x;
+    }
+
+  }
+
+}  // namespace cxx14
+
+#endif  // __cplusplus >= 201402L
+
+]])
+
+
+dnl  Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus <= 201402L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#if defined(__clang__)
+  #define REALLY_CLANG
+#else
+  #if defined(__GNUC__)
+    #define REALLY_GCC
+  #endif
+#endif
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+#if !defined(REALLY_CLANG)
+  namespace test_constexpr_lambdas
+  {
+
+    // TODO: test it with clang++ from git
+
+    constexpr int foo = [](){return 42;}();
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test::nested_namespace::definitions
+  {
+
+  }
+
+  namespace test_fold_expression
+  {
+
+    template<typename... Args>
+    int multiply(Args... args)
+    {
+      return (args * ... * 1);
+    }
+
+    template<typename... Args>
+    bool all(Args... args)
+    {
+      return (args && ...);
+    }
+
+  }
+
+  namespace test_extended_static_assert
+  {
+
+    static_assert (true);
+
+  }
+
+  namespace test_auto_brace_init_list
+  {
+
+    auto foo = {5};
+    auto bar {5};
+
+    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+    static_assert(std::is_same<int, decltype(bar)>::value);
+  }
+
+  namespace test_typename_in_template_template_parameter
+  {
+
+    template<template<typename> typename X> struct D;
+
+  }
+
+  namespace test_fallthrough_nodiscard_maybe_unused_attributes
+  {
+
+    int f1()
+    {
+      return 42;
+    }
+
+    [[nodiscard]] int f2()
+    {
+      [[maybe_unused]] auto unused = f1();
+
+      switch (f1())
+      {
+      case 17:
+        f1();
+        [[fallthrough]];
+      case 42:
+        f1();
+      }
+      return f1();
+    }
+
+  }
+
+  namespace test_extended_aggregate_initialization
+  {
+
+    struct base1
+    {
+      int b1, b2 = 42;
+    };
+
+    struct base2
+    {
+      base2() {
+        b3 = 42;
+      }
+      int b3;
+    };
+
+    struct derived : base1, base2
+    {
+        int d;
+    };
+
+    derived d1 {{1, 2}, {}, 4};  // full initialization
+    derived d2 {{}, {}, 4};      // value-initialized bases
+
+  }
+
+  namespace test_general_range_based_for_loop
+  {
+
+    struct iter
+    {
+      int i;
+
+      int& operator* ()
+      {
+        return i;
+      }
+
+      const int& operator* () const
+      {
+        return i;
+      }
+
+      iter& operator++()
+      {
+        ++i;
+        return *this;
+      }
+    };
+
+    struct sentinel
+    {
+      int i;
+    };
+
+    bool operator== (const iter& i, const sentinel& s)
+    {
+      return i.i == s.i;
+    }
+
+    bool operator!= (const iter& i, const sentinel& s)
+    {
+      return !(i == s);
+    }
+
+    struct range
+    {
+      iter begin() const
+      {
+        return {0};
+      }
+
+      sentinel end() const
+      {
+        return {5};
+      }
+    };
+
+    void f()
+    {
+      range r {};
+
+      for (auto i : r)
+      {
+        [[maybe_unused]] auto v = i;
+      }
+    }
+
+  }
+
+  namespace test_lambda_capture_asterisk_this_by_value
+  {
+
+    struct t
+    {
+      int i;
+      int foo()
+      {
+        return [*this]()
+        {
+          return i;
+        }();
+      }
+    };
+
+  }
+
+  namespace test_enum_class_construction
+  {
+
+    enum class byte : unsigned char
+    {};
+
+    byte foo {42};
+
+  }
+
+  namespace test_constexpr_if
+  {
+
+    template <bool cond>
+    int f ()
+    {
+      if constexpr(cond)
+      {
+        return 13;
+      }
+      else
+      {
+        return 42;
+      }
+    }
+
+  }
+
+  namespace test_selection_statement_with_initializer
+  {
+
+    int f()
+    {
+      return 13;
+    }
+
+    int f2()
+    {
+      if (auto i = f(); i > 0)
+      {
+        return 3;
+      }
+
+      switch (auto i = f(); i + 4)
+      {
+      case 17:
+        return 2;
+
+      default:
+        return 1;
+      }
+    }
+
+  }
+
+#if !defined(REALLY_CLANG)
+  namespace test_template_argument_deduction_for_class_templates
+  {
+
+    // TODO: test it with clang++ from git
+
+    template <typename T1, typename T2>
+    struct pair
+    {
+      pair (T1 p1, T2 p2)
+        : m1 {p1},
+          m2 {p2}
+      {}
+
+      T1 m1;
+      T2 m2;
+    };
+
+    void f()
+    {
+      [[maybe_unused]] auto p = pair{13, 42u};
+    }
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test_non_type_auto_template_parameters
+  {
+
+    template <auto n>
+    struct B
+    {};
+
+    B<5> b1;
+    B<'a'> b2;
+
+  }
+
+#if !defined(REALLY_CLANG)
+  namespace test_structured_bindings
+  {
+
+    // TODO: test it with clang++ from git
+
+    int arr[2] = { 1, 2 };
+    std::pair<int, int> pr = { 1, 2 };
+
+    auto f1() -> int(&)[2]
+    {
+      return arr;
+    }
+
+    auto f2() -> std::pair<int, int>&
+    {
+      return pr;
+    }
+
+    struct S
+    {
+      int x1 : 2;
+      volatile double y1;
+    };
+
+    S f3()
+    {
+      return {};
+    }
+
+    auto [ x1, y1 ] = f1();
+    auto& [ xr1, yr1 ] = f1();
+    auto [ x2, y2 ] = f2();
+    auto& [ xr2, yr2 ] = f2();
+    const auto [ x3, y3 ] = f3();
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+#if !defined(REALLY_CLANG)
+  namespace test_exception_spec_type_system
+  {
+
+    // TODO: test it with clang++ from git
+
+    struct Good {};
+    struct Bad {};
+
+    void g1() noexcept;
+    void g2();
+
+    template<typename T>
+    Bad
+    f(T*, T*);
+
+    template<typename T1, typename T2>
+    Good
+    f(T1*, T2*);
+
+    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test_inline_variables
+  {
+
+    template<class T> void f(T)
+    {}
+
+    template<class T> inline T g(T)
+    {
+      return T{};
+    }
+
+    template<> inline void f<>(int)
+    {}
+
+    template<> int g<>(int)
+    {
+      return 5;
+    }
+
+  }
+
+}  // namespace cxx17
+
+#endif  // __cplusplus <= 201402L
+
+]])

+ 485 - 0
libs/harfbuzz/m4/ax_pthread.m4

@@ -0,0 +1,485 @@
+# ===========================================================================
+#        https://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+#   This macro figures out how to build C programs using POSIX threads. It
+#   sets the PTHREAD_LIBS output variable to the threads library and linker
+#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+#   flags that are needed. (The user can also force certain compiler
+#   flags/libs to be tested by setting these environment variables.)
+#
+#   Also sets PTHREAD_CC to any special C compiler that is needed for
+#   multi-threaded programs (defaults to the value of CC otherwise). (This
+#   is necessary on AIX to use the special cc_r compiler alias.)
+#
+#   NOTE: You are assumed to not only compile your program with these flags,
+#   but also to link with them as well. For example, you might link with
+#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+#   If you are only building threaded programs, you may wish to use these
+#   variables in your default LIBS, CFLAGS, and CC:
+#
+#     LIBS="$PTHREAD_LIBS $LIBS"
+#     CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+#     CC="$PTHREAD_CC"
+#
+#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+#   has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
+#   that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+#   PTHREAD_CFLAGS.
+#
+#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
+#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+#   is not found. If ACTION-IF-FOUND is not specified, the default action
+#   will define HAVE_PTHREAD.
+#
+#   Please let the authors know if this macro fails on any platform, or if
+#   you have any other suggestions or comments. This macro was based on work
+#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
+#   grateful for the helpful feedback of numerous users.
+#
+#   Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <[email protected]>
+#   Copyright (c) 2011 Daniel Richard G. <[email protected]>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 24
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_SED])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on Tru64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
+        ax_pthread_save_CC="$CC"
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
+        AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
+        AC_MSG_RESULT([$ax_pthread_ok])
+        if test "x$ax_pthread_ok" = "xno"; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        CC="$ax_pthread_save_CC"
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
+#           (Note: HP C rejects this with "bad form for `-t' option")
+# -pthreads: Solaris/gcc (Note: HP C also rejects)
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads and
+#      -D_REENTRANT too), HP C (must be checked before -lpthread, which
+#      is present but should not be used directly; and before -mthreads,
+#      because the compiler interprets this as "-mt" + "-hreads")
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case $host_os in
+
+        freebsd*)
+
+        # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+        # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+
+        ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+        ;;
+
+        hpux*)
+
+        # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+        # multi-threading and also sets -lpthread."
+
+        ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+        ;;
+
+        openedition*)
+
+        # IBM z/OS requires a feature-test macro to be defined in order to
+        # enable POSIX threads at all, so give the user a hint if this is
+        # not set. (We don't define these ourselves, as they can affect
+        # other portions of the system API in unpredictable ways.)
+
+        AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
+            [
+#            if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+             AX_PTHREAD_ZOS_MISSING
+#            endif
+            ],
+            [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
+        ;;
+
+        solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed. (N.B.: The stubs are missing
+        # pthread_cleanup_push, or rather a function called by this macro,
+        # so we could check for that, but who knows whether they'll stub
+        # that too in a future libc.)  So we'll check first for the
+        # standard Solaris way of linking pthreads (-mt -lpthread).
+
+        ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
+        ;;
+esac
+
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+AS_IF([test "x$GCC" = "xyes"],
+      [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $host_os in
+        darwin* | hpux* | linux* | osf* | solaris*)
+        ax_pthread_check_macro="_REENTRANT"
+        ;;
+
+        aix*)
+        ax_pthread_check_macro="_THREAD_SAFE"
+        ;;
+
+        *)
+        ax_pthread_check_macro="--"
+        ;;
+esac
+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
+      [ax_pthread_check_cond=0],
+      [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
+
+# Are we compiling with Clang?
+
+AC_CACHE_CHECK([whether $CC is Clang],
+    [ax_cv_PTHREAD_CLANG],
+    [ax_cv_PTHREAD_CLANG=no
+     # Note that Autoconf sets GCC=yes for Clang as well as GCC
+     if test "x$GCC" = "xyes"; then
+        AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+            [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+#            if defined(__clang__) && defined(__llvm__)
+             AX_PTHREAD_CC_IS_CLANG
+#            endif
+            ],
+            [ax_cv_PTHREAD_CLANG=yes])
+     fi
+    ])
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+ax_pthread_clang_warning=no
+
+# Clang needs special handling, because older versions handle the -pthread
+# option in a rather... idiosyncratic way
+
+if test "x$ax_pthread_clang" = "xyes"; then
+
+        # Clang takes -pthread; it has never supported any other flag
+
+        # (Note 1: This will need to be revisited if a system that Clang
+        # supports has POSIX threads in a separate library.  This tends not
+        # to be the way of modern systems, but it's conceivable.)
+
+        # (Note 2: On some systems, notably Darwin, -pthread is not needed
+        # to get POSIX threads support; the API is always present and
+        # active.  We could reasonably leave PTHREAD_CFLAGS empty.  But
+        # -pthread does define _REENTRANT, and while the Darwin headers
+        # ignore this macro, third-party headers might not.)
+
+        PTHREAD_CFLAGS="-pthread"
+        PTHREAD_LIBS=
+
+        ax_pthread_ok=yes
+
+        # However, older versions of Clang make a point of warning the user
+        # that, in an invocation where only linking and no compilation is
+        # taking place, the -pthread option has no effect ("argument unused
+        # during compilation").  They expect -pthread to be passed in only
+        # when source code is being compiled.
+        #
+        # Problem is, this is at odds with the way Automake and most other
+        # C build frameworks function, which is that the same flags used in
+        # compilation (CFLAGS) are also used in linking.  Many systems
+        # supported by AX_PTHREAD require exactly this for POSIX threads
+        # support, and in fact it is often not straightforward to specify a
+        # flag that is used only in the compilation phase and not in
+        # linking.  Such a scenario is extremely rare in practice.
+        #
+        # Even though use of the -pthread flag in linking would only print
+        # a warning, this can be a nuisance for well-run software projects
+        # that build with -Werror.  So if the active version of Clang has
+        # this misfeature, we search for an option to squash it.
+
+        AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
+            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
+            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+             # Create an alternate version of $ac_link that compiles and
+             # links in two steps (.c -> .o, .o -> exe) instead of one
+             # (.c -> exe), because the warning occurs only in the second
+             # step
+             ax_pthread_save_ac_link="$ac_link"
+             ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+             ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
+             ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+             ax_pthread_save_CFLAGS="$CFLAGS"
+             for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+                AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
+                CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+                ac_link="$ax_pthread_save_ac_link"
+                AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+                    [ac_link="$ax_pthread_2step_ac_link"
+                     AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+                         [break])
+                    ])
+             done
+             ac_link="$ax_pthread_save_ac_link"
+             CFLAGS="$ax_pthread_save_CFLAGS"
+             AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
+             ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+            ])
+
+        case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+                no | unknown) ;;
+                *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+        esac
+
+fi # $ax_pthread_clang = yes
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+        case $ax_pthread_try_flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -mt,pthread)
+                AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
+                PTHREAD_CFLAGS="-mt"
+                PTHREAD_LIBS="-lpthread"
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+                PTHREAD_CFLAGS="$ax_pthread_try_flag"
+                ;;
+
+                pthread-config)
+                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+                AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+                PTHREAD_LIBS="-l$ax_pthread_try_flag"
+                ;;
+        esac
+
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+#                       if $ax_pthread_check_cond
+#                        error "$ax_pthread_check_macro must be defined"
+#                       endif
+                        static void routine(void *a) { a = 0; }
+                        static void *start_routine(void *a) { return a; }],
+                       [pthread_t th; pthread_attr_t attr;
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */])],
+            [ax_pthread_ok=yes],
+            [])
+
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+
+        AC_MSG_RESULT([$ax_pthread_ok])
+        AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = "xyes"; then
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+        AC_CACHE_CHECK([for joinable pthread attribute],
+            [ax_cv_PTHREAD_JOINABLE_ATTR],
+            [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+             for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+                 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+                                                 [int attr = $ax_pthread_attr; return attr /* ; */])],
+                                [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
+                                [])
+             done
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+               test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+               test "x$ax_pthread_joinable_attr_defined" != "xyes"],
+              [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
+                                  [$ax_cv_PTHREAD_JOINABLE_ATTR],
+                                  [Define to necessary symbol if this constant
+                                   uses a non-standard name on your system.])
+               ax_pthread_joinable_attr_defined=yes
+              ])
+
+        AC_CACHE_CHECK([whether more special flags are required for pthreads],
+            [ax_cv_PTHREAD_SPECIAL_FLAGS],
+            [ax_cv_PTHREAD_SPECIAL_FLAGS=no
+             case $host_os in
+             solaris*)
+             ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+             ;;
+             esac
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+               test "x$ax_pthread_special_flags_added" != "xyes"],
+              [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+               ax_pthread_special_flags_added=yes])
+
+        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+            [ax_cv_PTHREAD_PRIO_INHERIT],
+            [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+                                             [[int i = PTHREAD_PRIO_INHERIT;]])],
+                            [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+                            [ax_cv_PTHREAD_PRIO_INHERIT=no])
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+               test "x$ax_pthread_prio_inherit_defined" != "xyes"],
+              [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
+               ax_pthread_prio_inherit_defined=yes
+              ])
+
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != "xyes"; then
+            case $host_os in
+                aix*)
+                AS_CASE(["x/$CC"],
+                    [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+                    [#handle absolute path differently from PATH based program lookup
+                     AS_CASE(["x$CC"],
+                         [x/*],
+                         [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+                         [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+                ;;
+            esac
+        fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test "x$ax_pthread_ok" = "xyes"; then
+        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+        :
+else
+        ax_pthread_ok=no
+        $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD

+ 394 - 0
libs/harfbuzz/meson.build

@@ -0,0 +1,394 @@
+project('harfbuzz', 'c', 'cpp',
+  meson_version: '>= 0.55.0',
+  version: '5.3.1',
+  default_options: [
+    'cpp_rtti=false',       # Just to support msvc, we are passing -fno-exceptions also anyway
+    'cpp_std=c++11',
+    'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
+  ],
+)
+
+hb_version_arr = meson.project_version().split('.')
+hb_version_major = hb_version_arr[0].to_int()
+hb_version_minor = hb_version_arr[1].to_int()
+hb_version_micro = hb_version_arr[2].to_int()
+
+# libtool versioning
+hb_version_int = hb_version_major*10000 + hb_version_minor*100 + hb_version_micro
+hb_libtool_version_info = '@0@:0:@0@'.format(hb_version_int)
+
+pkgmod = import('pkgconfig')
+cpp = meson.get_compiler('cpp')
+null_dep = dependency('', required: false)
+
+if cpp.get_argument_syntax() == 'msvc'
+  # Ignore several spurious warnings for things HarfBuzz does very commonly.
+  # If a warning is completely useless and spammy, use '/wdXXXX' to suppress it
+  # If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
+  # NOTE: Only add warnings here if you are sure they're spurious
+  msvc_args = [
+    '/wd4018', # implicit signed/unsigned conversion
+    '/wd4146', # unary minus on unsigned (beware INT_MIN)
+    '/wd4244', # lossy type conversion (e.g. double -> int)
+    '/wd4305', # truncating type conversion (e.g. double -> float)
+    cpp.get_supported_arguments(['/utf-8']), # set the input encoding to utf-8
+  ]
+  add_project_arguments(msvc_args, language: ['c', 'cpp'])
+  # Disable SAFESEH with MSVC for libs that use external deps that are built with MinGW
+  # noseh_link_args = ['/SAFESEH:NO']
+  # disable exception handling
+  add_project_arguments(['/EHs-', '/EHc-'], language: 'cpp')
+endif
+
+add_project_link_arguments(cpp.get_supported_link_arguments([
+  '-Bsymbolic-functions'
+]), language: 'c')
+
+add_project_arguments(cpp.get_supported_arguments([
+  '-fno-exceptions',
+  '-fno-rtti',
+  '-fno-threadsafe-statics',
+  '-fvisibility-inlines-hidden',
+]), language: 'cpp')
+
+if host_machine.cpu_family() == 'arm' and cpp.alignment('struct { char c; }') != 1
+  if cpp.has_argument('-mstructure-size-boundary=8')
+    add_project_arguments('-mstructure-size-boundary=8', language: 'cpp')
+  endif
+endif
+
+if host_machine.system() == 'windows'
+  add_project_arguments(cpp.get_supported_arguments([
+    '-Wa,-mbig-obj'
+  ]), language : 'cpp')
+endif
+
+check_headers = [
+  ['unistd.h'],
+  ['sys/mman.h'],
+  ['stdbool.h'],
+  ['xlocale.h'],
+]
+
+check_funcs = [
+  ['atexit'],
+  ['mprotect'],
+  ['sysconf'],
+  ['getpagesize'],
+  ['mmap'],
+  ['isatty'],
+  ['uselocale'],
+  ['newlocale'],
+]
+
+m_dep = cpp.find_library('m', required: false)
+
+
+# Try pkgconfig name
+freetype_dep = dependency('freetype2', required: false)
+if not freetype_dep.found()
+  # Try cmake name
+  freetype_dep = dependency('freetype', required: false)
+endif
+if not freetype_dep.found()
+  # Subproject fallback, `allow_fallback: true` means the fallback will be
+  # tried even if the freetype option is set to `auto`.
+  freetype_dep = dependency('freetype2',
+                            required: get_option('freetype'),
+                            default_options: ['harfbuzz=disabled'],
+                            allow_fallback: true)
+endif
+
+glib_dep = dependency('glib-2.0', required: get_option('glib'))
+gobject_dep = dependency('gobject-2.0', required: get_option('gobject'))
+graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
+graphite_dep = dependency('graphite2', required: get_option('graphite'))
+
+# Try pkgconfig name
+icu_dep = dependency('icu-uc', required: false)
+if not icu_dep.found()
+  # Try cmake name
+  icu_dep = dependency('ICU',
+                       required: false,
+                       components: 'uc',
+                       method: 'cmake')
+endif
+if not icu_dep.found()
+  # Subproject fallback if icu option is enabled
+  icu_dep = dependency('icu-uc', required: get_option('icu'))
+endif
+
+if icu_dep.found() and icu_dep.type_name() == 'pkgconfig'
+  icu_defs = icu_dep.get_variable(pkgconfig: 'DEFS', default_value: '').split()
+  if icu_defs.length() > 0
+    add_project_arguments(icu_defs, language: ['c', 'cpp'])
+  endif
+endif
+
+cairo_dep = null_dep
+cairo_ft_dep = null_dep
+if not get_option('cairo').disabled()
+  cairo_dep = dependency('cairo', required: false)
+  cairo_ft_dep = dependency('cairo-ft', required: false)
+
+  if (not cairo_dep.found() and
+      cpp.get_argument_syntax() == 'msvc' and
+      cpp.has_header('cairo.h'))
+    cairo_dep = cpp.find_library('cairo', required: false)
+    if cairo_dep.found() and cpp.has_function('cairo_ft_font_face_create_for_ft_face',
+                                              prefix: '#include <cairo-ft.h>',
+                                              dependencies: cairo_dep)
+      cairo_ft_dep = cairo_dep
+    endif
+  endif
+
+  if not cairo_dep.found()
+    # Note that we don't have harfbuzz -> cairo -> freetype2 -> harfbuzz fallback
+    # dependency cycle here because we have configured freetype2 above with
+    # harfbuzz support disabled, so when cairo will lookup freetype2 dependency
+    # it will be forced to use that one.
+    cairo_dep = dependency('cairo', required: get_option('cairo'))
+    cairo_ft_dep = dependency('cairo-ft', required: get_option('cairo'))
+  endif
+endif
+
+chafa_dep = dependency('chafa', version: '>= 1.6.0', required: get_option('chafa'))
+
+conf = configuration_data()
+incconfig = include_directories('.')
+
+add_project_arguments('-DHAVE_CONFIG_H', language: ['c', 'cpp'])
+
+warn_cflags = [
+  '-Wno-non-virtual-dtor',
+]
+
+cpp_args = cpp.get_supported_arguments(warn_cflags)
+
+if glib_dep.found()
+  conf.set('HAVE_GLIB', 1)
+endif
+
+if gobject_dep.found()
+  conf.set('HAVE_GOBJECT', 1)
+endif
+
+if cairo_dep.found()
+  conf.set('HAVE_CAIRO', 1)
+  if cairo_dep.type_name() == 'internal'
+    conf.set('HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC', 1)
+  else
+    check_funcs += [['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}]]
+  endif
+endif
+
+if cairo_ft_dep.found()
+  conf.set('HAVE_CAIRO_FT', 1)
+endif
+
+if chafa_dep.found()
+  conf.set('HAVE_CHAFA', 1)
+endif
+
+if graphite2_dep.found() or graphite_dep.found()
+  conf.set('HAVE_GRAPHITE2', 1)
+endif
+
+if icu_dep.found()
+  conf.set('HAVE_ICU', 1)
+endif
+
+if get_option('icu_builtin')
+  conf.set('HAVE_ICU_BUILTIN', 1)
+endif
+
+if get_option('experimental_api')
+  conf.set('HB_EXPERIMENTAL_API', 1)
+endif
+
+if freetype_dep.found()
+  conf.set('HAVE_FREETYPE', 1)
+  check_freetype_funcs = [
+    ['FT_Get_Var_Blend_Coordinates', {'deps': freetype_dep}],
+    ['FT_Set_Var_Blend_Coordinates', {'deps': freetype_dep}],
+    ['FT_Done_MM_Var', {'deps': freetype_dep}],
+    ['FT_Get_Transform', {'deps': freetype_dep}],
+  ]
+
+  if freetype_dep.type_name() == 'internal'
+    foreach func: check_freetype_funcs
+      name = func[0]
+      conf.set('HAVE_@0@'.format(name.to_upper()), 1)
+    endforeach
+  else
+    check_funcs += check_freetype_funcs
+  endif
+endif
+
+gdi_uniscribe_deps = []
+# GDI (Uniscribe) (Windows)
+if host_machine.system() == 'windows' and not get_option('gdi').disabled()
+  if (get_option('directwrite').enabled() and
+      not (cpp.has_header('usp10.h') and cpp.has_header('windows.h')))
+    error('GDI/Uniscribe was enabled explicitly, but required headers are missing.')
+  endif
+
+  gdi_deps_found = true
+  foreach usplib : ['usp10', 'gdi32', 'rpcrt4']
+    dep = cpp.find_library(usplib, required: get_option('gdi'))
+    gdi_deps_found = gdi_deps_found and dep.found()
+    gdi_uniscribe_deps += dep
+  endforeach
+
+  if gdi_deps_found
+    conf.set('HAVE_UNISCRIBE', 1)
+    conf.set('HAVE_GDI', 1)
+  endif
+endif
+
+# DirectWrite (Windows)
+if host_machine.system() == 'windows' and not get_option('directwrite').disabled()
+  if get_option('directwrite').enabled() and not cpp.has_header('dwrite_1.h')
+    error('DirectWrite was enabled explicitly, but required header is missing.')
+  endif
+
+  conf.set('HAVE_DIRECTWRITE', 1)
+endif
+
+# CoreText (macOS)
+coretext_deps = []
+if host_machine.system() == 'darwin' and not get_option('coretext').disabled()
+  app_services_dep = dependency('appleframeworks', modules: ['ApplicationServices'], required: false)
+  if cpp.has_type('CTFontRef', prefix: '#include <ApplicationServices/ApplicationServices.h>', dependencies: app_services_dep)
+    coretext_deps += [app_services_dep]
+    conf.set('HAVE_CORETEXT', 1)
+  # On iOS CoreText and CoreGraphics are stand-alone frameworks
+  # Check for a different symbol to avoid getting cached result
+  else
+    coretext_dep = dependency('appleframeworks', modules: ['CoreText'], required: false)
+    coregraphics_dep = dependency('appleframeworks', modules: ['CoreGraphics'], required: false)
+    corefoundation_dep = dependency('appleframeworks', modules: ['CoreFoundation'], required: false)
+    if cpp.has_type('CTRunRef', prefix: '#include <CoreText/CoreText.h>', dependencies: [coretext_dep, coregraphics_dep, corefoundation_dep])
+      coretext_deps += [coretext_dep, coregraphics_dep, corefoundation_dep]
+      conf.set('HAVE_CORETEXT', 1)
+    elif get_option('coretext').enabled()
+      error('CoreText was enabled explicitly, but required headers or frameworks are missing.')
+    endif
+  endif
+endif
+
+# threads
+thread_dep = null_dep
+if host_machine.system() != 'windows'
+  thread_dep = dependency('threads', required: false)
+
+  if thread_dep.found()
+    conf.set('HAVE_PTHREAD', 1)
+  endif
+endif
+
+conf.set_quoted('PACKAGE_NAME', 'HarfBuzz')
+conf.set_quoted('PACKAGE_VERSION', meson.project_version())
+
+foreach check : check_headers
+  name = check[0]
+
+  if cpp.has_header(name)
+    conf.set('HAVE_@0@'.format(name.to_upper().underscorify()), 1)
+  endif
+endforeach
+
+harfbuzz_extra_deps = []
+foreach check : check_funcs
+  name = check[0]
+  opts = check.get(1, {})
+  link_withs = opts.get('link_with', [])
+  check_deps = opts.get('deps', [])
+  extra_deps = []
+  found = true
+
+  # First try without linking
+  found = cpp.has_function(name, dependencies: check_deps)
+
+  if not found and link_withs.length() > 0
+    found = true
+
+    foreach link_with : link_withs
+      dep = cpp.find_library(link_with, required: false)
+      if dep.found()
+        extra_deps += dep
+      else
+        found = false
+      endif
+    endforeach
+
+    if found
+      found = cpp.has_function(name, dependencies: check_deps + extra_deps)
+    endif
+  endif
+
+  if found
+    harfbuzz_extra_deps += extra_deps
+    conf.set('HAVE_@0@'.format(name.to_upper()), 1)
+  endif
+endforeach
+
+subdir('src')
+subdir('util')
+
+if not get_option('tests').disabled()
+  subdir('test')
+endif
+
+if not get_option('benchmark').disabled()
+  subdir('perf')
+endif
+
+if not get_option('docs').disabled()
+  subdir('docs')
+endif
+
+configure_file(output: 'config.h', configuration: conf)
+
+build_summary = {
+  'Directories':
+    {'prefix': get_option('prefix'),
+     'bindir': get_option('bindir'),
+     'libdir': get_option('libdir'),
+     'includedir': get_option('includedir'),
+     'datadir': get_option('datadir'),
+    },
+  'Unicode callbacks (you want at least one)':
+    {'Builtin': true,
+     'Glib': conf.get('HAVE_GLIB', 0) == 1,
+     'ICU': conf.get('HAVE_ICU', 0) == 1,
+    },
+  'Font callbacks (the more the merrier)':
+    {'FreeType': conf.get('HAVE_FREETYPE', 0) == 1,
+    },
+  'Dependencies used for command-line utilities':
+    {'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
+     'Chafa': conf.get('HAVE_CHAFA', 0) == 1,
+    },
+  'Additional shapers':
+    {'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,
+    },
+  'Platform shapers (not normally needed)':
+    {'CoreText': conf.get('HAVE_CORETEXT', 0) == 1,
+     'DirectWrite': conf.get('HAVE_DIRECTWRITE', 0) == 1,
+     'GDI/Uniscribe': (conf.get('HAVE_GDI', 0) == 1) and (conf.get('HAVE_UNISCRIBE', 0) == 1),
+    },
+  'Other features':
+    {'Documentation': conf.get('HAVE_GTK_DOC', 0) == 1,
+     'GObject bindings': conf.get('HAVE_GOBJECT', 0) == 1,
+     'Introspection': conf.get('HAVE_INTROSPECTION', 0) == 1,
+     'Experimental APIs': conf.get('HB_EXPERIMENTAL_API', 0) == 1,
+    },
+  'Testing':
+    {'Tests': get_option('tests').enabled(),
+     'Benchmark': get_option('benchmark').enabled(),
+    },
+}
+foreach section_title, section : build_summary
+  summary(section, bool_yn: true, section: section_title)
+endforeach

+ 42 - 0
libs/harfbuzz/meson_options.txt

@@ -0,0 +1,42 @@
+# HarfBuzz feature options
+option('glib', type: 'feature', value: 'auto',
+  description: 'Enable GLib unicode functions')
+option('gobject', type: 'feature', value: 'auto',
+  description: 'Enable GObject bindings')
+option('cairo', type: 'feature', value: 'auto',
+  description: 'Use Cairo graphics library')
+option('chafa', type: 'feature', value: 'auto',
+  description: 'Use Chafa terminal graphics library')
+option('icu', type: 'feature', value: 'auto',
+  description: 'Enable ICU library unicode functions')
+option('graphite', type: 'feature', value: 'disabled',
+  description: 'Deprecated use graphite2 option instead')
+option('graphite2', type: 'feature', value: 'disabled',
+  description: 'Enable Graphite2 complementary shaper')
+option('freetype', type: 'feature', value: 'auto',
+  description: 'Enable freetype interop helpers')
+option('gdi', type: 'feature', value: 'disabled',
+  description: 'Enable GDI helpers and Uniscribe shaper backend (Windows only)')
+option('directwrite', type: 'feature', value: 'disabled',
+  description: 'Enable DirectWrite shaper backend on Windows (experimental)')
+option('coretext', type: 'feature', value: 'disabled',
+  description: 'Enable CoreText shaper backend on macOS')
+
+# Common feature options
+option('tests', type: 'feature', value: 'enabled', yield: true,
+  description: 'Enable or disable unit tests')
+option('introspection', type: 'feature', value: 'auto', yield: true,
+  description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
+option('docs', type: 'feature', value: 'auto', yield: true,
+  description: 'Generate documentation with gtk-doc')
+
+option('benchmark', type: 'feature', value: 'disabled',
+  description: 'Enable benchmark tests')
+option('icu_builtin', type: 'boolean', value: false,
+  description: 'Don\'t separate ICU support as harfbuzz-icu module')
+option('experimental_api', type: 'boolean', value: false,
+  description: 'Enable experimental APIs')
+option('ragel_subproject', type: 'boolean', value: false,
+  description: 'Build Ragel subproject if no suitable version is found')
+option('fuzzer_ldflags', type: 'string',
+  description: 'Extra LDFLAGS used during linking of fuzzing binaries')

+ 30 - 0
libs/harfbuzz/mingw-configure.sh

@@ -0,0 +1,30 @@
+#!/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="-O2 -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-gdi \
+	--with-uniscribe \
+	--with-directwrite=auto \
+	"$@"

+ 23 - 0
libs/harfbuzz/perf/Makefile.am

@@ -0,0 +1,23 @@
+# Process this file with automake to produce Makefile.in
+
+NULL =
+EXTRA_DIST =
+SUBDIRS =
+
+EXTRA_DIST += \
+	meson.build \
+	benchmark-font.cc \
+	benchmark-map.cc \
+	benchmark-ot.cc \
+	benchmark-set.cc \
+	benchmark-shape.cc \
+	benchmark-subset.cc \
+	fonts \
+	texts \
+	$(NULL)
+
+# Convenience targets:
+lib:
+	@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+
+-include $(top_srcdir)/git.mk

+ 54 - 0
libs/harfbuzz/perf/README.md

@@ -0,0 +1,54 @@
+# Building and Running
+
+Benchmarks are implemented using [Google Benchmark](https://github.com/google/benchmark).
+
+To build the benchmarks in this directory you need to set the benchmark
+option while configuring the build with meson:
+
+```
+meson build -Dbenchmark=enabled --buildtype=release
+```
+or:
+```
+meson build -Dbenchmark=enabled --buildtype=debugoptimized
+```
+
+
+Then build a specific benchmark binaries with ninja:
+```
+ninja -Cbuild perf/benchmark-set
+```
+or just build the whole project:
+```
+ninja -Cbuild
+```
+
+Finally, to run one of the benchmarks:
+
+```
+./build/perf/benchmark-set
+```
+
+It's possible to filter the benchmarks being run and customize the output
+via flags to the benchmark binary. See the
+[Google Benchmark User Guide](https://github.com/google/benchmark/blob/main/docs/user_guide.md#user-guide) for more details.
+
+# Profiling
+
+Configure the build to include debug information for profiling:
+
+```
+CXXFLAGS="-fno-omit-frame-pointer" meson --reconfigure build -Dbenchmark=enabled --buildtype=debug
+ninja -Cbuild
+```
+
+Then run the benchmark with perf:
+
+```
+perf record -g build/perf/benchmark-subset --benchmark_filter="BM_subset_codepoints/subset_notocjk/100000" --benchmark_repetitions=5
+```
+You probably want to filter to a specific benchmark of interest and set the number of repititions high enough to get a good sampling of profile data.
+
+Finally view the profile with:
+
+perf report

+ 245 - 0
libs/harfbuzz/perf/benchmark-font.cc

@@ -0,0 +1,245 @@
+#include "benchmark/benchmark.h"
+#include <cassert>
+#include <cstring>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "hb.h"
+#include "hb-ot.h"
+#ifdef HAVE_FREETYPE
+#include "hb-ft.h"
+#endif
+
+
+#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
+
+struct test_input_t
+{
+  bool is_variable;
+  const char *font_path;
+} default_tests[] =
+{
+  {true , SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf"},
+  {false, SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf"},
+  {true , SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf"},
+  {true , SUBSET_FONT_BASE_PATH "SourceSerifVariable-Roman.ttf"},
+  {false, SUBSET_FONT_BASE_PATH "Comfortaa-Regular-new.ttf"},
+  {false, SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf"},
+  {false, SUBSET_FONT_BASE_PATH "NotoSerifMyanmar-Regular.otf"},
+};
+
+static test_input_t *tests = default_tests;
+static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
+
+enum backend_t { HARFBUZZ, FREETYPE };
+
+enum operation_t
+{
+  nominal_glyphs,
+  glyph_h_advances,
+  glyph_extents,
+  glyph_shape,
+};
+
+static void
+_hb_move_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, void *) {}
+
+static void
+_hb_line_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, void *) {}
+
+//static void
+//_hb_quadratic_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, float, float, void *) {}
+
+static void
+_hb_cubic_to (hb_draw_funcs_t *, void *, hb_draw_state_t *, float, float, float, float, float, float, void *) {}
+
+static void
+_hb_close_path (hb_draw_funcs_t *, void *, hb_draw_state_t *, void *) {}
+
+static hb_draw_funcs_t *
+_draw_funcs_create (void)
+{
+  hb_draw_funcs_t *draw_funcs = hb_draw_funcs_create ();
+  hb_draw_funcs_set_move_to_func (draw_funcs, _hb_move_to, nullptr, nullptr);
+  hb_draw_funcs_set_line_to_func (draw_funcs, _hb_line_to, nullptr, nullptr);
+  //hb_draw_funcs_set_quadratic_to_func (draw_funcs, _hb_quadratic_to, nullptr, nullptr);
+  hb_draw_funcs_set_cubic_to_func (draw_funcs, _hb_cubic_to, nullptr, nullptr);
+  hb_draw_funcs_set_close_path_func (draw_funcs, _hb_close_path, nullptr, nullptr);
+  return draw_funcs;
+}
+
+static void BM_Font (benchmark::State &state,
+		     bool is_var, backend_t backend, operation_t operation,
+		     const test_input_t &test_input)
+{
+  hb_font_t *font;
+  unsigned num_glyphs;
+  {
+    hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
+    assert (blob);
+    hb_face_t *face = hb_face_create (blob, 0);
+    hb_blob_destroy (blob);
+    num_glyphs = hb_face_get_glyph_count (face);
+    font = hb_font_create (face);
+    hb_face_destroy (face);
+  }
+
+  if (is_var)
+  {
+    hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
+    hb_font_set_variations (font, &wght, 1);
+  }
+
+  switch (backend)
+  {
+    case HARFBUZZ:
+      hb_ot_font_set_funcs (font);
+      break;
+
+    case FREETYPE:
+#ifdef HAVE_FREETYPE
+      hb_ft_font_set_funcs (font);
+#endif
+      break;
+  }
+
+  switch (operation)
+  {
+    case nominal_glyphs:
+    {
+      hb_set_t *set = hb_set_create ();
+      hb_face_collect_unicodes (hb_font_get_face (font), set);
+      unsigned pop = hb_set_get_population (set);
+      hb_codepoint_t *unicodes = (hb_codepoint_t *) calloc (pop, sizeof (hb_codepoint_t));
+      hb_codepoint_t *glyphs = (hb_codepoint_t *) calloc (pop, sizeof (hb_codepoint_t));
+
+      hb_codepoint_t *p = unicodes;
+      for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
+	   hb_set_next (set, &u);)
+        *p++ = u;
+      assert (p == unicodes + pop);
+
+      for (auto _ : state)
+	hb_font_get_nominal_glyphs (font,
+				    pop,
+				    unicodes, sizeof (*unicodes),
+				    glyphs, sizeof (*glyphs));
+
+      free (glyphs);
+      free (unicodes);
+      hb_set_destroy (set);
+      break;
+    }
+    case glyph_h_advances:
+    {
+      hb_codepoint_t *glyphs = (hb_codepoint_t *) calloc (num_glyphs, sizeof (hb_codepoint_t));
+      hb_position_t *advances = (hb_position_t *) calloc (num_glyphs, sizeof (hb_codepoint_t));
+
+      for (unsigned g = 0; g < num_glyphs; g++)
+        glyphs[g] = g;
+
+      for (auto _ : state)
+	hb_font_get_glyph_h_advances (font,
+				      num_glyphs,
+				      glyphs, sizeof (*glyphs),
+				      advances, sizeof (*advances));
+
+      free (advances);
+      free (glyphs);
+      break;
+    }
+    case glyph_extents:
+    {
+      hb_glyph_extents_t extents;
+      for (auto _ : state)
+	for (unsigned gid = 0; gid < num_glyphs; ++gid)
+	  hb_font_get_glyph_extents (font, gid, &extents);
+      break;
+    }
+    case glyph_shape:
+    {
+      hb_draw_funcs_t *draw_funcs = _draw_funcs_create ();
+      for (auto _ : state)
+	for (unsigned gid = 0; gid < num_glyphs; ++gid)
+	  hb_font_get_glyph_shape (font, gid, draw_funcs, nullptr);
+      break;
+      hb_draw_funcs_destroy (draw_funcs);
+    }
+  }
+
+
+  hb_font_destroy (font);
+}
+
+static void test_backend (backend_t backend,
+			  const char *backend_name,
+			  bool variable,
+			  operation_t op,
+			  const char *op_name,
+			  benchmark::TimeUnit time_unit,
+			  const test_input_t &test_input)
+{
+  char name[1024] = "BM_Font/";
+  strcat (name, op_name);
+  strcat (name, "/");
+  const char *p = strrchr (test_input.font_path, '/');
+  strcat (name, p ? p + 1 : test_input.font_path);
+  strcat (name, variable ? "/var" : "");
+  strcat (name, "/");
+  strcat (name, backend_name);
+
+  benchmark::RegisterBenchmark (name, BM_Font, variable, backend, op, test_input)
+   ->Unit(time_unit);
+}
+
+static void test_operation (operation_t op,
+			    const char *op_name,
+			    benchmark::TimeUnit time_unit)
+{
+  for (unsigned i = 0; i < num_tests; i++)
+  {
+    auto& test_input = tests[i];
+    for (int variable = 0; variable < int (test_input.is_variable) + 1; variable++)
+    {
+      bool is_var = (bool) variable;
+
+      test_backend (HARFBUZZ, "hb", is_var, op, op_name, time_unit, test_input);
+#ifdef HAVE_FREETYPE
+      test_backend (FREETYPE, "ft", is_var, op, op_name, time_unit, test_input);
+#endif
+    }
+  }
+}
+
+int main(int argc, char** argv)
+{
+  benchmark::Initialize(&argc, argv);
+
+  if (argc > 1)
+  {
+    num_tests = argc - 1;
+    tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
+    for (unsigned i = 0; i < num_tests; i++)
+    {
+      tests[i].is_variable = true;
+      tests[i].font_path = argv[i + 1];
+    }
+  }
+
+#define TEST_OPERATION(op, time_unit) test_operation (op, #op, time_unit)
+
+  TEST_OPERATION (nominal_glyphs, benchmark::kMicrosecond);
+  TEST_OPERATION (glyph_h_advances, benchmark::kMicrosecond);
+  TEST_OPERATION (glyph_extents, benchmark::kMicrosecond);
+  TEST_OPERATION (glyph_shape, benchmark::kMicrosecond);
+
+#undef TEST_OPERATION
+
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+
+  if (tests != default_tests)
+    free (tests);
+}

+ 68 - 0
libs/harfbuzz/perf/benchmark-map.cc

@@ -0,0 +1,68 @@
+/*
+ * Benchmarks for hb_map_t operations.
+ */
+#include "benchmark/benchmark.h"
+
+#include <cassert>
+#include <cstdlib>
+#include "hb.h"
+
+void RandomMap(unsigned size, hb_map_t* out) {
+  hb_map_clear(out);
+
+  srand(size);
+  for (unsigned i = 0; i < size; i++) {
+    while (true) {
+      hb_codepoint_t next = rand();
+      if (hb_map_has (out, next)) continue;
+
+      hb_map_set (out, next, rand ());
+      break;
+    }
+  }
+}
+
+/* Insert a single value into map of varying sizes. */
+static void BM_MapInsert(benchmark::State& state) {
+  unsigned map_size = state.range(0);
+
+  hb_map_t* original = hb_map_create ();
+  RandomMap(map_size, original);
+  assert(hb_map_get_population(original) == map_size);
+
+  auto needle = map_size / 2;
+  auto v = 0;
+  for (auto _ : state) {
+    // TODO(garretrieger): create a copy of the original map.
+    //                     Needs a hb_map_copy(..) in public api.
+
+    hb_map_set (original, needle++, v++);
+  }
+
+  hb_map_destroy(original);
+}
+BENCHMARK(BM_MapInsert)
+    ->Range(1 << 4, 1 << 20);
+
+/* Single value lookup on map of various sizes. */
+static void BM_MapLookup(benchmark::State& state) {
+  unsigned map_size = state.range(0);
+
+  hb_map_t* original = hb_map_create ();
+  RandomMap(map_size, original);
+  assert(hb_map_get_population(original) == map_size);
+
+  auto needle = map_size / 2;
+
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(
+        hb_map_get (original, needle++));
+  }
+
+  hb_map_destroy(original);
+}
+BENCHMARK(BM_MapLookup)
+    ->Range(1 << 4, 1 << 20); // Map size
+
+
+BENCHMARK_MAIN();

+ 44 - 0
libs/harfbuzz/perf/benchmark-ot.cc

@@ -0,0 +1,44 @@
+/*
+ * Benchmarks for hb_set_t operations.
+ */
+#include "benchmark/benchmark.h"
+
+#include "hb-ot.h"
+
+static void BM_hb_ot_tags_from_script_and_language (benchmark::State& state,
+						    hb_script_t script,
+						    const char *language_str) {
+
+  hb_language_t language = hb_language_from_string (language_str, -1);
+
+  for (auto _ : state)
+  {
+    hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+    unsigned script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
+
+    hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+    unsigned language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
+
+    hb_ot_tags_from_script_and_language (script,
+					 language,
+					 &script_count /* IN/OUT */,
+					 script_tags /* OUT */,
+					 &language_count /* IN/OUT */,
+					 language_tags /* OUT */);
+  }
+}
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON zh_abcd, HB_SCRIPT_COMMON, "zh_abcd");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON zh_hans, HB_SCRIPT_COMMON, "zh_hans");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON ab_abcd, HB_SCRIPT_COMMON, "ab_abcd");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON ab_abc, HB_SCRIPT_COMMON, "ab_abc");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON abcdef_XY, HB_SCRIPT_COMMON, "abcdef_XY");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON abcd_XY, HB_SCRIPT_COMMON, "abcd_XY");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON cxy_CN, HB_SCRIPT_COMMON, "cxy_CN");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON exy_CN, HB_SCRIPT_COMMON, "exy_CN");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON zh_CN, HB_SCRIPT_COMMON, "zh_CN");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON en_US, HB_SCRIPT_COMMON, "en_US");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, LATIN en_US, HB_SCRIPT_LATIN, "en_US");
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, COMMON none, HB_SCRIPT_LATIN, nullptr);
+BENCHMARK_CAPTURE (BM_hb_ot_tags_from_script_and_language, LATIN none, HB_SCRIPT_LATIN, nullptr);
+
+BENCHMARK_MAIN();

+ 151 - 0
libs/harfbuzz/perf/benchmark-set.cc

@@ -0,0 +1,151 @@
+/*
+ * Benchmarks for hb_set_t operations.
+ */
+#include "benchmark/benchmark.h"
+
+#include <cassert>
+#include <cstdlib>
+#include "hb.h"
+
+void RandomSet(unsigned size, unsigned max_value, hb_set_t* out) {
+  hb_set_clear(out);
+
+  srand(size * max_value);
+  for (unsigned i = 0; i < size; i++) {
+    while (true) {
+      unsigned next = rand() % max_value;
+      if (hb_set_has (out, next)) continue;
+
+      hb_set_add(out, next);
+      break;
+    }
+  }
+}
+
+// TODO(garretrieger): benchmark union/subtract/intersection etc.
+
+/* Insert a 1000 values into set of varying sizes. */
+static void BM_SetInsert_1000(benchmark::State& state) {
+  unsigned set_size = state.range(0);
+  unsigned max_value = state.range(0) * state.range(1);
+
+  hb_set_t* original = hb_set_create ();
+  RandomSet(set_size, max_value, original);
+  assert(hb_set_get_population(original) == set_size);
+
+  for (auto _ : state) {
+    state.PauseTiming ();
+    hb_set_t* data = hb_set_copy(original);
+    state.ResumeTiming ();
+    for (int i = 0; i < 1000; i++) {
+      hb_set_add(data, i * 2654435761u % max_value);
+    }
+    hb_set_destroy(data);
+  }
+
+  hb_set_destroy(original);
+}
+BENCHMARK(BM_SetInsert_1000)
+    ->Unit(benchmark::kMicrosecond)
+    ->Ranges(
+        {{1 << 10, 1 << 16}, // Set Size
+         {2, 512}});          // Density
+
+/* Insert a 1000 values into set of varying sizes. */
+static void BM_SetOrderedInsert_1000(benchmark::State& state) {
+  unsigned set_size = state.range(0);
+  unsigned max_value = state.range(0) * state.range(1);
+
+  hb_set_t* original = hb_set_create ();
+  RandomSet(set_size, max_value, original);
+  assert(hb_set_get_population(original) == set_size);
+
+  for (auto _ : state) {
+    state.PauseTiming ();
+    hb_set_t* data = hb_set_copy(original);
+    state.ResumeTiming ();
+    for (int i = 0; i < 1000; i++) {
+      hb_set_add(data, i);
+    }
+    hb_set_destroy(data);
+  }
+
+  hb_set_destroy(original);
+}
+BENCHMARK(BM_SetOrderedInsert_1000)
+    ->Unit(benchmark::kMicrosecond)
+    ->Ranges(
+        {{1 << 10, 1 << 16}, // Set Size
+         {2, 512}});          // Density
+
+/* Single value lookup on sets of various sizes. */
+static void BM_SetLookup(benchmark::State& state, unsigned interval) {
+  unsigned set_size = state.range(0);
+  unsigned max_value = state.range(0) * state.range(1);
+
+  hb_set_t* original = hb_set_create ();
+  RandomSet(set_size, max_value, original);
+  assert(hb_set_get_population(original) == set_size);
+
+  auto needle = max_value / 2;
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(
+        hb_set_has (original, (needle += interval) % max_value));
+  }
+
+  hb_set_destroy(original);
+}
+BENCHMARK_CAPTURE(BM_SetLookup, ordered, 3)
+    ->Ranges(
+        {{1 << 10, 1 << 16}, // Set Size
+         {2, 512}});          // Density
+BENCHMARK_CAPTURE(BM_SetLookup, random, 12345)
+    ->Ranges(
+        {{1 << 10, 1 << 16}, // Set Size
+         {2, 512}});          // Density
+
+/* Full iteration of sets of varying sizes. */
+static void BM_SetIteration(benchmark::State& state) {
+  unsigned set_size = state.range(0);
+  unsigned max_value = state.range(0) * state.range(1);
+
+  hb_set_t* original = hb_set_create ();
+  RandomSet(set_size, max_value, original);
+  assert(hb_set_get_population(original) == set_size);
+
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  for (auto _ : state) {
+    hb_set_next (original, &cp);
+  }
+
+  hb_set_destroy(original);
+}
+BENCHMARK(BM_SetIteration)
+    ->Ranges(
+        {{1 << 10, 1 << 16}, // Set Size
+         {2, 512}});          // Density
+
+/* Set copy. */
+static void BM_SetCopy(benchmark::State& state) {
+  unsigned set_size = state.range(0);
+  unsigned max_value = state.range(0) * state.range(1);
+
+  hb_set_t* original = hb_set_create ();
+  RandomSet(set_size, max_value, original);
+  assert(hb_set_get_population(original) == set_size);
+
+  for (auto _ : state) {
+    hb_set_t *s = hb_set_create ();
+    hb_set_set (s, original);
+    hb_set_destroy (s);
+  }
+
+  hb_set_destroy(original);
+}
+BENCHMARK(BM_SetCopy)
+    ->Unit(benchmark::kMicrosecond)
+    ->Ranges(
+        {{1 << 10, 1 << 16}, // Set Size
+         {2, 512}});          // Density
+
+BENCHMARK_MAIN();

+ 172 - 0
libs/harfbuzz/perf/benchmark-shape.cc

@@ -0,0 +1,172 @@
+#include "benchmark/benchmark.h"
+#include <cstring>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cassert>
+
+#include "hb.h"
+#include "hb-ot.h"
+#ifdef HAVE_FREETYPE
+#include "hb-ft.h"
+#endif
+
+#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
+
+struct test_input_t
+{
+  const char *font_path;
+  const char *text_path;
+  bool is_variable;
+} default_tests[] =
+{
+
+  {"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
+   "perf/texts/fa-thelittleprince.txt",
+   false},
+
+  {"perf/fonts/Amiri-Regular.ttf",
+   "perf/texts/fa-thelittleprince.txt",
+   false},
+
+  {"perf/fonts/Roboto-Regular.ttf",
+   "perf/texts/en-thelittleprince.txt",
+   false},
+
+  {"perf/fonts/Roboto-Regular.ttf",
+   "perf/texts/en-words.txt",
+   false},
+
+  {SUBSET_FONT_BASE_PATH "SourceSerifVariable-Roman.ttf",
+   "perf/texts/en-thelittleprince.txt",
+   true},
+};
+
+static test_input_t *tests = default_tests;
+static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
+
+enum backend_t { HARFBUZZ, FREETYPE };
+
+static void BM_Shape (benchmark::State &state,
+		      bool is_var,
+		      backend_t backend,
+		      const test_input_t &input)
+{
+  hb_font_t *font;
+  {
+    hb_blob_t *blob = hb_blob_create_from_file_or_fail (input.font_path);
+    assert (blob);
+    hb_face_t *face = hb_face_create (blob, 0);
+    hb_blob_destroy (blob);
+    font = hb_font_create (face);
+    hb_face_destroy (face);
+  }
+
+  if (is_var)
+  {
+    hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
+    hb_font_set_variations (font, &wght, 1);
+  }
+
+  switch (backend)
+  {
+    case HARFBUZZ:
+      hb_ot_font_set_funcs (font);
+      break;
+
+    case FREETYPE:
+#ifdef HAVE_FREETYPE
+      hb_ft_font_set_funcs (font);
+#endif
+      break;
+  }
+
+  hb_blob_t *text_blob = hb_blob_create_from_file_or_fail (input.text_path);
+  assert (text_blob);
+  unsigned orig_text_length;
+  const char *orig_text = hb_blob_get_data (text_blob, &orig_text_length);
+
+  hb_buffer_t *buf = hb_buffer_create ();
+  for (auto _ : state)
+  {
+    unsigned text_length = orig_text_length;
+    const char *text = orig_text;
+
+    const char *end;
+    while ((end = (const char *) memchr (text, '\n', text_length)))
+    {
+      hb_buffer_clear_contents (buf);
+      hb_buffer_add_utf8 (buf, text, text_length, 0, end - text);
+      hb_buffer_guess_segment_properties (buf);
+      hb_shape (font, buf, nullptr, 0);
+
+      unsigned skip = end - text + 1;
+      text_length -= skip;
+      text += skip;
+    }
+  }
+  hb_buffer_destroy (buf);
+
+  hb_blob_destroy (text_blob);
+  hb_font_destroy (font);
+}
+
+static void test_backend (backend_t backend,
+			  const char *backend_name,
+			  bool variable,
+			  const test_input_t &test_input)
+{
+  char name[1024] = "BM_Shape";
+  const char *p;
+  strcat (name, "/");
+  p = strrchr (test_input.font_path, '/');
+  strcat (name, p ? p + 1 : test_input.font_path);
+  strcat (name, "/");
+  p = strrchr (test_input.text_path, '/');
+  strcat (name, p ? p + 1 : test_input.text_path);
+  strcat (name, variable ? "/var" : "");
+  strcat (name, "/");
+  strcat (name, backend_name);
+
+  benchmark::RegisterBenchmark (name, BM_Shape, variable, backend, test_input)
+   ->Unit(benchmark::kMillisecond);
+}
+
+int main(int argc, char** argv)
+{
+  benchmark::Initialize(&argc, argv);
+
+  if (argc > 2)
+  {
+    num_tests = (argc - 1) / 2;
+    tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
+    for (unsigned i = 0; i < num_tests; i++)
+    {
+      tests[i].is_variable = true;
+      tests[i].font_path = argv[1 + i * 2];
+      tests[i].text_path = argv[2 + i * 2];
+    }
+  }
+
+  for (unsigned i = 0; i < num_tests; i++)
+  {
+    auto& test_input = tests[i];
+    for (int variable = 0; variable < int (test_input.is_variable) + 1; variable++)
+    {
+      bool is_var = (bool) variable;
+
+      test_backend (HARFBUZZ, "hb", is_var, test_input);
+#ifdef HAVE_FREETYPE
+      test_backend (FREETYPE, "ft", is_var, test_input);
+#endif
+    }
+  }
+
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+
+  if (tests != default_tests)
+    free (tests);
+}

+ 221 - 0
libs/harfbuzz/perf/benchmark-subset.cc

@@ -0,0 +1,221 @@
+#include "benchmark/benchmark.h"
+#include <cassert>
+#include <cstring>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "hb-subset.h"
+
+
+enum operation_t
+{
+  subset_codepoints,
+  subset_glyphs,
+  instance,
+};
+
+struct axis_location_t
+{
+  hb_tag_t axis_tag;
+  float axis_value;
+};
+
+static const axis_location_t
+_roboto_flex_instance_opts[] =
+{
+  {HB_TAG ('w', 'g', 'h', 't'), 600.f},
+  {HB_TAG ('w', 'd', 't', 'h'), 75.f},
+  {HB_TAG ('o', 'p', 's', 'z'), 90.f},
+  {HB_TAG ('G', 'R', 'A', 'D'), -100.f},
+  {HB_TAG ('s', 'l', 'n', 't'), -3.f},
+  {HB_TAG ('X', 'T', 'R', 'A'), 500.f},
+  {HB_TAG ('X', 'O', 'P', 'Q'), 150.f},
+  {HB_TAG ('Y', 'O', 'P', 'Q'), 100.f},
+  {HB_TAG ('Y', 'T', 'L', 'C'), 480.f},
+  {HB_TAG ('Y', 'T', 'U', 'C'), 600.f},
+  {HB_TAG ('Y', 'T', 'A', 'S'), 800.f},
+  {HB_TAG ('Y', 'T', 'D', 'E'), -50.f},
+  {HB_TAG ('Y', 'T', 'F', 'I'), 600.f},
+};
+
+static const axis_location_t
+_mplus_instance_opts[] =
+{
+  {HB_TAG ('w', 'g', 'h', 't'), 800.f},
+};
+
+template <typename Type, unsigned int n>
+static inline unsigned int ARRAY_LEN (const Type (&)[n]) { return n; }
+
+#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
+
+struct test_input_t
+{
+  const char *font_path;
+  const unsigned max_subset_size;
+  const axis_location_t *instance_opts;
+  const unsigned num_instance_opts;
+} tests[] =
+{
+  {SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 4000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "Mplus1p-Regular.ttf", 10000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "MPLUS1-Variable.ttf", 6000, _mplus_instance_opts, ARRAY_LEN (_mplus_instance_opts)},
+  {SUBSET_FONT_BASE_PATH "RobotoFlex-Variable.ttf", 900, _roboto_flex_instance_opts, ARRAY_LEN (_roboto_flex_instance_opts)},
+#if 0
+  {"perf/fonts/NotoSansCJKsc-VF.ttf", 100000},
+#endif
+};
+
+void AddCodepoints(const hb_set_t* codepoints_in_font,
+                   unsigned subset_size,
+                   hb_subset_input_t* input)
+{
+  auto *unicodes = hb_subset_input_unicode_set (input);
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  for (unsigned i = 0; i < subset_size; i++) {
+    // TODO(garretrieger): pick randomly.
+    if (!hb_set_next (codepoints_in_font, &cp)) return;
+    hb_set_add (unicodes, cp);
+  }
+}
+
+void AddGlyphs(unsigned num_glyphs_in_font,
+               unsigned subset_size,
+               hb_subset_input_t* input)
+{
+  auto *glyphs = hb_subset_input_glyph_set (input);
+  for (unsigned i = 0; i < subset_size && i < num_glyphs_in_font; i++) {
+    // TODO(garretrieger): pick randomly.
+    hb_set_add (glyphs, i);
+  }
+}
+
+// Preprocess face and populate the subset accelerator on it to speed up
+// the subsetting operations.
+static hb_face_t* preprocess_face(hb_face_t* face)
+{
+  #ifdef HB_EXPERIMENTAL_API
+  hb_face_t* new_face = hb_subset_preprocess(face);
+  hb_face_destroy(face);
+  return new_face;
+  #else
+  return face;
+  #endif
+}
+
+/* benchmark for subsetting a font */
+static void BM_subset (benchmark::State &state,
+                       operation_t operation,
+                       const test_input_t &test_input)
+{
+  unsigned subset_size = state.range(0);
+
+  hb_face_t *face;
+  {
+    hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
+    assert (blob);
+    face = hb_face_create (blob, 0);
+    hb_blob_destroy (blob);
+
+    face = preprocess_face (face);
+  }
+
+  hb_subset_input_t* input = hb_subset_input_create_or_fail ();
+  assert (input);
+
+  switch (operation)
+  {
+    case subset_codepoints:
+    {
+      hb_set_t* all_codepoints = hb_set_create ();
+      hb_face_collect_unicodes (face, all_codepoints);
+      AddCodepoints(all_codepoints, subset_size, input);
+      hb_set_destroy (all_codepoints);
+    }
+    break;
+
+    case subset_glyphs:
+    {
+      unsigned num_glyphs = hb_face_get_glyph_count (face);
+      AddGlyphs(num_glyphs, subset_size, input);
+    }
+    break;
+
+    case instance:
+#ifdef HB_EXPERIMENTAL_API
+    {
+      hb_set_t* all_codepoints = hb_set_create ();
+      hb_face_collect_unicodes (face, all_codepoints);
+      AddCodepoints(all_codepoints, subset_size, input);
+      hb_set_destroy (all_codepoints);
+
+      for (unsigned i = 0; i < test_input.num_instance_opts; i++)
+        hb_subset_input_pin_axis_location (input, face,
+                                           test_input.instance_opts[i].axis_tag,
+                                           test_input.instance_opts[i].axis_value);
+    }
+#endif
+    break;
+  }
+
+  for (auto _ : state)
+  {
+    hb_face_t* subset = hb_subset_or_fail (face, input);
+    assert (subset);
+    hb_face_destroy (subset);
+  }
+
+  hb_subset_input_destroy (input);
+  hb_face_destroy (face);
+}
+
+static void test_subset (operation_t op,
+                         const char *op_name,
+                         benchmark::TimeUnit time_unit,
+                         const test_input_t &test_input)
+{
+  if (op == instance && test_input.instance_opts == nullptr)
+    return;
+
+  char name[1024] = "BM_subset/";
+  strcat (name, op_name);
+  strcat (name, strrchr (test_input.font_path, '/'));
+
+  benchmark::RegisterBenchmark (name, BM_subset, op, test_input)
+      ->Range(10, test_input.max_subset_size)
+      ->Unit(time_unit);
+}
+
+static void test_operation (operation_t op,
+                            const char *op_name,
+                            benchmark::TimeUnit time_unit)
+{
+  for (auto& test_input : tests)
+  {
+      test_subset (op, op_name, time_unit, test_input);
+  }
+}
+
+int main(int argc, char** argv)
+{
+#define TEST_OPERATION(op, time_unit) test_operation (op, #op, time_unit)
+
+  TEST_OPERATION (subset_glyphs, benchmark::kMillisecond);
+  TEST_OPERATION (subset_codepoints, benchmark::kMillisecond);
+#ifdef HB_EXPERIMENTAL_API
+  TEST_OPERATION (instance, benchmark::kMillisecond);
+#endif
+
+#undef TEST_OPERATION
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+}

BIN
libs/harfbuzz/perf/fonts/Amiri-Regular.ttf


BIN
libs/harfbuzz/perf/fonts/NotoNastaliqUrdu-Regular.ttf


BIN
libs/harfbuzz/perf/fonts/Roboto-Regular.ttf


+ 62 - 0
libs/harfbuzz/perf/meson.build

@@ -0,0 +1,62 @@
+google_benchmark = subproject('google-benchmark')
+google_benchmark_dep = google_benchmark.get_variable('google_benchmark_dep')
+
+benchmark('benchmark-font', executable('benchmark-font', 'benchmark-font.cc',
+  dependencies: [
+    google_benchmark_dep, freetype_dep,
+  ],
+  cpp_args: [],
+  include_directories: [incconfig, incsrc],
+  link_with: [libharfbuzz],
+  install: false,
+), workdir: meson.current_source_dir() / '..', timeout: 100)
+
+benchmark('benchmark-map', executable('benchmark-map', 'benchmark-map.cc',
+  dependencies: [
+    google_benchmark_dep,
+  ],
+  cpp_args: [],
+  include_directories: [incconfig, incsrc],
+  link_with: [libharfbuzz],
+  install: false,
+), workdir: meson.current_source_dir() / '..', timeout: 100)
+
+benchmark('benchmark-ot', executable('benchmark-ot', 'benchmark-ot.cc',
+  dependencies: [
+    google_benchmark_dep,
+  ],
+  cpp_args: [],
+  include_directories: [incconfig, incsrc],
+  link_with: [libharfbuzz],
+  install: false,
+), workdir: meson.current_source_dir() / '..', timeout: 100)
+
+benchmark('benchmark-set', executable('benchmark-set', 'benchmark-set.cc',
+  dependencies: [
+    google_benchmark_dep,
+  ],
+  cpp_args: [],
+  include_directories: [incconfig, incsrc],
+  link_with: [libharfbuzz],
+  install: false,
+), workdir: meson.current_source_dir() / '..', timeout: 100)
+
+benchmark('benchmark-shape', executable('benchmark-shape', 'benchmark-shape.cc',
+  dependencies: [
+    google_benchmark_dep, freetype_dep,
+  ],
+  cpp_args: [],
+  include_directories: [incconfig, incsrc],
+  link_with: [libharfbuzz],
+  install: false,
+), workdir: meson.current_source_dir() / '..', timeout: 100)
+
+benchmark('benchmark-subset', executable('benchmark-subset', 'benchmark-subset.cc',
+  dependencies: [
+    google_benchmark_dep,
+  ],
+  cpp_args: [],
+  include_directories: [incconfig, incsrc],
+  link_with: [libharfbuzz, libharfbuzz_subset],
+  install: false,
+), workdir: meson.current_source_dir() / '..', timeout: 100)

+ 25 - 0
libs/harfbuzz/perf/run.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+CXX=clang++
+FONT=fonts/NotoNastaliqUrdu-Regular.ttf
+TEXT=texts/fa-monologue.txt
+
+$CXX ../util/hb-shape.cc ../util/options.cc ../src/harfbuzz.cc \
+  -lm -fno-rtti -fno-exceptions -fno-omit-frame-pointer -DHB_NO_MT \
+  -I../src $FLAGS $SOURCES \
+  -DPACKAGE_NAME='""' -DPACKAGE_VERSION='""' \
+  -DHAVE_GLIB $(pkg-config --cflags --libs glib-2.0) \
+  -o hb-shape -g -O2 # -O3 \
+  #-march=native -mtune=native \
+  #-Rpass=loop-vectorize -Rpass-missed=loop-vectorize \
+  #-Rpass-analysis=loop-vectorize -fsave-optimization-record
+
+# -march=native: enable all vector instructions current CPU can offer
+# -Rpass*: https://llvm.org/docs/Vectorizers.html#diagnostics
+
+#sudo rm capture.syscap > /dev/null
+#sysprof-cli -c "./a.out $@"
+#sysprof capture.syscap
+
+perf stat ./hb-shape -o /dev/null $FONT --text-file $TEXT --num-iterations=100 --font-funcs=ot
+#perf record -g ./hb-shape -O '' -o /dev/null $FONT --text-file $TEXT --num-iterations=100 --font-funcs=ot
+#perf report -g

+ 1893 - 0
libs/harfbuzz/perf/texts/en-thelittleprince.txt

@@ -0,0 +1,1893 @@
+Downloaded from https://archive.org/details/TheLittlePrince-English
+
+THE LITTLE PRINCE
+
+
+
+Antoine De Saint-Exupery
+
+
+
+
+Antoine de Saint-Exupery, who was a French author, journalist and pilot wrote
+The Little Prince in 1943, one year before his death.
+
+The Little Prince appears to be a simple children’s tale,
+some would say that it is actually a profound and deeply moving tale,
+written in riddles and laced with philosophy and poetic metaphor.
+
+
+
+
+Once when I was six years old I saw a magnificent picture in a book, called True Stories from
+Nature, about the primeval forest. It was a picture of a boa constrictor in the act of swallowing an
+animal. Here is a copy of the drawing.
+
+In the book it said: “Boa constrictors swallow their prey whole, without chewing it. After that they
+are not able to move, and they sleep through the six months that they need for digestion.” I
+pondered deeply, then, over the adventures of the jungle. And after some work with a coloured
+pencil I succeeded in making my first drawing. My Drawing Number One. It looked like this:
+
+
+
+
+I showed my masterpiece to the grown-ups, and asked them whether the drawing frightened them.
+But they answered: “Frighten? Why should any one be frightened by a hat?” My drawing was not
+a picture of a hat. It was a picture of a boa constrictor digesting an elephant. But since the grown-
+ups were not able to understand it, I made another drawing: I drew the inside of the boa
+constrictor, so that the grown-ups could see it clearly. They always need to have things explained.
+
+
+
+My Drawing Number Two looked like this:
+
+
+
+
+The grown-ups’ response, this time, was to advise me to lay aside my drawings of boa
+constrictors, whether from the inside or the outside, and devote myself instead to geography,
+history, arithmetic and grammar. That is why, at the age of six, I gave up what might have been a
+magnificent career as a painter. I had been disheartened by the failure of my Drawing Number
+One and my Drawing Number Two. Grown-ups never understand anything by themselves, and it is
+tiresome for children to be always and forever explaining things to them.
+
+So then I chose another profession, and learned to pilot air-planes. I have flown a little over all
+parts of the world; and it is true that geography has been very useful to me. At a glance I can
+distinguish China from Arizona. If one gets lost in the night, such knowledge is valuable. In the
+course of this life I have had a great many encounters with a great many people who have been
+concerned with matters of consequence. I have lived a great deal among grown-ups. I have seen
+them intimately, close at hand. And that hasn’t much improved my opinion of them.
+
+Whenever I met one of them who seemed to me at all clear-sighted, I tried the experiment of
+showing him my Drawing Number One, which I have always kept. I would try to find out, so, if this
+was a person of true understanding. But, whoever it was, he, or she, would always say: “That is a
+hat.” Then I would never talk to that person about boa constrictors, or primeval forests, or stars. I
+would bring myself down to his level. I would talk to him about bridge, and golf, and politics, and
+neckties. And the grown-up would be greatly pleased to have met such a sensible man.
+
+So I lived my life alone, without anyone that I could really talk to, until I had an accident with my
+plane in the Desert of Sahara, six years ago. Something was broken in my engine. And as I had
+with me neither a mechanic nor any passengers, I set myself to attempt the difficult repairs all
+alone. It was a question of life or death for me: I had scarcely enough drinking water to last a
+week.
+
+The first night, then, I went to sleep on the sand, a thousand miles from any human habitation. I
+was more isolated than a shipwrecked sailor on a raft in the middle of the ocean. Thus you can
+imagine my amazement, at sunrise, when I was awakened by an odd little voice.
+
+
+
+
+It said: “If you please, draw me a sheep!”
+
+“What!”
+
+“Draw me a sheep!”
+
+I jumped to my feet, completely thunderstruck. I blinked my eyes hard. I looked carefully all
+around me. And I saw a most extraordinary small person, who stood there examining me with
+great seriousness. Here you may see the best portrait that, later, I was able to make of him. But
+my drawing is certainly very much less charming than its model.
+
+That, however, is not my fault. The grown-ups discouraged me in my painter’s career when I was
+six years old, and I never learned to draw anything, except boas from the outside and boas from
+the inside.
+
+Now I stared at this sudden apparition with my eyes fairly starting out of my head in
+astonishment. Remember, I had crashed in the desert a thousand miles from any inhabited region.
+And yet my little man seemed neither to be straying uncertainly among the sands, nor to be
+fainting from fatigue or hunger or thirst or fear. Nothing about him gave any suggestion of a child
+lost in the middle of the desert, a thousand miles from any human habitation.
+
+When at last I was able to speak, I said to him: “But, what are you doing here?” And in answer he
+repeated, very slowly, as if he were speaking of a matter of great consequence:
+
+“If you please, draw me a sheep...”
+
+When a mystery is too overpowering, one dare not disobey. Absurd as it might seem to me, a
+thousand miles from any human habitation and in danger of death, I took out of my pocket a sheet
+of paper and my fountain pen. But then I remembered how my studies had been concentrated on
+geography, history, arithmetic, and grammar, and I told the little chap (a little crossly, too) that I
+did not know how to draw. He answered me: “That doesn’t matter. Draw me a sheep...”
+
+
+
+
+But I had never drawn a sheep. So I drew for him one of the two pictures I had drawn so often. It
+was that of the boa constrictor from the outside. And I was astounded to hear the little fellow
+greet it with, “No, no, no! I do not want an elephant inside a boa constrictor. A boa constrictor is a
+very dangerous creature, and an elephant is very cumbersome. Where I live, everything is very
+small. What I need is a sheep. Draw me a sheep.
+
+
+
+
+So then I made a drawing. He looked at it carefully, then he said: “No. This sheep is already very
+sickly. Make me another.” So I made another drawing. My friend smiled gently and indulgently.
+“You see yourself,” he said, “that this is not a sheep. This is a ram. It has horns.
+
+
+
+
+So then I did my drawing over once more. But it was rejected too, just like the others. “This one is
+too old. I want a sheep that will live a long time.
+
+By this time my patience was exhausted, because I was in a hurry to start taking my engine apart.
+So I tossed off this drawing. And I threw out an explanation with it.
+
+“This is only his box. The sheep you asked for is inside.”
+
+
+
+
+I was very surprised to see a light break over the face of my young judge:
+
+“That is exactly the way I wanted it! Do you think that this sheep will have to have a great deal of
+grass?”
+
+“Why?”
+
+“Because where I live everything is very small...”
+
+“There will surely be enough grass for him,” I said.
+
+“It is a very small sheep that I have given you.”
+
+He bent his head over the drawing: “Not so small that, Look! He has gone to sleep...”
+
+And that is how I made the acquaintance of the little prince.
+
+It took me a long time to learn where he came from. The little prince, who asked me so many
+questions, never seemed to hear the ones I asked him. It was from words dropped by chance that,
+little by little, everything was revealed to me.
+
+The first time he saw my air-plane, for instance (I shall not draw my air-plane; that would be much
+too complicated for me), he asked me: “What is that object?”
+
+“That is not an object. It flies. It is an air-plane. It is my air-plane.” And I was proud to have him
+learn that I could fly. He cried out, then: “What! You dropped down from the sky?”
+
+
+
+“Yes,” I answered, modestly.
+
+
+
+“Oh! That is funny!” And the little prince broke into a lovely peal of laughter, which irritated me
+very much. I like my misfortunes to be taken seriously.
+
+Then he added: “So you, too, come from the sky! Which is your planet?” At that moment I caught
+a gleam of light in the impenetrable mystery of his presence; and I demanded, abruptly: “Do you
+come from another planet?” But he did not reply. He tossed his head gently, without taking his
+eyes from my plane: “It is true that on that you can’t have come from very far away...” And he
+sank into a reverie, which lasted a long time. Then, taking my sheep out of his pocket, he buried
+himself in the contemplation of his treasure.
+
+You can imagine how my curiosity was aroused by this half-confidence about the “other planets.” I
+made a great effort, therefore, to find out more on this subject.
+
+“My little man, where do you come from? What is this ‘where I live,’ of which you speak? Where
+do you want to take your sheep?”
+
+After a reflective silence he answered: “The thing that is so good about the box you have given
+me is that at night he can use it as his house.”
+
+“That is so. And if you are good I will give you a string, too, so that you can tie him during the day,
+and a post to tie him to.”
+
+But the little prince seemed shocked by this offer: “Tie him! What a queer idea!”
+
+“But if you don’t tie him,” I said, “he will wander off somewhere, and get lost.”
+
+My friend broke into another peal of laughter: “But where do you think he would go?”
+“Anywhere. Straight ahead of him.”
+
+Then the little prince said, earnestly: “That doesn’t matter. Where I live, everything is so small!”
+And, with perhaps a hint of sadness, he added: “Straight ahead of him, nobody can go very far...”
+
+
+
+
+I had thus learned a second fact of great importance: this was that the planet the little prince
+came from was scarcely any larger than a house! But that did not really surprise me much. I knew
+very well that in addition to the great planets, such as the Earth, Jupiter, Mars, Venus, to which
+we have given names, there are also hundreds of others, some of which are so small that one has
+a hard time seeing them through the telescope.
+
+
+
+When an astronomer discovers one of these he does not give it a name, but only a number. He
+might call it, for example, “Asteroid 325.”
+
+
+
+
+I have serious reason to believe that the planet from which the little prince came is the asteroid
+known as B-612. This asteroid has only once been seen through the telescope. That was by a
+Turkish astronomer, in 1909.
+
+On making his discovery, the astronomer had presented it to the International Astronomical
+Congress, in a great demonstration. But he was in Turkish costume, and so nobody would believe
+what he said. Grown-ups are like that...
+
+Fortunately, however, for the reputation of Asteroid B-612, a Turkish dictator made a law that his
+subjects, under pain of death, should change to European costume. So in 1920 the astronomer
+gave his demonstration all over again, dressed with impressive style and elegance. And this time
+everybody accepted his report.
+
+If I have told you these details about the asteroid, and made a note of its number for you, it is on
+account of the grown-ups and their ways. When you tell them that you have made a new friend,
+they never ask you any questions about essential matters. They never say to you, “What does his
+voice sound like? What games does he love best? Does he collect butterflies?” Instead, they
+demand: “How old is he? How many brothers has he? How much does he weigh? How much
+money does his father make?”
+
+Only from these figures do they think they have learned anything about him.
+
+If you were to say to the grown-ups: “I saw a beautiful house made of rosy brick, with geraniums
+in the windows and doves on the roof,” they would not be able to get any idea of that house at all.
+
+You would have to say to them: “I saw a house that cost $ 20,000.” Then they would exclaim: “Oh,
+what a pretty house that is!” Just so, you might say to them: “The proof that the little prince
+existed is that he was charming, that he laughed, and that he was looking for a sheep. If anybody
+wants a sheep, that is a proof that he exists.” And what good would it do to tell them that? They
+would shrug their shoulders, and treat you like a child. But if you said to them: “The planet he
+came from is Asteroid B-612,” then they would be convinced, and leave you in peace from their
+questions. They are like that. One must not hold it against them. Children should always show
+great forbearance toward grown-up people. But certainly, for us who understand life, figures are a
+matter of indifference.
+
+I should have liked to begin this story in the fashion of the fairy-tales. I should have like to say:
+“Once upon a time there was a little prince who lived on a planet that was scarcely any bigger
+
+
+
+than himself, and who had need of a sheep...”
+
+
+
+To those who understand life, that would have given a much greater air of truth to my story. Fori
+do not want any one to read my book carelessly. I have suffered too much grief in setting down
+these memories. Six years have already passed since my friend went away from me, with his
+sheep. If I try to describe him here, it is to make sure that I shall not forget him. To forget a friend
+is sad. Not every one has had a friend. And if I forget him, I may become like the grown-ups who
+are no longer interested in anything but figures... It is for that purpose, again, that I have bought a
+box of paints and some pencils.
+
+It is hard to take up drawing again at my age, when I have never made any pictures except those
+of the boa constrictor from the outside and the boa constrictor from the inside, since I was six. I
+shall certainly try to make my portraits as true to life as possible. But I am not at all sure of
+success. One drawing goes along all right, and another has no resemblance to its subject. I make
+some errors, too, in the little prince’s height: in one place he is too tall and in another too short.
+And I feel some doubts about the colour of his costume. So I fumble along as best I can, now good,
+now bad, and I hope generally fair-to- middling. In certain more important details I shall make
+mistakes, also. But that is something that will not be my fault. My friend never explained anything
+to me. He thought, perhaps, that I was like himself. But I, alas, do not know how to see sheep
+through the walls of boxes. Perhaps I am a little like the grown-ups. I have had to grow old.
+
+As each day passed I would learn, in our talk, something about the little prince’s planet, his
+departure from it, his journey. The information would come very slowly, as it might chance to fall
+from his thoughts. It was in this way that I heard, on the third day, about the catastrophe of the
+baobabs.
+
+This time, once more, I had the sheep to thank for it. For the little prince asked me abruptly, as if
+seized by a grave doubt,
+
+“It is true, isn’t it, that sheep eat little bushes?”
+
+“Yes, that is true.”
+
+“Ah! I am glad!”
+
+I did not understand why it was so important that sheep should eat little bushes. But the little
+prince added: “Then it follows that they also eat baobabs?” I pointed out to the little prince that
+baobabs were not little bushes, but, on the contrary, trees as big as castles; and that even if he
+took a whole herd of elephants away with him, the herd would not eat up one single baobab.
+
+The idea of the herd of elephants made the little prince laugh. “We would have to put them one on
+top of the other,” he said. But he made a wise comment:
+
+“Before they grow so big, the baobabs start out by being little.”
+
+“That is strictly correct,” I said. “But why do you want the sheep to eat the little baobabs?”
+
+He answered me at once, “Oh, come, come!”, as if he were speaking of something that was self-
+evident. And I was obliged to make a great mental effort to solve this problem, without any
+assistance.
+
+Indeed, as I learned, there were on the planet where the little prince lived, as on all planets, good
+
+
+
+
+
+plants and bad plants. In consequence, there were good seeds from good plants, and bad seeds
+from bad plants. But seeds are invisible. They sleep deep in the heart of the earth’s darkness,
+until some one among them is seized with the desire to awaken. Then this little seed will stretch
+itself and begin, timidly at first, to push a charming little sprig inoffensively upward toward the
+sun. If it is only a sprout of radish or the sprig of a rose-bush, one would let it grow wherever it
+might wish. But when it is a bad plant, one must destroy it as soon as possible, the very first
+instant that one recognises it.
+
+Now there were some terrible seeds on the planet that was the home of the little prince; and these
+were the seeds of the baobab. The soil of that planet was infested with them. A baobab is
+something you will never, never be able to get rid of if you attend to it too late. It spreads over the
+entire planet. It bores clear through it with its roots. And if the planet is too small, and the
+baobabs are too many, they split it in pieces...
+
+“It is a question of discipline,” the little prince said to me later on.
+
+“When you’ve finished your own toilet in the morning, then it is time to attend to the toilet of your
+planet, just so, with the greatest care. You must see to it that you pull up regularly all the baobabs,
+at the very first moment when they can be distinguished from the rosebushes, which they
+resemble so closely in their earliest youth. It is very tedious work,” the little prince added, “but
+very easy.” And one day he said to me: “You ought to make a beautiful drawing, so that the
+children where you live can see exactly how all this is. That would be very useful to them if they
+were to travel some day.
+
+
+
+
+Sometimes,” he added, “there is no harm in putting off a piece of work until another day. But
+when it is a matter of baobabs, that always means a catastrophe.
+
+I knew a planet that was inhabited by a lazy man. He neglected three little bushes... So, as the
+little prince described it to me, I have made a drawing of that planet. I do not much like to take
+the tone of a moralist. But the danger of the baobabs is so little understood, and such considerable
+risks would be run by anyone who might get lost on an asteroid, that for once I am breaking
+through my reserve. “Children,” I say plainly, “watch out for the baobabs!” My friends, like
+myself, have been skirting this danger for a long time, without ever knowing it; and so it is for
+them that I have worked so hard over this drawing.
+
+The lesson which I pass on by this means is worth all the trouble it has cost me. Perhaps you will
+ask me, “Why are there no other drawing in this book as magnificent and impressive as this
+drawing of the baobabs?” The reply is simple. I have tried. But with the others I have not been
+successful. When I made the drawing of the baobabs I was carried beyond myself by the inspiring
+force of urgent necessity.
+
+Oh, little prince! Bit by bit I came to understand the secrets of your sad little life... For a long time
+you had found your only entertainment in the quiet pleasure of looking at the sunset.
+
+I learned that new detail on the morning of the fourth day, when you said to me:
+
+“I am very fond of sunsets. Come, let us go look at a sunset now.”
+
+“But we must wait,” I said.
+
+“Wait? For what?”
+
+“For the sunset. We must wait until it is time.”
+
+At first you seemed to be very much surprised. And then you laughed to yourself. You said to me:
+“I am always thinking that I am at home!”
+
+Just so. Everybody knows that when it is noon in the United States the sun is setting over France.
+If you could fly to France in one minute, you could go straight into the sunset, right from noon.
+Unfortunately, France is too far away for that. But on your tiny planet, my little prince, all you
+need do is move your chair a few steps. You can see the day end and the twilight falling whenever
+you like...
+
+“One day,” you said to me, “I saw the sunset forty-four times!”
+
+And a little later you added: “You know, one loves the sunset, when one is so sad...” “Were you so
+sad, then?” I asked, “on the day of the forty-four sunsets?”
+
+But the little prince made no reply.
+
+On the fifth day, again, as always, it was thanks to the sheep, the secret of the little prince’s life
+was revealed to me.
+
+Abruptly, without anything to lead up to it, and as if the question had been born of long and silent
+meditation on his problem, he demanded: “A sheep; if it eats little bushes, does it eat flowers,
+too?”
+
+
+
+
+“A sheep,” I answered, “eats anything it finds in its reach.”
+
+
+
+“Even flowers that have thorns?”
+
+“Yes, even flowers that have thorns.”
+
+“Then the thorns, what use are they?” I did not know.
+
+At that moment I was very busy trying to unscrew a bolt that had got stuck in my engine. I was
+very much worried, for it was becoming clear to me that the breakdown of my plane was
+extremely serious. And I had so little drinking water left that I had to fear for the worst.
+
+“The thorns, what use are they?”
+
+The little prince never let go of a question, once he had asked it. As for me, I was upset over that
+bolt. And I answered with the first thing that came into my head: “The thorns are of no use at all.
+Flowers have thorns just for spite!”
+
+“Oh!” There was a moment of complete silence.
+
+Then the little prince flashed back at me, with a kind of resentfulness: “I don’t believe you!
+Flowers are weak creatures. They are naive. They reassure themselves as best they can. They
+believe that their thorns are terrible weapons...”
+
+I did not answer. At that instant I was saying to myself: “If this bolt still won’t turn, I am going to
+knock it out with the hammer.”
+
+Again the little prince disturbed my thoughts. “And you actually believe that the flowers...”
+
+“Oh, no!” I cried. “No, no no! I don’t believe anything. I answered you with the first thing that
+came into my head. Don’t you see, I am very busy with matters of consequence!”
+
+He stared at me, thunderstruck. “Matters of consequence!”
+
+He looked at me there, with my hammer in my hand, my fingers black with engine grease, bending
+down over an object which seemed to him extremely ugly...
+
+“You talk just like the grown-ups!” That made me a little ashamed. But he went on, relentlessly:
+“You mix everything up together... You confuse everything...”
+
+He was really very angry. He tossed his golden curls in the breeze.
+
+“I know a planet where there is a certain red-faced gentleman. He has never smelled a flower. He
+has never looked at a star. He has never loved any one. He has never done anything in his life but
+add up figures. And all day he says over and over, just like you: ‘I am busy with matters of
+consequence!’ And that makes him swell up with pride.
+
+“But he is not a man, he is a mushroom!”
+
+
+
+“A what?”
+
+
+
+“A mushroom!” The little prince was now white with rage. “The flowers have been growing thorns
+for millions of years. For millions of years the sheep have been eating them just the same. And is
+it not a matter of consequence to try to understand why the flowers go to so much trouble to grow
+
+
+
+
+' '
+
+I \
+
+
+
+
+thorns, which are never of any use to them? Is the warfare between the sheep and the flowers not
+important? Is this not of more consequence than a fat red-faced gentleman’s sums? And if I know,
+I, myself, one flower which is unique in the world, which grows nowhere but on my planet, but
+which one little sheep can destroy in a single bite some morning, without even noticing what he is
+doing, Oh! You think that is not important! His face turned from white to red as he continued: “If
+some one loves a flower, of which just one single blossom grows in all the millions and millions of
+stars, it is enough to make him happy just to look at the stars.
+
+He can say to himself, ‘Somewhere, my flower is there...’ But if the sheep eats the flower, in one
+moment all his stars will be darkened... And you think that is not important!”
+
+He could not say anything more. His words were choked by sobbing. The night had fallen. I had
+let my tools drop from my hands. Of what moment now was my hammer, my bolt, or thirst, or
+death? On one star, one planet, my planet, the Earth, there was a little prince to be comforted. I
+took him in my arms, and rocked him. I said to him: “The flower that you love is not in danger. I
+will draw you a muzzle for your sheep. I will draw you a railing to put around your flower. I will...”
+
+I did not know what to say to him. I felt awkward and blundering. I did not know how I could reach
+him, where I could overtake him and go on hand in hand with him once more.
+
+It is such a secret place, the land of tears.
+
+I soon learned to know this flower better. On the little prince’s planet the flowers had always been
+very simple. They had only one ring of petals; they took up no room at all; they were a trouble to
+nobody. One morning they would appear in the grass, and by night they would have faded
+peacefully away. But one day, from a seed blown from no one knew where, a new flower had come
+up; and the little prince had watched very closely over this small sprout which was not like any
+other small sprouts on his planet.
+
+It might, you see, have been a new kind of baobab. The shrub soon stopped growing, and began to
+get ready to produce a flower. The little prince, who was present at the first appearance of a huge
+bud, felt at once that some sort of miraculous apparition must emerge from it. But the flower was
+not satisfied to complete the preparations for her beauty in the shelter of her green chamber. She
+
+
+
+chose her colours with the greatest care. She adjusted her petals one by one. She did not wish to
+go out into the world all rumpled, like the field poppies. It was only in the full radiance of her
+beauty that she wished to appear. Oh, yes! She was a coquettish creature! And her mysterious
+adornment lasted for days and days. Then one morning, exactly at sunrise, she suddenly showed
+herself. And, after working with all this painstaking precision, she yawned and said: “Ah! I am
+scarcely awake. I beg that you will excuse me. My petals are still all disarranged...” But the little
+prince could not restrain his admiration:
+
+“Oh! How beautiful you are!”
+
+“Am I not?” the flower responded, sweetly. “And I was born at the same moment as the sun...”
+
+The little prince could guess easily enough that she was not any too modest, but how moving, and
+exciting she was!
+
+“I think it is time for breakfast,” she added an instant later. “If you would have the kindness to
+think of my needs” And the little prince, completely abashed, went to look for a sprinkling can of
+fresh water.
+
+So, he tended the flower. So, too, she began very quickly to torment him with her vanity, which
+was, if the truth be known, a little difficult to deal with.
+
+One day, for instance, when she was speaking of her four thorns, she said to the little prince: “Let
+the tigers come with their claws!”
+
+“There are no tigers on my planet,” the little prince objected. “And, anyway, tigers do not eat
+weeds.”
+
+“I am not a weed,” the flower replied, sweetly. “Please excuse me...” “I am not at all afraid of
+tigers,” she went on, “but I have a horror of drafts. I suppose you wouldn’t screen for me?"
+
+“A horror of drafts, that is bad luck, for a plant,” remarked the little prince, and added to himself,
+“This flower is a very complex creature...”
+
+“At night I want you to put me under a glass globe. It is very cold where you live. In the place I
+came from...” But she interrupted herself at that point. She had come in the form of a seed. She
+could not have known anything of any other worlds.
+
+Embarrassed over having let herself be caught on the verge of such an untruth, she coughed two
+or three times, in order to put the little prince in the wrong.
+
+“The screen?”
+
+“I was just going to look for it when you spoke to me...”
+
+Then she forced her cough a little more so that he should suffer from remorse just the same. So
+the little prince, in spite of all the good will that was inseparable from his love, had soon come to
+doubt her. He had taken seriously words which were without importance, and it made him very
+unhappy.
+
+“I ought not to have listened to her,” he confided to me one day.
+
+“One never ought to listen to the flowers. One should simply look at them and breathe their
+
+
+
+
+fragrance. Mine perfumed all my planet. But I did not know how to take pleasure in all her grace.
+This tale of claws, which disturbed me so much, should only have filled my heart with tenderness
+and pity.”
+
+And he continued his confidences: “The fact is that I did not know how to understand anything! I
+ought to have judged by deeds and not by words. She cast her fragrance and her radiance over
+me. I ought never to have run away from her... I ought to have guessed all the affection that lay
+behind her poor little stratagems. Flowers are so inconsistent! But I was too young to know how to
+love her...”
+
+I believe that for his escape he took advantage of the migration of a flock of wild birds. On the
+morning of his departure he put his planet in perfect order. He carefully cleaned out his active
+volcanoes. He possessed two active volcanoes; and they were very convenient for heating his
+breakfast in the morning. He also had one volcano that was extinct. But, as he said, “One never
+knows!” So he cleaned out the extinct volcano, too. If they are well cleaned out, volcanoes burn
+slowly and steadily, without any eruptions. Volcanic eruptions are like fires in a chimney.
+
+On our earth we are obviously much too small to clean out our volcanoes. That is why they bring
+no end of trouble upon us. The little prince also pulled up, with a certain sense of dejection, the
+last little shoots of the baobabs. He believed that he would never want to return. But on this last
+morning all these familiar tasks seemed very precious to him. And when he watered the flower for
+the last time, and prepared to place her under the shelter of her glass globe, he realised that he
+was very close to tears. “Goodbye,” he said to the flower. But she made no answer. “Goodbye,”
+he said again. The flower coughed. But it was not because she had a cold.
+
+“I have been silly,” she said to him, at last. “I ask your forgiveness. Try to be happy...” He was
+surprised by this absence of reproaches. He stood there all bewildered, the glass globe held
+arrested in mid-air. He did not understand this quiet sweetness.
+
+“Of course I love you,” the flower said to him. “It is my fault that you have not known it all the
+while. That is of no importance. But you, you have been just as foolish as I. Try to be happy... let
+the glass globe be. I don’t want it any more.”
+
+“But the wind...” “My cold is not so bad as all that... the cool night air will do me good. I am a
+flower.”
+
+“But the animals...” “Well, I must endure the presence of two or three caterpillars if I wish to
+become acquainted with the butterflies. It seems that they are very beautiful. And if not the
+butterflies and the caterpillars who will call upon me? You will be far away... as for the large
+animals, I am not at all afraid of any of them. I have my claws.”
+
+And, naively, she showed her four thorns.
+
+Then she added: “Don’t linger like this. You have decided to go away. Now go!”
+
+For she did not want him to see her crying. She was such a proud flower...
+
+
+
+He found himself in the neighbourhood of the asteroids 325, 326, 327, 328, 329, and 330. He
+began, therefore, by visiting them, in order to add to his knowledge. The first of them was
+inhabited by a king. Clad in royal purple and ermine, he was seated upon a throne, which was at
+
+
+
+
+the same time both simple and majestic.
+
+
+
+“Ah! Here is a subject,” exclaimed the king, when he saw the little prince coming. And the little
+prince asked himself: “How could he recognise me when he had never seen me before?”
+
+He did not know how the world is simplified for kings. To them, all men are subjects. “Approach,
+so that I may see you better,” said the king, who felt consumingly proud of being at last a king
+over somebody.
+
+The little prince looked everywhere to find a place to sit down; but the entire planet was crammed
+and obstructed by the king’s magnificent ermine robe. So he remained standing upright, and, since
+he was tired, he yawned.
+
+“It is contrary to etiquette to yawn in the presence of a king,” the monarch said to him. “I forbid
+you to do so.”
+
+“I can’t help it. I can’t stop myself,” replied the little prince, thoroughly embarrassed.
+
+“I have come on a long journey, and I have had no sleep...”
+
+“Ah, then,” the king said. “I order you to yawn. It is years since I have seen anyone yawning.
+Yawns, to me, are objects of curiosity. Come, now! Yawn again! It is an order.”
+
+“That frightens me... I cannot, any more...” murmured the little prince, now completely abashed.
+
+“Hum! Hum!” replied the king. “Then I... I order you sometimes to yawn and sometimes to” He
+sputtered a little, and seemed vexed. For what the king fundamentally insisted upon was that his
+authority should be respected. He tolerated no disobedience. He was an absolute monarch. But,
+because he was a very good man, he made his orders reasonable.
+
+“If I ordered a general,” he would say, by way of example, “if I ordered a general to change
+himself into a sea bird, and if the general did not obey me, that would not be the fault of the
+general. It would be my fault.”
+
+“May I sit down?” came now a timid inquiry from the little prince. “I order you to do so,” the king
+answered him, and majestically gathered in a fold of his ermine mantle. But the little prince was
+wondering... The planet was tiny. Over what could this king really rule?
+
+“Sire,” he said to him, “I beg that you will excuse my asking you a question”
+
+“I order you to ask me a question,” the king hastened to assure him. “Sire, over what do you
+rule?” “Over everything,” said the king, with magnificent simplicity.
+
+“Over everything?” The king made a gesture, which took in his planet, the other planets, and all
+the stars. “Over all that?” asked the little prince. “Over all that,” the king answered. For his rule
+was not only absolute: it was also universal. “And the stars obey you?” “Certainly they do,” the
+king said. “They obey instantly. I do not permit insubordination.”
+
+Such power was a thing for the little prince to marvel at. If he had been master of such complete
+authority, he would have been able to watch the sunset, not forty-four times in one day, but
+seventy-two, or even a hundred, or even two hundred times, with out ever having to move his
+chair. And because he felt a bit sad as he remembered his little planet, which he had forsaken, he
+plucked up his courage to ask the king a favour:
+
+
+
+
+
+“I should like to see a sunset... do me that kindness... Order the sun to set...”
+
+“If I ordered a general to fly from one flower to another like a butterfly, or to write a tragic
+drama, or to change himself into a sea bird, and if the general did not carry out the order that he
+had received, which one of us would be in the wrong?” the king demanded. “The general, or
+myself?”
+
+“You,” said the little prince firmly.
+
+“Exactly. One much require from each one the duty which each one can perform,” the king went
+on. “Accepted authority rests first of all on reason. If you ordered your people to go and throw
+themselves into the sea, they would rise up in revolution. I have the right to require obedience
+because my orders are reasonable.”
+
+“Then my sunset?” the little prince reminded him: for he never forgot a question once he had
+asked it.
+
+“You shall have your sunset. I shall command it. But, according to my science of government, I
+shall wait until conditions are favourable.”
+
+“When will that be?” inquired the little prince. “Hum! Hum!” replied the king; and before saying
+anything else he consulted a bulky almanac. “Hum! Hum! That will be about... about... that will be
+this evening about twenty minutes to eight. And you will see how well I am obeyed.”
+
+The little prince yawned. He was regretting his lost sunset. And then, too, he was already
+beginning to be a little bored. “I have nothing more to do here,” he said to the king. “So I shall set
+out on my way again.” “Do not go,” said the king, who was very proud of having a subject. “Do
+not go. I will make you a Minister!” “Minister of what?” “Minster of...of Justice!” “But there is
+nobody here to judge!” “We do not know that,” the king said to him. “I have not yet made a
+complete tour of my kingdom. I am very old. There is no room here for a carriage. And it tires me
+to walk.” “Oh, but I have looked already!” said the little prince, turning around to give one more
+glance to the other side of the planet.
+
+On that side, as on this, there was nobody at all... “Then you shall judge yourself,” the king
+answered, “that is the most difficult thing of all. It is much more difficult to j udge oneself than to
+j udge others. If you succeed in j udging yourself rightly, then you are indeed a man of true
+wisdom.”
+
+
+
+“Yes,” said the little prince, “but I can judge myself anywhere. I do not need to live on this planet.
+“Hum! Hum!” said the king. “I have good reason to believe that somewhere on my planet there is
+an old rat. I hear him at night. You can judge this old rat. From time to time you will condemn him
+to death. Thus his life will depend on your j ustice. But you will pardon him on each occasion; for
+he must be treated thriftily. He is the only one we have.”
+
+“I,” replied the little prince, “do not like to condemn anyone to death. And now I think I will go on
+my way.” “No,” said the king. But the little prince, having now completed his preparations for
+departure, had no wish to grieve the old monarch. “If Your Majesty wishes to be promptly
+obeyed,” he said, “he should be able to give me a reasonable order. He should be able, for
+example, to order me to be gone by the end of one minute. It seems to me that conditions are
+favourable...” As the king made no answer, the little prince hesitated a moment.
+
+Then, with a sigh, he took his leave. “I made you my Ambassador,” the king called out, hastily.
+
+He had a magnificent air of authority.
+
+“The grown-ups are very strange,” the little prince said to himself, as he continued on his journey.
+The second planet was inhabited by a conceited man.
+
+
+
+
+
+
+
+
+
+
+“Ah! Ah! I am about to receive a visit from an admirer!” he exclaimed from afar, when he first
+saw the little prince coming. For, to conceited men, all other men are admirers.
+
+“Good morning,” said the little prince. “That is a queer hat you are wearing.”
+
+“It is a hat for salutes,” the conceited man replied. “It is to raise in salute when people acclaim
+me. Unfortunately, nobody at all ever passes this way.”
+
+“Yes?” said the little prince, who did not understand what the conceited man was talking about.
+
+“Clap your hands, one against the other,” the conceited man now directed him. The little prince
+clapped his hands. The conceited man raised his hat in a modest salute. “This is more entertaining
+than the visit to the king,” the little prince said to himself. And he began again to clap his hands,
+one against the other. The conceited man against raised his hat in salute. After five minutes of
+
+
+
+this exercise the little prince grew tired of the game’s monotony. “And what should one do to
+make the hat come down?” he asked. But the conceited man did not hear him. Conceited people
+never hear anything but praise.
+
+“Do you really admire me very much?” he demanded of the little prince. “What does that mean,
+‘admire’?”
+
+“To admire means that you regard me as the handsomest, the best-dressed, the richest, and the
+most intelligent man on this planet.” “But you are the only man on your planet!” “Do me this
+kindness. Admire me just the same.”
+
+“I admire you,” said the little prince, shrugging his shoulders slightly, “but what is there in that to
+interest you so much?”
+
+And the little prince went away. “The grown-ups are certainly very odd,” he said to himself, as he
+continued on his journey.
+
+The next planet was inhabited by a tippler.
+
+
+
+
+This was a very short visit, but it plunged the little prince into deep dejection. “What are you
+doing there?” he said to the tippler, whom he found settled down in silence before a collection of
+empty bottles and also a collection of full bottles.
+
+“I am drinking,” replied the tippler, with a lugubrious air.
+
+“Why are you drinking?” demanded the little prince.
+
+“So that I may forget,” replied the tippler. “Forget what?” inquired the little prince, who already
+was sorry for him.
+
+“Forget that I am ashamed,” the tippler confessed, hanging his head.
+
+“Ashamed of what?” insisted the little prince, who wanted to help him.
+
+“Ashamed of drinking!” The tippler brought his speech to an end, and shut himself up in an
+impregnable silence.
+
+And the little prince went away, puzzled. “The grown-ups are certainly very, very odd,” he said to
+himself, as he continued on his journey.
+
+The fourth planet belonged to a businessman.
+
+This man was so much occupied that he did not even raise his head at the little prince’s arrival.
+
+
+
+“Good morning,” the little prince said to him. “Your cigarette has gone out.”
+
+
+
+“Three and two make five. Five and seven make twelve. Twelve and three make fifteen. Good
+morning. Fifteen and seven make twenty-two. Twenty-two and six make twenty-eight. I haven’t
+time to light it again. Twenty-six and five make thirty-one. Phew ! Then that makes five-hundred-
+and-one-million, six-hundred-twenty-two-thousand, seven-hundred-thirty-one.”
+
+“Five hundred million what?” asked the little prince. “Eh? Are you still there? Five-hundred-and-
+one million, I can’t stop... I have so much to do! I am concerned with matters of consequence. I
+don’t amuse myself with balderdash. Two and five make seven...”
+
+“Five-hundred-and-one million what?” repeated the little prince, who never in his life had let go of
+a question once he had asked it.
+
+The businessman raised his head. “During the fifty-four years that I have inhabited this planet, I
+have been disturbed only three times. The first time was twenty-two years ago, when some giddy
+goose fell from goodness knows where. He made the most frightful noise that resounded all over
+the place, and I made four mistakes in my addition. The second time, eleven years ago, I was
+disturbed by an attack of rheumatism. I don’t get enough exercise. I have no time for loafing. The
+third time, well, this is it! I was saying, then, five -hundred-and-one millions”
+
+“Millions of what?” The businessman suddenly realised that there was no hope of being left in
+peace until he answered this question.
+
+“Millions of those little objects,” he said, “which one sometimes sees in the sky.” “Flies?” “Oh,
+no. Little glittering objects.” “Bees?” “Oh, no. Little golden objects that set lazy men to idle
+dreaming. As for me, I am concerned with matters of consequence. There is no time for idle
+dreaming in my life.” “Ah! You mean the stars?” “Yes, that’s it. The stars.” “And what do you do
+with five-hundred millions of stars?” “Five-hundred-and-one million, six-hundred-twenty-two
+thousand, seven-hundred-thirty-one. I am concerned with matters of consequence: I am
+accurate.”
+
+“And what do you do with these stars?” “What do I do with them?” “Yes.” “Nothing. I own them.”
+“You own the stars?” “Yes.” “But I have already seen a king who...” “Kings do not own, they
+reign over. It is a very different matter.”
+
+“And what good does it do you to own the stars?” “It does me the good of making me rich.”
+
+“And what good does it do you to be rich?”
+
+“It makes it possible for me to buy more stars, if any are ever discovered.”
+
+“This man,” the little prince said to himself, “reasons a little like my poor tippler...” Nevertheless,
+he still had some more questions. “How is it possible for one to own the stars?” “To whom do they
+belong?” the businessman retorted, peevishly. “I don’t know. To nobody.” “Then they belong to
+me, because I was the first person to think of it.” “Is that all that is necessary?” “Certainly.
+
+When you find a diamond that belongs to nobody, it is yours. When you discover an island that
+belongs to nobody, it is yours. When you get an idea before any one else, you take out a patent on
+it: it is yours. So with me: I own the stars, because nobody else before me ever thought of owning
+them.”
+
+“Yes, that is true,” said the little prince. “And what do you do with them?”
+
+
+
+
+“I administer them,” replied the businessman. “I count them and recount them. It is difficult. But I
+am a man who is naturally interested in matters of consequence.”
+
+The little prince was still not satisfied. “If I owned a silk scarf,” he said, “I could put it around my
+neck and take it away with me. If I owned a flower, I could pluck that flower and take it away with
+me. But you cannot pluck the stars from heaven...”
+
+“No. But I can put them in the bank.” “Whatever does that mean?” “That means that I write the
+number of my stars on a little paper. And then I put this paper in a drawer and lock it with a key.”
+
+“And that is all?”
+
+“That is enough,” said the businessman.
+
+“It is entertaining,” thought the little prince. “It is rather poetic. But it is of no great
+consequence.” On matters of consequence, the little prince had ideas, which were very different
+from those of the grown-ups.
+
+“I myself own a flower,” he continued his conversation with the businessman, “which I water
+every day. I own three volcanoes, which I clean out every week (for I also clean out the one that is
+extinct; one never knows). It is of some use to my volcanoes, and it is of some use to my flower,
+that I own them. But you are of no use to the stars...”
+
+The businessman opened his mouth, but he found nothing to say in answer. And the little prince
+went away. “The grown-ups are certainly altogether extraordinary,” he said simply, talking to
+himself as he continued on his journey.
+
+The fifth planet was very strange. It was the smallest of all. There was just enough room on it for
+a street lamp and a lamplighter.
+
+
+
+
+The little prince was not able to reach any explanation of the use of a street lamp and a
+lamplighter, somewhere in the heavens, on a planet, which had no people, and not one house.
+
+But he said to himself, nevertheless: “It may well be that this man is absurd. But he is not so
+absurd as the king, the conceited man, the businessman, and the tippler. For at least his work has
+
+
+
+some meaning. When he lights his street lamp, it is as if he brought one more star to life, or one
+flower. When he puts out his lamp, he sends the flower, or the star, to sleep. That is a beautiful
+occupation. And since it is beautiful, it is truly useful.”
+
+When he arrived on the planet he respectfully saluted the lamplighter.
+
+“Good morning. Why have you just put out your lamp?”
+
+“Those are the orders,” replied the lamplighter. “Good morning.”
+
+“What are the orders?”
+
+“The orders are that I put out my lamp. Good evening.” And he lighted his lamp again. “But why
+have you just lighted it again?”
+
+“Those are the orders,” replied the lamplighter.
+
+“I do not understand,” said the little prince.
+
+“There is nothing to understand,” said the lamplighter. “Orders are orders. Good morning.” And
+he put out his lamp.
+
+Then he mopped his forehead with a handkerchief decorated with red squares.
+
+“I follow a terrible profession. In the old days it was reasonable. I put the lamp out in the morning,
+and in the evening I lighted it again. I had the rest of the day for relaxation and the rest of the
+night for sleep.”
+
+“And the orders have been changed since that time?”
+
+“The orders have not been changed,” said the lamplighter. “That is the tragedy! From year to
+year the planet has turned more rapidly and the orders have not been changed!”
+
+“Then what?” asked the little prince.
+
+“Then the planet now makes a complete turn every minute, and I no longer have a single second
+for repose. Once every minute I have to light my lamp and put it out!”
+
+“That is very funny! A day lasts only one minute, here where you live!”
+
+“It is not funny at all!” said the lamplighter. “While we have been talking together a month has
+gone by.”
+
+“A month?”
+
+
+
+“Yes, a month. Thirty minutes. Thirty days. Good evening.” And he lighted his lamp again. As the
+little prince watched him, he felt that he loved this lamplighter who was so faithful to his orders.
+He remembered the sunsets, which he himself had gone to seek, in other days, merely by pulling
+up his chair; and he wanted to help his friend.
+
+“You know,” he said, “I can tell you a way you can rest whenever you want to...”
+
+“I always want to rest,” said the lamplighter. For it is possible for a man to be faithful and lazy at
+the same time.
+
+
+
+
+The little prince went on with his explanation: “Your planet is so small that three strides will take
+you all the way around it. To be always in the sunshine, you need only walk along rather slowly.
+When you want to rest, you will walk and the day will last as long as you like.”
+
+“That doesn’t do me much good,” said the lamplighter. “The one thing I love in life is to sleep.”
+
+“Then you’re unlucky,” said the little prince.
+
+“I am unlucky,” said the lamplighter. “Good morning.” And he put out his lamp.
+
+“That man,” said the little prince to himself, as he continued farther on his journey, “that man
+would be scorned by all the others: by the king, by the conceited man, by the tippler, by the
+businessman. Nevertheless he is the only one of them all who does not seem to me ridiculous.
+Perhaps that is because he is thinking of something else besides himself.”
+
+He breathed a sigh of regret, and said to himself, again: “That man is the only one of them all
+whom I could have made my friend. But his planet is indeed too small. There is no room on it for
+two people...” What the little prince did not dare confess was that he was sorry most of all to leave
+this planet, because it was blest every day with 1440 sunsets!
+
+The sixth planet was ten times larger than the last one. It was inhabited by an old gentleman who
+wrote voluminous books.
+
+
+
+
+“Oh, look! Here is an explorer!” he exclaimed to himself when he saw the little prince coming.
+
+The little prince sat down on the table and panted a little. He had already travelled so much and
+so far!
+
+“Where do you come from?” the old gentleman said to him.
+
+“What is that big book?” said the little prince. “What are you doing?”
+
+“I am a geographer,” the old gentleman said to him.
+
+“What is a geographer?” asked the little prince. “A geographer is a scholar who knows the
+location of all the seas, rivers, towns, mountains, and deserts.”
+
+“That is very interesting,” said the little prince. “Here at last is a man who has a real profession!”
+And he cast a look around him at the planet of the geographer.
+
+
+
+It was the most magnificent and stately planet that he had ever seen.
+
+“Your planet is very beautiful,” he said. “Has it any oceans?”
+
+“I couldn’t tell you,” said the geographer.
+
+“Ah!” The little prince was disappointed. “Has it any mountains?”
+
+“I couldn’t tell you,” said the geographer.
+
+“And towns, and rivers, and deserts?”
+
+“I couldn’t tell you that, either.”
+
+“But you are a geographer!”
+
+“Exactly,” the geographer said. “But I am not an explorer. I haven’t a single explorer on my
+planet. It is not the geographer who goes out to count the towns, the rivers, the mountains, the
+seas, the oceans, and the deserts. The geographer is much too important to go loafing about. He
+does not leave his desk. But he receives the explorers in his study. He asks them questions, and
+he notes down what they recall of their travels. And if the recollections of any one among them
+seem interesting to him, the geographer orders an inquiry into that explorer’s moral character.”
+
+“Why is that?”
+
+“Because an explorer who told lies would bring disaster on the books of the geographer. So would
+an explorer who drank too much.”
+
+“Why is that?” asked the little prince.
+
+“Because intoxicated men see double. Then the geographer would note down two mountains in a
+place where there was only one.”
+
+“I know some one,” said the little prince, “who would make a bad explorer.”
+
+“That is possible. Then, when the moral character of the explorer is shown to be good, an inquiry
+is ordered into his discovery.”
+
+“One goes to see it?”
+
+“No. That would be too complicated. But one requires the explorer to furnish proofs. For example,
+if the discovery in question is that of a large mountain, one requires that large stones be brought
+back from it.” The geographer was suddenly stirred to excitement. “But you come from far away!
+You are an explorer! You shall describe your planet to me!” And, having opened his big register,
+the geographer sharpened his pencil. The recitals of explorers are put down first in pencil. One
+waits until the explorer has furnished proofs, before putting them down in ink. “Well?” said the
+geographer expectantly.
+
+“Oh, where I live,” said the little prince, “it is not very interesting. It is all so small. I have three
+volcanoes. Two volcanoes are active and the other is extinct. But one never knows.”
+
+“One never knows,” said the geographer.
+
+
+
+“I have also a flower.”
+
+
+
+
+“We do not record flowers,” said the geographer.
+
+“Why is that? The flower is the most beautiful thing on my planet!”
+
+“We do not record them,” said the geographer, “because they are ephemeral.”
+
+“What does that mean ‘ephemeral’?”
+
+“Geographies,” said the geographer, “are the books which, of all books, are most concerned with
+matters of consequence. They never become old-fashioned. It is very rarely that a mountain
+changes its position. It is very rarely that an ocean empties itself of its waters. We write of eternal
+things.”
+
+“But extinct volcanoes may come to life again,” the little prince interrupted.
+
+“What does that mean ‘ephemeral’?”
+
+“Whether volcanoes are extinct or alive, it comes to the same thing for us,” said the geographer.
+“The thing that matters to us is the mountain. It does not change.”
+
+“But what does that mean ‘ephemeral’?” repeated the little prince, who never in his life had let go
+of a question, once he had asked it.
+
+“It means, ‘which is in danger of speedy disappearance.’ “
+
+“Is my flower in danger of speedy disappearance?”
+
+“Certainly it is.”
+
+“My flower is ephemeral,” the little prince said to himself, “and she has only four thorns to
+defend herself against the world. And I have left her on my planet, all alone!”
+
+That was his first moment of regret. But he took courage once more. “What place would you
+advise me to visit now?” he asked. “The planet Earth,” replied the geographer. “It has a good
+reputation.” And the little prince went away, thinking of his flower.
+
+
+
+
+So then the seventh planet was the Earth.
+
+The Earth is not just an ordinary planet!
+
+One can count, there 111 kings (not forgetting, to be sure, the Negro kings among them), 7000
+geographers, 900,000 businessmen, 7,500,000 tipplers, 311,000,000 conceited men, that is to say,
+about 2,000,000,000 grown-ups.
+
+To give you an idea of the size of the Earth, I will tell you that before the invention of electricity it
+was necessary to maintain, over the whole of the six continents, a veritable army of 462,511
+lamplighters for the street lamps. Seen from a slight distance, that would make a splendid
+spectacle.
+
+The movements of this army would be regulated like those of the ballet in the opera. First would
+come the turn of the lamplighters of New Zealand and Australia. Having set their lamps alight,
+these would go off to sleep. Next, the lamplighters of China and Siberia would enter for their steps
+in the dance, and then they too would be waved back into the wings. After that would come the
+turn of the lamplighters of Russia and the Indies; then those of Africa and Europe, then those of
+South America; then those of North America. And never would they make a mistake in the order
+of their entry upon the stage. It would be magnificent.
+
+Only the man who was in charge of the single lamp at the North Pole, and his colleague who was
+responsible for the single lamp at the South Pole, only these two would live free from toil and
+care: they would be busy twice a year.
+
+When one wishes to play the wit, he sometimes wanders a little from the truth.
+
+I have not been altogether honest in what I have told you about the lamplighters. And I realise
+that I run the risk of giving a false idea of our planet to those who do not know it.
+
+Men occupy a very small place upon the Earth. If the two billion inhabitants who people its
+surface were all to stand upright and somewhat crowded together, as they do for some big public
+assembly, they could easily be put into one public square twenty miles long and twenty miles wide.
+All humanity could be piled up on a small Pacific islet.
+
+The grown-ups, to be sure, will not believe you when you tell them that. They imagine that they fill
+a great deal of space. They fancy themselves as important as the baobabs. You should advise
+them, then, to make their own calculations. They adore figures, and that will please them. But do
+not waste your time on this extra task. It is unnecessary. You have, I know, confidence in me.
+
+When the little prince arrived on the Earth, he was very much surprised not to see any people. He
+was beginning to be afraid he had come to the wrong planet, when a coil of gold, the colour of the
+moonlight, flashed across the sand.
+
+“Good evening,” said the little prince courteously.
+
+“Good evening,” said the snake.
+
+“What planet is this on which I have come down?” asked the little prince.
+
+“This is the Earth; this is Africa,” the snake answered.
+
+“Ah! Then there are no people on the Earth?”
+
+
+
+
+“This is the desert. There are no people in the desert. The Earth is large,” said the snake.
+
+The little prince sat down on a stone, and raised his eyes toward the sky.
+
+“I wonder,” he said, “whether the stars are set alight in heaven so that one day each one of us
+may find his own again... Look at my planet. It is right there above us. But how far away it is!”
+
+“It is beautiful,” the snake said. “What has brought you here?”
+
+“I have been having some trouble with a flower,” said the little prince. “Ah!” said the snake. And
+they were both silent.
+
+“Where are the men?” the little prince at last took up the conversation again. “It is a little lonely
+in the desert...”
+
+“It is also lonely among men,” the snake said. The little prince gazed at him for a long time.
+
+“You are a funny animal,” he said at last. “You are no thicker than a finger...”
+
+“But I am more powerful than the finger of a king,” said the snake.
+
+The little prince smiled. “You are not very powerful. You haven’t even any feet. You cannot even
+travel...”
+
+“I can carry you farther than any ship could take you,” said the snake. He twined himself around
+the little prince’s ankle, like a golden bracelet.
+
+“Whomever I touch, I send back to the earth from whence he came,” the snake spoke again. “But
+you are innocent and true, and you come from a star...”
+
+The little prince made no reply. “You move me to pity, you are so weak on this Earth made of
+granite,” the snake said. “I can help you, some day, if you grow too homesick for your own planet.
+I can...”
+
+“Oh! I understand you very well,” said the little prince. “But why do you always speak in
+riddles?”
+
+“I solve them all,” said the snake. And they were both silent.
+
+The little prince crossed the desert and met with only one flower.
+
+It was a flower with three petals, a flower of no account at all.
+
+“Good morning,” said the little prince.
+
+“Good morning,” said the flower.
+
+“Where are the men?” the little prince asked, politely. The flower had once seen a caravan
+passing.
+
+“Men?” she echoed. “I think there are six or seven of them in existence. I saw them, several
+years ago. But one never knows where to find them. The wind blows them away. They have no
+roots, and that makes their life very difficult.”
+
+
+
+“Goodbye,” said the little prince.
+
+
+
+
+“Goodbye,” said the flower.
+
+
+
+After that, the little prince climbed a high mountain. The only mountains he had ever known were
+the three volcanoes, which came up to his knees. And he used the extinct volcano as a footstool.
+
+“From a mountain as high as this one,” he said to himself, “I shall be able to see the whole planet
+at one glance, and all the people...” But he saw nothing, save peaks of rock that were sharpened
+like needles.
+
+
+
+
+“Good morning,” he said courteously.
+
+“Good morning...Good morning...Good morning,” answered the echo.
+
+“Who are you?” said the little prince.
+
+“Who are you...Who are you...Who are you?” answered the echo.
+
+“Be my friends. I am all alone,” he said.
+
+“I am all alone...all alone. ..all alone,” answered the echo.
+
+“What a queer planet!” he thought. “It is altogether dry, and altogether pointed, and altogether
+harsh and forbidding. And the people have no imagination. They repeat whatever one says to
+them... On my planet I had a flower; she always was the first to speak...”
+
+But it happened that after walking for a long time through sand, and rocks, and snow, the little
+prince at last came upon a road. And all roads lead to the abodes of men.
+
+“Good morning,” he said. He was standing before a garden, all a-bloom with roses.
+
+“Good morning,” said the roses.
+
+The little prince gazed at them. They all looked like his flower.
+
+“Who are you?” he demanded, thunderstruck.
+
+“We are roses,” the roses said. And he was overcome with sadness. His flower had told him that
+she was the only one of her kind in all the universe. And here were five thousand of them, all
+alike, in one single garden!
+
+“She would be very much annoyed,” he said to himself, “if she should see that... she would cough
+
+
+
+most dreadfully, and she would pretend that she was dying, to avoid being laughed at. And I
+should be obliged to pretend that I was nursing her back to life, for if I did not do that, to humble
+myself also, she would really allow herself to die...”
+
+Then he went on with his reflections: “I thought that I was rich, with a flower that was unique in all
+the world; and all I had was a common rose. A common rose, and three volcanoes that come up to
+my knees — and one of them perhaps extinct forever... that doesn’t make me a very great
+prince...” And he lay down in the grass and cried.
+
+It was then that the fox appeared.
+
+“Good morning,” said the fox.
+
+“Good morning,” the little prince responded politely, although when he turned around he saw
+nothing.
+
+“I am right here,” the voice said, “under the apple tree.” “
+
+Who are you?” asked the little prince, and added, “You are very pretty to look at.”
+
+“I am a fox,” said the fox.
+
+“Come and play with me,” proposed the little prince.
+
+“I am so unhappy.” “I cannot play with you,” the fox said. “I am not tamed.”
+
+“Ah! Please excuse me,” said the little prince. But, after some thought, he added: “What does
+that mean, ‘tame’?”
+
+
+
+
+“You do not live here,” said the fox. “What is it that you are looking for?”
+
+“I am looking for men,” said the little prince. “What does that mean, ‘tame’?”
+
+“Men,” said the fox. “They have guns, and they hunt. It is very disturbing. They also raise
+chickens. These are their only interests. Are you looking for chickens?”
+
+“No,” said the little prince. “I am looking for friends. What does that mean, ‘tame’?”
+
+“It is an act too often neglected,” said the fox. It means to establish ties.”
+
+
+
+“‘To establish ties’?”
+
+
+
+“Just that,” said the fox. “To me, you are still nothing more than a little boy who is just like a
+hundred thousand other little boys. And I have no need of you. And you, on your part, have no
+need of me. To you, I am nothing more than a fox like a hundred thousand other foxes. But if you
+tame me, then we shall need each other. To me, you will be unique in all the world. To you, I shall
+be unique in all the world...”
+
+“I am beginning to understand,” said the little prince. “There is a flower... I think that she has
+tamed me...”
+
+“It is possible,” said the fox. “On the Earth one sees all sorts of things.”
+
+“Oh, but this is not on the Earth!” said the little prince. The fox seemed perplexed, and very
+curious.
+
+“On another planet?”
+
+“Yes.”
+
+“Are there hunters on this planet?”
+
+“No.”
+
+“Ah, that is interesting! Are there chickens?”
+
+“No.”
+
+“Nothing is perfect,” sighed the fox. But he came back to his idea. “My life is very monotonous,”
+the fox said. “I hunt chickens; men hunt me. All the chickens are just alike, and all the men are
+just alike. And, in consequence, I am a little bored. But if you tame me, it will be as if the sun
+came to shine on my life. I shall know the sound of a step that will be different from all the others.
+Other steps send me hurrying back underneath the ground. Yours will call me, like music, out of
+my burrow. And then look: you see the grain-fields down yonder? I do not eat bread. Wheat is of
+no use to me. The wheat fields have nothing to say to me. And that is sad. But you have hair that
+is the colour of gold. Think how wonderful that will be when you have tamed me! The grain, which
+is also golden, will bring me back the thought of you. And I shall love to listen to the wind in the
+wheat...” The fox gazed at the little prince, for a long time. “Please, tame me!” he said.
+
+“I want to, very much,” the little prince replied. “But I have not much time. I have friends to
+discover, and a great many things to understand.”
+
+“One only understands the things that one tames,” said the fox. “Men have no more time to
+understand anything. They buy things all ready-made at the shops. But there is no shop anywhere
+where one can buy friendship, and so men have no friends any more. If you want a friend, tame
+me...”
+
+“What must I do, to tame you?” asked the little prince.
+
+“You must be very patient,” replied the fox. “First you will sit down at a little distance from me,
+like that, in the grass. I shall look at you out of the corner of my eye, and you will say nothing.
+Words are the source of misunderstandings. But you will sit a little closer to me, every day...”
+
+
+
+
+The next day the little prince came back.
+
+
+
+“It would have been better to come back at the same hour,” said the fox. “If, for example, you
+come at four o’clock in the afternoon, then at three o’clock I shall begin to be happy. I shall feel
+happier and happier as the hour advances. At four o’clock, I shall already be worrying and
+jumping about. I shall show you how happy I am! But if you come at just any time, I shall never
+know at what hour my heart is to be ready to greet you... One must observe the proper rites...”
+
+“What is a rite?” asked the little prince.
+
+“Those also are actions too often neglected,” said the fox. “They are what make one day
+different from other days, one hour from other hours. There is a rite, for example, among my
+hunters. Every Thursday they dance with the village girls. So Thursday is a wonderful day for me!
+I can take a walk as far as the vineyards. But if the hunters danced at just any time, every day
+would be like every other day, and I should never have any vacation at all.”
+
+So the little prince tamed the fox. And when the hour of his departure drew near...
+
+“Ah,” said the fox, “I shall cry.”
+
+“It is your own fault,” said the little prince. “I never wished you any sort of harm; but you wanted
+me to tame you...”
+
+“Yes, that is so,” said the fox.
+
+“But now you are going to cry!” said the little prince.
+
+“Yes, that is so,” said the fox.
+
+“Then it has done you no good at all!”
+
+“It has done me good,” said the fox, “because of the colour of the wheat fields.” And then he
+added: “Go and look again at the roses. You will understand now that yours is unique in all the
+world. Then come back to say goodbye to me, and I will make you a present of a secret.”
+
+The little prince went away, to look again at the roses. “You are not at all like my rose,” he said.
+“As yet you are nothing. No one has tamed you, and you have tamed no one. You are like my fox
+when I first knew him. He was only a fox like a hundred thousand other foxes. But I have made
+him my friend, and now he is unique in all the world.” And the roses were very much embarrassed.
+“You are beautiful, but you are empty,” he went on. “One could not die for you. To be sure, an
+ordinary passer-by would think that my rose looked just like you, the rose that belongs to me. But
+in herself alone she is more important than all the hundreds of you other roses: because it is she
+that I have watered; because it is she that I have put under the glass globe; because it is she that
+I have sheltered behind the screen; because it is for her that I have killed the caterpillars (except
+the two or three that we saved to become butterflies); because it is she that I have listened to,
+when she grumbled, or boasted, or even sometimes when she said nothing. Because she is my
+rose.
+
+And he went back to meet the fox. “Goodbye,” he said.
+
+“Goodbye,” said the fox. “And now here is my secret, a very simple secret: It is only with the
+heart that one can see rightly; what is essential is invisible to the eye.”
+
+
+
+
+“What is essential is invisible to the eye,” the little prince repeated, so that he would be sure to
+remember.
+
+“It is the time you have wasted for your rose that makes your rose so important.”
+
+“It is the time I have wasted for my rose...” said the little prince, so that he would be sure to
+remember.
+
+“Men have forgotten this truth,” said the fox. “But you must not forget it. You become
+responsible, forever, for what you have tamed. You are responsible for your rose...”
+
+“I am responsible for my rose,” the little prince repeated, so that he would be sure to remember.
+
+“Good morning,” said the little prince.
+
+“Good morning,” said the railway switchman.
+
+“What do you do here?” the little prince asked.
+
+“I sort out travellers, in bundles of a thousand,” said the switchman. “I send off the trains that
+carry them; now to the right, now to the left.” And a brilliantly lighted express train shook the
+switchman’s cabin as it rushed by with a roar like thunder.
+
+“They are in a great hurry,” said the little prince. “What are they looking for?”
+
+“Not even the locomotive engineer knows that,” said the switchman. And a second brilliantly
+lighted express thundered by, in the opposite direction.
+
+“Are they coming back already?” demanded the little prince. “These are not the same ones,” said
+the switchman. “It is an exchange.”
+
+“Were they not satisfied where they were?” asked the little prince.
+
+“No one is ever satisfied where he is,” said the switchman. And they heard the roaring thunder of
+a third brilliantly lighted express.
+
+“Are they pursuing the first travellers?” demanded the little prince.
+
+“They are pursuing nothing at all,” said the switchman. “They are asleep in there, or if they are
+not asleep they are yawning. Only the children are flattening their noses against the
+windowpanes.”
+
+“Only the children know what they are looking for,” said the little prince.
+
+“They waste their time over a rag doll and it becomes very important to them; and if anybody
+takes it away from them, they cry...” “They are lucky,” the switchman said.
+
+“Good morning,” said the little prince.
+
+“Good morning,” said the merchant.
+
+This was a merchant who sold pills that had been invented to quench thirst. You need only swallow
+one pill a week, and you would feel no need of anything to drink.
+
+
+
+
+“Why are you selling those?” asked the little prince.
+
+
+
+“Because they save a tremendous amount of time,” said the merchant. “Computations have been
+made by experts. With these pills, you save fifty-three minutes in every week.”
+
+“And what do I do with those fifty-three minutes?”
+
+“Anything you like...”
+
+“As for me,” said the little prince to himself, “if I had fifty-three minutes to spend as I liked, I
+should walk at my leisure toward a spring of fresh water.”
+
+It was now the eighth day since I had had my accident in the desert, and I had listened to the story
+of the merchant as I was drinking the last drop of my water supply.
+
+“Ah,” I said to the little prince, “these memories of yours are very charming; but I have not yet
+succeeded in repairing my plane; I have nothing more to drink; and I, too, should be very happy if
+I could walk at my leisure toward a spring of fresh water!”
+
+“My friend the fox...” the little prince said to me.
+
+“My dear little man, this is no longer a matter that has anything to do with the fox!”
+
+“Why not?”
+
+“Because I am about to die of thirst...”
+
+He did not follow my reasoning, and he answered me: “It is a good thing to have had a friend,
+even if one is about to die. I, for instance, am very glad to have had a fox as a friend...”
+
+“He has no way of guessing the danger,” I said to myself. “He has never been either hungry or
+thirsty. A little sunshine is all he needs...”
+
+But he looked at me steadily, and replied to my thought: “I am thirsty, too. Let us look for a
+well...” I made a gesture of weariness. It is absurd to look for a well, at random, in the immensity
+of the desert. But nevertheless we started walking.
+
+When we had trudged along for several hours, in silence, the darkness fell, and the stars began to
+come out. Thirst had made me a little feverish, and I looked at them as if I were in a dream. The
+little prince’s last words came reeling back into my memory: “Then you are thirsty, too?” I
+demanded. But he did not reply to my question. He merely said to me: “Water may also be good
+for the heart...”
+
+I did not understand this answer, but I said nothing. I knew very well that it was impossible to
+cross-examine him. He was tired. He sat down. I sat down beside him. And, after a little silence,
+he spoke again: “The stars are beautiful, because of a flower that cannot be seen.”
+
+I replied, “Yes, that is so.” And, without saying anything more, I looked across the ridges of sand
+that were stretched out before us in the moonlight.
+
+“The desert is beautiful,” the little prince added.
+
+And that was true. I have always loved the desert. One sits down on a desert sand dune, sees
+
+
+
+
+
+nothing, hears nothing. Yet through the silence something throbs, and gleams...
+
+“What makes the desert beautiful,” said the little prince, “is that somewhere it hides a well...”
+
+I was astonished by a sudden understanding of that mysterious radiation of the sands. When I was
+a little boy I lived in an old house, and legend told us that a treasure was buried there. To be sure,
+no one had ever known how to find it; perhaps no one had ever even looked for it. But it cast an
+enchantment over that house. My home was hiding a secret in the depths of its heart... “Yes,” I
+said to the little prince. “The house, the stars, the desert — what gives them their beauty is
+something that is invisible!”
+
+“I am glad,” he said, “that you agree with my fox.” As the little prince dropped off to sleep, I took
+him in my arms and set out walking once more. I felt deeply moved, and stirred. It seemed to me
+that I was carrying a very fragile treasure. It seemed to me, even, that there was nothing more
+fragile on all Earth. In the moonlight I looked at his pale forehead, his closed eyes, his locks of
+hair that trembled in the wind, and I said to myself:
+
+“What I see here is nothing but a shell. What is most important is invisible...”
+
+As his lips opened slightly with the suspicious of a half-smile, I said to myself, again: “What
+moves me so deeply, about this little prince who is sleeping here, is his loyalty to a flower — the
+image of a rose that shines through his whole being like the flame of a lamp, even when he is
+asleep...”
+
+And I felt him to be more fragile still. I felt the need of protecting him, as if he himself were a
+flame that might be extinguished by a little puff of wind... And, as I walked on so, I found the well,
+at daybreak.
+
+“Men,” said the little prince, “set out on their way in express trains, but they do not know what
+they are looking for. Then they rush about, and get excited, and turn round and round...” And he
+added: “It is not worth the trouble...”
+
+
+
+The well that we had come to was not like the wells of the Sahara. The wells of the Sahara are
+mere holes dug in the sand. This one was like a well in a village. But there was no village here,
+and I thought I must be dreaming...
+
+“It is strange,” I said to the little prince. “Everything is ready for use: the pulley, the bucket, the
+rope...” He laughed, touched the rope, and set the pulley to working. And the pulley moaned, like
+an old weathervane, which the wind has long since forgotten.
+
+“Do you hear?” said the little prince. “We have wakened the well, and it is singing...”
+
+I did not want him to tire himself with the rope.
+
+“Leave it to me,” I said. “It is too heavy for you.” I hoisted the bucket slowly to the edge of the
+well and set it there, happy, tired as I was, over my achievement. The song of the pulley was still
+in my ears, and I could see the sunlight shimmer in the still trembling water.
+
+“I am thirsty for this water,” said the little prince. “Give me some of it to drink...”
+
+And I understood what he had been looking for. I raised the bucket to his lips. He drank, his eyes
+closed. It was as sweet as some special festival treat. This water was indeed a different thing from
+ordinary nourishment. Its sweetness was born of the walk under the stars, the song of the pulley,
+the effort of my arms. It was good for the heart, like a present. When I was a little boy, the lights
+of the Christmas tree, the music of the Midnight Mass, the tenderness of smiling faces, used to
+make up, so, the radiance of the gifts I received.
+
+“The men where you live,” said the little prince, “raise five thousand roses in the same garden
+and they do not find in it what they are looking for.”
+
+“They do not find it,” I replied.
+
+“And yet what they are looking for could be found in one single rose, or in a little water.”
+
+“Yes, that is true,” I said.
+
+And the little prince added: “But the eyes are blind. One must look with the heart...”
+
+I had drunk the water. I breathed easily. At sunrise the sand is the colour of honey. And that
+honey colour was making me happy, too. What brought me, then, this sense of grief?
+
+“You must keep your promise,” said the little prince, softly, as he sat down beside me once more.
+“What promise?” “You know, a muzzle for my sheep... I am responsible for this flower...”
+
+I took my rough drafts of drawings out of my pocket. The little prince looked them over, and
+laughed as he said:
+
+“Your baobabs, they look a little like cabbages.”
+
+“Oh!” I had been so proud of my baobabs! “Your fox, his ears look a little like horns; and they are
+too long.” And he laughed again.
+
+“You are not fair, little prince,” I said. “I don’t know how to draw anything except boa constrictors
+from the outside and boa constrictors from the inside.”
+
+
+
+
+
+“Oh, that will be all right,” he said, “children understand.”
+
+So then I made a pencil sketch of a muzzle. And as I gave it to him my heart was torn.
+
+“You have plans that I do not know about,” I said. But he did not answer me. He said to me,
+instead: “You know, my descent to the earth... Tomorrow will be its anniversary.” Then, after a
+silence, he went on: “I came down very near here.” And he flushed.
+
+And once again, without understanding why, I had a queer sense of sorrow. One question,
+however, occurred to me: “Then it was not by chance that on the morning when I first met you — a
+week ago — you were strolling along like that, all alone, a thousand miles from any inhabited
+region? You were on the your way back to the place where you landed?”
+
+The little prince flushed again. And I added, with some hesitancy: “Perhaps it was because of the
+anniversary?” The little prince flushed once more. He never answered questions, but when one
+flushes does that not mean “Yes”?
+
+“Ah,” I said to him, “I am a little frightened...”
+
+But he interrupted me. “Now you must work. You must return to your engine. I will be waiting for
+you here. Come back tomorrow evening...”
+
+But I was not reassured. I remembered the fox. One runs the risk of weeping a little, if one lets
+himself be tamed...
+
+Beside the well there was the ruin of an old stone wall. When I came back from my work, the next
+evening, I saw from some distance away my little prince sitting on top of a wall, with his feet
+dangling. And I heard him say: “Then you don’t remember. This is not the exact spot.” Another
+voice must have answered him, for he replied to it: “Yes, yes! It is the right day, but this is not the
+place.”
+
+I continued my walk toward the wall. At no time did I see or hear anyone. The little prince,
+however, replied once again: “...Exactly. You will see where my track begins, in the sand. You have
+nothing to do but wait for me there. I shall be there tonight.”
+
+
+
+I was only twenty metres from the wall, and I still saw nothing. After a silence the little prince
+spoke again: “You have good poison? You are sure that it will not make me suffer too long?” I
+stopped in my tracks, my heart torn asunder; but still I did not understand. “Now go away,” said
+the little prince. “I want to get down from the wall.”
+
+I dropped my eyes, then, to the foot of the wall... and I leaped into the air. There before me, facing
+the little prince, was one of those yellow snakes that take just thirty seconds to bring your life to
+an end. Even as I was digging into my pocked to get out my revolver I made a running step back.
+But, at the noise I made, the snake let himself flow easily across the sand like the dying spray of
+a fountain, and, in no apparent hurry, disappeared, with a light metallic sound, among the stones. I
+reached the wall just in time to catch my little man in my arms; his face was white as snow.
+
+“What does this mean?” I demanded. “Why are you talking with snakes?”
+
+I had loosened the golden muffler that he always wore. I had moistened his temples, and had
+given him some water to drink. And now I did not dare ask him any more questions. He looked at
+me very gravely, and put his arms around my neck. I felt his heart beating like the heart of a
+dying bird, shot with someone’s rifle...
+
+“I am glad that you have found what was the matter with your engine,” he said. “Now you can go
+back home”
+
+“How do you know about that?” I was just coming to tell him that my work had been successful,
+beyond anything that I had dared to hope.
+
+He made no answer to my question, but he added: “I, too, am going back home today...” Then,
+sadly, “It is much farther... it is much more difficult...” I realised clearly that something
+extraordinary was happening. I was holding him close in my arms as if he were a little child; and
+yet it seemed to me that he was rushing headlong toward an abyss from which I could do nothing
+to restrain him... His look was very serious, like some one lost far away.
+
+“I have your sheep. And I have the sheep’s box. And I have the muzzle...”
+
+And he gave me a sad smile. I waited a long time. I could see that he was reviving little by little.
+
+“Dear little man,” I said to him, “you are afraid...” He was afraid, there was no doubt about that.
+But he laughed lightly.
+
+“I shall be much more afraid this evening...”
+
+Once again I felt myself frozen by the sense of something irreparable. And I knew that I could not
+bear the thought of never hearing that laughter any more. For me, it was like a spring of fresh
+water in the desert.
+
+“Little man,” I said, “I want to hear you laugh again.” But he said to me: “Tonight, it will be a
+year... my star, then, can be found right above the place where I came to the Earth, a year ago...”
+
+“Little man,” I said, “tell me that it is only a bad dream, this affair of the snake, and the meeting-
+place, and the star...” But he did not answer my plea.
+
+He said to me, instead: “The thing that is important is the thing that is not seen...” “Yes, I
+know...”
+
+
+
+
+“It is just as it is with the flower. If you love a flower that lives on a star, it is sweet to look at the
+sky at night. All the stars are a-bloom with flowers...”
+
+“Yes, I know...”
+
+“It is just as it is with the water. Because of the pulley, and the rope, what you gave me to drink
+was like music. You remember, how good it was.”
+
+“Yes, I know...”
+
+“And at night you will look up at the stars. Where I live everything is so small that I cannot show
+you where my star is to be found. It is better, like that. My star will just be one of the stars, for
+you. And so you will love to watch all the stars in the heavens... they will all be your friends. And,
+besides, I am going to make you a present...” He laughed again.
+
+“Ah, little prince, dear little prince! I love to hear that laughter!”
+
+“That is my present. Just that. It will be as it was when we drank the water...”
+
+“What are you trying to say?”
+
+“All men have the stars,” he answered, “but they are not the same things for different people. For
+some, who are travellers, the stars are guides. For others they are no more than little lights in the
+sky. For others, who are scholars, they are problems. For my businessman they were wealth. But
+all these stars are silent. You, you alone, will have the stars as no one else has them”
+
+“What are you trying to say?”
+
+“In one of the stars I shall be living. In one of them I shall be laughing. And so it will be as if all
+the stars were laughing, when you look at the sky at night... you, only you, will have stars that can
+laugh!”
+
+And he laughed again. “And when your sorrow is comforted (time soothes all sorrows) you will be
+content that you have known me. You will always be my friend. You will want to laugh with me. And
+you will sometimes open your window, so, for that pleasure... and your friends will be properly
+astonished to see you laughing as you look up at the sky! Then you will say to them, ‘Yes, the
+stars always make me laugh!’ And they will think you are crazy. It will be a very shabby trick that
+I shall have played on you...”
+
+And he laughed again. “It will be as if, in place of the stars, I had given you a great number of
+little bells that knew how to laugh...”
+
+And he laughed again. Then he quickly became serious: “Tonight, you know... do not come,” said
+the little prince.
+
+“I shall not leave you,” I said.
+
+“I shall look as if I were suffering. I shall look a little as if I were dying. It is like that. Do not
+come to see that. It is not worth the trouble...”
+
+“I shall not leave you.”
+
+
+
+But he was worried. “I tell you, it is also because of the snake. He must not bite you. Snakes, they
+
+
+
+
+are malicious creatures. This one might bite you just for fun...”
+
+
+
+“I shall not leave you.”
+
+But a thought came to reassure him: “It is true that they have no more poison for a second bite.”
+
+That night I did not see him set out on his way. He got away from me without making a sound.
+When I succeeded in catching up with him he was walking along with a quick and resolute step. He
+said to me merely: “Ah! You are there...” And he took me by the hand. But he was still worrying.
+“It was wrong of you to come. You will suffer. I shall look as if I were dead; and that will not be
+true...”
+
+I said nothing.
+
+“You understand... it is too far. I cannot carry this body with me. It is too heavy.”
+
+I said nothing.
+
+“But it will be like an old abandoned shell. There is nothing sad about old shells...”
+
+I said nothing. He was a little discouraged. But he made one more effort: “You know, it will be
+very nice. I, too, shall look at the stars. All the stars will be wells with a rusty pulley. All the stars
+will pour out fresh water for me to drink...”
+
+I said nothing.
+
+“That will be so amusing! You will have five hundred million little bells, and I shall have five
+hundred million springs of fresh water...” And he too said nothing more, because he was crying...
+
+“Here it is. Let me go on by myself.” And he sat down, because he was afraid. Then he said,
+again: “You know, my flower... I am responsible for her. And she is so weak! She has four thorns,
+of no use at all, to protect herself against all the world...”
+
+I too sat down, because I was not able to stand up any longer. “There now, that is all...”
+
+He still hesitated a little; then he got up. He took one step. I could not move. There was nothing
+but a flash of yellow close to his ankle. He remained motionless for an instant. He did not cry out.
+He fell as gently as a tree falls. There was not even any sound, because of the sand.
+
+And now six years have already gone by... I have never yet told this story.
+
+The companions who met me on my return were well content to see me alive. I was sad, but I told
+them: “I am tired.” Now my sorrow is comforted a little. That is to say, not entirely. But I know
+that he did go back to his planet, because I did not find his body at daybreak. It was not such a
+heavy body... and at night I love to listen to the stars. It is like five hundred million little bells...
+But there is one extraordinary thing... when I drew the muzzle for the little prince, I forgot to add
+the leather strap to it. He will never have been able to fasten it on his sheep.
+
+So now I keep wondering: what is happening on his planet? Perhaps the sheep has eaten the
+flower... At one time I say to myself: “Surely not! The little prince shuts his flower under her glass
+globe every night, and he watches over his sheep very carefully...” Then I am happy. And there is
+sweetness in the laughter of all the stars.
+
+
+
+
+But at another time I say to myself: “At some moment or other one is absent-minded, and that is
+enough! On some one evening he forgot the glass globe, or the sheep got out, without making any
+noise, in the night...” And then the little bells are changed to tears... Here, then, is a great
+mystery.
+
+For you who also love the little prince, and for me, nothing in the universe can be the same if
+somewhere, we do not know where, a sheep that we never saw has eaten a rose... Look up at the
+sky. Ask yourselves: is it yes or no?
+
+Has the sheep eaten the flower? And you will see how everything changes... And no grown-up will
+ever understand that this is a matter of so much importance! This is, to me, the loveliest and
+saddest landscape in the world. It is the same as that on the preceding page, but I have drawn it
+again to impress it on your memory. It is here that the little prince appeared on Earth, and
+disappeared. Look at it carefully so that you will be sure to recognise it in case you travel some
+day to the African desert. And, if you should come upon this spot, please do not hurry on. Wait for
+a time, exactly under the star. Then, if a little man appears who laughs, who has golden hair and
+who refuses to answer questions, you will know who he is. If this should happen, please comfort
+me. Send me word that he has come back.
+
+
+
+END

+ 12391 - 0
libs/harfbuzz/perf/texts/en-words.txt

@@ -0,0 +1,12391 @@
+a
+A
+aa
+AA
+aaa
+AAA
+aaae
+AAAu
+AAB
+AAC
+aacute
+Aacute
+Aacutesmall
+AAD
+aae
+AAE
+aaf
+AAF
+aalt
+aao
+aarch
+Aari
+aat
+AAT
+aatFeatureType
+AAu
+ab
+AB
+Abaza
+abb
+ABBREV
+abc
+ABC
+abcde
+abcdefghijklmnopqrstuvwxyz
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+ABD
+ABE
+ABEu
+ABF
+ABFu
+abh
+ABI
+ability
+Abkhazian
+able
+Aboriginal
+ABORIGINAL
+abort
+about
+above
+Above
+ABOVE
+abq
+abs
+absolute
+absolutely
+absorb
+abstraction
+abstractions
+ABu
+abuse
+abv
+ABVF
+abvm
+abvs
+ABVS
+ABx
+ABxCD
+ABxD
+ac
+AC
+acb
+ACBu
+acc
+ACC
+accel
+Accelerate
+accelerator
+ACCELERATOR
+accels
+accent
+ACCENT
+accents
+accept
+acceptable
+accepted
+accepting
+accepts
+access
+Access
+accessed
+accessible
+accessing
+accessors
+accommodate
+Accommodate
+accompanying
+accomplish
+according
+According
+account
+accounting
+ACCu
+accumulate
+Accumulate
+accuracy
+accurate
+AccuT
+ACDu
+acf
+ach
+Achi
+achieve
+Acholi
+achung
+achVendID
+acircumflex
+Acircumflex
+Acircumflexsmall
+ack
+acm
+Acoli
+acom
+acq
+ACQ
+acquire
+ACQUIRE
+acr
+across
+act
+action
+Action
+ACTION
+actionable
+actionClass
+actionData
+actionLength
+actions
+Actions
+ActionSubrecord
+ActionSubrecordHeader
+actionType
+ActionType
+activated
+activates
+active
+acts
+actual
+Actual
+actualGlyphsCount
+actually
+ACu
+acute
+Acutesmall
+acw
+acx
+acy
+ad
+AD
+ada
+Adamawa
+Adangme
+Adap
+adapt
+Adapted
+Adaptors
+aData
+adb
+ADBu
+add
+Add
+addcnt
+added
+AddFontMemResourceEx
+addGlyph
+adding
+Adding
+addition
+Addition
+additional
+Additional
+additionalCount
+additions
+addr
+AddRef
+address
+addressof
+adds
+ADDu
+Adeni
+adequate
+adf
+adieresis
+Adieresis
+Adieresissmall
+Adilabad
+adjacent
+Adjacent
+adjust
+Adjust
+adjusted
+adjustment
+adjustments
+Adjusts
+ADL
+Adlam
+ADLAM
+adobe
+Adobe
+adopt
+Adopted
+adorned
+adp
+ADu
+adv
+advance
+Advance
+Advanced
+advanceMax
+advanceMeasurement
+advanceOffset
+advances
+ADVANCES
+Advancing
+advantage
+ADVISED
+advMap
+ady
+Adyghe
+ae
+AE
+aea
+aeaf
+aeb
+aec
+AEDu
+AEEu
+AEFu
+Aegean
+AEsmall
+AEu
+af
+AF
+afa
+afadd
+Afar
+AFAu
+afb
+AFBAu
+AFBu
+AFDKO
+AFEu
+AFF
+affect
+affected
+affecting
+affects
+affinity
+Afghanistan
+Africa
+Afrikaans
+after
+After
+AFTER
+afterGrowLimit
+afterShrinkLimit
+AFu
+AG
+again
+against
+Agaw
+Agfa
+agnostic
+agrave
+Agrave
+Agravesmall
+agree
+agreement
+ahead
+Aheri
+ahg
+Ahom
+AHOM
+aht
+Ahtena
+ai
+AI
+aii
+AIN
+aio
+Aiton
+aiw
+AIX
+ajp
+ak
+aka
+AKA
+Akan
+AKAT
+AKHN
+alaph
+ALAPH
+alas
+Alaska
+Alaskan
+Albania
+Albanian
+ALBANIAN
+Albay
+alef
+Alef
+ALEF
+Algeria
+Algerian
+algorithm
+Algorithm
+algorithmic
+algorithms
+Algorithms
+algs
+ALGS
+alias
+aliased
+aliases
+aliasing
+align
+aligned
+alignment
+alignof
+aligns
+alive
+all
+All
+ALL
+ALLAH
+AllDirections
+Allison
+alloc
+Alloc
+allocate
+Allocate
+ALLOCATE
+allocated
+allocates
+allocating
+allocation
+Allocation
+allocations
+Allocations
+allocator
+allow
+Allow
+allowed
+allowing
+allows
+almost
+aln
+alone
+along
+alpha
+Alpha
+alphabet
+Alphabet
+alphabetic
+Alphabetic
+alphabetical
+alphabetically
+Alphanumeric
+Alphanumerics
+already
+als
+Alsatian
+also
+Also
+alt
+ALT
+Altai
+alter
+alternate
+Alternate
+ALTERNATE
+alternates
+ALTERNATES
+alternateSet
+AlternateSet
+AlternateSubst
+AlternateSubstFormat
+alternative
+Alternatively
+ALTERNATIVES
+although
+Although
+alts
+always
+Always
+am
+AM
+ambiguity
+ambiguous
+Ambo
+Amend
+American
+Americanist
+amf
+Amharic
+among
+amongst
+amount
+Amoy
+amp
+ampersand
+ampersandsmall
+amw
+an
+An
+AN
+Ana
+analysis
+Analysis
+ANALYSIS
+analyze
+Analyze
+analyzer
+Analyzer
+analyzers
+Analyzes
+AnalyzeScript
+ANATOLIAN
+Ancash
+anchor
+Anchor
+anchorData
+anchored
+AnchorFormat
+AnchorMatrix
+anchorPoint
+anchors
+Ancient
+and
+And
+AND
+android
+Android
+ANDROID
+ang
+angle
+Angle
+ANGLE
+Anglo
+ankr
+ANKR
+ankrActionIndex
+ankrData
+annex
+annotate
+Annotated
+annotation
+ANNOTATION
+annotations
+another
+Another
+Ansi
+Antankarana
+Antillean
+any
+Any
+ANY
+anymore
+anything
+Anything
+anyway
+ap
+Apache
+apc
+apd
+Api
+API
+apis
+APIs
+apj
+apk
+apl
+apm
+APP
+Apparently
+appear
+appearance
+appearing
+append
+Append
+APPEND
+appended
+appending
+Appendix
+AppendixF
+Appends
+Appl
+APPL
+apple
+Apple
+APPLE
+AppleColorEmoji
+applicable
+Applicable
+APPLICABLE
+application
+applications
+Applications
+ApplicationServices
+applied
+applies
+apply
+Apply
+APPLY
+applying
+Applying
+approach
+approaches
+appropriate
+approxequal
+approximate
+appveyor
+April
+apt
+Apurímac
+apw
+AQ
+ar
+Arabia
+ARABIAN
+arabic
+Arabic
+ARABIC
+ArabicShaping
+Aragonese
+Arakanese
+Arakwal
+Aramaic
+ARAMAIC
+arb
+Arbëreshë
+arbitrarily
+arbitrary
+ARC
+Archaic
+architecturally
+archive
+archives
+are
+ARE
+area
+Area
+Arequipa
+arg
+ARG
+Argentina
+Argh
+args
+ARGS
+argStack
+argument
+arguments
+aring
+Aring
+Aringsmall
+ARISING
+arith
+arithmetic
+Ariza
+armcc
+Armenia
+Armenian
+ARMENIAN
+arn
+Aromanian
+around
+arounds
+Arpitan
+arq
+arr
+arranged
+array
+Array
+ARRAY
+ArrayOf
+ArrayOfM
+arrays
+arrayZ
+arrive
+Arrows
+ars
+Arsi
+articles
+Arvanitika
+ary
+arz
+as
+As
+AS
+Asat
+ascender
+ASCENDER
+ascenderOffset
+ascending
+ascent
+ASCENT
+ascii
+ASCII
+asciicircum
+asciitilde
+Asho
+Asian
+aSize
+asked
+Asking
+Asmall
+Asomtavruli
+aspect
+aspects
+aspx
+Assamese
+assembly
+assert
+ASSERT
+assertion
+ASSERTION
+assign
+Assign
+ASSIGN
+assignable
+assigned
+assigns
+assistance
+assisted
+associated
+associates
+associating
+Association
+assume
+Assume
+assumed
+Assumed
+assuming
+Assuming
+assumption
+Assumption
+Assyrian
+ast
+asterisk
+ASTERISK
+Asturian
+asuperior
+at
+At
+atexit
+ATEXIT
+aTextPosition
+ath
+Athapascan
+Athapaskan
+Atikamekw
+atilde
+Atilde
+Atildesmall
+atj
+Atlas
+atleast
+ATLEAST
+atomic
+Atomic
+ATOMIC
+Atomically
+atomics
+atsFont
+ATSFontGetFileReference
+ATSFontRef
+attach
+Attach
+ATTACH
+attached
+ATTACHED
+attaches
+attaching
+attachList
+AttachList
+attachment
+Attachment
+ATTACHMENT
+attachments
+attachPoint
+AttachPoint
+attempt
+attempted
+attempts
+Attempts
+attr
+ATTR
+attractive
+attrib
+attribute
+ATTRIBUTE
+attributed
+attributes
+Attributes
+attrs
+atv
+au
+Au
+AU
+audiences
+augmented
+Australia
+Austria
+Author
+AUTHOR
+authors
+auto
+AUTO
+autoconf
+autogen
+automake
+automatic
+Automatic
+automatically
+auxiliary
+Auxiliary
+auz
+av
+AV
+Avagraha
+AVAGRAHA
+avail
+Availability
+AvailabilityMacros
+available
+avar
+Avar
+AVAR
+Avaric
+AVESTAN
+avl
+avoid
+Avoid
+avoided
+avoiding
+avoids
+aw
+awa
+Awa
+Awadhi
+aware
+away
+awful
+ax
+Ax
+AxCD
+AxD
+axes
+axesZ
+axis
+Axis
+AXIS
+axisCount
+axisIndex
+axisNameID
+AxisRecord
+axisSize
+axisTag
+AxisValue
+axisValueCount
+AxisValueFormat
+AxisValueMap
+AxisValueRecord
+axisValues
+ay
+Ayacucho
+ayc
+ayh
+AYIN
+ayl
+Aymara
+ayn
+ayp
+ayr
+az
+azb
+Azerbaijan
+Azerbaijani
+Azeri
+azj
+b
+B
+ba
+BA
+Babalia
+Babine
+BABu
+Bacanese
+back
+backend
+backends
+background
+Background
+BACKGROUND
+backing
+backslash
+backtrack
+backtrackClassDef
+backtrackCount
+backtracking
+backward
+BACKWARD
+backwards
+Backwards
+bad
+Badaga
+badly
+BADLY
+bae
+BAEu
+BAFu
+Bagheli
+Baghelkhandi
+Bagirmi
+Bagri
+Baharna
+Bahrain
+bai
+bail
+Bakhtiari
+bal
+Balanta
+Balante
+Balinese
+BALINESE
+Balkan
+Balkar
+Balochi
+Balti
+Baltic
+Baluchi
+Bamanankan
+Bambara
+Bamileke
+BAMUM
+ban
+Banda
+Bandjalang
+Bangka
+Bangladesh
+Bangun
+Banjar
+Banna
+Baoulé
+bar
+Bara
+BARREE
+barrier
+Barrier
+bars
+Bas
+base
+Base
+BASE
+baseArray
+BaseArray
+BaseCoord
+BaseCoordFormat
+baseCoords
+baseCoverage
+BaseCoverage
+based
+Based
+BaseFontBlend
+baseFontName
+BaseFontName
+BaseGlyph
+BaseGlyphRecord
+baseGlyphsZ
+BaseLangSysRecord
+baseLangSysRecords
+BaseLangSysRecords
+baseLangSysTag
+baseline
+Baseline
+BASELINE
+baselines
+BaselineTableFormat
+baselinetags
+baselineTags
+bases
+baseScript
+BaseScript
+baseScriptList
+BaseScriptList
+BaseScriptRecord
+baseScriptRecords
+BaseScriptRecords
+baseScriptTag
+baseTagCount
+baseTagList
+BaseTagList
+baseValues
+BaseValues
+Bashkir
+basic
+Basic
+BASIC
+basically
+BASIS
+Basque
+BASSA
+Batak
+BATAK
+batch
+BAu
+Baulé
+Bavarian
+Bawm
+BB
+BBAu
+BBBu
+bbc
+bbee
+BBEu
+BBF
+BBu
+bbz
+bc
+BC
+bca
+BCA
+BCAu
+BCBu
+bcc
+BCCu
+bcd
+BCD
+BCDu
+BCEu
+bci
+bcl
+bcp
+BCP
+bcq
+bcr
+BCu
+bcursor
+bd
+BD
+bdadd
+bdfaab
+bdu
+BDu
+bdy
+be
+Be
+BE
+bea
+BEAM
+bearing
+bearings
+bearingX
+bearingY
+Beaver
+beb
+Bebele
+Bebil
+bec
+because
+Because
+become
+BECOME
+becomes
+bed
+Bedawi
+BEEH
+been
+BEEN
+BEEu
+before
+Before
+BEFORE
+beforeGrowLimit
+beforehand
+beforeShrinkLimit
+BeforeSub
+began
+begin
+BEGIN
+beginning
+Beginning
+BEH
+behave
+behaved
+behaving
+behavior
+behaviors
+behaviour
+Behdad
+BEHEH
+behind
+Bei
+being
+Being
+BEInt
+Belarus
+Belarusian
+Belarussian
+Belgium
+Belize
+belong
+belonging
+belongs
+below
+Below
+BELOW
+bem
+Bemba
+Bench
+bend
+benefits
+BENG
+Bengali
+BENGALI
+ber
+Berau
+Berber
+best
+Bet
+BET
+Beti
+bets
+Betsimisaraka
+better
+between
+BEu
+beyond
+bf
+BF
+bfaeafe
+BFAu
+bfb
+BFF
+bffc
+BFFu
+bfind
+BFIND
+bfq
+bft
+bfu
+BFu
+bfy
+bg
+bgc
+bgn
+bgp
+bgq
+bgr
+BGRAColor
+Bhaiksuki
+BHAIKSUKI
+Bhasha
+bhb
+bhi
+Bhilali
+Bhili
+bhk
+bho
+Bhojpuri
+bhr
+bi
+Bi
+bias
+biased
+biasedSubrs
+Bible
+Bicolano
+bidi
+bidirectional
+BiDirectional
+bidirectionality
+big
+Big
+BIG
+BigGlyphMetrics
+bik
+Bikol
+BILD
+Bilen
+Bilin
+billion
+bimap
+BIMAP
+bin
+binaries
+binary
+Binary
+BINARY
+bindings
+Bindu
+BINDU
+Bindus
+BinSearchArrayOf
+BinSearchHeader
+Bishnupriya
+Bislama
+bit
+Bit
+bitcount
+bitDepth
+bitfield
+bithacks
+Bithacks
+bitmap
+Bitmap
+BITMAP
+bitmaps
+BitmapSizeTable
+bits
+Bits
+BITS
+BitScanForward
+BitScanReverse
+bitset
+bitsize
+bitwise
+bjj
+bjn
+BJN
+bjq
+bjt
+bl
+BL
+bla
+black
+Black
+BLACK
+Blackfoot
+blackhole
+blacklist
+BLACKLIST
+blacklisted
+blacklisting
+Blas
+ble
+blend
+Blend
+BLEND
+blendcs
+blenddict
+blended
+blending
+BlendInterpEnv
+blends
+Blink
+blk
+bln
+blob
+BLOB
+blobs
+Blobs
+block
+Block
+BLOCK
+blocked
+Blocked
+blocks
+Blocks
+Bloom
+blow
+blown
+blue
+Blue
+BlueFuzz
+BlueScale
+BlueShift
+BlueValues
+blwf
+BLWF
+blwm
+blws
+BLWS
+bm
+bmg
+bmm
+bmp
+BMP
+bn
+bo
+Bodo
+body
+bok
+Bokmal
+Bokmål
+bold
+Bold
+BOLD
+bolder
+Bolivia
+Bolivian
+book
+Book
+bookbold
+bookkeeping
+bool
+BOOL
+Boolean
+Booleans
+BOOM
+Bopomofo
+BOPOMOFO
+Borana
+BORDERS
+Borgu
+Borrowed
+Bosnia
+Bosnian
+BOT
+both
+bother
+bottom
+Bottom
+BOTTOM
+bottomSide
+bound
+Bound
+boundaries
+boundary
+Boundary
+bounding
+bounds
+Bounds
+BOUNDS
+Bouyei
+box
+Box
+BOX
+boxed
+BOXED
+boxes
+bpy
+bqi
+br
+BR
+bra
+braceleft
+braceright
+braces
+Bracket
+BRACKET
+bracketleft
+bracketright
+Brahmi
+BRAHMI
+Brahui
+Braille
+BRAILLE
+Braj
+branches
+brand
+Brawer
+Brazil
+break
+BREAK
+breakfast
+breaking
+breakpoint
+BREAKPOINT
+breaks
+bretagne
+Breton
+breve
+Brevesmall
+brew
+brh
+brief
+broken
+Broken
+brokenbar
+Brunei
+Bruno
+bruteforce
+brx
+bs
+bsb
+bsearch
+bsk
+bsln
+BSLN
+Bsmall
+bsuperior
+bswap
+btb
+btj
+bto
+bts
+btt
+BTT
+bu
+Bu
+Bualkhaw
+Bubble
+bucket
+buf
+buff
+buffArray
+buffer
+Buffer
+BUFFER
+buffers
+Buffers
+BUFSIZ
+bug
+BUG
+buggy
+Buginese
+BUGINESE
+Bugis
+bugs
+bugzilla
+Buhi
+Buhid
+BUHID
+build
+builder
+Builder
+building
+Building
+builds
+built
+builtin
+BUILTIN
+builtins
+Bukit
+Bukusu
+Bulgaria
+Bulgarian
+bulk
+bullet
+Bulu
+bum
+Bumthangkha
+bundles
+burden
+Buriat
+Burmese
+Burushaski
+business
+but
+But
+BUT
+BV
+bve
+bvu
+bxk
+bxp
+bxr
+by
+By
+BY
+Byagowi
+Byelorussian
+byes
+byn
+byte
+Byte
+BYTE
+byteArray
+byteOffsetToIndex
+bytes
+Bytes
+BYTES
+bytesArray
+bytesX
+bytesZ
+byv
+Byzantine
+bzc
+c
+C
+ca
+Ca
+CA
+CABu
+caca
+cache
+Cache
+CACHE
+cacheable
+cached
+caches
+caching
+Caching
+cacute
+Cacute
+caf
+cairo
+Cairo
+cairographics
+Cajamarca
+Cajatambo
+Cajun
+cak
+calcOffSize
+CalcTableChecksum
+calculate
+Calculate
+calculated
+calculates
+calculation
+Calderón
+Calibry
+call
+Call
+callback
+Callback
+callbacks
+CALLBACKS
+called
+Called
+caller
+callers
+callgsubr
+calling
+calloc
+calls
+Calls
+callStack
+callsubr
+calt
+Cambodia
+Cameroon
+Campidanese
+can
+Can
+Canada
+Canadian
+CANADIAN
+Cañar
+CANCEL
+candidate
+candidates
+cannot
+Cannot
+canon
+canonical
+Canonical
+CANONICAL
+canonically
+cantarell
+Cantarell
+Cantillation
+CANTILLATION
+cap
+Cap
+CAP
+capabilities
+capable
+capital
+CAPS
+care
+careful
+carefully
+caret
+Caret
+CARET
+caretOffset
+carets
+caretSlopeDenominator
+caretSlopeNumerator
+caretSlopeRise
+caretSlopeRun
+CaretValue
+caretValueFormat
+CaretValueFormat
+caretValuePoint
+Carian
+CARIAN
+Caribbean
+caron
+Caronsmall
+Carpathian
+Carrier
+carry
+cas
+cascade
+cascading
+case
+CASE
+cases
+cast
+Cast
+casting
+casts
+Casts
+cat
+Cat
+CAT
+Catalan
+Catanduanes
+catch
+categories
+Categories
+CATEGORIES
+categorization
+categorize
+categorized
+categorizes
+category
+Category
+CATEGORY
+Cateories
+CAu
+CAUCASIAN
+cause
+caused
+causes
+causing
+cautious
+cb
+CB
+cbb
+CBCu
+cbdt
+CBDT
+CBEu
+CBFu
+cbk
+cbl
+cblc
+CBLC
+CBu
+cc
+Cc
+CC
+ccaron
+Ccaron
+CCAu
+CCBu
+ccc
+CCC
+ccccae
+cccf
+CCCu
+CCD
+CCDu
+ccedilla
+Ccedilla
+Ccedillasmall
+CCEu
+cChars
+ccmp
+cco
+ccq
+CCu
+cd
+CD
+CDATA
+cdd
+cdo
+CDu
+CDx
+CDxA
+CDxAB
+CDxBA
+ce
+CE
+ceb
+Cebuano
+CECu
+cedilla
+Cedillasmall
+CEDu
+CEEu
+ceil
+CEIL
+cent
+center
+Center
+centered
+CENTERED
+centinferior
+centoldstyle
+CentOS
+central
+Central
+centsuperior
+ceparams
+certain
+Certain
+CEu
+cf
+Cf
+CF
+cfar
+CFAR
+CFArrayAppendValue
+CFArrayCreate
+CFArrayCreateMutable
+CFArrayGetCount
+CFArrayGetValueAtIndex
+CFArrayRef
+CFAttributedStringCreateMutable
+CFAttributedStringRemoveAttribute
+CFAttributedStringReplaceString
+CFAttributedStringSetAttribute
+CFComparisonResult
+cfd
+CFData
+CFDataGetBytePtr
+CFDataGetLength
+CFDataRef
+CFDictionaryCreate
+CFDictionaryGetValue
+CFDictionaryRef
+CFDu
+CFEqual
+cff
+CFF
+cfff
+CFFIndex
+CFFIndexOf
+CFFTag
+CFFu
+CFIndex
+cfm
+CFMutableArrayRef
+CFMutableAttributedStringRef
+CFNumberCreate
+CFNumberRef
+CFRange
+CFRangeMake
+CFRelease
+CFRetain
+CFSTR
+CFStringCompare
+CFStringCreateWithCharactersNoCopy
+CFStringCreateWithCStringNoCopy
+CFStringGetCharacterAtIndex
+CFStringHasPrefix
+CFStringHasSuffix
+CFStringRef
+CFu
+CFURLCreateFromFSRef
+CFURLRef
+cg
+CGDataProviderCreateWithData
+CGDataProviderRef
+CGDataProviderRelease
+CGFloat
+CGFont
+CGFontCopyPostScriptName
+CGFontCopyTableForTag
+CGFontCreateWithDataProvider
+CGFontRef
+CGFontRelease
+CGFontRetain
+cgg
+CGGlyph
+cgi
+cgit
+CGJ
+cGlyphs
+CGPoint
+ch
+Chachapoyas
+Chadian
+Chaha
+chain
+Chain
+chainContext
+ChainContext
+ChainContextApplyLookupContext
+ChainContextClosureLookupContext
+ChainContextCollectGlyphsLookupContext
+ChainContextFormat
+ChainContextPos
+ChainContextSubst
+chainCount
+chaining
+Chaining
+ChainRule
+ChainRuleSet
+chains
+Chains
+ChainSubtable
+Chakma
+CHAKMA
+Chaldean
+Cham
+CHAM
+Chamorro
+chance
+chandas
+change
+Change
+changed
+changes
+Changes
+changing
+channel
+channels
+Chap
+chapter
+Chapter
+char
+Char
+CHAR
+character
+Character
+CHARACTER
+characterCode
+characterize
+characters
+Characters
+CHARACTERS
+characterVariants
+charmap
+Charmap
+charMirror
+CHARPROP
+chars
+charset
+Charset
+CHARSET
+CharsetID
+charsetInfo
+CharsetOffset
+charstreing
+charstring
+CharString
+charstrings
+charStrings
+CharStrings
+charStringsInfo
+charStringsOffset
+CharstringType
+charts
+chattawa
+CHATTAWA
+Chattisgarhi
+Chaungtha
+Chavacano
+cheaper
+Chechen
+check
+Check
+CHECK
+checked
+CHECKED
+checking
+Checking
+checks
+Checks
+checksum
+checkSum
+CheckSum
+checkSumAdjustment
+Cherokee
+CHEROKEE
+Chetco
+Chewa
+Cheyenne
+Chhattisgarhi
+Chichewa
+Chiga
+Chiki
+CHIKI
+Chilcotin
+child
+children
+Chile
+Chilean
+Chillus
+Chiltepec
+Chimborazo
+Chin
+China
+Chinantec
+Chinbon
+Chincha
+Chinese
+Chipewyan
+Chippewa
+Chiquián
+Chiricahua
+Chiripá
+Chittagonian
+chj
+chk
+CHL
+cho
+Choctaw
+choice
+choices
+choose
+Choose
+chooses
+choosing
+chop
+Chop
+chosen
+CHOSEONG
+chp
+chq
+chr
+chris
+Chris
+chromium
+Chromium
+Chuanqiandian
+Chukchi
+Chukot
+chunk
+ChunkLen
+chunks
+Church
+Chuukese
+Chuvash
+chy
+chz
+ci
+CI
+CID
+cidCount
+CIDCount
+CIDFontRevision
+CIDFontType
+CIDFontVersion
+CIN
+cInChars
+CIP
+circle
+CIRCLE
+circles
+circuit
+CIRCUIT
+circumflex
+Circumflexsmall
+circumstances
+circumvents
+citer
+CITI
+ciw
+cja
+CJCT
+CJK
+cjm
+cjy
+ck
+CK
+cka
+ckb
+ckt
+cl
+Clamp
+clang
+clarity
+Clasen
+class
+Class
+CLASS
+classArray
+classCount
+classDef
+ClassDef
+ClassDefFormat
+classes
+classFormat
+Classic
+Classical
+classifications
+classified
+classify
+classTable
+ClassTable
+ClassType
+ClassTypeNarrow
+ClassTypeWide
+classValue
+classValueArray
+clc
+cld
+cle
+clean
+Clean
+cleanest
+clear
+Clear
+cleared
+clearing
+clearly
+clears
+Clears
+ClearType
+ClearType™
+client
+Client
+clients
+Clients
+clig
+clipping
+CLIPPING
+clockwise
+close
+Close
+CLOSE
+CloseHandle
+closely
+closer
+closest
+CLOSEST
+closure
+Closure
+CLOSURE
+closures
+cluster
+Cluster
+CLUSTER
+clustering
+clusterMap
+clusters
+Clusters
+CLUSTERS
+clz
+clzl
+clzll
+CM
+CMAbv
+cmake
+cmap
+CMAP
+cmapsubtable
+CmapSubtable
+CmapSubtableFormat
+CmapSubtableLongGroup
+CmapSubtableLongSegmented
+CmapSubtableTrimmed
+cMaxGlyphs
+cMaxItems
+CMBlw
+cmn
+cmp
+cmpexch
+cmplexch
+cmpswap
+cmr
+cn
+Cn
+cnb
+cnh
+cnk
+cnl
+cnt
+cntrmask
+cnw
+co
+Co
+coa
+Cocos
+code
+Code
+CODE
+codebase
+coded
+codepath
+codepoint
+CODEPOINT
+codepoints
+codepont
+codes
+Codethink
+Coeng
+COENG
+coengs
+col
+Col
+collect
+Collect
+COLLECT
+collected
+collection
+Collection
+collections
+Collections
+collects
+Colombia
+colon
+COLON
+colonmonetary
+color
+Color
+COLOR
+colorIdx
+colorLabelsZ
+ColorRecord
+colorRecordIndicesZ
+colorRecordsZ
+colorRef
+colors
+colorType
+Colour
+colr
+COLR
+cols
+COLS
+columnCount
+columnIndexTable
+com
+Comaltepec
+combination
+combinations
+combine
+COMBINE
+combined
+combiner
+combiners
+combining
+Combining
+COMBINING
+come
+comes
+comfortably
+coming
+comma
+COMMA
+commainferior
+command
+Command
+commands
+commas
+commasuperior
+comment
+Commenting
+comments
+commit
+commitcomment
+commits
+common
+Common
+COMMON
+commonly
+Comorian
+comp
+compact
+Compact
+compar
+compare
+Compare
+compared
+compares
+comparing
+Comparing
+comparison
+compat
+compatibility
+Compatibility
+COMPATIBILITY
+compatible
+COMPATIBLE
+compensate
+compilable
+compile
+Compile
+compiled
+compiler
+Compiler
+compilers
+compiles
+COMPILES
+compiling
+complains
+complang
+Complement
+complete
+Complete
+completely
+complex
+Complex
+COMPLEX
+COMPLEXITY
+complicated
+component
+COMPONENT
+componentData
+ComponentGlyph
+components
+Components
+COMPONENTS
+ComponentsArray
+composable
+compose
+composed
+COMPOSED
+composePair
+composes
+Composes
+composing
+composite
+COMPOSITE
+CompositeGlyph
+CompositeGlyphChain
+composites
+composition
+Composition
+COMPOSITION
+COMPOUND
+compressed
+compressionMethod
+comprise
+comprising
+comps
+compute
+Compute
+Computes
+computing
+concepts
+Concepts
+conceptual
+Conceptually
+concern
+concerned
+Conchucos
+cond
+Cond
+condensed
+Condensed
+CONDENSED
+condition
+Condition
+conditional
+conditionalAddGlyphAction
+ConditionalAddGlyphAction
+conditionally
+ConditionFormat
+conditions
+Conditions
+ConditionSet
+config
+CONFIG
+configs
+configuration
+Configuration
+configurations
+configure
+configured
+conflicting
+confused
+confusing
+Congo
+conjunct
+connect
+CONNECT
+connected
+CONNECTED
+connecting
+connection
+CONNECTION
+connector
+CONNECTOR
+Cons
+CONS
+consecutive
+CONSEQUENTIAL
+Consequently
+consider
+Consider
+considerably
+consideration
+considerations
+considered
+consist
+consistent
+consists
+consonant
+Consonant
+CONSONANT
+consonants
+const
+CONST
+constant
+CONSTANT
+constants
+Constants
+constexpr
+constituent
+constitute
+constitutes
+constraints
+CONSTRAINTS
+construct
+constructed
+constructible
+construction
+constructor
+constructors
+Constructors
+constructs
+consult
+consumed
+contain
+contained
+container
+containers
+containing
+contains
+ContainsTextPosition
+contemporary
+content
+CONTENT
+contents
+context
+Context
+CONTEXT
+ContextApplyFuncs
+ContextApplyLookupContext
+ContextClosureFuncs
+ContextClosureLookupContext
+ContextCollectGlyphsFuncs
+ContextCollectGlyphsLookupContext
+ContextFormat
+ContextPos
+contexts
+ContextSubst
+contextual
+Contextual
+CONTEXTUAL
+ContextualSubtable
+contiguous
+continuation
+CONTINUATION
+continuations
+continue
+continues
+contour
+Contour
+contours
+contract
+CONTRACT
+contrary
+contrast
+contributing
+Contributor
+control
+Control
+CONTROL
+controlling
+controls
+convenience
+conveniences
+convenient
+conventions
+Conversely
+conversion
+Conversion
+Conversions
+convert
+Convert
+converted
+Converted
+converters
+convertible
+converting
+Converts
+convoluted
+coord
+coordinate
+Coordinate
+coordinates
+Coordinates
+COORDINATES
+coordinatesZ
+coordPoint
+coords
+coorinates
+cop
+copied
+Copied
+copies
+Copies
+Coptic
+COPTIC
+copy
+Copy
+COPY
+copyable
+copying
+copyright
+Copyright
+COPYRIGHT
+coq
+Coquille
+core
+CoreGraphics
+coretext
+CoreText
+CORETEXT
+corner
+CORNER
+corners
+Cornish
+Corongo
+correct
+correction
+correctionHeight
+correctly
+Correctly
+correctness
+correlate
+correspond
+corresponding
+corresponds
+corrupt
+Corsican
+cost
+Costa
+costs
+costy
+cotfRecords
+could
+Could
+count
+Count
+COUNT
+countChar
+counted
+counter
+counting
+Counting
+CountMask
+countries
+counts
+couple
+Courier
+course
+courtesy
+cover
+coverage
+Coverage
+COVERAGE
+coverageFormat
+CoverageFormat
+coverageZ
+covered
+COVERED
+covering
+covers
+cp
+CP
+cpa
+cpal
+CPAL
+CPALV
+cpe
+cpf
+cplusplus
+cpp
+cppreference
+CPR
+CPrf
+cpx
+cqd
+cqu
+cr
+CRAMPED
+cRanges
+crap
+Crap
+CRAP
+CrapHelper
+CrapOrNull
+CrapOrNullHelper
+CrapPool
+crash
+crashes
+crazy
+crbug
+create
+Create
+CREATE
+CreateCustomFontFileReference
+created
+CreateFile
+CREATEFILE
+CreateFileMapping
+CreateFileMappingFromApp
+CreateFileW
+CreateFontFace
+CreateFontIndirectW
+creates
+Creates
+CreateStreamFromKey
+CreateTextAnalyzer
+creating
+Creating
+creation
+creator
+Cree
+Creek
+Creole
+creoles
+Creoles
+crh
+Crimean
+Crioulo
+criteria
+CRITICAL
+crj
+crk
+crl
+crm
+Croatia
+Croatian
+cross
+Cross
+crossStream
+CrossStream
+crp
+crucial
+crx
+cs
+Cs
+CS
+csa
+csb
+csh
+Csmall
+cso
+csop
+CSOPSET
+CSR
+CSS
+CSType
+csw
+cswh
+csy
+ct
+ctc
+ctd
+cte
+CTFont
+CTFontCopyAttribute
+CTFontCopyGraphicsFont
+CTFontCopyName
+CTFontCopyPostScriptName
+CTFontCreateCopyWithAttributes
+CTFontCreateUIFontForLanguage
+ctfontcreatewithgraphicsfont
+CTFontCreateWithGraphicsFont
+CTFontDescriptorCreateWithAttributes
+CTFontDescriptorCreateWithNameAndSize
+CTFontDescriptorRef
+CTFontGetPlatformFont
+CTFontGetSize
+CTFontRef
+CTFontUIFontType
+ctg
+CTGetCoreTextVersion
+ctl
+CTLineGetGlyphRuns
+CTLineGetTrailingWhitespaceWidth
+CTLineRef
+ctlPoints
+ctor
+CTRunGetAttributes
+CTRunGetGlyphCount
+CTRunGetGlyphs
+CTRunGetGlyphsPtr
+CTRunGetPositions
+CTRunGetPositionsPtr
+CTRunGetStatus
+CTRunGetStringIndices
+CTRunGetStringIndicesPtr
+CTRunGetStringRange
+CTRunGetTypographicBounds
+CTRunRef
+CTRunStatus
+cts
+CTTypesetterCreateLine
+CTTypesetterCreateWithAttributedStringAndOptions
+CTTypesetterRef
+CTYPE
+ctz
+ctzl
+ctzll
+cu
+Cu
+cuc
+cuk
+cumulated
+Cumulative
+Cuneiform
+CUNEIFORM
+cur
+curEntry
+Curiously
+CURISVE
+CURLY
+curr
+curradv
+curradvx
+curradvy
+currAnchor
+currAnchorPoint
+currclus
+currControlPoint
+currency
+Currency
+CURRENCY
+current
+Current
+CurrentCategory
+currentIndex
+currentInsertBefore
+CurrentInsertBefore
+currentInsertCount
+CurrentInsertCount
+currentInsertIndex
+currentInsertList
+CurrentIsKashidaLike
+currently
+Currently
+currX
+currY
+curs
+cursive
+Cursive
+CURSIVE
+CursivePos
+CursivePosFormat
+cursor
+Cursor
+cursoring
+curve
+CURVE
+Cusco
+custom
+Custom
+customization
+customize
+customizing
+Customizing
+CustomRange
+cut
+CUT
+cutting
+cv
+cvn
+CVT
+cvXX
+cwd
+CWS
+cx
+cy
+CYGWIN
+Cypriot
+CYPRIOT
+Cyrillic
+CYRILLIC
+Czech
+czh
+czo
+czt
+d
+D
+da
+DA
+Daai
+DAD
+DAFu
+dagesh
+DAGESH
+dagger
+daggerdbl
+DAHAL
+Dai
+DAL
+DALATH
+DALET
+dam
+DAMAGE
+DAMAGES
+damma
+dammatan
+Dan
+dance
+dangerous
+Dangme
+Danish
+dao
+dap
+dar
+Dargwa
+Dari
+dark
+DARK
+Darkhat
+Darussalam
+Darwazi
+DASH
+data
+Data
+DATA
+dataArray
+dataArrayLen
+Database
+dataLen
+dataLength
+DataMap
+dataMaps
+dataOffset
+dataset
+dataSets
+dataSize
+dataSizeArray
+dataZ
+Date
+DAu
+David
+Daw
+dax
+day
+Dayi
+db
+DB
+DBAu
+DBBu
+DBCu
+DBEu
+DBF
+dbfo
+DBL
+DBu
+dc
+DC
+DCA
+DCAu
+DCBu
+DCFu
+dcroat
+DCu
+DCx
+DCxA
+DCxAB
+DCxBA
+dd
+DD
+DDA
+DDAHAL
+DDAL
+DDAu
+DDCu
+DDD
+DDDu
+dde
+DDEu
+ddf
+DDF
+DDFu
+DDu
+de
+DE
+deabc
+Dead
+DEAD
+deal
+deallocate
+Deallocate
+DEALLOCATE
+deallocation
+dealt
+DEAu
+Debian
+debug
+Debug
+DEBUG
+debugging
+Debugging
+dec
+decay
+decender
+decide
+Decide
+deciding
+DECIMAL
+decipoints
+decision
+decisions
+declaration
+declarations
+declare
+Declare
+DECLARE
+declared
+declaring
+decls
+DECLS
+declspec
+decltype
+declval
+decode
+DECODE
+decomp
+decompose
+Decompose
+DECOMPOSE
+decomposed
+DECOMPOSED
+decomposedglyphs
+decomposes
+decomposing
+decomposition
+DECOMPOSITION
+decompositionAction
+DecompositionAction
+decompositions
+decompressed
+deconstructed
+DECORATIVE
+DecorativeBorders
+decrease
+decreased
+decreases
+Decreases
+decreasing
+deduce
+deduced
+deduces
+deem
+deemed
+deep
+def
+DEF
+defaul
+default
+Default
+DEFAULT
+defaultBaseline
+defaultFlags
+defaultIndex
+DefaultJstfLangSys
+defaultLangSys
+DefaultLangSys
+defaultMinMax
+defaults
+defaultUVS
+DefaultUVS
+defaultValue
+defaultVertOriginY
+defaultWidthX
+define
+DEFINE
+defined
+Defined
+DEFINED
+defines
+Defines
+defining
+Defining
+definition
+Definition
+definitions
+Definitions
+DEFu
+Degexit
+degree
+DEGREE
+degrees
+Dehong
+DejaVu
+del
+delayed
+delete
+DELETE
+DeleteCriticalSection
+deleted
+DELETED
+DeleteObject
+deleting
+delimited
+DELIMITED
+delta
+Delta
+DELTA
+deltaFormat
+deltaGlyphID
+deltas
+DELTAS
+DeltaSetIndexMap
+DeltaValue
+deltaValueZ
+Democratic
+demonstrate
+den
+DENIED
+Denmark
+denom
+DENOM
+DENOMINATOR
+denote
+density
+depend
+dependant
+dependencies
+dependency
+dependent
+Dependent
+DEPENDENT
+depending
+depends
+deprecated
+Deprecated
+DEPRECATED
+depth
+deref
+dereference
+dereferenced
+dereferencing
+derived
+Derived
+DerivedCoreProperties
+desc
+descendent
+descender
+DESCENDER
+descending
+descent
+DESCENT
+describe
+described
+describes
+describing
+description
+Description
+DESCRIPTION
+descriptor
+descriptors
+Deseret
+DESERET
+deserialize
+DESERIALIZE
+design
+Design
+DESIGN
+designated
+designates
+designAxesOffset
+designAxisCount
+designAxisSize
+designed
+designer
+DESIGNER
+designSize
+desirable
+desired
+desktop
+dest
+destroy
+Destroy
+DESTROY
+destroyed
+destroying
+destroys
+Destroys
+destruct
+destructed
+destructible
+destruction
+desubroutinize
+detail
+detailed
+details
+detect
+detected
+determine
+Determine
+determined
+determines
+determining
+Determining
+DEu
+dev
+DEVA
+devanagari
+Devanagari
+DEVANAGARI
+devel
+develop
+developed
+developer
+developers
+developing
+development
+Deviate
+device
+Device
+DeviceHeader
+DeviceRecord
+devices
+deviceTable
+devnet
+df
+DF
+DFAu
+dfde
+DFDu
+dfe
+DFF
+DFFu
+dflt
+DFLT
+dfont
+DFont
+DFontTag
+DFu
+dgo
+dgr
+Dhangu
+dhd
+dhg
+Dhivehi
+Dhofari
+Dhundari
+Dhuwal
+Dhuwaya
+diacritic
+Diacritical
+diacritics
+DIACRITICS
+diagnostic
+DIAGNOSTIC
+DIAGONAL
+DIAMOND
+dib
+dict
+Dict
+DICT
+dictionary
+dicts
+dictsSize
+dictval
+DICTVAL
+did
+didn
+Didn
+didnt
+dieresis
+Dieresissmall
+diff
+DIFF
+differ
+difference
+differences
+different
+Different
+differentiate
+differently
+differing
+differs
+difficult
+difficulty
+digest
+DIGEST
+digests
+digit
+Digit
+DIGIT
+digital
+Digits
+dik
+dimensional
+dimensions
+Dimli
+din
+Dingbats
+DINGBATS
+Dinka
+dip
+DIPHTHONG
+diq
+dir
+DIR
+direct
+DIRECT
+direction
+Direction
+DIRECTION
+directional
+directionality
+directions
+directive
+directly
+directory
+directwrite
+DirectWrite
+DIRECTWRITE
+dirty
+disable
+Disable
+DISABLE
+disabled
+disableFlags
+disables
+disabling
+disallow
+disallows
+disambiguated
+Disc
+discard
+Discarding
+discards
+discern
+DISCLAIMS
+discover
+Discovered
+discretionary
+discussed
+Discussion
+dispatch
+Dispatch
+DISPATCH
+displacement
+display
+Display
+DISPLAY
+displaying
+dist
+distance
+Distance
+DISTANCE
+distances
+distinct
+distinction
+distinguish
+distinguishes
+distinguishing
+distribute
+distribution
+ditto
+div
+DIV
+Divehi
+divert
+divide
+DIVIDE
+divided
+divisible
+diw
+Djambarrpuyngu
+dje
+djr
+dks
+DLBAR
+dlig
+dll
+DLL
+dllexport
+dm
+dng
+dnj
+dnom
+do
+Do
+DO
+DOACHASHMEE
+doc
+Doc
+docbook
+DocBook
+docbookx
+docs
+DOCTYPE
+document
+Document
+documentation
+DOCUMENTATION
+documented
+documents
+Documents
+does
+Does
+doesn
+Doesn
+doesnt
+Dogra
+DOGRA
+Dogri
+Dogrib
+doi
+doing
+dollar
+dollarinferior
+dollaroldstyle
+dollarsuperior
+Domain
+dominant
+Dominican
+Domino
+don
+Don
+DON
+done
+Done
+DONE
+Dong
+dont
+DONT
+DontAdvance
+Dos
+DoS
+dot
+Dot
+DOT
+dotaccent
+Dotaccentsmall
+dotlessi
+dotsection
+dotted
+DOTTED
+dottedcircle
+DOTTEDCIRCLE
+Dotyali
+double
+DOUBLE
+down
+DOWN
+download
+downloaded
+Downloading
+downstream
+downward
+DPI
+DR
+dragons
+drain
+draw
+Draw
+drawing
+Drawing
+DRAWINGS
+drawn
+Drepper
+drh
+drive
+driver
+Driver
+drop
+Drop
+DROP
+dropped
+dropping
+drops
+drw
+ds
+dsb
+Dsmall
+dsohowto
+dst
+dsuperior
+dtd
+DTD
+dtor
+dty
+du
+Du
+dual
+Duano
+duct
+ductile
+ductileGlyphAction
+DuctileGlyphAction
+ductility
+due
+duj
+DUL
+dumb
+dumber
+Dumbest
+dummy
+Dummy
+Dungan
+dup
+dupe
+duplicate
+DUPLICATE
+duplicated
+Duplicated
+duplicates
+duplication
+DUPLOYAN
+dupped
+duration
+during
+During
+Dutch
+dv
+dw
+dwFeatures
+dwFileAttributes
+dwFileFlags
+DWORD
+dwrite
+DWrite
+DWRITE
+DWriteCreateFactory
+dwriteFactory
+DWriteFontFileLoader
+DWriteFontFileStream
+dwSecurityQosFlags
+dwSize
+dwu
+dwy
+dx
+Dx
+DxA
+DxAB
+DxBA
+dy
+DYEH
+dynamic
+dyu
+Dyula
+dz
+Dzongkha
+e
+E
+ea
+EA
+EAAu
+EABu
+each
+Each
+eachother
+EACu
+eacute
+Eacute
+Eacutesmall
+EADu
+eae
+EAEu
+EAFu
+eager
+earlier
+Earlier
+early
+EARLY
+easier
+East
+eastasian
+Eastern
+easy
+EAu
+eb
+EB
+EBAu
+EBBu
+EBCu
+ebdt
+EBDT
+EBDu
+EBEu
+EBFu
+Ebira
+eblc
+Ebrahim
+EBu
+ec
+EC
+ECAu
+ECBu
+ECCu
+ECD
+ecde
+ECDu
+ECE
+ECEu
+ecfb
+ECFu
+ecircumflex
+Ecircumflex
+Ecircumflexsmall
+ECu
+Ecuador
+ed
+ED
+eda
+EDAu
+EDBu
+EDCu
+EDDu
+EDEu
+EDFu
+edge
+edges
+edieresis
+Edieresis
+Edieresissmall
+edit
+edits
+EDITS
+Edo
+EDu
+ee
+EE
+EEAu
+EEBu
+EECu
+EEDu
+EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE
+EEELLLGGGGEEEE
+EEEu
+EEFu
+EEu
+ef
+EF
+EFEu
+EFF
+effect
+effectively
+effects
+efficiency
+efficiently
+effort
+efi
+Efik
+EFu
+eg
+Eg
+egrave
+Egrave
+Egravesmall
+Egypt
+Egyptian
+EGYPTIAN
+eight
+EIGHT
+EIGHTEEN
+eightinferior
+eightoldstyle
+eightsuperior
+EINTR
+either
+Either
+EK
+ekk
+el
+El
+ELBASAN
+ELEM
+element
+ELEMENT
+elements
+Elements
+ELEVEN
+elidable
+ELIDABLE
+elidedFallbackNameID
+elie
+Elie
+elif
+ellipsis
+ELLIPSIS
+else
+Else
+elt
+ELT
+ELYMAIC
+em
+EM
+embed
+embedded
+EmbeddedPeakTuple
+embedding
+EMBEDDING
+emboldening
+EMBOX
+emdash
+emk
+emoji
+Emoji
+EMOJI
+emphasis
+empty
+Empty
+EMPTY
+ems
+en
+EN
+enable
+Enable
+enabled
+ENABLED
+enableFlags
+enables
+enabling
+enb
+enc
+Enclosed
+enclosing
+ENCLOSING
+encode
+ENCODE
+encoded
+Encoded
+encoder
+Encodes
+encoding
+Encoding
+ENCODING
+encodingID
+EncodingID
+encodingOffset
+EncodingOffset
+encodingrec
+EncodingRecIter
+encodingRecord
+EncodingRecord
+encodings
+encounter
+encountered
+end
+End
+END
+endash
+endchar
+endCharCode
+endcode
+endCode
+endConnectorLength
+endCoord
+endCount
+endcp
+ended
+endGlyphID
+endGlyphIndex
+endian
+Endian
+ENDIAN
+endif
+ending
+EndPtr
+endPtsOfContours
+ends
+endSize
+Enets
+enf
+enforce
+engine
+Engine
+engines
+English
+ENGRAVED
+enh
+ENHANCEMENTS
+enlarge
+Enlarge
+enough
+ensure
+Ensure
+ensures
+enter
+EnterCriticalSection
+entire
+entirely
+entirety
+ENTITY
+entries
+Entries
+entry
+Entry
+entryAnchor
+EntryAnchor
+EntryData
+EntryExit
+entryExitRecord
+EntryExitRecord
+entrySelector
+EntryT
+entryTable
+enum
+enumerate
+enumerated
+Enumerates
+enumeration
+enumerations
+enums
+env
+ENV
+environment
+eo
+eof
+EOT
+epsilon
+eq
+equal
+EQUAL
+equality
+equally
+equals
+Equatorial
+equivalent
+Eric
+err
+Err
+Erratic
+erratically
+erring
+errno
+ERRNO
+error
+Error
+ERROR
+errors
+errs
+Erzya
+es
+ESC
+escape
+escapes
+eScript
+Esfahbod
+esg
+esi
+esk
+Esmall
+esp
+especially
+Esperanto
+esque
+essence
+essentially
+Estero
+estimate
+estimated
+estimates
+Estonia
+Estonian
+Estrangela
+Estrangelo
+esu
+esuperior
+et
+etc
+eth
+Eth
+Ethiopia
+Ethiopic
+ETHIOPIC
+Ethsmall
+eto
+Eton
+eu
+Eu
+eval
+evaluate
+evaluating
+eve
+even
+Even
+EVEN
+Evenki
+event
+EVENT
+events
+eventual
+ever
+every
+Every
+everyone
+everything
+evidence
+evident
+evn
+Ewe
+ewo
+Ewondo
+exact
+exactly
+examine
+examines
+examining
+example
+examples
+exceed
+exceeds
+except
+Except
+exception
+exceptional
+exceptions
+excess
+excessive
+exch
+exchange
+exclam
+EXCLAMATION
+exclamdown
+exclamdownsmall
+exclamsmall
+excluded
+exclusion
+exclusive
+Exclusive
+exclusivity
+exe
+executable
+execute
+EXECUTE
+exhaust
+exist
+existence
+existent
+existing
+EXISTING
+exists
+exit
+exitAnchor
+ExitAnchor
+exp
+EXP
+expand
+expanded
+EXPANDED
+ExpansionFactor
+expect
+expected
+expects
+expensive
+experience
+experimental
+experimentally
+expert
+EXPERT
+ExpertCharset
+ExpertEncoding
+ExpertSubsetCharset
+explanation
+explicit
+EXPLICIT
+explicitLevel
+explicitly
+explore
+exponent
+EXPONENTS
+export
+EXPORT
+exported
+exports
+expose
+Expose
+exposed
+exposing
+Exposing
+expr
+EXPR
+express
+Express
+expressed
+expression
+expressions
+extend
+Extend
+extended
+Extended
+EXTENDED
+extendedShapeCoverage
+ExtendedTypes
+Extender
+EXTENDER
+ExtenderGlyph
+extenderGlyphs
+ExtenderGlyphs
+extensibility
+extension
+Extension
+extensionDisableGPOS
+extensionDisableGSUB
+extensionEnableGPOS
+extensionEnableGSUB
+ExtensionFormat
+extensionJstfMax
+extensionLookupType
+extensionOffset
+ExtensionOffset
+ExtensionPos
+extensions
+Extensions
+EXTENSIONS
+ExtensionSubst
+extensively
+extent
+Extent
+extents
+EXTENTS
+extern
+EXTERN
+external
+externally
+externs
+extlang
+extra
+Extra
+EXTRA
+extract
+extracted
+EXTRAS
+extreme
+extremely
+eye
+Eye
+eyelash
+eyo
+f
+F
+fa
+FA
+FAAu
+fabs
+FABu
+FAbv
+faca
+face
+Face
+FACE
+faceBlob
+Facebook
+faces
+FACESIZE
+facet
+faceType
+facilities
+facility
+fact
+factor
+FACTOR
+factors
+factory
+FACTORY
+factoryType
+FACu
+FADu
+FAEu
+FAFu
+fail
+Fail
+FAIL
+failed
+Failed
+FAILED
+failing
+FAILLING
+fails
+Fails
+failure
+FAILURE
+failures
+fairly
+Falam
+fall
+Fall
+fallback
+Fallback
+FALLBACK
+falling
+falls
+fallthrough
+FALLTHROUGH
+false
+FALSE
+family
+Family
+FAMILY
+FamilyBlues
+familyName
+FamilyName
+FamilyOtherBlues
+fan
+Fancy
+Fang
+Fanti
+faq
+far
+Faroe
+Faroese
+Farsi
+FARSI
+fashion
+fast
+faster
+fat
+fatha
+FATHA
+fathatan
+FAu
+faulty
+favor
+fb
+FB
+fba
+FBAu
+FBBu
+FBCu
+FBDu
+fbe
+FBFu
+fbl
+FBlw
+FBu
+fc
+FC
+FCAu
+fcc
+FCCu
+FCDu
+FCEu
+FCFu
+fclose
+fcntl
+FCu
+fd
+FD
+fda
+fdArray
+FDArray
+FDArrayInfo
+FDArrayOffset
+FDAu
+fdcount
+fdCount
+FDDu
+fde
+FDEFs
+FDEu
+FDF
+FDFu
+FDIndex
+fdmap
+fds
+fdsc
+FDSC
+fdselect
+fdSelect
+FDSelect
+FDSELECT
+FDSelectInfo
+FDSelectOffset
+FDu
+fe
+Fe
+FE
+feat
+FEAT
+FeatMinMaxRecord
+featMinMaxRecords
+FeatMinMaxRecords
+feats
+featUILableNameID
+featUITooltipTextNameID
+feature
+Feature
+FEATURE
+featureCount
+featureFlags
+featureIndex
+featureList
+FeatureList
+FeatureName
+featureNameCount
+featureParams
+FeatureParams
+FeatureParamsCharacterVariants
+FeatureParamsSize
+FeatureParamsStylisticSet
+featureRangeLengths
+features
+Features
+FEATURES
+featureSetting
+FeatureTableSubstitution
+FeatureTableSubstitutionRecord
+featureTableTag
+featureType
+featureval
+FeatureVariationRecord
+FeatureVariations
+featureVars
+featureZ
+FEAu
+Feb
+February
+FEBu
+FECu
+Fedora
+FEDu
+fee
+feed
+feel
+fees
+FEFF
+FEH
+fence
+feof
+ferror
+fetch
+Fetch
+fetched
+fetches
+Fetches
+fetching
+FetchNextRun
+FEu
+few
+fewer
+ff
+FF
+FFA
+FFAu
+ffbfea
+ffcdf
+FFCu
+FFEu
+FFF
+FFFD
+FFFF
+FFFFF
+FFFFFF
+FFFFFFF
+FFFFFFFFULL
+FFFFFu
+FFFFu
+FFFFULL
+FFFu
+ffi
+ffl
+ffm
+FFu
+FFULL
+ffuncs
+ffunctions
+fh
+fi
+fi
+fid
+field
+fields
+FIFTEEN
+figure
+FIGURE
+figuredash
+Fijian
+fil
+file
+File
+FILE
+filename
+fileOffset
+files
+fileSize
+fileType
+Filipino
+fill
+Fill
+filled
+FILLER
+filling
+Filling
+filter
+Filter
+filtered
+filtering
+filterMethod
+filterRangeMaxValue
+filterRangeMinValue
+filters
+FIN
+fina
+FINA
+final
+Final
+FINAL
+finalcode
+finalize
+finalizer
+Finalizer
+finally
+Finally
+finaLookup
+finaSubLookup
+find
+Find
+FINDFONT
+finding
+finds
+Finds
+fine
+fini
+finish
+Finish
+finished
+finite
+Finland
+Finnish
+Firefox
+first
+First
+FIRST
+firstAxis
+firstAxisSegmentMaps
+firstChain
+firstDeviceRecord
+firstGlyph
+firstGlyphIndex
+FirstGlyphs
+firstLayerIdx
+firstPairValueRecord
+firstParamUILabelNameID
+firstSubtable
+firstSubTable
+fit
+FITNESS
+fitting
+five
+FIVE
+fiveeighths
+fiveinferior
+fiveoldstyle
+fivesuperior
+fix
+Fix
+fixed
+Fixed
+FIXED
+fixedcs
+FixedType
+FixedVersion
+Fixes
+fixup
+Fixup
+fj
+fl
+flag
+Flag
+FLAG
+flags
+Flags
+FLAGS
+flat
+flatStr
+flatten
+Flatten
+FLATTENED
+flattener
+fLayoutRTL
+Flemish
+Fleurons
+FLEURONS
+flex
+flip
+flm
+float
+floating
+fLogicalOrder
+flooded
+floor
+florin
+flow
+Flowery
+FLT
+flush
+fly
+FM
+FMAbv
+FMBlw
+fMergeNeutralItems
+fmp
+FMPst
+fmt
+fNoGlyphIndex
+fo
+folded
+follow
+followed
+Followed
+following
+Following
+follows
+fon
+Fon
+fonipa
+fonnapa
+font
+Font
+FONT
+FontBBox
+fontconfig
+Fontconfig
+FontConfig
+FontDescriptor
+fontdict
+FontDict
+fontdicts
+fontDicts
+fontDictStr
+fontDirectionHint
+fontEmSize
+fontFace
+fontFile
+fontFileKey
+fontFileLoader
+fontFileReferenceKey
+fontFileReferenceKeySize
+fontFileStream
+FontInfo
+fontlab
+FontMatrix
+fontName
+FontName
+fontRevision
+fonts
+Fonts
+fontSzr
+fonttools
+fontTools
+FontTools
+foo
+fopen
+for
+For
+FOR
+forbid
+Force
+ForceBold
+forced
+foreach
+foreground
+Forest
+forget
+forgives
+fork
+Fork
+form
+Form
+FORM
+format
+Format
+FORMAT
+formatReserved
+formats
+Formats
+formatting
+formed
+former
+Former
+formerly
+forms
+Forms
+FORMS
+FORMULA
+forum
+forw
+forward
+FORWARD
+forwards
+found
+Found
+FOUND
+Foundation
+four
+Four
+FOUR
+fourinferior
+fouroldstyle
+foursuperior
+FOURTEEN
+fourth
+fOverrideDirection
+fp
+fprintf
+FPst
+fr
+frac
+FRACT
+fraction
+FRACTION
+fractional
+fractions
+FRACTIONS
+fragmentContext
+fragmentSize
+fragmentStart
+frame
+framework
+franc
+France
+frc
+fread
+Frédéric
+free
+Free
+FREE
+freed
+freedesktop
+Freedesktop
+freeing
+FreeLibrary
+freelocale
+freely
+freetype
+FreeType
+FREETYPE
+fref
+French
+frequent
+frequently
+fribidi
+friend
+Frisian
+Friulian
+from
+From
+FROM
+fromCoord
+FromGlyphs
+front
+frozen
+frp
+fRTL
+fscale
+Fsmall
+fsref
+FSRef
+fsSelection
+fstat
+fsType
+ft
+FT
+FTStringRange
+fu
+Fu
+fub
+fuc
+fue
+fuf
+fuh
+fui
+Fujian
+Fukien
+Fulah
+fulfilled
+Fulfulde
+full
+Full
+FULL
+fullAdvance
+fullName
+FullName
+fullset
+Fullwidth
+FULLWIDTH
+fully
+Fully
+fun
+func
+Func
+FUNC
+FUNCOBJ
+funcs
+Funcs
+FUNCS
+FUNCSIG
+function
+Function
+FUNCTION
+functionality
+functions
+Functions
+FuncType
+funcZ
+fundamental
+fundamentals
+FUnit
+FUnits
+fuq
+fur
+further
+Furthermore
+Futa
+future
+fuv
+Fuzhou
+fuzz
+fvar
+FVAR
+FVSes
+FWIDTH
+FWORD
+fy
+FYROM
+g
+G
+ga
+Ga
+gaa
+Gade
+Gaelic
+GAF
+gag
+Gagauz
+Gah
+Gahri
+Galice
+Galician
+Galla
+Gallurese
+gan
+Gan
+Ganda
+Ganja
+gap
+GAP
+gaps
+garbage
+Garhwali
+Garo
+Garret
+Garshuni
+gasp
+GASP
+GaspRange
+gaspRanges
+gather
+gaw
+gax
+gaz
+GB
+gbm
+GBoxedCopyFunc
+GBoxedFreeFunc
+gbreve
+Gbreve
+gbytes
+GBytes
+gc
+GC
+gcc
+GCC
+gce
+gchar
+gconstpointer
+gd
+gda
+gdef
+GDEF
+gdi
+GDI
+Ge
+Geez
+Gemination
+GEMINATION
+gen
+Gen
+GEN
+general
+General
+GENERAL
+generally
+Generally
+generate
+generated
+GenerateResults
+generates
+Generates
+Generating
+generic
+Generic
+GENERIC
+geok
+Geok
+Geometric
+Georgia
+Georgian
+GEORGIAN
+German
+germandbls
+Germany
+get
+Get
+GET
+GetCharVariantIndex
+getCombiningClass
+GetDC
+getenv
+GETENV
+GetFileSize
+GetFileSizeEx
+GetFontData
+GetGlyphPlacements
+getglyphs
+GetGlyphs
+getIntPropertyMaxValue
+getIntPropertyValue
+GetJustificationOpportunities
+getjustifiedglyphs
+GetJustifiedGlyphs
+GetLastWriteTime
+GetLocaleName
+GetModuleHandle
+getNFCInstance
+getNFDInstance
+GetNumberSubstitution
+getpagesize
+GETPAGESIZE
+GetParagraphReadingDirection
+GetProcAddress
+getRawDecomposition
+gets
+Gets
+getScript
+GetScriptProperties
+getShortName
+getter
+getters
+GetTextAtPosition
+GetTextBeforePosition
+getting
+Getting
+gez
+gfxShapedWord
+ggo
+GHAIN
+Gheg
+GHUNNA
+gid
+GID
+gidDDD
+gids
+gih
+Gikuyu
+gil
+Gilaki
+Gilbertese
+Gilyak
+GIMEL
+ginfo
+git
+Githabul
+github
+GitHub
+give
+Give
+given
+Given
+gives
+giving
+gju
+gkp
+gl
+Glagolitic
+GLAGOLITIC
+gld
+glib
+GLib
+GLIB
+glibc
+GLIBC
+glk
+global
+Global
+GLOBAL
+GlobalSubr
+globalsubrs
+globalSubrs
+globalSubrsInfo
+glue
+glyf
+GLYF
+glyid
+glyID
+glyph
+Glyph
+GLYPH
+glyphAdvances
+GlyphAnchors
+glyphArray
+glyphAssembly
+GlyphAssembly
+GlyphBitmapDataFormat
+glyphClassDef
+GlyphClasses
+glyphConstruction
+glyphCount
+glyphDataFormat
+glyphDataOffsets
+glyphFormat
+GlyphHeader
+glyphid
+glyphId
+glyphID
+GlyphID
+GLYPHID
+glyphIdArray
+glyphIdArrayLength
+GlyphIDs
+glyphIndex
+glyphIndices
+glyphMetrics
+glyphNameIndex
+glyphOffsets
+GLYPHPROP
+glyphProperties
+glyphs
+Glyphs
+GLYPHS
+glyphset
+GlyphVarData
+GM
+gmappedfile
+GMT
+gn
+gname
+gnn
+gno
+gnome
+gnu
+GNU
+GNUC
+gnw
+go
+goal
+GOAL
+goals
+Goan
+gobject
+GObject
+GOBJECT
+GOFFSET
+gog
+Gogo
+going
+gom
+gon
+Gondi
+GONDI
+gone
+good
+google
+Google
+Goronzy
+got
+Got
+Gothic
+GOTHIC
+goto
+gpos
+GPOS
+GPOSProxy
+gr
+grab
+graduated
+grained
+granted
+GRANTED
+Grantha
+GRANTHA
+granular
+granularly
+graph
+grapheme
+Grapheme
+GRAPHEME
+graphemes
+Graphemes
+GRAPHEMES
+graphic
+graphics
+Graphics
+graphicType
+graphite
+Graphite
+GRAPHITE
+grave
+Gravesmall
+greater
+greaterequal
+Greece
+Greek
+GREEK
+green
+Green
+Greenland
+Greenlandic
+greg
+grep
+grface
+Grid
+GRID
+Grigori
+grigorig
+group
+GROUP
+grouped
+Groupings
+grouprecord
+groups
+grow
+growFlags
+growing
+grows
+growth
+grt
+gru
+gsize
+Gsmall
+gsub
+GSUB
+gsubgpos
+GSUBGPOS
+GSUBProxy
+gsw
+gt
+gtk
+GTK
+gtype
+GType
+gu
+Guarani
+Guaraní
+guarantee
+guaranteed
+guarantees
+guards
+Guatemala
+guc
+GUEH
+guess
+guessing
+guf
+gug
+gui
+Guibei
+Guibian
+guillemotleft
+guillemotright
+guilsinglleft
+guilsinglright
+Guinea
+Guiyang
+Gujarati
+GUJARATI
+Gujari
+Guji
+GUJR
+guk
+Gulf
+Gumatj
+Gumuz
+gun
+GUnicodeScript
+GUnicodeType
+Gunjala
+GUNJALA
+Gupapuyngu
+Gurage
+Gurmukhi
+GURMUKHI
+GURU
+Gusii
+guz
+gv
+gvar
+GVAR
+gwi
+Gwich
+GX
+gxFontDescriptor
+gzip
+h
+H
+ha
+haa
+hack
+HACKMEM
+had
+Hadothi
+Hadrami
+hae
+HAFS
+HAH
+Haible
+HAIR
+Haitian
+Haji
+hak
+Hakha
+Hakka
+Halam
+halant
+Halant
+HALANT
+halants
+half
+Half
+HALF
+Halfwidth
+HALFWIDTH
+Halh
+HALN
+Hamer
+Hammer
+HAMZA
+HAMZAH
+Han
+HAN
+hand
+Hand
+handed
+handing
+handle
+Handle
+HANDLE
+handled
+handler
+handles
+handling
+hang
+hanging
+Hanging
+HANGING
+hangul
+Hangul
+HANGUL
+Hanifi
+HANIFI
+HANJA
+hans
+Hans
+hant
+Hant
+Hanunoo
+HANUNOO
+happen
+happened
+happening
+happens
+Happens
+happier
+happy
+har
+Harari
+Harauti
+hard
+harder
+hardest
+harfbuzz
+HarfBuzz
+HarffBuzz
+Haryanvi
+has
+Has
+HAS
+hash
+hashmap
+Hat
+hataf
+HATRAN
+HAU
+Hausa
+have
+Have
+HAVE
+having
+haw
+Hawaiian
+hAxis
+hay
+Haya
+haz
+Hazaragi
+hb
+HB
+HBASELINE
+HBFixed
+HBGlyphID16
+HBINT
+hbot
+hbotABCD
+hbsc
+hbshape
+hbsubset
+HBUCHAR
+HBUINT
+HBUSHORT
+hbview
+hdc
+HDC
+hdmx
+HDMX
+he
+HE
+hea
+head
+Head
+HEAD
+header
+Header
+HEADER
+headerfile
+headers
+Headers
+headerSize
+HeadlessArrayOf
+heap
+heavier
+heavily
+hebrew
+Hebrew
+HEBREW
+HEH
+height
+HEIGHT
+heightCount
+heights
+help
+helper
+Helper
+helpers
+helpful
+helps
+hence
+Hence
+here
+Here
+hereby
+Herero
+HEREUNDER
+Herzegovina
+HET
+heuristic
+Hexagram
+hflex
+hfont
+HFONT
+hh
+HH
+hhcurveto
+hhea
+HHEA
+hi
+hidden
+HIDDEN
+hide
+HIDE
+hiding
+HIEROGLYPHS
+high
+High
+HIGH
+higher
+highest
+Highland
+HIGHLEVEL
+highlight
+highlighting
+highly
+Hijazi
+hil
+Hiligaynon
+himalaya
+Himalaya
+Hindi
+Hindko
+hinstLib
+hint
+hinted
+hinting
+HINTING
+HintingDevice
+hintmask
+hints
+Hiragana
+HIRAGANA
+Hiri
+hiriq
+HIRIQ
+historical
+HISTORICAL
+history
+hit
+hji
+hk
+HK
+hlineto
+hlt
+hma
+hmc
+hmd
+hme
+hmetrics
+hmg
+hmh
+hmi
+hmj
+hml
+hmm
+hmn
+HMODULE
+Hmong
+HMONG
+hmoveto
+hmp
+hmq
+hms
+hmtx
+HMTX
+hmtxvmtx
+hmw
+hmy
+hmz
+HN
+hnd
+hne
+hnj
+hno
+ho
+Ho
+hoc
+hoi
+hoj
+HOJO
+Hokkien
+Hoklo
+holam
+HOLAM
+hold
+holder
+Holder
+HOLDER
+holding
+holds
+Holikachuk
+home
+Homebrew
+Honduras
+Hong
+Hongshuihe
+hood
+hook
+Hook
+hooks
+horiBearingX
+horiBearingY
+horiz
+HORIZ
+horizData
+horizGlyphCount
+horizGlyphCoverage
+horizontal
+Horizontal
+HORIZONTAL
+horizontally
+Horned
+Hosken
+Hosny
+hosted
+house
+House
+how
+however
+However
+HOWEVER
+HP
+hr
+HRESULT
+hrm
+hsb
+Hsmall
+hsn
+hstem
+hstemhm
+ht
+hTemplateFile
+html
+http
+https
+hu
+Huallaga
+Huamalíes
+Huánuco
+Huaylas
+Huaylla
+huge
+Huishui
+Huizhou
+huj
+human
+Humm
+Hungarian
+HUNGARIAN
+hungarumlaut
+Hungarumlautsmall
+Hungary
+hup
+Hupa
+hvar
+HVAR
+HVARTag
+HVARVVAR
+hvcurveto
+HVM
+hy
+hyphen
+HYPHEN
+hyphenation
+hypheninferior
+HYPHENS
+hyphensuperior
+hyw
+hz
+i
+I
+ia
+iacute
+Iacute
+Iacutesmall
+iba
+Iban
+ibb
+Ibibio
+IBMCPP
+ibmxl
+ibo
+ic
+Iceland
+Icelandic
+iCharPos
+iche
+icircumflex
+Icircumflex
+Icircumflexsmall
+icu
+ICU
+id
+ID
+ida
+Idakho
+idDelta
+idea
+ideal
+Ideally
+ideas
+IDEFs
+idempotent
+identical
+identically
+identification
+identified
+identifier
+identifiers
+identifies
+identify
+identifying
+identity
+IDEO
+Ideograms
+Ideographic
+IDEOGRAPHIC
+Ideographs
+IDEOGRAPHS
+idieresis
+Idieresis
+Idieresissmall
+Ido
+Idotaccent
+idRangeOffset
+ids
+IDs
+IDWriteFactory
+IDWriteFontFace
+IDWriteFontFile
+IDWriteFontFileLoader
+IDWriteFontFileStream
+IDWriteNumberSubstitution
+IDWriteTextAnalysisSink
+IDWriteTextAnalysisSource
+IDWriteTextAnalyzer
+idx
+ie
+Ie
+ietf
+IETF
+if
+If
+IF
+IFACEMETHOD
+IFACEMETHODIMP
+ifdef
+ifelse
+iff
+ifndef
+ig
+Igalia
+igb
+Igbo
+ignorable
+Ignorable
+IGNORABLE
+ignorables
+IGNORABLES
+ignore
+Ignore
+IGNORE
+IgnoreBaseGlyphs
+ignored
+Ignored
+IGNORED
+IgnoreFlags
+IgnoreLigatures
+IgnoreMarks
+ignoring
+igrave
+Igrave
+Igravesmall
+IHDR
+ii
+II
+iid
+IID
+ijc
+ijo
+Ijo
+ik
+ike
+ikt
+ill
+illegal
+ILLUMINATED
+illustrates
+ilo
+Ilokano
+Iloko
+image
+imageDataOffset
+imageFormat
+imageOffsetsZ
+images
+imagine
+Imbabura
+IMC
+immediately
+immutable
+IMPERIAL
+impl
+IMPL
+implement
+Implement
+IMPLEMENT
+implementation
+IMPLEMENTATION
+implementations
+Implementations
+implemented
+IMPLEMENTED
+implementing
+Implementing
+implementor
+implements
+Implements
+implicit
+IMPLICIT
+implied
+IMPLIED
+implies
+important
+Important
+impose
+impossible
+improve
+improved
+iMu
+in
+In
+IN
+inaccuracy
+Inari
+inc
+Inc
+inch
+INCIDENTAL
+Incidentally
+include
+Include
+included
+includes
+Includes
+including
+Including
+INCLUDING
+inclusion
+inclusive
+incoming
+incompatible
+incomplete
+inconsistencies
+incorporating
+incorrect
+incorrectly
+incorrectness
+increase
+Increase
+increased
+increases
+Increases
+increasing
+incrementally
+incurs
+IND
+indeed
+indefinitely
+indented
+independent
+Independent
+INDEPENDENT
+independently
+index
+Index
+INDEX
+IndexArray
+indexed
+Indexed
+indexes
+indexFormat
+indexing
+IndexMask
+IndexOf
+IndexSubtable
+IndexSubtableArray
+indexSubtableArrayOffset
+IndexSubtableFormat
+IndexSubtableHeader
+IndexSubtableRecord
+indexSubtablesZ
+indexTablesSize
+indexToLocFormat
+India
+indic
+Indic
+INDIC
+indicate
+indicated
+indicates
+Indicates
+indicating
+indication
+indices
+indicies
+IndicPositionalCategory
+IndicShapingInvalidCluster
+IndicSMatraCategory
+IndicSyllabicCategory
+IndicSyllableCategory
+INDIRECT
+indirection
+individual
+Individual
+individually
+indivisible
+Indonesia
+Indonesian
+inds
+industry
+IndV
+indx
+indy
+ineffective
+inefficient
+INEQUALITY
+inert
+INERT
+inf
+infer
+Infer
+INFERIORS
+inferred
+infinite
+infinitum
+infinity
+info
+INFO
+informaltable
+informatimago
+information
+Information
+infos
+infrequent
+ing
+Ingush
+inh
+INHERENT
+inherit
+Inherit
+INHERITED
+inherits
+inhibit
+init
+Init
+INIT
+initial
+Initial
+INITIAL
+Initialization
+initialize
+InitializeCriticalSection
+InitializeCriticalSectionEx
+initialized
+initializer
+INITIALIZER
+initializers
+initially
+Initially
+initialRandomSeed
+initiated
+initLookup
+initmediSubLookup
+initpos
+initSubLookup
+InitT
+ink
+inline
+inner
+innerIndex
+inout
+INOUT
+inplace
+input
+Input
+INPUT
+inputClassDef
+inputCount
+inputs
+inputX
+inputZ
+Inremental
+ins
+insane
+INSCRIPTIONAL
+insert
+Insert
+INSERT
+inserted
+insertion
+Insertion
+insertionAction
+insertions
+InsertionSubtable
+inserts
+inside
+Inside
+inspect
+inspecting
+inspects
+install
+Install
+installed
+installing
+Installing
+instance
+INSTANCE
+instanceCoords
+instanceCount
+InstanceRecord
+instances
+Instances
+instanceSize
+INSTANTIATE
+instantiated
+instead
+Instead
+instruct
+instruction
+instructionLength
+instructions
+Instructions
+INSTRUCTIONS
+INSUFFICIENT
+int
+Int
+INT
+integer
+Integer
+INTEGER
+integers
+integral
+integrate
+integrating
+integration
+Integration
+intel
+INTEL
+intended
+intentional
+intentionally
+Intentionally
+Inter
+interact
+InterCharacter
+interest
+interested
+interface
+interfaces
+interfering
+interim
+Interix
+interlaceMethod
+Interlingua
+Interlingue
+InterlockedCompareExchangePointer
+InterlockedExchange
+InterlockedExchangeAdd
+intermediate
+intermediateEndTuple
+IntermediateRegion
+intermediateStartTuple
+intermixed
+intern
+internal
+Internal
+INTERNAL
+internally
+Internally
+internals
+International
+INTERNATIONAL
+InternationalSymbols
+interp
+INTERP
+interpolate
+Interpolate
+interpolation
+interpret
+interpretation
+Interpretation
+interpreter
+interpreting
+INTERROBANG
+intersect
+intersections
+intersects
+INTERSECTS
+interviews
+intl
+into
+intOp
+intptr
+intrin
+intro
+introduced
+Introduced
+introducing
+Introduction
+ints
+IntType
+INTTYPE
+inttypes
+intuition
+Inuinnaqtun
+Inuktitut
+Inupiaq
+Inupiat
+Inupiatun
+invalid
+Invalid
+INVALID
+invert
+INVERTED
+inverts
+investigated
+investigation
+invisible
+Invisible
+INVISIBLE
+invocation
+invoke
+invoked
+invol
+involve
+involved
+involves
+io
+iOS
+iota
+IOTA
+ip
+IPA
+IPHONE
+Iran
+Iranian
+IranNastaliq
+Iraq
+Ireland
+Irish
+irrelevant
+is
+Is
+IS
+Isaac
+ISALNUM
+ISALPHA
+ISC
+isCombinedS
+isCombiningL
+isCombiningT
+isCombiningV
+isEmojiFont
+isFixedPitch
+ish
+isHangulTone
+isiXhosa
+isiZulu
+isL
+Islamic
+Islands
+Ismall
+isn
+iso
+ISO
+ISOAdobeCharset
+ISOL
+ISOLATE
+isolated
+ISOLATED
+Israel
+isRightToLeft
+ISSPACE
+issue
+issuecomment
+issues
+issuetracker
+isSupported
+isT
+Isukha
+isuperior
+isV
+it
+It
+ital
+Italian
+italic
+Italic
+ITALIC
+italicAngle
+ItalicAngle
+italics
+Italics
+italicsCorrection
+Italy
+item
+Item
+ITEM
+itemCount
+itemizedlist
+itemizer
+items
+Items
+ITEMS
+ItemSize
+iter
+Iter
+ITER
+iterable
+Iterable
+iterables
+iterate
+Iterate
+iterated
+iteration
+iterations
+iterator
+Iterator
+IteratorIn
+IteratorOut
+iterators
+iters
+its
+Its
+ITS
+itself
+iu
+IUnknown
+ivs
+iw
+Izon
+izzi
+j
+J
+ja
+jak
+Jakun
+jam
+Jamaica
+Jamaican
+Jambi
+jamo
+Jamo
+January
+Japan
+Japanese
+Jauja
+Javanese
+JAVANESE
+jax
+jbo
+jct
+JEEM
+JEH
+jg
+ji
+Jicarilla
+Jing
+Jinyu
+JIS
+JMO
+job
+join
+joiner
+Joiner
+JOINER
+joiners
+JOINERS
+joining
+Joining
+JOINING
+Jonathan
+Jordan
+jpg
+Jsmall
+json
+JSON
+jstf
+JSTF
+JstfLangSys
+JstfLangSysRecords
+JstfMax
+JstfModList
+JstfPriority
+JstfScript
+JstfScripts
+jt
+Jula
+JUNGSEONG
+Junín
+junk
+just
+Just
+JUST
+justClass
+JustClass
+justClassTable
+justification
+Justification
+JUSTIFICATION
+JustificationCategory
+justificationCharacter
+JustificationHeader
+justificationOpportunities
+justified
+justifiedGlyphAdvances
+justifiedGlyphOffsets
+justify
+JustifyGlyphAdvances
+JustWidthDeltaEntry
+jv
+jw
+jy
+k
+K
+ka
+kaa
+kab
+Kabardian
+Kabras
+Kabuverdianu
+Kabyle
+Kachchi
+Kachhi
+KAF
+Kaithi
+KAITHI
+Kalenjin
+Kalmyk
+Kalo
+Kalpak
+kam
+Kamba
+Kambaata
+kana
+KANA
+Kanaq
+Kanauji
+Kanbun
+Kangri
+Kangxi
+Kanji
+Kannada
+KANNADA
+Kanuri
+Kaqchikel
+kar
+Kara
+Karachay
+Karaim
+Karakalpak
+Karelian
+Karen
+kashida
+Kashida
+KashidaLike
+Kashmiri
+Kashubian
+Kaska
+kasra
+kasratan
+Katakana
+KATAKANA
+Katanga
+Kato
+kau
+Kaur
+Kayah
+KAYAH
+Kazakh
+Kazakhstan
+Kazim
+kb
+kbd
+kby
+kByte
+kca
+kCFAllocatorDefault
+kCFAllocatorNull
+kCFBooleanTrue
+kCFCompareEqualTo
+kCFNumberIntType
+kCFStringEncodingUTF
+kCFTypeArrayCallBacks
+kCFTypeDictionaryKeyCallBacks
+kCFTypeDictionaryValueCallBacks
+kCTFontAttributeName
+kCTFontCascadeListAttribute
+kCTFontEmphasizedSystemFontType
+kCTFontFeatureSelectorIdentifierKey
+kCTFontFeatureSettingsAttribute
+kCTFontFeatureTypeIdentifierKey
+kCTFontPostScriptNameKey
+kCTFontSystemFontType
+kCTFontUIFontEmphasizedSystem
+kCTFontUIFontSystem
+kCTFontURLAttribute
+kCTKernAttributeName
+kCTLanguageAttributeName
+kCTRunStatusNonMonotonic
+kCTRunStatusRightToLeft
+kCTTypesetterOptionForcedEmbeddingLevel
+kCTVersionNumber
+kCTVerticalFormsAttributeName
+kde
+kdr
+kdt
+kea
+Kebena
+Kedah
+keep
+Keep
+keeping
+KEHEH
+Keith
+Keiyo
+kek
+Kekchi
+Kentohe
+Kenya
+kept
+Kerinci
+kern
+KERN
+KernAAT
+KernAATSubTableHeader
+kernAction
+kernActionIndex
+KERNEL
+kernIndex
+kerning
+Kerning
+KERNING
+kerningv
+KernOT
+KernOTSubTableHeader
+KernPair
+kerns
+KernSubTable
+KernSubTableFormat
+KernSubTableHeader
+kernValue
+kernValueCount
+kernValueZ
+kerx
+KERX
+KerxSubTable
+KerxSubTableFormat
+KerxSubTableHeader
+KerxTable
+kerxTupleKern
+Kew
+kex
+key
+Key
+KEY
+keys
+kfa
+KFGQPC
+kfr
+kfx
+kfy
+kg
+kha
+KHAH
+Khakas
+Khakass
+Khaled
+Khamti
+Khanty
+Kharoshthi
+KHAROSHTHI
+Khasi
+Khayo
+khb
+Khengkha
+Khimi
+khk
+khmer
+Khmer
+KHMER
+KhmerUI
+Khojki
+KHOJKI
+Khorasani
+Khowar
+kht
+Khudawadi
+KHUDAWADI
+Khumi
+Khutsuri
+khw
+ki
+kick
+KIKAKUI
+Kikongo
+Kikuyu
+Kildin
+Killer
+KILLER
+Kimbundu
+kind
+kinda
+kinds
+Kingdom
+kinoho
+kINVALID
+Kinyarwanda
+Kiowa
+Kipsigis
+Kirghiz
+KIRGHIZ
+Kiribati
+Kirmanjki
+Kisa
+Kisi
+Kisii
+Kissi
+Kistane
+Kiswahili
+Kita
+Kituba
+kiu
+Kiwai
+kj
+kjd
+kjh
+kjp
+kjz
+kk
+kkz
+kl
+klass
+klasses
+kln
+km
+kMaxCallLimit
+kmb
+kmr
+kmw
+kmz
+kn
+knc
+KNDA
+kng
+knn
+know
+knowing
+Knowing
+knowledge
+known
+Known
+knows
+Knuth
+ko
+Ko
+Kodagu
+Kodava
+koi
+kok
+Kokni
+Kölsch
+Komi
+Komo
+Komso
+Kong
+Kongo
+Konkani
+Konso
+Konyanka
+Koongo
+Koorete
+Korea
+Korean
+Koryak
+kos
+Kosraean
+Kota
+koy
+Koyukon
+kpe
+Kpelle
+kpv
+kpy
+kqs
+kqy
+kr
+krc
+kri
+Krio
+krl
+krt
+kru
+Krymchak
+ks
+ksh
+kShort
+kSizeLimit
+Ksmall
+kss
+ksw
+ktb
+ktu
+ktw
+ku
+Kuanyama
+Kubu
+Kui
+Kukna
+Kullu
+Kulvi
+kum
+Kumaoni
+Kumyk
+Kumzari
+Kuna
+Kurdish
+Kurukh
+Kuskokwim
+Kutai
+kuu
+Kuwait
+Kuy
+kv
+kvb
+kvr
+kw
+KW
+kwy
+kxc
+kxd
+kxu
+ky
+Kyrgyz
+Kyrgyzstan
+kyu
+kZero
+l
+L
+la
+La
+Laari
+label
+LABEL
+labels
+lack
+lad
+Ladakhi
+Ladin
+Ladino
+Lahuli
+laid
+Lak
+Laki
+Lalana
+Lam
+LAM
+lamAlefLigaturesSubLookup
+Lambadi
+Lambani
+Lambayeque
+LAMED
+lamInitLigature
+lamLigatureSet
+Lampung
+lang
+langs
+langsys
+langSys
+LangSys
+LANGSYS
+LangSysRecords
+LangSysTag
+LangTag
+language
+Language
+LANGUAGE
+LanguageGroup
+languageID
+languages
+Languages
+LANGUAGES
+languagetags
+Lanka
+Lao
+LAO
+large
+Large
+LARGE
+larger
+largest
+Largest
+LArrayOf
+lash
+last
+Last
+LAST
+lastCode
+lastGlyphIndex
+LastResort
+lastWriteTime
+LATE
+later
+latest
+latg
+Latg
+Latgalian
+latin
+Latin
+LATIN
+latn
+latter
+Latvia
+Latvian
+Lauricocha
+Lawoi
+lay
+layer
+Layer
+layering
+LayerRecord
+layers
+layersZ
+layout
+Layout
+LAYOUT
+LayoutRTL
+lays
+Laz
+lazily
+lazy
+Lazy
+lb
+LBAR
+LBase
+LBASE
+lbe
+lbj
+lbl
+LC
+lcar
+LCAR
+lcarFormat
+lce
+lcf
+LCount
+LCOUNT
+ld
+ldi
+Le
+LE
+lead
+LEADER
+leading
+Leading
+LEADING
+leadingBearingX
+Lealao
+LEAN
+leans
+least
+leave
+Leave
+LeaveCriticalSection
+leaving
+Lebanon
+Leboa
+left
+Left
+LEFT
+leftC
+leftClass
+leftClassCount
+leftClassTable
+leftSide
+legacy
+Legacy
+LEGACY
+legally
+legit
+Lemberg
+len
+LEN
+LENG
+length
+Length
+LENGTH
+lengthed
+lengths
+lengthy
+lenient
+lenM
+lenP
+LENTICULAR
+LenType
+Leone
+Lepcha
+LEPCHA
+less
+lessequal
+let
+Let
+lets
+Lets
+letter
+Letter
+LETTER
+Letterlike
+letters
+Letters
+Levantine
+level
+Level
+LEVEL
+levels
+leverage
+lexicographic
+lez
+Lezghian
+Lezgi
+lf
+LF
+lfCharSet
+lfFaceName
+lfHeight
+lg
+lhs
+Lhs
+li
+Li
+LI
+LIABLE
+Lianshan
+libc
+libcairo
+Liberia
+libfreetype
+libglib
+libharfbuzz
+libkern
+Libon
+libraries
+Libraries
+library
+Library
+LibreOffice
+libs
+libstdc
+libtool
+Libya
+Libyan
+license
+LICENSE
+lidentity
+Liechtenstein
+lif
+life
+lifecycle
+lifecycles
+lig
+LIG
+liga
+ligAction
+LigActionFlags
+ligActionIndex
+LigActionLast
+LigActionOffset
+LigActionStore
+ligActionTable
+ligate
+ligated
+LIGATED
+ligating
+ligation
+ligature
+Ligature
+LIGATURE
+ligatureArray
+LigatureArray
+LigatureAttach
+ligatureCoverage
+LigatureCoverage
+ligatureData
+LigatureEntry
+LigatureEntryT
+LigatureGlyph
+ligatures
+Ligatures
+LIGATURES
+ligatureSet
+LigatureSet
+LigatureSetOffsets
+LigatureSetOffsetsArray
+LigatureSubst
+LigatureSubstFormat
+LigatureSubtable
+ligbase
+LIGBASE
+LigCaretClassEntry
+ligCaretList
+LigCaretList
+ligGlyph
+LigGlyph
+light
+Light
+LIGHT
+lighter
+lightweight
+ligs
+Ligurian
+lij
+like
+Like
+likely
+Likewise
+Lima
+Limbu
+LIMBU
+Limburgish
+limit
+Limit
+LIMIT
+limitation
+limited
+Limited
+LIMITED
+limiting
+limits
+lindex
+line
+LINE
+linear
+Linear
+LINEAR
+linearly
+Linebreak
+lineBreakpoints
+lineGap
+lines
+lineWidth
+Lingala
+lingo
+linguistic
+LINGUISTIC
+linguistically
+linguistics
+link
+linked
+linkedValue
+linking
+links
+linux
+Linux
+Lipan
+lis
+list
+List
+LIST
+listed
+listinfo
+listitem
+lists
+Lisu
+LISU
+literal
+Literary
+Lithuania
+Lithuanian
+little
+LITTLE
+Liujiang
+Liuqian
+liw
+ljmo
+LJMO
+ljp
+lkb
+lki
+lklug
+lko
+lks
+ll
+Ll
+lld
+LLLEEEEEEEGGGG
+LLONG
+LLVM
+lm
+Lm
+lmn
+lmo
+ln
+LNNOffsetTo
+lo
+Lo
+load
+Load
+LOAD
+loaded
+loader
+loaders
+loading
+LoadLibrary
+loc
+loca
+local
+locale
+Locale
+LOCALE
+localeName
+localized
+localsubr
+LocalSubr
+localsubrs
+localSubrs
+localSubrsInfos
+Locate
+located
+location
+Location
+locations
+lock
+lockable
+Lockable
+locl
+locName
+LOffsetArrayOf
+LOffsetLArrayOf
+LOffsetTo
+log
+LOG
+LOGFONT
+logfontw
+LOGFONTW
+logic
+logical
+Logical
+logicalnot
+LogicalOrder
+Logo
+logograms
+Logooli
+LOGOS
+Logudorese
+Lohar
+lohit
+Lohit
+Loja
+lojban
+Lojban
+lom
+Loma
+Lombard
+Lomwe
+Loncong
+lone
+Lonely
+long
+Long
+LONG
+LONGDATETIME
+longer
+longint
+longintdict
+LongMetric
+longMetricZ
+longword
+look
+Look
+lookahead
+lookaheadClassDef
+lookaheadCount
+lookaheadX
+looked
+looking
+Looking
+looks
+Looks
+lookup
+Lookup
+LOOKUP
+lookupCount
+lookupFlag
+LookupFlag
+LookupFlags
+LookupFormat
+lookupIndex
+lookupList
+LookupList
+lookupListIndex
+lookupOffset
+lookupOrderZ
+lookupRecord
+LookupRecord
+LookupRecords
+lookupRecordX
+lookups
+Lookups
+LOOKUPS
+LookupSegmentArray
+LookupSegmentSingle
+LookupSingle
+lookupTable
+lookupType
+LookupType
+lookupX
+loop
+Loop
+loops
+loose
+loosely
+Lortie
+lose
+LOSS
+lossless
+lost
+lot
+Lots
+low
+Low
+LOW
+lower
+Lower
+LOWER
+lowercase
+LOWERCASE
+lowercased
+lowerLimit
+lowest
+lowestRecPPEM
+Lowland
+LowPart
+lozenge
+lParameter
+lps
+lpSecurityAttributes
+LR
+lrc
+lri
+lrm
+lsb
+lsbMap
+lsearch
+lslash
+Lslash
+Lslashsmall
+lsm
+Lsmall
+lsuperior
+lt
+Lt
+ltag
+LTAG
+ltg
+lto
+ltr
+LTR
+lts
+lu
+Lu
+Lü
+lua
+Luba
+Lubu
+Lucian
+Lue
+LUE
+Lule
+Lulua
+luo
+Luo
+Luopohe
+Luri
+lus
+Lushai
+lux
+Luxembourg
+Luxembourgish
+luy
+Luyia
+luz
+lv
+LV
+lvalue
+lvalues
+lvs
+LVT
+lwg
+lwsync
+lx
+Lycian
+LYCIAN
+Lydian
+LYDIAN
+lzh
+lzz
+m
+M
+ma
+Maasina
+MAbv
+mac
+Mac
+MAC
+Macao
+Macedonia
+Macedonian
+machine
+MACHINE
+machinery
+MACHINERY
+machines
+Macintosh
+macos
+macOS
+MacPorts
+macro
+macrolanguage
+macroman
+MACROMAN
+macron
+Macronsmall
+macros
+Macros
+macStyle
+mad
+MADDA
+MADDAH
+made
+Madura
+Madurese
+mag
+Magahi
+magic
+magicNumber
+Mahafaly
+Mahajani
+MAHAJANI
+Mahjong
+mai
+MAI
+mailing
+mailman
+main
+Main
+MAIN
+mainly
+maintain
+maintained
+MAINTENANCE
+MAITAIKHU
+Maithili
+Majang
+major
+Major
+MAJOR
+mak
+Makasar
+MAKASAR
+make
+Make
+MAKE
+makeotf
+makeOTF
+MakeOTF
+makes
+Makes
+Makhuwa
+making
+Making
+Makonde
+MAKSURA
+Malagasy
+Malay
+Malayalam
+MALAYALAM
+Malaysia
+Maldives
+Maldivian
+Male
+Malinke
+malloc
+Malta
+Maltese
+Malvi
+mam
+Mam
+man
+Manado
+manage
+managed
+management
+manages
+Manchu
+Mandaic
+MANDAIC
+Mandar
+Mandarin
+Mandingo
+Mandinka
+Manga
+Manichaean
+MANICHAEAN
+manifest
+Manifest
+MANIFEST
+manifestData
+ManifestLookup
+Maninka
+Maninkakan
+Manipuri
+manner
+manpage
+Mansi
+manual
+Manual
+MANUAL
+manufacturer
+MANUFACTURER
+Manx
+many
+Many
+Maore
+Maori
+map
+Map
+MAP
+mapCount
+mapDataZ
+mapLen
+mapped
+mapper
+mapping
+Mapping
+mappings
+maps
+Maps
+Mapudungun
+MapViewOfFile
+MapViewOfFileFromApp
+Mara
+Marachi
+Marama
+Marathi
+MARBUTA
+March
+Marchen
+MARCHEN
+margins
+Margos
+Mari
+mark
+Mark
+MARK
+markAnchor
+markAnchorPoint
+markArray
+MarkArray
+markAttachClassDef
+MarkAttachmentType
+markBase
+MarkBase
+MarkBasePos
+MarkBasePosFormat
+MarkCategory
+markControlPoint
+markCoverage
+MarkCoverage
+marked
+markedInsertBefore
+MarkedInsertBefore
+markedInsertCount
+MarkedInsertCount
+markedInsertIndex
+markedInsertList
+MarkedIsKashidaLike
+markers
+markFilteringSet
+markFilteringSetX
+MarkFirst
+MarkGlyph
+MarkGlyphSets
+markGlyphSetsDef
+MarkGlyphSetsFormat
+markIndex
+marking
+MarkLast
+markLig
+MarkLig
+MarkLigPos
+MarkLigPosFormat
+markMark
+MarkMark
+MarkMarkPos
+MarkMarkPosFormat
+MarkRecord
+MarkRecords
+marks
+Marks
+MARKS
+Markweeta
+markX
+markY
+Marma
+Marshallese
+Martin
+Martín
+Marwari
+Masaram
+MASARAM
+Mashan
+Masikoro
+mask
+Mask
+MASK
+masks
+Masks
+master
+Master
+MASTERS
+match
+Match
+MATCH
+matched
+matcher
+matches
+matching
+material
+math
+Math
+MATH
+mathConstants
+MathConstants
+mathematical
+Mathematical
+MATHEMATICAL
+mathematics
+MathGlyphAssembly
+MathGlyphConstruction
+mathGlyphInfo
+MathGlyphInfo
+MathGlyphPartRecord
+mathGlyphVariantRecord
+MathGlyphVariantRecord
+MathGlyphVariantRecords
+mathItalicsCorrectionInfo
+MathItalicsCorrectionInfo
+mathKern
+MathKern
+mathKernCoverage
+mathKernInfo
+MathKernInfo
+MathKernInfoRecord
+mathKernInfoRecords
+MathKernInfoRecords
+MathSymbols
+mathTopAccentAttachment
+MathTopAccentAttachment
+MathValueRecord
+mathValueRecords
+MathValueRecords
+mathValueRecordsZ
+mathVariants
+MathVariants
+matra
+Matra
+MATRA
+matras
+Matras
+matrix
+Matrix
+matrixZ
+matter
+Matthias
+Mattole
+Matu
+max
+Max
+MAX
+maxBeforeBL
+maxComponentDepth
+maxComponentElements
+maxCompositeContours
+maxCompositePoints
+maxContours
+maxCoord
+MaxDebugDepth
+maxExtent
+maxFunctionDefs
+maxGlyphCount
+maximum
+Maximum
+maximumLimit
+maximums
+maxInstructionDefs
+maxMemType
+maxp
+MAXP
+maxPoints
+maxpV
+maxSizeOfInstructions
+maxStackElements
+maxStorage
+maxTwilightPoints
+maxVal
+maxValue
+maxWidth
+maxZones
+may
+May
+MAY
+Mayan
+maybe
+Maybe
+MAYBE
+Mayek
+MAYEK
+Mayo
+Mazanderani
+mb
+MB
+mbarrier
+Mbembe
+mBidiLevel
+MBlw
+mbo
+Mbo
+mbstowcs
+Mbundu
+Mbyá
+Mc
+mcm
+mct
+mCurrentRun
+md
+MD
+mdash
+mData
+mdf
+mdr
+mdy
+me
+Me
+mean
+MEAN
+meaning
+meaningfully
+meanings
+means
+Meanwhile
+measurable
+measure
+MEASURE
+measured
+measuring
+mechanical
+mechanism
+MED
+MEDEFAIDRIN
+medi
+MEDI
+medial
+Medial
+MEDIAL
+median
+medifinaLamAlefSubLookup
+mediLookup
+mediSubLookup
+Medium
+MEDIUM
+Medumba
+MEEM
+Meetei
+MEETEI
+Meh
+MEM
+memaccess
+member
+members
+Members
+memcmp
+memcpy
+memmove
+memoize
+memory
+Memory
+MEMORY
+MemoryBarrier
+memset
+men
+Mende
+MENDE
+Mengisa
+mentioned
+mentions
+menu
+meo
+mer
+MERCHANTABILITY
+merge
+Merge
+merged
+merger
+merges
+merging
+Merging
+MEROITIC
+Meru
+Merwari
+Mescalero
+Mesopotamian
+message
+MESSAGE
+messaging
+messed
+meta
+Meta
+META
+metadata
+Metadata
+metamorphosis
+Metamorphosis
+meteg
+method
+methods
+Methods
+metric
+METRIC
+metricDataFormat
+metrics
+Metrics
+METRICS
+Mewari
+Mewati
+Mexico
+mfa
+mfb
+mfe
+mFontFileStream
+mg
+mGlyphCount
+mGlyphStart
+mh
+MH
+mhr
+mhv
+mi
+Miao
+MIAO
+Michiharu
+micro
+MICRO
+microsoft
+Microsoft
+microsqoft
+MicroType
+mid
+middle
+Middle
+midnight
+might
+Might
+min
+Min
+MIN
+minAdvanceSB
+minAfterBL
+Minangkabau
+minConnectorOverlap
+minCoord
+mind
+mingw
+MinGW
+MINGW
+minHeight
+MINI
+minimal
+minimum
+Minimum
+minimumLimit
+minimums
+Minjangbal
+Minjungbal
+minLeadingBearing
+minlen
+minMax
+MinMax
+minMaxCoord
+minMemType
+Minnan
+minor
+MINOR
+minOriginSB
+minorVersion
+minstd
+minTrailingBearing
+minus
+MINUS
+minVal
+minValue
+minVersion
+Minz
+Mirandese
+Miraya
+mirror
+mirroring
+Mirroring
+misc
+Misc
+Miscellaneous
+MISMATCH
+mIsSideways
+missing
+MIT
+mix
+mixed
+mixin
+Mixin
+Mixing
+mixture
+Mizo
+mk
+mkmk
+mku
+mkw
+ml
+ML
+mLocaleName
+mlq
+MLYM
+mm
+MM
+mman
+MMAN
+mmap
+Mmap
+MMAP
+mmr
+mn
+Mn
+mnc
+mnemonics
+mni
+mnk
+mnp
+mns
+mnw
+mo
+mod
+MOD
+mode
+Mode
+MODE
+model
+models
+Modern
+modes
+Modi
+MODI
+modification
+Modification
+modifications
+MODIFICATIONS
+modified
+Modified
+MODIFIED
+modifiedClusterMap
+modifiedGlyphAdvances
+modifiedGlyphIndices
+modifiedGlyphOffsets
+modifier
+Modifier
+MODIFIER
+modifiers
+modify
+Modify
+modifying
+Modifying
+MODIFYING
+modulo
+moh
+Mohawk
+Moksha
+Moldavian
+Moldova
+Moldovan
+Moluccan
+Mon
+Monaco
+Mongolia
+mongolian
+Mongolian
+MONGOLIAN
+Mono
+monospaced
+MONOSPACED
+monotone
+MONOTONE
+monotonic
+monotonically
+monster
+Months
+Moose
+more
+More
+MORE
+MoreToolbox
+Morisyen
+Moroccan
+Morocco
+morphHeader
+mort
+MORT
+mortmorx
+morx
+MORX
+mos
+Mossi
+most
+Most
+mostly
+Motorola
+Motu
+move
+Move
+moved
+moves
+moveto
+moving
+Moving
+mozilla
+Mozilla
+mpe
+MPre
+mprotect
+MPROTECT
+MPst
+mqg
+mr
+MR
+mReadingDirection
+mrh
+mrj
+Mro
+MRO
+mRunHead
+ms
+MS
+msc
+MSC
+mScript
+msdn
+msg
+MSG
+msgidx
+msgstr
+msh
+msi
+mSize
+Msmall
+msuperior
+MSVC
+mt
+MT
+mText
+mTextLength
+mTextStart
+mtr
+mtx
+mu
+much
+mui
+MUJ
+mul
+MulFix
+Muller
+mult
+Multani
+MULTANI
+multi
+multiple
+Multiple
+MULTIPLE
+MultipleSubst
+MultipleSubstFormat
+multiplication
+multiplicative
+multiplied
+MULTIPLIED
+multiply
+MULTIPLY
+multiplying
+mults
+Mundari
+munmap
+mup
+muq
+mus
+Muscogee
+Musi
+Musical
+MUSICAL
+must
+Must
+MUST
+mutable
+mutex
+MUTEX
+mutually
+mvar
+MVAR
+mvb
+mve
+mvf
+MW
+Mwali
+mwk
+mwl
+mwr
+mww
+my
+MY
+myanmar
+Myanmar
+MYANMAR
+mym
+mymr
+myn
+myq
+myv
+mzn
+n
+N
+na
+NABATAEAN
+Nacional
+nag
+Naga
+Nagari
+Nagri
+NAGRI
+nags
+nah
+Nahuatl
+naive
+Najdi
+nalf
+nalfType
+name
+Name
+NAME
+named
+Named
+nameid
+nameID
+NameID
+nameids
+nameIndex
+NameIndex
+nameIndexOffset
+nameList
+namely
+Namely
+nameOffset
+NameRecord
+nameRecordZ
+names
+Names
+NAMES
+nameSIDs
+namespace
+Namespace
+NAMESPACE
+namesX
+namesZ
+nameTag
+Naming
+nan
+Nan
+Nanai
+Nandi
+Nandinagari
+NANDINAGARI
+nap
+Napo
+NARROW
+narrowing
+nasalization
+Naskapi
+native
+NativeFontResourceDWrite
+natural
+Nauru
+Nauruan
+navajo
+Navajo
+nb
+NC
+nClasses
+nCodes
+NCount
+NCOUNT
+nd
+Nd
+ndash
+Ndau
+ndc
+Ndebele
+NDEBUG
+Ndonga
+nds
+Ndzwani
+ne
+Neapolitan
+necessarily
+necessary
+need
+Need
+needed
+needing
+needs
+Needs
+neg
+NEG
+negation
+negative
+Negative
+NEGATIVE
+Negeri
+NEGLIGENCE
+negotiate
+neighboring
+neither
+nel
+Nenets
+Neo
+Nepal
+Nepali
+nesting
+NESTING
+net
+NetBSD
+Netherlands
+neuter
+neutrals
+never
+Never
+nevertheless
+new
+New
+NEW
+Newa
+NEWA
+Newari
+newBits
+newCount
+newer
+newlocale
+NEWLOCALE
+newly
+newRun
+newState
+next
+Next
+NEXT
+nextRun
+NFC
+NFD
+ng
+NG
+nga
+Ngawn
+Ngazidja
+Ngbaka
+ngl
+ngo
+NGOEH
+Ngoni
+nhd
+nibble
+Nibble
+nibbles
+Nicaragua
+nice
+Niger
+Nigeria
+Nigerian
+nikhahit
+Nikhahit
+NIKHAHIT
+nil
+NIL
+Nimadi
+nindex
+nine
+NINE
+nineinferior
+nineoldstyle
+ninesuperior
+NINETEEN
+niq
+Nirmala
+Nisi
+niu
+Niuean
+niv
+NJ
+Njua
+njz
+NKD
+nko
+NKo
+NKO
+Nkoo
+nl
+Nl
+NLCCHARACTERS
+nle
+nLeft
+nmemb
+nn
+NNOffsetTo
+no
+No
+NO
+nod
+node
+nodes
+noe
+noErr
+nog
+Nogai
+nominal
+NOMINAL
+nominalValue
+nominalWidthX
+non
+Non
+NON
+Nonaka
+NonAlphabetic
+nonbreakingspace
+noncontextual
+Noncontextual
+NoncontextualSubtable
+nonDefault
+nonDefaultUVS
+NonDefaultUVS
+none
+NONE
+nonexistent
+Nong
+nonliteral
+nonmarkingreturn
+nonmonotonic
+nonnull
+nonspacing
+NonStop
+nonzero
+NOON
+NOP
+noporpoise
+nor
+Nor
+NORESERVE
+Norfolk
+normal
+NORMAL
+normalization
+Normalization
+NORMALIZATION
+normalize
+NORMALIZE
+normalized
+normalizer
+normally
+Normally
+North
+NORTH
+Northeastern
+Northern
+Northwest
+Northwestern
+Norway
+Norwegian
+noStretchValue
+not
+Not
+NOT
+notable
+notably
+Notably
+Notation
+notdef
+NOTDEF
+NotDefault
+note
+Note
+NOTE
+noted
+notequal
+notes
+NOTES
+nothing
+Nothing
+notice
+Notice
+noticeably
+notification
+notified
+notifiers
+NOTIMPL
+noting
+notionally
+Noto
+NotoSerif
+nounihan
+nov
+novalidate
+NOVAR
+Novial
+now
+Now
+np
+npi
+nqo
+nr
+nRanges
+nSettings
+nSizes
+nsk
+NSLanguage
+Nsmall
+nso
+nSubrs
+nsuperior
+nSups
+ntilde
+Ntilde
+Ntildesmall
+nTracks
+Nüa
+Nuke
+NUKT
+nukta
+Nukta
+NUKTA
+nul
+NUL
+null
+Null
+NULL
+nullable
+NullHelper
+NullPool
+NullPriority
+nullptr
+num
+Num
+NUM
+numBaseGlyphs
+number
+Number
+NUMBER
+numberOfContours
+numberOfFaces
+numberOfIndexSubtables
+numberOfLongMetrics
+numbers
+Numbers
+NUMBERS
+numbersign
+numberSubstitution
+numBlends
+numColorRecords
+numColors
+numeral
+NUMERAL
+numerals
+Numerals
+numeration
+NUMERATOR
+numeric
+numerical
+Numerical
+numGlyphs
+numLayers
+numNamedParameters
+numOfHMetrics
+numPalettes
+numParameters
+numr
+numRecords
+numScriptCode
+numTables
+numValues
+NUN
+nUnits
+NUSHU
+Nuskhuri
+nv
+ny
+Nyala
+Nyamwezi
+Nyanja
+Nyankole
+nyd
+NYEH
+NYIAKENG
+Nyishi
+nym
+nyn
+Nynorsk
+Nyore
+nza
+o
+O
+oacute
+Oacute
+Oacutesmall
+oasis
+OASIS
+obj
+OBJ
+object
+Object
+OBJECT
+objects
+Objects
+objidx
+OBLIGATION
+oblique
+Oblique
+OBLIQUE
+obliqueing
+obscure
+Obsolete
+obsoleted
+ObsoleteTypes
+obtained
+obvious
+oc
+occasionally
+Occitan
+occupancy
+occupy
+occurrence
+occurrences
+occurring
+occurs
+ocircumflex
+Ocircumflex
+Ocircumflexsmall
+odd
+oddly
+Odia
+odieresis
+Odieresis
+Odieresissmall
+oe
+OE
+OEM
+OEsmall
+of
+Of
+OF
+off
+Off
+OFF
+offer
+offers
+offload
+offs
+OFFS
+offset
+Offset
+OFFSET
+OffsetArrayOf
+offsetArrayZ
+OffsetListOf
+offsetof
+offsets
+Offsets
+OffsetTable
+OffsetTables
+OffsetTo
+offsetToAxisValueOffsets
+offsetToIndex
+offsetToSubtable
+OffsetType
+offsetZ
+offSize
+ofs
+Ofs
+often
+Often
+og
+Ogham
+OGHAM
+ogonek
+Ogoneksmall
+ograve
+Ograve
+Ogravesmall
+Oh
+Oirat
+oj
+ojb
+ojc
+ojg
+Oji
+Ojibwa
+Ojibway
+Ojitlán
+ojs
+ojw
+ok
+Ok
+OK
+oki
+Okiek
+okm
+Ol
+OL
+old
+Old
+OLD
+older
+Older
+OLDER
+om
+Oman
+Omani
+Omega
+omitted
+on
+On
+ON
+once
+Once
+one
+One
+ONE
+OneByteIntFirst
+OneByteIntLast
+onedotenleader
+oneeighth
+onefitted
+onehalf
+oneinferior
+oneoldstyle
+onequarter
+ones
+onesuperior
+onethird
+only
+Only
+ONLY
+onto
+OOP
+op
+Op
+OP
+opaque
+Opaque
+opbd
+OPBD
+opbdFormat
+opcode
+OpCode
+opcodes
+opeator
+open
+Open
+OPEN
+OpenBSD
+opentype
+OpenType
+OPENTYPE
+OpenTypeFontFace
+OpenTypeFontFile
+OpenTypeTable
+operand
+operands
+operate
+operates
+operating
+operation
+operations
+Operations
+operator
+Operator
+OPERATOR
+operators
+Operators
+opportunities
+OPPORTUNITY
+opposite
+ops
+OPS
+opset
+OPSET
+opStart
+opstr
+OPSTR
+opsz
+opszr
+optical
+Optical
+OPTICAL
+OpticalBounds
+OpticalSize
+optimal
+optimally
+optimization
+optimizations
+optimize
+Optimize
+OPTIMIZE
+optimized
+opting
+option
+OPTION
+optional
+Optional
+OPTIONAL
+optionally
+options
+OPTIONS
+opts
+or
+Or
+OR
+oracle
+Orang
+orc
+order
+Order
+ORDER
+ordered
+orderedlist
+ordering
+ordfeminine
+ordinal
+ORDINALS
+ordmasculine
+org
+Organization
+oriented
+orig
+origin
+Origin
+original
+originally
+Originally
+originated
+origins
+origRun
+Oriya
+ORIYA
+Orma
+orn
+ORNAMENT
+ORNAMENTS
+Oromo
+ors
+orthogonal
+orthographic
+Orthographic
+orthographically
+ory
+ORYA
+os
+OS
+OSAGE
+OSAtomic
+OSAtomicAdd
+OSAtomicCompareAndSwap
+OSAtomicCompareAndSwapPtrBarrier
+oslash
+Oslash
+Oslashsmall
+Osmall
+Osmanya
+OSMANYA
+OSMemoryBarrier
+Ossetian
+OSStatus
+osuperior
+ot
+OT
+otf
+otFeatureTag
+OTFontFileVal
+OTHeader
+other
+Other
+OTHER
+OtherBlues
+others
+otherwise
+Otherwise
+OTHERWISE
+otilde
+Otilde
+Otildesmall
+otspec
+Ottawa
+OTTO
+otw
+Ouch
+OUCH
+ought
+our
+Our
+ourself
+ourselves
+out
+Out
+OUT
+outbuffer
+outcome
+outer
+Outer
+outerIndex
+outline
+Outline
+OUTLINE
+OUTLINED
+outlines
+OUTOFMEMORY
+outOfRange
+output
+Output
+OutputArray
+outside
+outward
+over
+OVERBAR
+overflow
+OVERFLOW
+Overflowed
+overflows
+Overflows
+overhead
+overlap
+OVERLAP
+OVERLAPPED
+overlapping
+OVERLAPPING
+OVERLAY
+overloaded
+overloading
+overridden
+override
+Override
+OVERRIDE
+overriden
+overrides
+Overrides
+overriding
+overstrike
+Overstruck
+OVERSTRUCK
+overview
+overwrite
+Owen
+own
+owned
+ownership
+Ozumacín
+p
+P
+pa
+Pa
+PA
+pABC
+Pacaraos
+pack
+package
+packages
+packed
+pad
+padauk
+Padauk
+padded
+padding
+PADMA
+pag
+page
+PAGE
+pages
+pagesize
+PAGESIZE
+Pahari
+PAHAWH
+Pahlavi
+PAHLAVI
+PaintType
+pair
+Pair
+Paired
+pairing
+PairPos
+PairPosFormat
+pairs
+Pairs
+pairSet
+PairSet
+PairValueRecord
+PairValueRecords
+pairwise
+Paite
+Pakistan
+Palantla
+Palauan
+Palaung
+Palestinian
+palette
+Palette
+PALETTE
+paletteFlagsZ
+paletteLabelsZ
+palettes
+Pali
+PALMYRENE
+Palpa
+pam
+Pampanga
+Pampangan
+Panama
+Panao
+Pangasinan
+pango
+Pango
+Panjabi
+panose
+Pao
+pap
+Papiamento
+Papiamentu
+para
+paragraph
+PARAGRAPH
+paragraphs
+Paraguay
+Paraguayan
+parallel
+param
+PARAM
+parameter
+parameters
+Parameters
+PARAMETERS
+params
+PARAMS
+paren
+parenleft
+parenleftinferior
+parenleftsuperior
+parenright
+parenrightinferior
+parenrightsuperior
+parent
+Parent
+parentheses
+PARENTHESIS
+parity
+parse
+parsed
+parser
+PARSER
+parses
+Parses
+parsing
+part
+Part
+PART
+partFlags
+PartFlags
+PARTHIAN
+partial
+Partial
+partialdiff
+PARTIALIZE
+partially
+PARTIALLY
+partically
+participate
+participates
+particular
+PARTICULAR
+particularly
+partRecords
+parts
+Parts
+PARTY
+Pascal
+Pasco
+Pashto
+pass
+Pass
+passed
+PASSED
+passes
+passing
+passthru
+past
+Pastaza
+paste
+PASTE
+patah
+path
+PATH
+Pattani
+pattern
+patterns
+Patterns
+pau
+PAU
+pause
+pauses
+pb
+pbt
+pbu
+Pc
+PC
+pcc
+pcd
+pce
+pcGlyphs
+pCharProps
+pchars
+pcItems
+pck
+pcTable
+pd
+Pd
+pdc
+pdefault
+pdf
+PDF
+pdfs
+pe
+Pe
+PE
+peak
+peakCoord
+peakTuple
+peculiarities
+peculiarity
+pedantic
+Pedi
+peek
+PEH
+PEHEH
+Pekal
+pel
+pend
+Pennsylvania
+people
+People
+per
+Per
+PER
+percent
+Percent
+PERCENT
+percentage
+percentScaleDown
+perfect
+perform
+Perform
+performAction
+PerformAction
+performance
+PERFORMANCE
+performed
+performing
+Performing
+performs
+Performs
+perhaps
+period
+PERIOD
+periodcentered
+periodinferior
+PERIODS
+periodsuperior
+peripheral
+Peripheral
+permanently
+PERMIC
+permissible
+permission
+Permission
+permissions
+permissive
+permitted
+permute
+Permyak
+perpendicular
+Persian
+PERSIAN
+persistent
+person
+perspective
+pertaining
+perthousand
+Peru
+pes
+PETITE
+Pf
+pg
+pga
+pglyph
+pGlyphProps
+pGoffset
+pgwide
+Phags
+PHAGS
+Phaistos
+Phake
+Phalaa
+phantom
+PHANTOM
+phantoms
+phase
+Phase
+phases
+Phases
+phi
+Philippines
+PHINTHU
+phk
+Phoenician
+PHOENICIAN
+PHONE
+Phonetic
+phrase
+PHRASE
+PHRU
+pi
+Pi
+PI
+piAdvance
+Picard
+PiCharacters
+pick
+picks
+pictographic
+Pictographic
+Pictures
+PICTURES
+Pidgin
+pidgins
+piece
+piecemeal
+pieces
+Piemontese
+pih
+pinfo
+pipes
+Pisin
+Pitcairn
+pItems
+pivot
+Pivot
+pivots
+pixel
+Pixel
+pixels
+pixelSize
+pj
+pk
+PK
+pkey
+pkg
+pkgconfig
+pko
+pl
+place
+Place
+placed
+placeholder
+Placeholder
+PLACEHOLDER
+placeholders
+placement
+PLACEMENT
+placements
+plain
+Plains
+plan
+Plan
+PLAN
+plane
+Plane
+planes
+planned
+planner
+planning
+plans
+Plans
+Plateau
+platform
+Platform
+platformID
+platforms
+ple
+please
+plen
+plevel
+pll
+plookups
+plp
+plt
+plus
+PLUS
+plusminus
+pms
+pnb
+png
+PNG
+PNGHeader
+po
+Po
+Pocomchi
+poh
+Pohnpeian
+point
+Point
+POINT
+pointed
+pointer
+Pointer
+pointers
+pointing
+points
+POINTS
+POISON
+Pökoot
+Poland
+Polish
+polyton
+polytonic
+Polytonic
+pon
+pool
+POOL
+pools
+poor
+pop
+popcount
+popcountl
+popcountll
+popped
+pops
+populate
+Populate
+population
+Poqomchi
+port
+Port
+portability
+portal
+Portugal
+Portuguese
+pos
+Pos
+POS
+positinoing
+position
+Position
+POSITION
+Positional
+positioned
+positioning
+Positioning
+positions
+POSITIONS
+positive
+Positive
+POSIX
+PosLookup
+PosLookupSubTable
+possibility
+POSSIBILITY
+possible
+Possible
+possibly
+post
+Post
+POST
+PosTable
+postcompensation
+PostcompensationActionChain
+posted
+postfix
+Postfixed
+POSTFIXED
+postponing
+postprocess
+postscript
+Postscript
+PostScript
+POSTSCRIPT
+postScriptNameIDX
+postV
+potential
+potentially
+potfRecords
+Pournader
+pOutGlyphProps
+pow
+power
+powers
+pp
+ppa
+ppc
+ppem
+PPEM
+ppemX
+ppemY
+PPI
+ppObject
+pPos
+pr
+practical
+practice
+pragma
+PRAGMA
+pragmas
+PRC
+pre
+Pre
+PRE
+precede
+precedence
+preceding
+Preceding
+PRECEDING
+precious
+precision
+precomposed
+Pred
+predef
+predefined
+Predicate
+predicates
+predictable
+pref
+PREF
+prefer
+Prefer
+preferable
+preference
+preferences
+preferred
+Preferred
+prefers
+prefix
+PREFIX
+prefixed
+Prefixed
+PREFIXED
+preloadAll
+prepare
+Prepare
+preparing
+preprocess
+preprocessor
+PREREQ
+pres
+PRES
+presence
+present
+PRESENT
+presentation
+Presentation
+preserve
+PRESERVE
+preserved
+preserving
+presForm
+presidential
+pressure
+PRETTY
+prev
+PREV
+prevent
+PREVENT
+prevented
+preventing
+prevents
+previous
+previously
+Previously
+Pri
+primarily
+primary
+prime
+primitives
+PRIMITIVES
+Principality
+print
+Print
+printed
+printer
+Printer
+printf
+PRINTF
+printing
+prints
+prior
+priorities
+prioritize
+priority
+Priority
+priv
+private
+Private
+PRIVATE
+PrivateDict
+privateDictInfo
+privateDictInfos
+privateDicts
+privateDictsOffset
+privateInfos
+PrivatePointNumbers
+privDictStr
+PRIVDICTVAL
+privInfo
+PRIVOPSET
+privSzr
+pro
+probable
+probably
+Probably
+Probing
+problem
+problems
+Procedure
+proceed
+proceeding
+process
+Process
+processed
+processes
+processing
+procs
+produce
+produced
+Produced
+produces
+product
+Profile
+PROFITS
+program
+programlisting
+programming
+programs
+Programs
+Proj
+project
+projection
+Projection
+promise
+promotion
+propagate
+Propagate
+proper
+properly
+properties
+PROPERTIES
+property
+PROPORTIONAL
+proportionally
+props
+PROPS
+PROT
+protected
+Protection
+prototypes
+provenc
+Provençal
+proves
+provide
+PROVIDE
+provided
+PROVIDED
+provider
+provides
+Provides
+Province
+proxy
+Proxy
+prs
+prune
+ps
+Ps
+PS
+psa
+Psalter
+PSALTER
+psc
+psControl
+pScriptTags
+pse
+pseudo
+Psmall
+psState
+pst
+pstf
+PSTF
+PString
+PSTS
+psva
+pt
+PT
+ptem
+pthread
+PTHREAD
+ptr
+PTR
+ptrdiff
+Pu
+pua
+PUA
+PUACHUE
+public
+Public
+PUBLIC
+publicly
+published
+Puerto
+Pulaar
+Pular
+pull
+Pull
+punctuation
+Punctuation
+PUNCTUATION
+Punjabi
+Puno
+pure
+Pure
+PURE
+purely
+purpose
+PURPOSE
+purposes
+push
+Push
+put
+Put
+puts
+pv
+pval
+pwcChars
+pwcInChars
+pwGlyphs
+pwLogClust
+pwo
+Pwo
+pwOutGlyphs
+px
+py
+Python
+q
+Q
+Qaai
+QAF
+qamats
+QAMATS
+Qatar
+Qiandong
+Qimant
+Qiubei
+QOF
+Qsmall
+qsort
+QSORT
+QType
+qu
+QUAD
+QuadPart
+qualifiers
+quantity
+QUARTER
+qub
+qubuts
+quc
+qud
+Quechua
+queried
+queries
+query
+querying
+QueryInterface
+question
+QUESTION
+questiondown
+questiondownsmall
+questions
+questionsmall
+quf
+qug
+quh
+Quichua
+quick
+quickly
+quicksort
+Quicksort
+Quiotepec
+quite
+quk
+qul
+quot
+quotation
+quotations
+quote
+quotedbl
+quotedblbase
+quotedblleft
+quotedblright
+quoteleft
+quoteright
+QUOTES
+quotesinglbase
+quotesingle
+Quotient
+Quoting
+qup
+qur
+qus
+qut
+quw
+qux
+quy
+quz
+qva
+qvc
+qve
+qvh
+qvi
+qvj
+qvl
+qvm
+qvn
+qvo
+qvp
+qvs
+qvw
+qvz
+qwa
+qwc
+qwh
+qws
+qxa
+qxc
+qxh
+qxl
+qxn
+qxo
+qxp
+qxr
+qxt
+qxu
+qxw
+r
+R
+ra
+Ra
+RA
+race
+races
+radical
+RADICAL
+radicalDegreeBottomRaisePercent
+Radicals
+rafe
+RAFE
+rag
+ragel
+Raise
+RAISE
+raises
+raj
+Rajasthani
+Rakhine
+ran
+rand
+random
+Random
+RANDOM
+randomize
+Randomly
+range
+Range
+RANGE
+rangeCount
+rangeEnd
+rangeGaspBehavior
+rangeMaxPPEM
+rangeMaxValue
+rangeMinValue
+rangeoffset
+rangeOffset
+rangeRecord
+RangeRecord
+ranges
+Ranges
+RANGES
+rangeShift
+RangeShift
+rangeStart
+Ranglong
+rar
+rare
+RARE
+Rarely
+Rarotongan
+rasterizer
+rate
+rather
+ratio
+raw
+rb
+rbb
+rbl
+RC
+rclt
+rcRangeChars
+RCU
+rcurveline
+RD
+RDONLY
+re
+Re
+reach
+reaches
+read
+Read
+READ
+readable
+reader
+ReadFileFragment
+READING
+readingDirection
+readjusting
+readonly
+READONLY
+ready
+real
+Real
+realistic
+reality
+realloc
+reallocate
+Reallocate
+reallocating
+really
+Really
+rearranged
+rearrangement
+Rearrangement
+REARRANGEMENT
+RearrangementSubtable
+reason
+reasons
+reassign
+reassigned
+reassignment
+reassignSIDs
+rebuild
+REBUS
+rec
+recalculated
+recategorize
+receive
+recent
+recently
+Recognition
+recognizable
+recognize
+recognized
+recognizes
+recom
+recommended
+recompose
+recomposed
+recomposing
+recomposition
+reconfiguration
+reconfigured
+reconfiguring
+record
+Record
+RECORD
+RecordArrayOf
+recording
+RecordList
+RecordListOf
+records
+Records
+Recover
+recovery
+recreate
+recurring
+recurse
+recursed
+Recursed
+recursing
+recursion
+recursive
+recursively
+Recursively
+red
+Red
+redefine
+redefined
+redirected
+redone
+Redu
+reduce
+redundant
+reenabling
+ref
+refcount
+refer
+reference
+Reference
+REFERENCE
+referenced
+referenceGlyph
+references
+referred
+referring
+refers
+REFIID
+refine
+refinements
+reflect
+reflecting
+reflects
+Reformed
+refs
+REGARD
+regardless
+Regex
+region
+Region
+regionCount
+regionIndices
+regions
+register
+Register
+REGISTER
+registered
+RegisterFontFileLoader
+registers
+registry
+Registry
+regular
+Regular
+REGULAR
+REH
+reinterpret
+rej
+Rejang
+REJANG
+reject
+Reject
+rejection
+rel
+REL
+related
+relation
+relationship
+relative
+relax
+relaxed
+RELAXED
+release
+Release
+RELEASE
+released
+releasedc
+ReleaseDC
+ReleaseFileFragment
+ReleaseFontTable
+releases
+relevant
+relicensed
+relies
+relocating
+rely
+Rely
+relying
+remain
+remainder
+remained
+remaining
+remains
+remap
+remapping
+remaps
+Remarks
+remember
+Remember
+remembered
+Removable
+removal
+remove
+Remove
+REMOVE
+removed
+RemoveFontMemResourceEx
+removing
+rename
+render
+rendered
+renderer
+rendering
+renders
+renum
+renumber
+Renumber
+renumbering
+renumbers
+reorder
+Reorder
+reordered
+REORDERED
+reordering
+Reordering
+reorders
+Reorders
+Repack
+repeat
+REPEAT
+repeated
+repeatedAddGlyphAction
+RepeatedAddGlyphAction
+repeating
+REPEATING
+reph
+Reph
+REPH
+repha
+Repha
+REPHA
+replace
+Replace
+replaced
+REPLACEME
+replacement
+REPLACEMENT
+replaces
+Replaces
+replacing
+replicate
+report
+Report
+reports
+Reports
+repositioned
+repositioning
+repository
+represent
+representation
+representations
+represented
+representing
+represents
+Represents
+reproduces
+Republic
+reqFeatureIndex
+request
+requested
+requests
+require
+Require
+required
+REQUIRED
+requirement
+requirements
+requires
+Requires
+requiring
+res
+resCountM
+research
+reserved
+Reserved
+RESERVED
+reservedESC
+ReservedESC
+reservedPad
+reset
+Reset
+Resets
+RESH
+reshaping
+reside
+resize
+resizing
+resolution
+resolutions
+resolve
+Resolved
+resolvedLevel
+resolver
+resolves
+resort
+Resort
+resource
+Resource
+ResourceForkHeader
+ResourceMap
+ResourceRecord
+resources
+resourcesZ
+ResourceTypeRecord
+respect
+respective
+respectively
+responsibilities
+responsibility
+responsible
+resreved
+rest
+RESTORE
+restrict
+restructuring
+result
+resulted
+resulting
+RESULTING
+results
+resume
+ret
+Ret
+RET
+retain
+Retain
+retained
+retains
+RETAINS
+retired
+retrieve
+retrieved
+retrieves
+Retrieves
+retry
+return
+Return
+RETURN
+returned
+Returned
+returning
+returns
+Returns
+reuse
+reused
+reusing
+reverse
+REVERSE
+reverseChainContextSingle
+ReverseChainSingle
+ReverseChainSingleSubst
+ReverseChainSingleSubstFormat
+reversed
+Reverses
+reversing
+revert
+revised
+rewind
+Rewind
+rewinding
+Rewinding
+Rewrite
+rfHeader
+RHA
+RHEL
+rhs
+Rhs
+ri
+ria
+Riang
+Rica
+Rico
+ridentity
+Rieger
+rif
+right
+Right
+RIGHT
+rightC
+rightClass
+rightClassCount
+rightClassTable
+rightSide
+RightToLeft
+Rinconada
+ring
+Ringsmall
+Ripuarian
+rise
+RISE
+RISH
+risking
+rit
+Ritarungo
+rki
+RKRF
+rkw
+rl
+rlig
+rligLookup
+rligMarksLookup
+rlinecurve
+rlineto
+rm
+RM
+rmc
+rmf
+rml
+rmn
+rmo
+rmoveto
+rmw
+rmy
+rmz
+rn
+rnl
+RNOON
+ro
+Ro
+RO
+road
+Robatic
+Roberts
+rock
+Rod
+Roderick
+Rohingya
+ROHINGYA
+role
+roll
+rom
+Roman
+ROMAN
+Romani
+Romania
+Romanian
+ROMANIZATION
+Romansh
+Romany
+room
+root
+rooted
+Roozbeh
+ros
+ROS
+rotate
+rotated
+Rotuman
+round
+ROUND
+ROUNDED
+roundf
+ROUNDF
+rounding
+rounds
+routine
+routines
+roux
+Roux
+row
+rowCount
+rowIndexTable
+rows
+rowWidth
+royalty
+RP
+rpc
+rphf
+RPHF
+rpRangeProperties
+RRA
+rrcurveto
+RREH
+RS
+rsb
+rsbMap
+Rsmall
+rsuperior
+Rsv
+rt
+rtl
+RTL
+rtlm
+rtm
+ru
+Ruanda
+RUBY
+Ruching
+rue
+rule
+Rule
+RULE
+rules
+Rules
+ruleSet
+RuleSet
+rulesets
+ruleSets
+Rumai
+run
+Run
+RUN
+Rundi
+runHead
+Runic
+RUNIC
+running
+runs
+runtime
+Runtime
+rup
+rupiah
+Russia
+Russian
+Rusyn
+rvalue
+rvalues
+Rvalues
+rw
+Rwanda
+rwr
+Ryan
+s
+S
+sa
+Saamia
+Sabah
+Sabaot
+Sad
+SAD
+Sadri
+safe
+safely
+safest
+sah
+Saharan
+said
+Saidi
+Saint
+Sakalava
+sake
+Sakha
+sakot
+SAKOT
+sal
+Salasaca
+salt
+Salvador
+sam
+Samaritan
+SAMARITAN
+Sambalpuri
+same
+Same
+SAME
+SAMEKH
+Sami
+Samoan
+Samogitian
+sample
+SAMPLE
+sampleTextNameId
+sampleTextNameID
+San
+Sanaani
+sandboxed
+sane
+Sango
+sanitization
+sanitizations
+sanitize
+Sanitize
+SANITIZE
+sanitized
+sanitizer
+sanitizing
+Sanitizing
+sanity
+Sankaran
+Sans
+Sanskrit
+Santa
+Santali
+Santiago
+santization
+SAR
+sara
+SARA
+Saraiki
+Sardinian
+Sarsi
+sas
+Sasak
+Sascha
+Sassarese
+sat
+Saterfriesisch
+Saterland
+Saudi
+Saurashtra
+SAURASHTRA
+save
+Save
+SAVE
+saved
+savedprops
+Saves
+saw
+Saxon
+say
+Sayisi
+says
+sb
+SBase
+SBASE
+SBitLineMetrics
+sbix
+SBIX
+SBIXGlyph
+SBIXStrike
+sbl
+SBL
+SBLHebrewUserManual
+sc
+Sc
+SC
+Scalable
+scalar
+Scalar
+scalars
+scale
+SCALE
+scaled
+SCALED
+scalef
+scaler
+scaling
+scan
+Scan
+sCapHeight
+scaron
+Scaron
+Scaronsmall
+scedilla
+Scedilla
+scenario
+scenarios
+SCHAR
+sched
+SCHED
+scheme
+Schouten
+science
+SCIENTIFIC
+sck
+scn
+sco
+sconsumed
+scope
+score
+Scots
+Scottish
+scount
+SCount
+SCOUNT
+scratch
+SCRATCH
+screen
+script
+Script
+SCRIPT
+scriptAnalysis
+scriptCode
+ScriptExtensions
+ScriptFreeCache
+ScriptItemize
+ScriptItemizeOpenType
+scriptList
+ScriptList
+ScriptPlace
+ScriptPlaceOpenType
+scriptProperties
+scripts
+Scripts
+SCRIPTS
+ScriptShape
+ScriptShapeOpenType
+ScriptTag
+scripttags
+scs
+scursor
+sd
+SD
+sDageshForms
+sdc
+sdh
+SDL
+sdn
+se
+seac
+search
+Search
+SEARCH
+searched
+searching
+searchRange
+Sebat
+sec
+second
+Second
+secondGlyph
+seconds
+sect
+section
+SECTION
+sections
+security
+sed
+see
+See
+seeing
+seek
+seem
+seems
+Seems
+seen
+SEEN
+seenCrossStream
+seequence
+sees
+seg
+segcount
+segCount
+segCountX
+segment
+Segment
+SEGMENT
+segmented
+segmenting
+SegmentMaps
+segments
+segol
+seh
+Seigo
+sek
+Sekani
+Sekota
+sel
+select
+Select
+selected
+selecting
+selection
+selections
+selectively
+SelectObject
+selector
+Selector
+SELECTOR
+selectors
+Selectors
+SELECTORs
+selectorToDisable
+selectorToEnable
+selects
+Seletar
+self
+Selkup
+semantic
+semantical
+SEMANTICS
+Sembilan
+semi
+SEMI
+Semibold
+semicolon
+SEMICOLON
+Sena
+send
+sending
+Senegal
+sense
+sensible
+sensitive
+SENSITIVE
+sensitivity
+sent
+sentence
+Senthang
+sentinel
+SENTINEL
+separate
+separated
+separately
+separation
+Separator
+SEPARATOR
+seq
+sequence
+Sequence
+sequenceIndex
+sequences
+SEQUENCES
+sequential
+sequentially
+Serbia
+Serbian
+Serer
+serial
+serialization
+serialize
+Serialize
+SERIALIZE
+serialized
+serializer
+SERIALIZER
+Serializes
+series
+Serif
+serve
+servers
+serves
+Sesotho
+set
+Set
+SET
+SetBidiLevel
+SetComponent
+SetCurrentRun
+SetLineBreakpoints
+setlocale
+SETLOCALE
+SetMark
+SetNumberSubstitution
+sets
+Sets
+SETS
+SetScriptAnalysis
+Setswana
+setter
+setters
+setting
+Setting
+SettingName
+settings
+settingTableZ
+setup
+Setup
+seven
+SEVEN
+seveneighths
+seveninferior
+sevenoldstyle
+sevensuperior
+SEVENTEEN
+several
+severely
+Severn
+sez
+sFamilyClass
+sfinae
+SFINAE
+sfm
+SFNSDisplay
+SFNSText
+sfnt
+Sfnt
+SFNT
+sfntVersion
+sg
+sga
+sgc
+sgi
+sgs
+sgw
+sh
+sha
+shadda
+Shadda
+SHADDA
+shaddaLigature
+shaddaLigatureSet
+shaddaLigaturesSubLookup
+Shadow
+SHADOW
+shall
+SHALL
+shallow
+Shan
+shape
+Shape
+SHAPE
+shaped
+shaper
+Shaper
+SHAPER
+shaperprefs
+shapers
+Shapers
+SHAPERS
+shapes
+Shapes
+SHAPES
+shaping
+Shaping
+SHAPING
+Sharada
+SHARADA
+share
+SHARE
+shared
+Shared
+SHARED
+SharedPointNumbers
+sharedTupleCount
+sharedTuples
+Shavian
+SHAVIAN
+SHEEN
+Sheeter
+Shekhawati
+shell
+SHELL
+sheva
+shi
+shift
+Shift
+SHIFT
+shifted
+Shifter
+SHIFTER
+shifting
+Shifting
+Shihhi
+shin
+SHIN
+ship
+shipped
+shn
+Shona
+short
+Short
+SHORT
+shortCount
+shortcut
+shortcuts
+shortest
+shortfall
+Shorthand
+SHORTHAND
+shortint
+shoudln
+should
+Should
+shouldn
+Shouldn
+show
+SHOW
+showing
+shows
+shrink
+Shrinkage
+shrinkageDisableGPOS
+shrinkageDisableGSUB
+shrinkageEnableGPOS
+shrinkageEnableGSUB
+shrinkageJstfMax
+shrinkFlags
+SHRT
+shu
+Shua
+shuffle
+Shurishkar
+shut
+Shut
+Shwe
+si
+Sibe
+SIBLING
+Sichuan
+Sicilian
+sid
+SID
+Sidamo
+Siddham
+SIDDHAM
+side
+sidebearing
+sides
+sidmap
+sids
+SIDs
+Sierra
+sign
+Sign
+signature
+signed
+Signed
+SIGNED
+signedness
+significance
+significant
+significantly
+signifying
+signs
+SIGNWRITING
+Sihuas
+Siksika
+sil
+SIL
+silently
+Silesian
+silf
+Silf
+SILF
+Silt
+Silte
+Simalungun
+similar
+Similar
+similarly
+Similarly
+SIMP
+simple
+Simple
+SIMPLE
+SimpleGlyph
+simpler
+simplest
+simplicity
+simplification
+simplified
+Simplified
+SIMPLIFIED
+simplifies
+Simplifies
+simplify
+simply
+SIMULATIONS
+sin
+SIN
+since
+Since
+Sindhi
+Singapore
+single
+Single
+SINGLE
+SinglePos
+SinglePosFormat
+SingleSubst
+SingleSubstFormat
+singleton
+singletons
+singular
+SINH
+sinhala
+Sinhala
+SINHALA
+Sinhalese
+sink
+Sink
+sinks
+Sinte
+SIOT
+Sit
+site
+sites
+situations
+six
+SIX
+sixinferior
+sixoldstyle
+sixsuperior
+sixteen
+SIXTEEN
+Siyin
+size
+Size
+SIZE
+sized
+SIZED
+sizeDeviceRecord
+sizeof
+sizes
+sizeTable
+sizeTables
+sizing
+sjd
+sjo
+sk
+Sk
+SKEWED
+skg
+skip
+Skip
+SKIP
+skippable
+skipped
+skipping
+Skipping
+skippy
+Skolt
+skr
+sl
+SL
+slant
+Slant
+SLANT
+slanted
+slash
+SLASH
+SLASHED
+Slave
+Slavey
+Slavonic
+slen
+slightly
+slim
+slnt
+slope
+slot
+slots
+Slovak
+Slovakia
+Slovenia
+Slovenian
+slower
+sm
+Sm
+SM
+sma
+SMAbv
+small
+Small
+SMALL
+smaller
+smallest
+Smallest
+SmallGlyphMetrics
+smart
+SMART
+SMBlw
+smj
+smn
+smoking
+sms
+SMVD
+sn
+snap
+snapshot
+sniff
+snk
+snprintf
+so
+So
+Sochiapam
+Sodo
+SOFT
+software
+Software
+SOFTWARE
+Soga
+Sogdian
+SOGDIAN
+Solaris
+SOLARIS
+solely
+solution
+Somali
+some
+Some
+Somebody
+somefunc
+somehow
+Somehow
+someone
+something
+sometime
+sometimes
+somewhat
+SOMPENG
+Songe
+Soninke
+soon
+sop
+SORA
+Sorbian
+sort
+Sort
+SORT
+sorted
+Sorted
+SORTED
+SortedArrayOf
+sortedness
+SortedUnsizedArrayOf
+sorting
+SORTING
+Sotho
+SOUND
+sounds
+source
+Source
+SOURCE
+sourceware
+South
+SOUTH
+Southeast
+Southeastern
+Southern
+Southwestern
+Soyombo
+SOYOMBO
+spac
+space
+Space
+SPACE
+spaced
+spaces
+Spaces
+spacing
+Spacing
+SPACING
+Spain
+Spanish
+spans
+speaking
+spec
+Spec
+special
+Special
+SPECIAL
+Specialization
+specializations
+Specializations
+Specialize
+specially
+Specials
+specific
+specifically
+SPECIFICALLY
+specification
+specifications
+specificed
+specifics
+specified
+specifies
+specify
+specifying
+specs
+speculative
+speed
+Speed
+speeds
+split
+Split
+SplitCurrentRun
+splitPoint
+splitPosition
+Spoon
+SPOT
+Spread
+spreadsheets
+Spring
+spv
+spy
+sq
+sqrt
+Square
+SQUARE
+SQUARED
+squeezing
+sr
+src
+Sri
+sro
+srr
+srs
+ss
+ssh
+Ssmall
+SSOT
+ssuperior
+ssxx
+ssXX
+st
+stable
+stack
+Stack
+STACK
+Stacker
+STACKER
+stacking
+stackoverflow
+stage
+stages
+STAGES
+stale
+standalone
+standard
+Standard
+StandardEncoding
+standardheaderfiles
+standards
+stands
+start
+Start
+START
+startCharCode
+startcode
+startCode
+startConnectorLength
+startCoord
+startCount
+started
+Started
+starter
+Starter
+startGlyph
+startGlyphID
+startGlyphIndex
+starting
+Starting
+StartOfText
+starts
+startSize
+startUnicodeValue
+stat
+STAT
+StatAxisRecord
+state
+State
+STATE
+stateArrayTable
+stateHeader
+statement
+states
+States
+STATES
+StateTable
+StateTableDriver
+stateTableOffset
+static
+Static
+STATIC
+status
+stay
+stays
+stch
+STCH
+std
+STD
+stdarg
+stddef
+stderr
+stdGlyph
+StdHW
+stdint
+stdio
+stdlib
+STDMETHODCALLTYPE
+STDMETHODIMP
+StdVW
+stem
+StemSnapH
+StemSnapV
+step
+STEP
+stepping
+steps
+sterling
+stHeader
+still
+Still
+stmt
+STMT
+stop
+Stop
+STOP
+stopped
+stops
+storage
+Storage
+store
+Store
+STORE
+stored
+Stored
+storing
+stq
+str
+STR
+straight
+Straight
+straightforward
+strategic
+strategy
+Strategy
+strbuf
+strchr
+strcmp
+strcpy
+strdup
+stream
+streams
+strerror
+stretch
+Stretch
+STRETCH
+stretchable
+stretched
+stretchGlyphAction
+StretchGlyphAction
+stretching
+Stribley
+Strict
+STRICT
+strictly
+stride
+strike
+strikeout
+STRIKEOUT
+strikes
+string
+String
+STRING
+stringIndex
+StringIndex
+stringIndexInfo
+stringOffset
+strings
+strlen
+strncmp
+strncpy
+stroke
+Strokes
+StrokeWidth
+strong
+strongly
+strstr
+strtod
+STRTOD
+strtol
+strtoul
+struct
+StructAfter
+StructAtOffset
+StructAtOffsetOrNull
+StructAtOffsetUnaligned
+structs
+STRUCTS
+structure
+Structure
+structures
+Studio
+stuff
+stupid
+stv
+style
+Style
+STYLE
+stylistic
+Stylistic
+STYLISTIC
+stylisticSet
+sTypoAscender
+sTypoDescender
+sTypoLineGap
+su
+sub
+SUB
+subarray
+subclass
+Subclass
+subclasses
+subdivided
+subdivision
+subfamily
+SUBFAMILY
+subfamilyID
+subfamilyNameID
+subFeatureFlags
+subfonts
+SubFormat
+subject
+subjoined
+Subjoined
+SUBJOINED
+subjoining
+sublookup
+SUBLOOKUP
+SubLookupOffsets
+SubLookupOffsetsArray
+submerged
+subpixel
+subr
+subrecord
+subroffset
+subroutine
+Subroutine
+subroutines
+subrs
+Subrs
+SUBRS
+subrsOffset
+subs
+subscript
+Subscript
+SUBSCRIPT
+subscripts
+Subscripts
+subsequence
+subsequences
+subsequent
+subset
+Subset
+SUBSET
+SubsetGlyph
+Subsets
+subsetted
+subsetter
+SUBSETTER
+subsetting
+subst
+SUBST
+substantially
+substGlyph
+substitued
+substitute
+Substitute
+SUBSTITUTE
+substituted
+SUBSTITUTED
+substitutes
+substituteX
+substitution
+Substitution
+SUBSTITUTION
+substitutions
+substitutionTables
+SubstLookup
+SubstLookupSubTable
+substr
+substring
+substThreshold
+subsystem
+subtable
+subTable
+Subtable
+SubTable
+subtableCount
+SubTableFlags
+subtableGlyphCoverageArray
+SubTableHeader
+subtables
+Subtables
+SubTables
+SUBTABLES
+SubtableType
+subtag
+SUBTAG
+subtags
+subtending
+subtract
+subtracting
+subtraction
+succeed
+succeeded
+SUCCEEDED
+Succeeding
+SUCCEEDING
+succeeds
+success
+successful
+successfully
+successive
+such
+SUCH
+sucks
+Sudanese
+sudo
+sufficient
+SUFFICIENT
+suggest
+suggested
+Suggested
+suggests
+suit
+suitable
+suite
+Suite
+suk
+Sukuma
+sukun
+SUKUN
+sum
+Sum
+summation
+Summer
+sun
+Sundanese
+SUNDANESE
+SUNPRO
+SUPER
+superimposing
+SUPERIORS
+superscript
+SUPERSCRIPT
+superscripts
+Superscripts
+supp
+suppData
+suppEncData
+SuppEncData
+SuppEncoding
+supplement
+Supplement
+Supplemental
+supplied
+supply
+supplying
+support
+Support
+SUPPORT
+supported
+Supported
+SUPPORTED
+supporting
+supports
+Supports
+supposed
+supposedly
+suppress
+supps
+suq
+sure
+Suri
+surprise
+surprises
+surrogate
+SURROGATE
+Surrogates
+surrounding
+survive
+survived
+survives
+sutable
+Sutu
+sv
+sva
+Svan
+svg
+SVG
+svgDoc
+svgDocEntries
+svgDocLength
+SVGDocumentIndexEntry
+SVR
+sw
+Swadaya
+Swahili
+Swampy
+swap
+Swap
+SWAP
+swaplp
+swapped
+swaps
+SWASH
+SWASHES
+Swati
+swb
+swc
+Sweden
+Swedish
+Sweep
+swh
+switch
+Switch
+switched
+switches
+Switzerland
+swv
+sxHeight
+sxu
+syc
+syl
+Sylheti
+Syllabary
+syllabic
+Syllabic
+SYLLABIC
+Syllabics
+SYLLABICS
+syllable
+Syllable
+SYLLABLE
+syllables
+Syllables
+Syloti
+SYLOTI
+SYM
+symbol
+Symbol
+SYMBOL
+symbolic
+symbols
+Symbols
+SYMBOLS
+symmetric
+sync
+synchronize
+syntatically
+syntax
+Syntax
+synthesize
+synthesizes
+synthesizing
+SyntheticBase
+syr
+Syrc
+syre
+Syre
+Syria
+syriac
+Syriac
+SYRIAC
+syrj
+Syrj
+syrn
+Syrn
+sys
+SYS
+sysconf
+SYSCONF
+system
+System
+SYSTEM
+systems
+sz
+szl
+t
+T
+ta
+Ta
+taa
+tab
+Tabasaran
+Tabassaran
+table
+Table
+TABLE
+tableCount
+tablelist
+TableRecord
+TableRecords
+tables
+Tables
+TABLES
+tableTag
+TableType
+Tachelhit
+Tachoni
+tag
+Tag
+TAG
+Tagalog
+TAGALOG
+Tagbanwa
+TAGBANWA
+tagFeature
+tagged
+Tagin
+Tagish
+tagLangSys
+tagRanges
+tags
+Tags
+TAGS
+tagScript
+TAH
+Tahaggart
+Tahitian
+Tahltan
+tahoma
+Tahoma
+tahomabd
+Tai
+TAI
+tail
+Tail
+tailored
+Taiwan
+Taiwanese
+Tajik
+Tajiki
+Tajikistan
+take
+Take
+taken
+takes
+taking
+Takri
+TAKRI
+TALL
+Tamahaq
+Tamajaq
+Tamajeq
+Tamashek
+Tamasheq
+Tamazight
+Tamil
+TAMIL
+TAML
+Tanacross
+Tanaina
+Tanana
+TANDEM
+Tandroy
+Tangshewi
+TANGUT
+Tanosy
+Tanzania
+taq
+tarball
+Tarball
+target
+TARGET
+TargetConditionals
+targs
+Tarifit
+tasks
+Tatar
+tator
+tau
+TAV
+Tawallammat
+Tawr
+Tày
+Tayart
+Taylor
+TB
+TBase
+TBASE
+tbl
+tbody
+TBR
+tcb
+tce
+TCHEH
+TCHEHEH
+TCodepoint
+TCount
+TCOUNT
+tcp
+tcy
+tcz
+tdd
+tdx
+te
+tec
+technetwork
+Technical
+technicalities
+Technically
+Tedim
+TEH
+TEHEH
+telecom
+tell
+tells
+TELU
+Telugu
+TELUGU
+tem
+Temne
+temp
+templ
+template
+Template
+templates
+temporarily
+temporary
+tempting
+Temuan
+TEN
+Tena
+Tenggarong
+Tepetotutla
+Tepinapa
+Terik
+term
+terminal
+Terminal
+terminate
+terminated
+terminates
+terminating
+termination
+Termination
+TerminationWordCount
+terminator
+terminology
+Terminology
+terms
+Tesaka
+test
+Test
+TEST
+tested
+testing
+Testing
+tests
+Tests
+tet
+TET
+Tetum
+text
+Text
+TEXT
+TextAnalysis
+textAnalyzer
+textLength
+textPosition
+textProperties
+TEXTRANGE
+textString
+textual
+tfn
+tg
+tgj
+tgroup
+tgx
+th
+TH
+tha
+Thaana
+THAANA
+Thado
+thai
+Thai
+THAI
+Thailand
+THAL
+Tham
+THAM
+than
+THAN
+THANTHAKHAT
+that
+That
+the
+The
+THE
+thead
+THEH
+their
+them
+themed
+themselves
+then
+Then
+theory
+thep
+there
+There
+therefore
+Therefore
+these
+These
+they
+They
+thickness
+THICKNESS
+THIN
+thing
+things
+Things
+thingy
+think
+third
+Third
+THIRD
+THIRTEEN
+this
+This
+THIS
+thiz
+THO
+thorn
+Thorn
+Thornsmall
+those
+though
+thread
+Thread
+threading
+threads
+threadsafe
+threadsafely
+three
+Three
+THREE
+threeeighths
+threeinferior
+threeoldstyle
+threequarters
+threequartersemdash
+threesuperior
+through
+throughout
+throw
+tht
+thus
+thv
+thz
+ti
+Tibetan
+TIBETAN
+Tidy
+tiff
+Tifinagh
+TIFINAGH
+tig
+tight
+Tigon
+Tigre
+Tigrinya
+tilde
+Tildesmall
+tile
+tiles
+Tiles
+time
+timeouts
+times
+Times
+timesbi
+timesi
+Timne
+tindex
+Tiny
+TINY
+Tirhuta
+TIRHUTA
+Tiriki
+title
+TITLECASE
+TITLING
+tiv
+Tiv
+tjmo
+TJMO
+tk
+tkg
+tl
+TL
+Tlacoatzintepec
+tlen
+tlist
+TLookup
+TLookupList
+TLR
+TM
+tmh
+tmp
+tmw
+tn
+tnf
+to
+To
+TO
+Toba
+Tobago
+TObject
+toCoord
+tod
+today
+Todo
+TODO
+toe
+together
+ToGlyphs
+toi
+tok
+Tok
+tol
+Tolowa
+TOLOWER
+Toma
+tombstone
+tombstones
+tone
+Tone
+TONE
+tones
+Tonga
+Tongan
+too
+took
+toolkit
+tools
+tooltip
+top
+Top
+TOP
+topAccentAttachment
+topAccentCoverage
+topdict
+topDict
+TopDict
+topDictIndex
+TopDictIndex
+topDictInfo
+topDictModSIDs
+topDictSize
+topDictStr
+toplevel
+topographical
+Topographical
+topologically
+topSide
+topSzr
+Torki
+TORTIOUS
+TORTOISE
+Tosk
+total
+Total
+totalDataSize
+totally
+touch
+TOUCH
+touches
+TOUPPER
+towards
+tpi
+tr
+TR
+trace
+Trace
+TRACE
+tracing
+track
+Track
+trackData
+TrackData
+tracking
+Tracking
+trackNameID
+tracks
+trackTable
+trackTableEntry
+TrackTableEntry
+TRAD
+trade
+trademark
+TRADEMARK
+trademarks
+Traditional
+TRADITIONAL
+trailed
+trailing
+trak
+TRAK
+trampoline
+trans
+TRANSCODING
+transcription
+transfer
+Transfer
+transform
+Transform
+transformation
+transformed
+transforming
+transient
+Transient
+transition
+transitioning
+transitive
+translatation
+translate
+translating
+translation
+TRANSLITERATION
+transparent
+traversal
+treat
+treated
+treatment
+treats
+tree
+trees
+TRI
+trick
+trickiest
+tricky
+Tricky
+tried
+tries
+Tries
+trigger
+triggered
+triggers
+trim
+trimmable
+trimmed
+Trimming
+Trinidad
+trivial
+Trivial
+trivially
+trouble
+troubleshooting
+tru
+true
+TRUE
+TrueTag
+TrueType
+TRUETYPE
+TrueTypeTag
+truly
+truncate
+truncated
+try
+Try
+TryGetFontTable
+trying
+Trying
+ts
+Ts
+TSA
+TSADI
+tsb
+tsere
+Tsetsaut
+Tshangla
+Tsimihety
+tsj
+Tsmall
+Tsonga
+Tsotso
+TSubTable
+tsuperior
+Tswana
+tt
+TTA
+ttb
+TTB
+ttc
+TTC
+ttcf
+ttcHeader
+TTCHeader
+TTCHeaderVersion
+ttcTag
+TTCTag
+TTEH
+TTEHEH
+ttf
+ttm
+ttq
+Tugen
+Tulu
+tum
+Tumari
+Tumbuka
+Tundra
+Tunisia
+Tunisian
+tuple
+Tuple
+tupleCount
+tupleIndex
+TupleIndexMask
+tuples
+tupleVarCount
+TupleVarCount
+TupleVarHeader
+tupleVarHeaders
+Tupple
+TuppleIndex
+Turkey
+Turkic
+TURKIC
+Turkish
+Turkmen
+Turkmenistan
+turn
+Turn
+Turner
+turning
+turns
+Turns
+Turoyo
+Tusi
+Tutchone
+Tututni
+tuu
+Tuvalu
+Tuvin
+Tuvinian
+tuy
+tvalue
+tvl
+tw
+tweaks
+TWELVE
+TWENTY
+Twi
+twice
+twilight
+two
+Two
+TWO
+TwoByteNegInt
+TwoBytePosInt
+twodotenleader
+twoinferior
+twooldstyle
+twosuperior
+twothirds
+tx
+txc
+txt
+txy
+ty
+tying
+Typ
+type
+Type
+TYPE
+typed
+typedef
+typedefs
+typeface
+typefaces
+typeList
+typename
+TypeName
+types
+Types
+TYPES
+typesetter
+typesetting
+typical
+typically
+typo
+TYPO
+typographic
+Typographic
+TYPOGRAPHIC
+typographical
+typography
+Typography
+typos
+tyv
+tyz
+tze
+tzm
+tzo
+Tzotzil
+u
+U
+uacute
+Uacute
+Uacutesmall
+UARRAY
+ub
+uBidiLevel
+ubl
+Ubuntu
+ubyte
+ubytes
+ucd
+UCD
+ucdn
+UCDN
+uchar
+UChar
+UCHAR
+ucircumflex
+Ucircumflex
+Ucircumflexsmall
+ucs
+udieresis
+Udieresis
+Udieresissmall
+udm
+Udmurt
+ue
+UE
+UEE
+UErrorCode
+ufuncs
+ufunctions
+UFWORD
+ug
+Ugaritic
+UGARITIC
+UGC
+Ugh
+ugly
+Ugly
+UGLY
+ugrave
+Ugrave
+Ugravesmall
+UHEADLESSARRAY
+UI
+UIDBase
+Uighur
+uiLabelNameId
+uiNameID
+uint
+UINT
+uintptr
+UIPC
+UISC
+uk
+Ukraine
+Ukrainian
+ULBAR
+ulCodePageRange
+ulink
+ULL
+ULLONG
+ULong
+ULONG
+Ulrich
+ultimately
+ULTRA
+ulUnicodeOS
+ulUnicodeRange
+umb
+Umbundu
+Umm
+un
+unassigned
+UNASSIGNED
+unbounded
+UNBOUNDED
+unchanged
+UNCLASSIFIED
+UnclassifiedGlyph
+unclear
+unconditionalAddGlyphAction
+UnconditionalAddGlyphAction
+unconditionally
+UNCONNECTED
+unconst
+und
+undef
+UNDEF
+undefined
+UNDEFINED
+under
+Under
+UNDERBAR
+underflow
+undergone
+underline
+Underline
+UNDERLINE
+underlinePosition
+UnderlinePosition
+underlineThickness
+UnderlineThickness
+underlining
+underlying
+underneath
+underscore
+UNDERSCORE
+understand
+understandable
+understood
+undertake
+Undetermined
+undo
+undocumented
+Undocumented
+unequal
+UNFITTED
+unforced
+unformed
+unfortunate
+unfortunately
+Unfortunately
+unhide
+uni
+unichar
+UniChar
+unicode
+Unicode
+UNICODE
+UnicodeData
+unicodes
+UNICODES
+unicodeValue
+UnicodeValueRange
+Unified
+uniform
+uninitialized
+union
+UNION
+Unión
+unions
+unique
+UNIQUE
+UniqueID
+uniscribe
+Uniscribe
+UNISCRIBE
+unistd
+UNISTD
+unit
+United
+units
+Units
+unitSize
+unitsPerEm
+uniUUUU
+Universal
+unix
+unknown
+Unknown
+UNKNOWN
+unless
+Unless
+unlike
+unlikely
+unlimited
+UnlimiteGap
+unloaded
+unlock
+Unmake
+unmap
+UnmapViewOfFile
+unmarked
+unnecessary
+unnormalize
+unoffset
+unorm
+UNormalizer
+unpack
+unpadded
+unpop
+unprocessed
+unr
+unrecognized
+unref
+unreferenced
+UnregisterFontFileLoader
+unsafe
+Unsafe
+UNSAFE
+UNSCALED
+unset
+unsigned
+Unsized
+UnsizedArrayOf
+UnsizedByteStr
+UnsizedOffsetArrayOf
+UnsizedOffsetListOf
+unsorted
+UNSUCCESSFUL
+unsupported
+UNSUPPORTED
+unsure
+UNTAG
+until
+untouched
+unused
+Unused
+UNUSED
+unusual
+unwanted
+unwise
+unzip
+uoffset
+up
+UP
+update
+updated
+UPDATES
+upem
+UPEM
+upon
+upper
+Upper
+UPPER
+uppercase
+UPPERCASE
+upperLimit
+upright
+UPROPS
+upward
+ur
+Urak
+Urdu
+urk
+url
+URL
+Uruguay
+us
+USABLE
+usage
+usBreakChar
+uscript
+USCRIPT
+UScriptCode
+usDefaultChar
+use
+Use
+USE
+used
+Used
+useful
+Useful
+useless
+UseMarkFilteringSet
+user
+User
+USER
+userfeatures
+users
+uses
+Uses
+usFirstCharIndex
+USHRT
+Usila
+using
+Using
+USING
+usLastCharIndex
+usLowerOpticalPointSize
+Usmall
+usMaxContext
+usp
+USP
+ustr
+ustring
+usually
+Usually
+usUpperOpticalPointSize
+usWeightClass
+usWidthClass
+usWinAscent
+usWinDescent
+utf
+UTF
+Uthmanic
+util
+utilities
+Utilities
+utility
+utilize
+UTS
+uu
+UU
+UUID
+UuidCreate
+uuidof
+UVCRDOypOtijlMDLNNyyLk
+uversion
+uvs
+UVS
+UVSMapping
+Uyghur
+uz
+Uzbek
+Uzbeki
+Uzbekistan
+uzn
+uzs
+v
+V
+va
+VA
+VAbv
+VAH
+Vai
+VAI
+Vakhi
+val
+Val
+VAL
+ValCount
+valFormat
+valid
+Valid
+VALID
+validate
+validated
+Validator
+validity
+Valle
+valuable
+value
+Value
+VALUE
+valueArrayZ
+valueCount
+valueFormat
+ValueFormat
+valueFormats
+valueIndex
+valueNameID
+ValueRecord
+valueRecordCount
+ValueRecords
+valueRecordSize
+values
+Values
+VALUES
+ValuesAreLong
+valueSize
+valuesZ
+valueTag
+ValueType
+var
+Var
+VAR
+vararg
+varation
+VarData
+varDataSize
+variable
+Variable
+variablelist
+variables
+variant
+Variant
+VARIANT
+variantGlyph
+variants
+Variants
+variation
+Variation
+VARIATION
+variationAxis
+VariationAxisRecord
+VariationDevice
+variations
+Variations
+VARIATIONS
+VariationSelectorRecord
+variationsTag
+VariationStore
+VariationValueRecord
+varidx
+varIdx
+varies
+variety
+varika
+variour
+various
+Various
+varlistentry
+varname
+varRecords
+VarRegionAxis
+VarRegionList
+vars
+varSelector
+VarSizedBinSearchArrayOf
+VarSizedBinSearchHeader
+varStore
+varStoreOffset
+vary
+vattu
+vatu
+Vatu
+VATU
+VAV
+vAxis
+VBAR
+VBase
+VBASE
+VBlw
+VCount
+VCOUNT
+vcpkg
+VD
+ve
+VE
+vec
+vector
+Vector
+VECTOR
+vectorization
+vectorized
+vedic
+Vedic
+VEH
+ven
+Venda
+VENDOR
+Venetian
+Venezuela
+VER
+Verb
+verbatim
+verify
+versa
+version
+Version
+VERSION
+versions
+versionZ
+vert
+VERT
+vertAdvance
+vertBearingX
+vertBearingY
+vertData
+vertGlyphCount
+vertGlyphCoverage
+vertical
+Vertical
+VERTICAL
+vertically
+VertOriginMetric
+vertOriginY
+vertYOrigins
+very
+vfprintf
+vhcurveto
+vhea
+vi
+VI
+via
+vice
+Viet
+VIET
+Vietnam
+Vietnamese
+view
+vindex
+vINVALID
+violation
+virama
+Virama
+VIRAMA
+viramas
+virtual
+Virtualizing
+vis
+Visarga
+VISARGA
+VISATTR
+visibility
+VISIBILITY
+visible
+visibly
+visit
+visited
+visitLangSys
+visitScript
+vista
+Vista
+visual
+Visual
+VISUAL
+vjmo
+VJMO
+vkk
+vkt
+Vlaams
+Vlax
+vlineto
+vls
+VM
+VMAbv
+VMBlw
+vmoveto
+VMPre
+VMPst
+vmtx
+vmw
+vo
+Vo
+VOICED
+VOICING
+void
+Void
+VOID
+VOL
+Volapük
+volatile
+volt
+vorg
+VORG
+vorgMap
+Võro
+vowel
+Vowel
+VOWEL
+vowels
+Vowels
+vp
+VPre
+VPst
+VRBAR
+vrinda
+vro
+Vs
+VS
+vsindex
+vsindexcs
+vsindexdict
+Vsmall
+vsnprintf
+vstem
+vstemhm
+vstore
+vstoreOffset
+vtable
+vv
+vvar
+VVAR
+VVARTag
+vvcurveto
+w
+W
+wa
+Wa
+Wagdi
+Wailaki
+walk
+Walk
+walks
+Wall
+Walloon
+Wanca
+WANCHO
+Wang
+Wanga
+want
+wanted
+wants
+war
+WARANG
+Waray
+warn
+warning
+Warning
+WARNING
+warnings
+Warnings
+WARRANTIES
+was
+Was
+WASLA
+wasn
+waste
+Watch
+watchout
+Watchout
+WAVY
+WAW
+way
+ways
+Wayuu
+wbm
+wbr
+Wbuiltin
+Wc
+Wcast
+WCE
+wchar
+WCHAR
+Wclass
+Wconversion
+wdcTable
+Wdelete
+Wdeprecated
+Wdisabled
+Wdouble
+wdRecord
+wdth
+we
+We
+WE
+weak
+weight
+Weight
+WEIGHT
+weights
+weird
+welcome
+well
+Welsh
+Wembedded
+went
+were
+Werner
+West
+Western
+Weverything
+Wextra
+Wformat
+wght
+what
+What
+WHAT
+whatever
+Whatever
+whatsoever
+WHATSOEVER
+when
+When
+whenever
+Whenever
+where
+whereas
+Whereas
+WheresData
+WheresFace
+wherever
+whether
+Whether
+WHETHER
+which
+Which
+while
+While
+white
+WHITE
+Whitelist
+whitespace
+Whitespace
+who
+whole
+whose
+why
+Why
+wide
+widely
+width
+Width
+WIDTH
+WidthDeltaCluster
+WidthDeltaPair
+widthMax
+widths
+widthsZ
+Wignored
+wiki
+wikipedia
+wild
+will
+Will
+willing
+willis
+wilson
+Wilson
+Wimplicit
+win
+Win
+WIN
+WINAPI
+windows
+Windows
+Winit
+Winjected
+WINNT
+Winter
+Wipe
+wish
+wishes
+with
+With
+WITH
+within
+Within
+without
+Without
+WJ
+wlc
+wle
+wlk
+Wlogical
+Wmaybe
+Wmissing
+Wnested
+wni
+wo
+Wolane
+Wold
+Wolof
+won
+Woods
+word
+Word
+WORD
+wording
+wordOffsetToIndex
+words
+WORDS
+work
+Work
+worked
+working
+Working
+works
+Works
+world
+worry
+worrying
+worth
+would
+Would
+WOULD
+wouldbn
+wouldn
+Wow
+Wpacked
+Wpointer
+Wpragmas
+wrap
+wrapper
+wrappers
+wrapping
+Wredundant
+Wreorder
+writable
+Writable
+WRITABLE
+write
+Write
+WRITE
+writer
+writing
+written
+Written
+wrong
+wrote
+wry
+Ws
+wsg
+Wshadow
+Wsign
+Wsmall
+Wstrict
+Wstring
+Wswitch
+Wtautological
+wtm
+Wtype
+Wu
+Wundef
+Wunknown
+Wunneeded
+Wunsafe
+Wunused
+wuu
+Wvla
+ww
+Wwrite
+WWS
+www
+x
+X
+xa
+xA
+xaa
+xAA
+xAAF
+xAB
+xabc
+xABC
+xABFFu
+xAC
+xAdvance
+xAdvDevice
+xAFF
+xal
+XALLOCATE
+Xamtanga
+xan
+xAu
+xAvgCharWidth
+xb
+xB
+xBA
+xBB
+xBFF
+xBytes
+xc
+xC
+xCD
+xCFF
+Xconstructor
+xCoordinate
+xCULL
+xD
+xDBFFu
+xDC
+xDE
+xDeviceTable
+xDFDFDFDF
+xDFDFDFDFu
+xDFF
+xDFFF
+xDFFFu
+xDFu
+xe
+xE
+xEFF
+xEFu
+xF
+xFAFF
+xFB
+xFBA
+xFBAAu
+xFBABu
+xFBACu
+xFBADu
+xFBAEu
+xFBAFu
+xFBB
+xFBD
+xFBDAu
+xFBDBu
+xFBDCu
+xFBDDu
+xFBDEu
+xFBDFu
+xFBE
+xFBFCu
+xFBFDu
+xFBFEu
+xFBFFu
+xFDFF
+xfe
+xFE
+xFEA
+xFEAAu
+xFEABu
+xFEACu
+xFEADu
+xFEAEu
+xFEAFu
+xFEB
+xFEBAu
+xFEBBu
+xFEBCu
+xFEBDu
+xFEBEu
+xFEBFu
+xFEC
+xFECAu
+xFECBu
+xFECCu
+xFECDu
+xFECEu
+xFECFu
+xFED
+xFEDAu
+xFEDBu
+xFEDCu
+xFEDDu
+xFEDEu
+xFEDFu
+xFEE
+xFEEAu
+xFEEBu
+xFEECu
+xFEEDu
+xFEEEu
+xFEEFu
+xFEF
+xFEFAu
+xFEFBu
+xFEFCu
+xFEFF
+xFEFFu
+xff
+xFF
+xFFEF
+xFFF
+xFFFC
+xFFFD
+xFFFDu
+xFFFE
+xFFFF
+xFFFFD
+xFFFFF
+xFFFFFF
+xFFFFFFFF
+xFFFFFFFFFFFFFull
+xFFFFFFFFu
+xFFFFu
+xFFu
+xFu
+Xgroup
+xh
+Xhb
+Xhosa
+xi
+Xian
+Xiang
+Xiangxi
+Xibe
+XInclude
+xjb
+xkf
+xlocale
+XLOCALE
+xMax
+xMin
+xml
+XML
+xmlns
+xmm
+xmv
+xmw
+xnr
+xOffset
+xog
+xor
+XP
+xpe
+xPlacement
+xPlaDevice
+xscale
+xsl
+Xsmall
+xst
+Xuan
+XUID
+xwo
+xx
+XXX
+XY
+y
+Y
+Ya
+yacute
+Yacute
+Yacutesmall
+yAdvance
+yAdvDevice
+Yakut
+Yanahuanca
+Yang
+Yangbye
+yao
+Yao
+yap
+Yapese
+Yarowilca
+Yauyos
+Yay
+yb
+ybd
+yBytes
+yCoordinate
+ydd
+yDeviceTable
+ydieresis
+Ydieresis
+Ydieresissmall
+YEH
+Yemen
+yen
+yes
+Yes
+YES
+yet
+Ygroup
+yi
+Yi
+YI
+Yiddish
+YIDDISH
+yield
+YIELD
+yields
+yih
+Yijing
+YING
+yMax
+yMin
+yml
+yo
+YO
+YOD
+yOffset
+Yongbei
+Yongnan
+Yoruba
+yos
+Yos
+Yosemite
+you
+You
+Youjiang
+your
+yourinputtext
+yourself
+yPlacement
+yPlaDevice
+yrk
+yscale
+Ysmall
+yStrikeoutPosition
+yStrikeoutSize
+ySubscriptXOffset
+ySubscriptXSize
+ySubscriptYOffset
+ySubscriptYSize
+ySuperscriptXOffset
+ySuperscriptXSize
+ySuperscriptYOffset
+ySuperscriptYSize
+YU
+yue
+Yue
+Yugoslav
+yum
+Yupik
+z
+Z
+za
+ZAH
+ZAIN
+Zambia
+Zamboanga
+Zanabazar
+ZANABAZAR
+Zande
+Zarma
+zawgyi
+Zawgyi
+ZAWGYI
+ZAYIN
+Zazaki
+zcaron
+Zcaron
+Zcaronsmall
+zch
+zdj
+zea
+Zealand
+Zealandic
+Zeeuws
+zeh
+zero
+Zero
+ZERO
+zeroed
+zeroinferior
+zeroing
+zeroint
+zerooldstyle
+zeros
+zerosuperior
+zgb
+zgh
+zgm
+zgn
+zh
+zhd
+zhe
+zhn
+Zhong
+Zhuang
+Zimbabwe
+zip
+zipped
+zk
+Zl
+zlj
+zlm
+zln
+zlq
+zmi
+zne
+zo
+zom
+zone
+Zotung
+Zou
+Zp
+zqe
+Zs
+zsm
+Zsmall
+zu
+Zulu
+zum
+Zuojiang
+zwj
+ZWJ
+zwnj
+ZWNJ
+zyb
+zyg
+zyj
+zyn
+Zyrian
+zza
+zzj

File diff suppressed because it is too large
+ 133 - 0
libs/harfbuzz/perf/texts/fa-thelittleprince.txt


+ 21 - 0
libs/harfbuzz/replace-enum-strings.cmake

@@ -0,0 +1,21 @@
+# CMake script to replace items
+# in sources generated by glib-mkenums
+
+FILE(READ ${ENUM_INPUT_SRC} enum_in)
+
+STRING(REPLACE
+  "_t_get_type"
+  "_get_type"
+  enum_out_tmp
+  "${enum_in}"
+  )
+
+STRING(REPLACE
+  "_T ("
+  " ("
+  enum_out
+  "${enum_out_tmp}"
+  )
+
+FILE(WRITE ${ENUM_OUTPUT_SRC} "${enum_out}")
+FILE(REMOVE ${ENUM_INPUT_SRC})

+ 250 - 0
libs/harfbuzz/src/ArabicPUASimplified.txt

@@ -0,0 +1,250 @@
+#
+#    Name:     Legacy Simplified Arabic encoding
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the PUA code (in hex as 0xXXXX)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in PUA order
+#
+0xF100	0x063B	# ARABIC LETTER KEHEH WITH TWO DOTS ABOVE
+0xF100	0x063C	# ARABIC LETTER KEHEH WITH THREE DOTS BELOW
+0xF100	0x063D	# ARABIC LETTER FARSI YEH WITH INVERTED V
+0xF100	0x063E	# ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE
+0xF100	0x063F	# ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+0xF100	0x0653	# ARABIC MADDAH ABOVE
+0xF100	0x0654	# ARABIC HAMZA ABOVE
+0xF100	0x0655	# ARABIC HAMZA BELOW
+0xF100	0x0656	# ARABIC SUBSCRIPT ALEF
+0xF100	0x0657	# ARABIC INVERTED DAMMA
+0xF100	0x0658	# ARABIC MARK NOON GHUNNA
+0xF100	0x0659	# ARABIC ZWARAKAY
+0xF100	0x065A	# ARABIC VOWEL SIGN SMALL V ABOVE
+0xF100	0x065B	# ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
+0xF100	0x065C	# ARABIC VOWEL SIGN DOT BELOW
+0xF100	0x065D	# ARABIC REVERSED DAMMA
+0xF100	0x065E	# ARABIC FATHA WITH TWO DOTS
+0xF10C	0x200C	# ZERO WIDTH NON-JOINER
+0xF10D	0x200D	# ZERO WIDTH JOINER
+0xF10E	0x200E	# LEFT-TO-RIGHT MARK
+0xF10F	0x200F	# RIGHT-TO-LEFT MARK
+0xF120	0x0020	# SPACE
+0xF121	0x0021	# EXCLAMATION MARK
+0xF122	0x0022	# QUOTATION MARK
+0xF123	0x00AB	# LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xF124	0x00BB	# RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xF125	0x0025	# PERCENT SIGN
+0xF126	0x00D7	# MULTIPLICATION SIGN
+0xF127	0x00F7	# DIVISION SIGN
+0xF128	0x0028	# LEFT PARENTHESIS
+0xF129	0x0029	# RIGHT PARENTHESIS
+0xF12A	0x002A	# ASTERISK
+0xF12B	0x002B	# PLUS SIGN
+0xF12C	0x060C	# ARABIC COMMA
+0xF12D	0x002D	# HYPHEN-MINUS
+0xF12E	0x002E	# FULL STOP
+0xF12F	0x002F	# SOLIDUS
+0xF130	0x0660	# ARABIC-INDIC DIGIT ZERO
+0xF131	0x0661	# ARABIC-INDIC DIGIT ONE
+0xF132	0x0662	# ARABIC-INDIC DIGIT TWO
+0xF133	0x0663	# ARABIC-INDIC DIGIT THREE
+0xF134	0x0664	# ARABIC-INDIC DIGIT FOUR
+0xF135	0x0665	# ARABIC-INDIC DIGIT FIVE
+0xF136	0x0666	# ARABIC-INDIC DIGIT SIX
+0xF137	0x0667	# ARABIC-INDIC DIGIT SEVEN
+0xF138	0x0668	# ARABIC-INDIC DIGIT EIGHT
+0xF139	0x0669	# ARABIC-INDIC DIGIT NINE
+0xF13A	0x003A	# COLON
+0xF13B	0x003B	# SEMICOLON
+0xF13B	0x061B	# ARABIC SEMICOLON
+0xF13C	0x2018	# LEFT SINGLE QUOTATION MARK
+0xF13D	0x003D	# EQUALS SIGN
+0xF13E	0x2019	# RIGHT SINGLE QUOTATION MARK
+0xF13F	0x003F	# QUESTION MARK
+0xF13F	0x061F	# ARABIC QUESTION MARK
+0xF141	0x0627	# ARABIC LETTER ALEF
+0xF141	0xFE8D	# ARABIC LETTER ALEF ISOLATED FORM
+0xF142	0xFE8E	# ARABIC LETTER ALEF FINAL FORM
+0xF143	0x0623	# ARABIC LETTER ALEF WITH HAMZA ABOVE
+0xF143	0xFE83	# ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+0xF144	0xFE84	# ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+0xF145	0x0622	# ARABIC LETTER ALEF WITH MADDA ABOVE
+0xF145	0xFE81	# ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+0xF146	0xFE82	# ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+0xF147	0x0625	# ARABIC LETTER ALEF WITH HAMZA BELOW
+0xF147	0xFE87	# ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM
+0xF148	0xFE88	# ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
+0xF149	0xFE91	# ARABIC LETTER BEH INITIAL FORM
+0xF149	0xFE92	# ARABIC LETTER BEH MEDIAL FORM
+0xF14A	0x0628	# ARABIC LETTER BEH
+0xF14A	0xFE8F	# ARABIC LETTER BEH ISOLATED FORM
+0xF14A	0xFE90	# ARABIC LETTER BEH FINAL FORM
+0xF14B	0xFE97	# ARABIC LETTER TEH INITIAL FORM
+0xF14B	0xFE98	# ARABIC LETTER TEH MEDIAL FORM
+0xF14C	0x062A	# ARABIC LETTER TEH
+0xF14C	0xFE95	# ARABIC LETTER TEH ISOLATED FORM
+0xF14C	0xFE96	# ARABIC LETTER TEH FINAL FORM
+0xF14D	0xFE9B	# ARABIC LETTER THEH INITIAL FORM
+0xF14D	0xFE9C	# ARABIC LETTER THEH MEDIAL FORM
+0xF14E	0x062B	# ARABIC LETTER THEH
+0xF14E	0xFE99	# ARABIC LETTER THEH ISOLATED FORM
+0xF14E	0xFE9A	# ARABIC LETTER THEH FINAL FORM
+0xF14F	0xFE9F	# ARABIC LETTER JEEM INITIAL FORM
+0xF14F	0xFEA0	# ARABIC LETTER JEEM MEDIAL FORM
+0xF150	0xFE9E	# ARABIC LETTER JEEM FINAL FORM
+0xF151	0x062C	# ARABIC LETTER JEEM
+0xF151	0xFE9D	# ARABIC LETTER JEEM ISOLATED FORM
+0xF152	0xFEA3	# ARABIC LETTER HAH INITIAL FORM
+0xF152	0xFEA4	# ARABIC LETTER HAH MEDIAL FORM
+0xF153	0xFEA2	# ARABIC LETTER HAH FINAL FORM
+0xF154	0x062D	# ARABIC LETTER HAH
+0xF154	0xFEA1	# ARABIC LETTER HAH ISOLATED FORM
+0xF155	0xFEA7	# ARABIC LETTER KHAH INITIAL FORM
+0xF155	0xFEA8	# ARABIC LETTER KHAH MEDIAL FORM
+0xF156	0xFEA6	# ARABIC LETTER KHAH FINAL FORM
+0xF157	0x062E	# ARABIC LETTER KHAH
+0xF157	0xFEA5	# ARABIC LETTER KHAH ISOLATED FORM
+0xF158	0x062F	# ARABIC LETTER DAL
+0xF158	0xFEA9	# ARABIC LETTER DAL ISOLATED FORM
+0xF158	0xFEAA	# ARABIC LETTER DAL FINAL FORM
+0xF159	0x0630	# ARABIC LETTER THAL
+0xF159	0xFEAB	# ARABIC LETTER THAL ISOLATED FORM
+0xF159	0xFEAC	# ARABIC LETTER THAL FINAL FORM
+0xF15A	0x0631	# ARABIC LETTER REH
+0xF15A	0xFEAD	# ARABIC LETTER REH ISOLATED FORM
+0xF15A	0xFEAE	# ARABIC LETTER REH FINAL FORM
+0xF15B	0x005B	# LEFT SQUARE BRACKET
+0xF15C	0x005C	# REVERSE SOLIDUS
+0xF15D	0x005D	# RIGHT SQUARE BRACKET
+0xF15E	0x002C	# COMMA
+0xF15E	0x066B	# ARABIC DECIMAL SEPARATOR
+0xF15E	0x066C	# ARABIC THOUSANDS SEPARATOR
+0xF15F	0x0640	# ARABIC TATWEEL
+0xF160	0x0632	# ARABIC LETTER ZAIN
+0xF160	0xFEAF	# ARABIC LETTER ZAIN ISOLATED FORM
+0xF160	0xFEB0	# ARABIC LETTER ZAIN FINAL FORM
+0xF161	0xFEB3	# ARABIC LETTER SEEN INITIAL FORM
+0xF161	0xFEB4	# ARABIC LETTER SEEN MEDIAL FORM
+0xF162	0x0633	# ARABIC LETTER SEEN
+0xF162	0xFEB1	# ARABIC LETTER SEEN ISOLATED FORM
+0xF162	0xFEB2	# ARABIC LETTER SEEN FINAL FORM
+0xF163	0xFEB7	# ARABIC LETTER SHEEN INITIAL FORM
+0xF163	0xFEB8	# ARABIC LETTER SHEEN MEDIAL FORM
+0xF164	0x0634	# ARABIC LETTER SHEEN
+0xF164	0xFEB5	# ARABIC LETTER SHEEN ISOLATED FORM
+0xF164	0xFEB6	# ARABIC LETTER SHEEN FINAL FORM
+0xF165	0xFEBB	# ARABIC LETTER SAD INITIAL FORM
+0xF165	0xFEBC	# ARABIC LETTER SAD MEDIAL FORM
+0xF166	0x0635	# ARABIC LETTER SAD
+0xF166	0xFEB9	# ARABIC LETTER SAD ISOLATED FORM
+0xF166	0xFEBA	# ARABIC LETTER SAD FINAL FORM
+0xF167	0xFEBF	# ARABIC LETTER DAD INITIAL FORM
+0xF167	0xFEC0	# ARABIC LETTER DAD MEDIAL FORM
+0xF168	0x0636	# ARABIC LETTER DAD
+0xF168	0xFEBD	# ARABIC LETTER DAD ISOLATED FORM
+0xF168	0xFEBE	# ARABIC LETTER DAD FINAL FORM
+0xF169	0x0637	# ARABIC LETTER TAH
+0xF169	0xFEC1	# ARABIC LETTER TAH ISOLATED FORM
+0xF169	0xFEC2	# ARABIC LETTER TAH FINAL FORM
+0xF169	0xFEC3	# ARABIC LETTER TAH INITIAL FORM
+0xF169	0xFEC4	# ARABIC LETTER TAH MEDIAL FORM
+0xF16A	0x0638	# ARABIC LETTER ZAH
+0xF16A	0xFEC5	# ARABIC LETTER ZAH ISOLATED FORM
+0xF16A	0xFEC6	# ARABIC LETTER ZAH FINAL FORM
+0xF16A	0xFEC7	# ARABIC LETTER ZAH INITIAL FORM
+0xF16A	0xFEC8	# ARABIC LETTER ZAH MEDIAL FORM
+0xF16B	0xFECB	# ARABIC LETTER AIN INITIAL FORM
+0xF16C	0xFECC	# ARABIC LETTER AIN MEDIAL FORM
+0xF16D	0xFECA	# ARABIC LETTER AIN FINAL FORM
+0xF16E	0x0639	# ARABIC LETTER AIN
+0xF16E	0xFEC9	# ARABIC LETTER AIN ISOLATED FORM
+0xF16F	0xFECF	# ARABIC LETTER GHAIN INITIAL FORM
+0xF170	0xFED0	# ARABIC LETTER GHAIN MEDIAL FORM
+0xF171	0xFECE	# ARABIC LETTER GHAIN FINAL FORM
+0xF172	0x063A	# ARABIC LETTER GHAIN
+0xF172	0xFECD	# ARABIC LETTER GHAIN ISOLATED FORM
+0xF173	0xFED3	# ARABIC LETTER FEH INITIAL FORM
+0xF174	0xFED4	# ARABIC LETTER FEH MEDIAL FORM
+0xF175	0x0641	# ARABIC LETTER FEH
+0xF175	0xFED1	# ARABIC LETTER FEH ISOLATED FORM
+0xF175	0xFED2	# ARABIC LETTER FEH FINAL FORM
+0xF176	0xFED7	# ARABIC LETTER QAF INITIAL FORM
+0xF177	0xFED8	# ARABIC LETTER QAF MEDIAL FORM
+0xF178	0x0642	# ARABIC LETTER QAF
+0xF178	0xFED5	# ARABIC LETTER QAF ISOLATED FORM
+0xF178	0xFED6	# ARABIC LETTER QAF FINAL FORM
+0xF179	0xFEDB	# ARABIC LETTER KAF INITIAL FORM
+0xF179	0xFEDC	# ARABIC LETTER KAF MEDIAL FORM
+0xF17A	0x0643	# ARABIC LETTER KAF
+0xF17A	0xFED9	# ARABIC LETTER KAF ISOLATED FORM
+0xF17A	0xFEDA	# ARABIC LETTER KAF FINAL FORM
+0xF17B	0xFEDF	# ARABIC LETTER LAM INITIAL FORM
+0xF17B	0xFEE0	# ARABIC LETTER LAM MEDIAL FORM
+0xF17C	0x0644	# ARABIC LETTER LAM
+0xF17C	0xFEDD	# ARABIC LETTER LAM ISOLATED FORM
+0xF17C	0xFEDE	# ARABIC LETTER LAM FINAL FORM
+0xF17D	0xFEE3	# ARABIC LETTER MEEM INITIAL FORM
+0xF17D	0xFEE4	# ARABIC LETTER MEEM MEDIAL FORM
+0xF17E	0x0645	# ARABIC LETTER MEEM
+0xF17E	0xFEE1	# ARABIC LETTER MEEM ISOLATED FORM
+0xF17E	0xFEE2	# ARABIC LETTER MEEM FINAL FORM
+0xF17F	0xFEE7	# ARABIC LETTER NOON INITIAL FORM
+0xF17F	0xFEE8	# ARABIC LETTER NOON MEDIAL FORM
+0xF1A1	0xFEEB	# ARABIC LETTER HEH INITIAL FORM
+0xF1A2	0xFEEC	# ARABIC LETTER HEH MEDIAL FORM
+0xF1A3	0xFEEA	# ARABIC LETTER HEH FINAL FORM
+0xF1A4	0x0647	# ARABIC LETTER HEH
+0xF1A4	0xFEE9	# ARABIC LETTER HEH ISOLATED FORM
+0xF1A5	0x0648	# ARABIC LETTER WAW
+0xF1A5	0xFEED	# ARABIC LETTER WAW ISOLATED FORM
+0xF1A5	0xFEEE	# ARABIC LETTER WAW FINAL FORM
+0xF1A6	0xFEF3	# ARABIC LETTER YEH INITIAL FORM
+0xF1A6	0xFEF4	# ARABIC LETTER YEH MEDIAL FORM
+0xF1A7	0xFEF2	# ARABIC LETTER YEH FINAL FORM
+0xF1A8	0x064A	# ARABIC LETTER YEH
+0xF1A8	0xFEF1	# ARABIC LETTER YEH ISOLATED FORM
+0xF1A9	0x0629	# ARABIC LETTER TEH MARBUTA
+0xF1A9	0xFE93	# ARABIC LETTER TEH MARBUTA ISOLATED FORM
+0xF1AA	0xFE94	# ARABIC LETTER TEH MARBUTA FINAL FORM
+0xF1AB	0xFEF0	# ARABIC LETTER ALEF MAKSURA FINAL FORM
+0xF1AC	0x0649	# ARABIC LETTER ALEF MAKSURA
+0xF1AC	0xFEEF	# ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+0xF1AD	0x0621	# ARABIC LETTER HAMZA
+0xF1AE	0xFE8B	# ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+0xF1AE	0xFE8C	# ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
+0xF1AF	0xFE8A	# ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
+0xF1B0	0x0030	# DIGIT ZERO
+0xF1B1	0x0031	# DIGIT ONE
+0xF1B2	0x0032	# DIGIT TWO
+0xF1B3	0x0033	# DIGIT THREE
+0xF1B4	0x0034	# DIGIT FOUR
+0xF1B5	0x0035	# DIGIT FIVE
+0xF1B6	0x0036	# DIGIT SIX
+0xF1B7	0x0037	# DIGIT SEVEN
+0xF1B8	0x0038	# DIGIT EIGHT
+0xF1B9	0x0039	# DIGIT NINE
+0xF1BA	0x0626	# ARABIC LETTER YEH WITH HAMZA ABOVE
+0xF1BA	0xFE89	# ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
+0xF1BB	0x0624	# ARABIC LETTER WAW WITH HAMZA ABOVE
+0xF1BB	0xFE85	# ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+0xF1BB	0xFE86	# ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
+0xF1BC	0xFEFC	# ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+0xF1BD	0xFEFB	# ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+0xF1BE	0xFEF7	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+0xF1BF	0xFEF8	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+0xF1C0	0xFEF5	# ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+0xF1C1	0xFEF6	# ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+0xF1C2	0xFEF9	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
+0xF1C3	0xFEFA	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
+0xF1C4	0x064E	# ARABIC FATHA
+0xF1C5	0x064F	# ARABIC DAMMA
+0xF1C6	0x0652	# ARABIC SUKUN
+0xF1C7	0x064B	# ARABIC FATHATAN
+0xF1C8	0x064C	# ARABIC DAMMATAN
+0xF1C9	0x0651	# ARABIC SHADDA
+0xF1CA	0x0650	# ARABIC KASRA
+0xF1CB	0x064D	# ARABIC KASRATAN
+0xF1E1	0x0646	# ARABIC LETTER NOON
+0xF1E1	0xFEE5	# ARABIC LETTER NOON ISOLATED FORM
+0xF1E1	0xFEE6	# ARABIC LETTER NOON FINAL FORM

+ 295 - 0
libs/harfbuzz/src/ArabicPUATraditional.txt

@@ -0,0 +1,295 @@
+#
+#    Name:    Legacy Traditional Arabic encoding
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the PUA code (in hex as 0xXXXX)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in PUA order
+#
+0xF200	0x063B	# ARABIC LETTER KEHEH WITH TWO DOTS ABOVE
+0xF200	0x063C	# ARABIC LETTER KEHEH WITH THREE DOTS BELOW
+0xF200	0x063D	# ARABIC LETTER FARSI YEH WITH INVERTED V
+0xF200	0x063E	# ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE
+0xF200	0x063F	# ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+0xF200	0x0653	# ARABIC MADDAH ABOVE
+0xF200	0x0654	# ARABIC HAMZA ABOVE
+0xF200	0x0655	# ARABIC HAMZA BELOW
+0xF200	0x0656	# ARABIC SUBSCRIPT ALEF
+0xF200	0x0657	# ARABIC INVERTED DAMMA
+0xF200	0x0658	# ARABIC MARK NOON GHUNNA
+0xF200	0x0659	# ARABIC ZWARAKAY
+0xF200	0x065A	# ARABIC VOWEL SIGN SMALL V ABOVE
+0xF200	0x065B	# ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
+0xF200	0x065C	# ARABIC VOWEL SIGN DOT BELOW
+0xF200	0x065D	# ARABIC REVERSED DAMMA
+0xF200	0x065E	# ARABIC FATHA WITH TWO DOTS
+0xF202	0xFC08	# ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM
+0xF203	0xFC0E	# ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM
+0xF204	0xFC12	# ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM
+0xF205	0xFC42	# ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM
+0xF206	0xFC4E	# ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM
+0xF20C	0x200C	# ZERO WIDTH NON-JOINER
+0xF20D	0x200D	# ZERO WIDTH JOINER
+0xF20E	0x200E	# LEFT-TO-RIGHT MARK
+0xF20F	0x200F	# RIGHT-TO-LEFT MARK
+0xF210	0xFD88	# ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM
+0xF212	0xFC3F	# ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM
+0xF213	0xFC40	# ARABIC LIGATURE LAM WITH HAH ISOLATED FORM
+0xF214	0xFC41	# ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM
+0xF215	0xFC6A	# ARABIC LIGATURE BEH WITH REH FINAL FORM
+0xF216	0xFC70	# ARABIC LIGATURE TEH WITH REH FINAL FORM
+0xF217	0xFC91	# ARABIC LIGATURE YEH WITH REH FINAL FORM
+0xF218	0xFCB0	# ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM
+0xF219	0xFD30	# ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM
+0xF21A	0xFCCD	# ARABIC LIGATURE LAM WITH HEH INITIAL FORM
+0xF21C	0xFC44	# ARABIC LIGATURE LAM WITH YEH ISOLATED FORM
+0xF21D	0xFC0A	# ARABIC LIGATURE BEH WITH YEH ISOLATED FORM
+0xF21E	0xFC10	# ARABIC LIGATURE TEH WITH YEH ISOLATED FORM
+0xF21F	0xFC50	# ARABIC LIGATURE NOON WITH YEH ISOLATED FORM
+0xF220	0x0020	# SPACE
+0xF221	0x0021	# EXCLAMATION MARK
+0xF222	0x0022	# QUOTATION MARK
+0xF223	0x00AB	# LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xF224	0x00BB	# RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xF225	0x0025	# PERCENT SIGN
+0xF226	0x00D7	# MULTIPLICATION SIGN
+0xF227	0x00F7	# DIVISION SIGN
+0xF228	0x0028	# LEFT PARENTHESIS
+0xF229	0x0029	# RIGHT PARENTHESIS
+0xF22A	0x002A	# ASTERISK
+0xF22B	0x002B	# PLUS SIGN
+0xF22C	0x060C	# ARABIC COMMA
+0xF22D	0x002D	# HYPHEN-MINUS
+0xF22E	0x002E	# FULL STOP
+0xF22F	0x002F	# SOLIDUS
+0xF230	0x0660	# ARABIC-INDIC DIGIT ZERO
+0xF231	0x0661	# ARABIC-INDIC DIGIT ONE
+0xF232	0x0662	# ARABIC-INDIC DIGIT TWO
+0xF233	0x0663	# ARABIC-INDIC DIGIT THREE
+0xF234	0x0664	# ARABIC-INDIC DIGIT FOUR
+0xF235	0x0665	# ARABIC-INDIC DIGIT FIVE
+0xF236	0x0666	# ARABIC-INDIC DIGIT SIX
+0xF237	0x0667	# ARABIC-INDIC DIGIT SEVEN
+0xF238	0x0668	# ARABIC-INDIC DIGIT EIGHT
+0xF239	0x0669	# ARABIC-INDIC DIGIT NINE
+0xF23A	0x003A	# COLON
+0xF23B	0x003B	# SEMICOLON
+0xF23B	0x061B	# ARABIC SEMICOLON
+0xF23C	0x201C	# LEFT DOUBLE QUOTATION MARK
+0xF23D	0x003D	# EQUALS SIGN
+0xF23E	0x201D	# RIGHT DOUBLE QUOTATION MARK
+0xF23F	0x003F	# QUESTION MARK
+0xF23F	0x061F	# ARABIC QUESTION MARK
+0xF241	0x0627	# ARABIC LETTER ALEF
+0xF241	0xFE8D	# ARABIC LETTER ALEF ISOLATED FORM
+0xF242	0xFE8E	# ARABIC LETTER ALEF FINAL FORM
+0xF243	0x0623	# ARABIC LETTER ALEF WITH HAMZA ABOVE
+0xF243	0xFE83	# ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+0xF244	0xFE84	# ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+0xF245	0x0622	# ARABIC LETTER ALEF WITH MADDA ABOVE
+0xF245	0xFE81	# ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+0xF246	0xFE82	# ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+0xF247	0x0625	# ARABIC LETTER ALEF WITH HAMZA BELOW
+0xF247	0xFE87	# ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM
+0xF248	0xFE88	# ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
+0xF249	0xFE91	# ARABIC LETTER BEH INITIAL FORM
+0xF24A	0xFE92	# ARABIC LETTER BEH MEDIAL FORM
+0xF24B	0xFE90	# ARABIC LETTER BEH FINAL FORM
+0xF24C	0x0628	# ARABIC LETTER BEH
+0xF24C	0xFE8F	# ARABIC LETTER BEH ISOLATED FORM
+0xF24D	0xFE97	# ARABIC LETTER TEH INITIAL FORM
+0xF24E	0xFE98	# ARABIC LETTER TEH MEDIAL FORM
+0xF24F	0xFE96	# ARABIC LETTER TEH FINAL FORM
+0xF250	0x062A	# ARABIC LETTER TEH
+0xF250	0xFE95	# ARABIC LETTER TEH ISOLATED FORM
+0xF251	0xFE9B	# ARABIC LETTER THEH INITIAL FORM
+0xF252	0xFE9C	# ARABIC LETTER THEH MEDIAL FORM
+0xF253	0xFE9A	# ARABIC LETTER THEH FINAL FORM
+0xF254	0x062B	# ARABIC LETTER THEH
+0xF254	0xFE99	# ARABIC LETTER THEH ISOLATED FORM
+0xF255	0xFE9F	# ARABIC LETTER JEEM INITIAL FORM
+0xF256	0xFEA0	# ARABIC LETTER JEEM MEDIAL FORM
+0xF257	0xFE9E	# ARABIC LETTER JEEM FINAL FORM
+0xF258	0x062C	# ARABIC LETTER JEEM
+0xF258	0xFE9D	# ARABIC LETTER JEEM ISOLATED FORM
+0xF259	0xFEA3	# ARABIC LETTER HAH INITIAL FORM
+0xF25A	0xFEA4	# ARABIC LETTER HAH MEDIAL FORM
+0xF25B	0x005B	# LEFT SQUARE BRACKET
+0xF25C	0xFEA2	# ARABIC LETTER HAH FINAL FORM
+0xF25D	0x005D	# RIGHT SQUARE BRACKET
+0xF25E	0x002C	# COMMA
+0xF25E	0x066B	# ARABIC DECIMAL SEPARATOR
+0xF25E	0x066C	# ARABIC THOUSANDS SEPARATOR
+0xF25F	0x0640	# ARABIC TATWEEL
+0xF260	0x062D	# ARABIC LETTER HAH
+0xF260	0xFEA1	# ARABIC LETTER HAH ISOLATED FORM
+0xF261	0xFEA7	# ARABIC LETTER KHAH INITIAL FORM
+0xF262	0xFEA8	# ARABIC LETTER KHAH MEDIAL FORM
+0xF263	0xFEA6	# ARABIC LETTER KHAH FINAL FORM
+0xF264	0x062E	# ARABIC LETTER KHAH
+0xF264	0xFEA5	# ARABIC LETTER KHAH ISOLATED FORM
+0xF265	0x062F	# ARABIC LETTER DAL
+0xF265	0xFEA9	# ARABIC LETTER DAL ISOLATED FORM
+0xF266	0xFEAA	# ARABIC LETTER DAL FINAL FORM
+0xF267	0x0630	# ARABIC LETTER THAL
+0xF267	0xFEAB	# ARABIC LETTER THAL ISOLATED FORM
+0xF268	0xFEAC	# ARABIC LETTER THAL FINAL FORM
+0xF269	0x0631	# ARABIC LETTER REH
+0xF269	0xFEAD	# ARABIC LETTER REH ISOLATED FORM
+0xF26A	0xFEAE	# ARABIC LETTER REH FINAL FORM
+0xF26B	0x0632	# ARABIC LETTER ZAIN
+0xF26B	0xFEAF	# ARABIC LETTER ZAIN ISOLATED FORM
+0xF26C	0xFEB0	# ARABIC LETTER ZAIN FINAL FORM
+0xF26D	0xFEB3	# ARABIC LETTER SEEN INITIAL FORM
+0xF26E	0xFEB4	# ARABIC LETTER SEEN MEDIAL FORM
+0xF26F	0xFEB2	# ARABIC LETTER SEEN FINAL FORM
+0xF270	0x0633	# ARABIC LETTER SEEN
+0xF270	0xFEB1	# ARABIC LETTER SEEN ISOLATED FORM
+0xF271	0xFEB7	# ARABIC LETTER SHEEN INITIAL FORM
+0xF272	0xFEB8	# ARABIC LETTER SHEEN MEDIAL FORM
+0xF273	0xFEB6	# ARABIC LETTER SHEEN FINAL FORM
+0xF274	0x0634	# ARABIC LETTER SHEEN
+0xF274	0xFEB5	# ARABIC LETTER SHEEN ISOLATED FORM
+0xF275	0xFEBB	# ARABIC LETTER SAD INITIAL FORM
+0xF276	0xFEBC	# ARABIC LETTER SAD MEDIAL FORM
+0xF277	0xFEBA	# ARABIC LETTER SAD FINAL FORM
+0xF278	0x0635	# ARABIC LETTER SAD
+0xF278	0xFEB9	# ARABIC LETTER SAD ISOLATED FORM
+0xF279	0xFEBF	# ARABIC LETTER DAD INITIAL FORM
+0xF27A	0xFEC0	# ARABIC LETTER DAD MEDIAL FORM
+0xF27B	0xFD3E	# ORNATE LEFT PARENTHESIS
+0xF27C	0xFEBE	# ARABIC LETTER DAD FINAL FORM
+0xF27D	0xFD3F	# ORNATE RIGHT PARENTHESIS
+0xF27E	0x0636	# ARABIC LETTER DAD
+0xF27E	0xFEBD	# ARABIC LETTER DAD ISOLATED FORM
+0xF27F	0xFEC3	# ARABIC LETTER TAH INITIAL FORM
+0xF280	0xFC9C	# ARABIC LIGATURE BEH WITH JEEM INITIAL FORM
+0xF281	0xFC9D	# ARABIC LIGATURE BEH WITH HAH INITIAL FORM
+0xF282	0xFC9E	# ARABIC LIGATURE BEH WITH KHAH INITIAL FORM
+0xF283	0xFCA1	# ARABIC LIGATURE TEH WITH JEEM INITIAL FORM
+0xF284	0xFCA2	# ARABIC LIGATURE TEH WITH HAH INITIAL FORM
+0xF285	0xFCA3	# ARABIC LIGATURE TEH WITH KHAH INITIAL FORM
+0xF286	0xFCC9	# ARABIC LIGATURE LAM WITH JEEM INITIAL FORM
+0xF287	0xFCCA	# ARABIC LIGATURE LAM WITH HAH INITIAL FORM
+0xF288	0xFCCB	# ARABIC LIGATURE LAM WITH KHAH INITIAL FORM
+0xF289	0xFCCE	# ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM
+0xF28A	0xFCCF	# ARABIC LIGATURE MEEM WITH HAH INITIAL FORM
+0xF28B	0xFCD0	# ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM
+0xF28D	0xFCD2	# ARABIC LIGATURE NOON WITH JEEM INITIAL FORM
+0xF28E	0xFCD3	# ARABIC LIGATURE NOON WITH HAH INITIAL FORM
+0xF28F	0xFCDA	# ARABIC LIGATURE YEH WITH JEEM INITIAL FORM
+0xF290	0xFCDB	# ARABIC LIGATURE YEH WITH HAH INITIAL FORM
+0xF291	0xFCDC	# ARABIC LIGATURE YEH WITH KHAH INITIAL FORM
+0xF292	0xFC6D	# ARABIC LIGATURE BEH WITH NOON FINAL FORM
+0xF293	0xFC73	# ARABIC LIGATURE TEH WITH NOON FINAL FORM
+0xF294	0xFC94	# ARABIC LIGATURE YEH WITH NOON FINAL FORM
+0xF295	0xFC86	# ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM
+0xF296	0xFC9F	# ARABIC LIGATURE BEH WITH MEEM INITIAL FORM
+0xF297	0xFCA4	# ARABIC LIGATURE TEH WITH MEEM INITIAL FORM
+0xF298	0xFCD5	# ARABIC LIGATURE NOON WITH MEEM INITIAL FORM
+0xF299	0xFCDD	# ARABIC LIGATURE YEH WITH MEEM INITIAL FORM
+0xF29A	0xFCA8	# ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM
+0xF29B	0xFCAA	# ARABIC LIGATURE HAH WITH MEEM INITIAL FORM
+0xF29C	0xFCAC	# ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM
+0xF29D	0xFCCC	# ARABIC LIGATURE LAM WITH MEEM INITIAL FORM
+0xF29E	0xFCD1	# ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM
+0xF29F	0xFC32	# ARABIC LIGATURE FEH WITH YEH ISOLATED FORM
+0xF2A1	0xFEC2	# ARABIC LETTER TAH FINAL FORM
+0xF2A2	0x0637	# ARABIC LETTER TAH
+0xF2A2	0xFEC1	# ARABIC LETTER TAH ISOLATED FORM
+0xF2A3	0x0638	# ARABIC LETTER ZAH
+0xF2A3	0xFEC7	# ARABIC LETTER ZAH INITIAL FORM
+0xF2A4	0xFEC8	# ARABIC LETTER ZAH MEDIAL FORM
+0xF2A5	0xFEC6	# ARABIC LETTER ZAH FINAL FORM
+0xF2A6	0xFEC5	# ARABIC LETTER ZAH ISOLATED FORM
+0xF2A7	0xFECB	# ARABIC LETTER AIN INITIAL FORM
+0xF2A8	0xFECC	# ARABIC LETTER AIN MEDIAL FORM
+0xF2A9	0xFECA	# ARABIC LETTER AIN FINAL FORM
+0xF2AA	0x0639	# ARABIC LETTER AIN
+0xF2AA	0xFEC9	# ARABIC LETTER AIN ISOLATED FORM
+0xF2AB	0xFECF	# ARABIC LETTER GHAIN INITIAL FORM
+0xF2AC	0xFED0	# ARABIC LETTER GHAIN MEDIAL FORM
+0xF2AD	0xFECE	# ARABIC LETTER GHAIN FINAL FORM
+0xF2AE	0x063A	# ARABIC LETTER GHAIN
+0xF2AE	0xFECD	# ARABIC LETTER GHAIN ISOLATED FORM
+0xF2AF	0xFED3	# ARABIC LETTER FEH INITIAL FORM
+0xF2B0	0xFED4	# ARABIC LETTER FEH MEDIAL FORM
+0xF2B1	0xFED2	# ARABIC LETTER FEH FINAL FORM
+0xF2B2	0x0641	# ARABIC LETTER FEH
+0xF2B2	0xFED1	# ARABIC LETTER FEH ISOLATED FORM
+0xF2B3	0xFED7	# ARABIC LETTER QAF INITIAL FORM
+0xF2B4	0xFED8	# ARABIC LETTER QAF MEDIAL FORM
+0xF2B5	0xFED6	# ARABIC LETTER QAF FINAL FORM
+0xF2B6	0x0642	# ARABIC LETTER QAF
+0xF2B6	0xFED5	# ARABIC LETTER QAF ISOLATED FORM
+0xF2B7	0xFEDB	# ARABIC LETTER KAF INITIAL FORM
+0xF2B8	0xFEDC	# ARABIC LETTER KAF MEDIAL FORM
+0xF2B9	0xFEDA	# ARABIC LETTER KAF FINAL FORM
+0xF2BA	0x0643	# ARABIC LETTER KAF
+0xF2BA	0xFED9	# ARABIC LETTER KAF ISOLATED FORM
+0xF2BB	0xFEDF	# ARABIC LETTER LAM INITIAL FORM
+0xF2BC	0xFEE0	# ARABIC LETTER LAM MEDIAL FORM
+0xF2BD	0xFEDE	# ARABIC LETTER LAM FINAL FORM
+0xF2BE	0x0644	# ARABIC LETTER LAM
+0xF2BE	0xFEDD	# ARABIC LETTER LAM ISOLATED FORM
+0xF2BF	0xFEE3	# ARABIC LETTER MEEM INITIAL FORM
+0xF2C0	0xFEE4	# ARABIC LETTER MEEM MEDIAL FORM
+0xF2C1	0xFEE2	# ARABIC LETTER MEEM FINAL FORM
+0xF2C2	0x0645	# ARABIC LETTER MEEM
+0xF2C2	0xFEE1	# ARABIC LETTER MEEM ISOLATED FORM
+0xF2C3	0xFEE7	# ARABIC LETTER NOON INITIAL FORM
+0xF2C4	0xFEE8	# ARABIC LETTER NOON MEDIAL FORM
+0xF2C5	0xFEE6	# ARABIC LETTER NOON FINAL FORM
+0xF2C6	0x0646	# ARABIC LETTER NOON
+0xF2C6	0xFEE5	# ARABIC LETTER NOON ISOLATED FORM
+0xF2C7	0xFEEB	# ARABIC LETTER HEH INITIAL FORM
+0xF2C8	0xFEEC	# ARABIC LETTER HEH MEDIAL FORM
+0xF2C9	0xFEEA	# ARABIC LETTER HEH FINAL FORM
+0xF2CA	0x0647	# ARABIC LETTER HEH
+0xF2CA	0xFEE9	# ARABIC LETTER HEH ISOLATED FORM
+0xF2CB	0x0648	# ARABIC LETTER WAW
+0xF2CB	0xFEED	# ARABIC LETTER WAW ISOLATED FORM
+0xF2CC	0xFEEE	# ARABIC LETTER WAW FINAL FORM
+0xF2CD	0xFEF3	# ARABIC LETTER YEH INITIAL FORM
+0xF2CE	0xFEF4	# ARABIC LETTER YEH MEDIAL FORM
+0xF2CF	0xFEF2	# ARABIC LETTER YEH FINAL FORM
+0xF2D0	0x064A	# ARABIC LETTER YEH
+0xF2D0	0xFEF1	# ARABIC LETTER YEH ISOLATED FORM
+0xF2D1	0x0629	# ARABIC LETTER TEH MARBUTA
+0xF2D1	0xFE93	# ARABIC LETTER TEH MARBUTA ISOLATED FORM
+0xF2D2	0xFE94	# ARABIC LETTER TEH MARBUTA FINAL FORM
+0xF2D3	0xFEF0	# ARABIC LETTER ALEF MAKSURA FINAL FORM
+0xF2D4	0x0649	# ARABIC LETTER ALEF MAKSURA
+0xF2D4	0xFEEF	# ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+0xF2D5	0x0621	# ARABIC LETTER HAMZA
+0xF2D6	0xFE8B	# ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+0xF2D7	0xFE8C	# ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
+0xF2D8	0xFE8A	# ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
+0xF2D9	0x0626	# ARABIC LETTER YEH WITH HAMZA ABOVE
+0xF2D9	0xFE89	# ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
+0xF2DA	0x0624	# ARABIC LETTER WAW WITH HAMZA ABOVE
+0xF2DA	0xFE85	# ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+0xF2DB	0xFE86	# ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
+0xF2DC	0xFEFB	# ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+0xF2DD	0xFEFC	# ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+0xF2DE	0xFEF7	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+0xF2DF	0xFEF8	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+0xF2E0	0xFEF5	# ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+0xF2E1	0xFEF6	# ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+0xF2E2	0xFEF9	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
+0xF2E3	0xFEFA	# ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
+0xF2E4	0x064E	# ARABIC FATHA
+0xF2E5	0x064F	# ARABIC DAMMA
+0xF2E6	0x0652	# ARABIC SUKUN
+0xF2E7	0x064B	# ARABIC FATHATAN
+0xF2E8	0x064C	# ARABIC DAMMATAN
+0xF2E9	0x0651	# ARABIC SHADDA
+0xF2EA	0x0650	# ARABIC KASRA
+0xF2EB	0x064D	# ARABIC KASRATAN
+0xF2EC	0xFC60	# ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM
+0xF2ED	0xFC61	# ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM
+0xF2EF	0xFC5E	# ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM
+0xF2F0	0xFC62	# ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM
+0xF2F1	0xFEC4	# ARABIC LETTER TAH MEDIAL FORM

+ 522 - 0
libs/harfbuzz/src/Makefile.am

@@ -0,0 +1,522 @@
+# Process this file with automake to produce Makefile.in
+
+NULL =
+SUBDIRS =
+DIST_SUBDIRS =
+BUILT_SOURCES =
+EXTRA_DIST =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
+TESTS =
+check_PROGRAMS =
+
+EXTRA_DIST += harfbuzz.cc harfbuzz-subset.cc
+EXTRA_DIST += meson.build
+EXTRA_DIST += fix_get_types.py
+
+# Convenience targets:
+lib: $(BUILT_SOURCES) libharfbuzz.la
+libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
+tiny:
+	$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Os -DHB_TINY $(CPPFLAGS)" libs
+tinyz:
+	$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Oz -DHB_TINY $(CPPFLAGS)" libs
+
+lib_LTLIBRARIES = libharfbuzz.la
+
+include Makefile.sources
+
+HBCFLAGS =
+HBLIBS =
+HBNONPCLIBS =
+HBDEPS =
+HBSOURCES =  $(HB_BASE_sources)
+HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
+HBHEADERS = $(HB_BASE_headers)
+
+if HAVE_PTHREAD
+HBCFLAGS += $(PTHREAD_CFLAGS)
+HBNONPCLIBS += $(PTHREAD_LIBS)
+endif
+
+if HAVE_GLIB
+HBCFLAGS += $(GLIB_CFLAGS)
+HBLIBS   += $(GLIB_LIBS)
+HBDEPS   += $(GLIB_DEPS)
+HBSOURCES += $(HB_GLIB_sources)
+HBHEADERS += $(HB_GLIB_headers)
+endif
+
+if HAVE_FREETYPE
+HBCFLAGS += $(FREETYPE_CFLAGS)
+HBLIBS   += $(FREETYPE_LIBS)
+HBDEPS   += $(FREETYPE_DEPS)
+HBSOURCES += $(HB_FT_sources)
+HBHEADERS += $(HB_FT_headers)
+endif
+
+if HAVE_GRAPHITE2
+HBCFLAGS += $(GRAPHITE2_CFLAGS)
+HBLIBS   += $(GRAPHITE2_LIBS)
+HBDEPS   += $(GRAPHITE2_DEPS)
+HBSOURCES += $(HB_GRAPHITE2_sources)
+HBHEADERS += $(HB_GRAPHITE2_headers)
+endif
+
+if HAVE_UNISCRIBE
+HBCFLAGS += $(UNISCRIBE_CFLAGS)
+HBNONPCLIBS += $(UNISCRIBE_LIBS)
+HBSOURCES += $(HB_UNISCRIBE_sources)
+HBHEADERS += $(HB_UNISCRIBE_headers)
+endif
+
+if HAVE_DIRECTWRITE
+HBCFLAGS += $(DIRECTWRITE_CXXFLAGS)
+HBNONPCLIBS += $(DIRECTWRITE_LIBS)
+HBSOURCES += $(HB_DIRECTWRITE_sources)
+HBHEADERS += $(HB_DIRECTWRITE_headers)
+endif
+
+if HAVE_GDI
+HBCFLAGS += $(GDI_CXXFLAGS)
+HBNONPCLIBS += $(GDI_LIBS)
+HBSOURCES += $(HB_GDI_sources)
+HBHEADERS += $(HB_GDI_headers)
+endif
+
+if HAVE_CORETEXT
+HBCFLAGS += $(CORETEXT_CFLAGS)
+HBNONPCLIBS += $(CORETEXT_LIBS)
+HBSOURCES += $(HB_CORETEXT_sources)
+HBHEADERS += $(HB_CORETEXT_headers)
+endif
+
+
+BUILT_SOURCES += \
+	hb-version.h
+
+$(srcdir)/hb-version.h: hb-version.h.in $(top_srcdir)/configure.ac
+	$(AM_V_GEN) $(SED) \
+		-e 's/[@]HB_VERSION_MAJOR@/$(HB_VERSION_MAJOR)/' \
+		-e 's/[@]HB_VERSION_MINOR@/$(HB_VERSION_MINOR)/' \
+		-e 's/[@]HB_VERSION_MICRO@/$(HB_VERSION_MICRO)/' \
+		-e 's/[@]HB_VERSION@/$(HB_VERSION)/' \
+		"$<" > "$@" || ($(RM) "$@"; false)
+
+# Put the library together
+
+HBLIBS += $(HBNONPCLIBS)
+
+if OS_WIN32
+export_symbols = -export-symbols harfbuzz.def
+harfbuzz_def_dependency = harfbuzz.def
+export_symbols_subset = -export-symbols harfbuzz-subset.def
+harfbuzz_subset_def_dependency = harfbuzz-subset.def
+export_symbols_icu = -export-symbols harfbuzz-icu.def
+harfbuzz_icu_def_dependency = harfbuzz-icu.def
+export_symbols_gobject = -export-symbols harfbuzz-gobject.def
+harfbuzz_gobject_def_dependency = harfbuzz-gobject.def
+chosen_linker = $(CXXLINK)
+else
+if WITH_LIBSTDCXX
+chosen_linker = $(CXXLINK)
+else
+if HAVE_GCC
+# Use a C linker for GCC, not C++; Don't link to libstdc++
+chosen_linker = $(LINK)
+else
+chosen_linker = $(CXXLINK)
+endif
+endif
+endif
+
+@CODE_COVERAGE_RULES@
+
+base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
+libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS)
+libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
+libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS)
+libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols) $(CODE_COVERAGE_LDFLAGS)
+libharfbuzz_la_LIBADD = $(HBLIBS)
+EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
+pkginclude_HEADERS = $(HBHEADERS)
+nodist_pkginclude_HEADERS =
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = harfbuzz.pc
+cmakedir = $(libdir)/cmake/harfbuzz
+cmake_DATA = harfbuzz-config.cmake
+EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
+
+lib_LTLIBRARIES += libharfbuzz-subset.la
+libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
+libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
+libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS)
+libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset) $(CODE_COVERAGE_LDFLAGS)
+libharfbuzz_subset_la_LIBADD = libharfbuzz.la
+EXTRA_libharfbuzz_subset_la_DEPENDENCIES = $(harfbuzz_subset_def_dependency)
+pkginclude_HEADERS += $(HB_SUBSET_headers)
+pkgconfig_DATA += harfbuzz-subset.pc
+EXTRA_DIST += harfbuzz-subset.pc.in
+
+harfbuzz-subset.cc: Makefile.sources
+	$(AM_V_GEN) \
+	LANG=C; \
+	for f in \
+		$(HB_BASE_sources) \
+		$(HB_SUBSET_sources) \
+		; do echo '#include "'$$f'"'; done | \
+	sort -u | \
+	grep '[.]cc"' > $(srcdir)/harfbuzz-subset.cc \
+	|| ($(RM) $(srcdir)/harfbuzz-subset.cc; false)
+BUILT_SOURCES += harfbuzz-subset.cc
+
+if HAVE_ICU
+if HAVE_ICU_BUILTIN
+HBCFLAGS += $(ICU_CFLAGS)
+HBLIBS += $(ICU_LIBS)
+HBSOURCES += $(HB_ICU_sources)
+HBHEADERS += $(HB_ICU_headers)
+else
+lib_LTLIBRARIES += libharfbuzz-icu.la
+libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
+libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS) $(CODE_COVERAGE_CFLAGS)
+libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu) $(CODE_COVERAGE_LDFLAGS)
+libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
+EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
+pkginclude_HEADERS += $(HB_ICU_headers)
+pkgconfig_DATA += harfbuzz-icu.pc
+endif
+endif
+EXTRA_DIST += harfbuzz-icu.pc.in
+
+if HAVE_GOBJECT
+lib_LTLIBRARIES += libharfbuzz-gobject.la
+libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS)
+libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_DIST_sources)
+nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_NODIST_sources)
+libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(GOBJECT_CFLAGS) $(CODE_COVERAGE_CFLAGS)
+libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags) $(CODE_COVERAGE_LDFLAGS)
+libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
+EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency)
+pkginclude_HEADERS += $(HB_GOBJECT_DIST_headers)
+nodist_pkginclude_HEADERS += $(HB_GOBJECT_NODIST_headers)
+pkgconfig_DATA += harfbuzz-gobject.pc
+
+BUILT_SOURCES += \
+	$(HB_GOBJECT_ENUM_sources) \
+	$(HB_GOBJECT_ENUM_headers) \
+	$(NULL)
+DISTCLEANFILES += \
+	$(HB_GOBJECT_ENUM_sources) \
+	$(HB_GOBJECT_ENUM_headers) \
+	$(NULL)
+hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS)
+	$(AM_V_GEN) PYTHONIOENCODING=UTF-8 $(GLIB_MKENUMS) \
+		--identifier-prefix hb_ --symbol-prefix hb_gobject \
+		--template $^ | \
+	sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
+	|| ($(RM) "$@"; false)
+endif
+EXTRA_DIST += \
+	harfbuzz-gobject.pc.in \
+	hb-gobject-enums.cc.tmpl \
+	hb-gobject-enums.h.tmpl \
+	$(NULL)
+
+
+%.pc: %.pc.in $(top_builddir)/config.status
+	$(AM_V_GEN) \
+	$(SED)	-e 's@%prefix%@$(prefix)@g' \
+		-e 's@%exec_prefix%@$(exec_prefix)@g' \
+		-e 's@%libdir%@$(libdir)@g' \
+		-e 's@%includedir%@$(includedir)@g' \
+		-e 's@%libs_private%@$(HBNONPCLIBS)@g' \
+		-e 's@%requires_private%@$(HBDEPS)@g' \
+		-e 's@%VERSION%@$(VERSION)@g' \
+	"$<" > "$@" \
+	|| ($(RM) "$@"; false)
+
+CLEANFILES += $(pkgconfig_DATA)
+
+
+DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated-symbols.txt
+if HAVE_GOBJECT
+DEF_FILES += harfbuzz-gobject.def
+endif
+check: $(DEF_FILES) # For check-symbols.sh
+CLEANFILES += $(DEF_FILES)
+harfbuzz.def: $(top_builddir)/config.status
+harfbuzz.def: $(HBHEADERS)
+	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
+harfbuzz-subset.def: $(HB_SUBSET_headers)
+	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
+harfbuzz-icu.def: $(HB_ICU_headers)
+	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
+harfbuzz-gobject.def: $(HB_GOBJECT_headers)
+	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
+harfbuzz-deprecated-symbols.txt: $(srcdir)/hb-deprecated.h
+	$(AM_V_GEN) PLAIN_LIST=1 $(srcdir)/gen-def.py "$@" $^
+
+
+GENERATORS = \
+	gen-arabic-joining-list.py \
+	gen-arabic-table.py \
+	gen-def.py \
+	gen-emoji-table.py \
+	gen-harfbuzzcc.py \
+	gen-hb-version.py \
+	gen-indic-table.py \
+	gen-os2-unicode-ranges.py \
+	gen-ragel-artifacts.py \
+	gen-tag-table.py \
+	gen-ucd-table.py \
+	gen-use-table.py \
+	gen-vowel-constraints.py \
+	$(NULL)
+EXTRA_DIST += $(GENERATORS)
+
+built-sources: $(BUILT_SOURCES)
+
+.PHONY: built-sources
+
+RAGEL_GENERATED = \
+	$(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
+	$(NULL)
+BUILT_SOURCES += $(RAGEL_GENERATED)
+EXTRA_DIST += \
+	$(HB_BASE_RAGEL_sources) \
+	$(NULL)
+# We decided to add ragel-generated files to git...
+#MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
+$(srcdir)/%.hh: $(srcdir)/%.rl
+	$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
+	|| ($(RM) "$@"; false)
+
+harfbuzz.cc: Makefile.sources
+	$(AM_V_GEN) \
+	LANG=C; \
+	for f in \
+		$(HB_BASE_sources) \
+		$(HB_GLIB_sources) \
+		$(HB_FT_sources) \
+		$(HB_GRAPHITE2_sources) \
+		$(HB_UNISCRIBE_sources) \
+		$(HB_GDI_sources) \
+		$(HB_DIRECTWRITE_sources) \
+		$(HB_CORETEXT_sources) \
+		; do echo '#include "'$$f'"'; done | \
+	sort -u | \
+	grep '[.]cc"' > $(srcdir)/harfbuzz.cc \
+	|| ($(RM) $(srcdir)/harfbuzz.cc; false)
+BUILT_SOURCES += harfbuzz.cc
+
+noinst_PROGRAMS = \
+	main \
+	test \
+	test-buffer-serialize \
+	test-ot-meta \
+	test-ot-name \
+	test-ot-glyphname \
+	test-gpos-size-params \
+	test-gsub-would-substitute \
+	test-use-table \
+	$(NULL)
+bin_PROGRAMS =
+
+main_SOURCES = main.cc
+main_CPPFLAGS = $(HBCFLAGS)
+main_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_SOURCES = test.cc
+test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
+test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+
+test_buffer_serialize_SOURCES = test-buffer-serialize.cc
+test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
+test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_ot_meta_SOURCES = test-ot-meta.cc
+test_ot_meta_CPPFLAGS = $(HBCFLAGS)
+test_ot_meta_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_ot_name_SOURCES = test-ot-name.cc
+test_ot_name_CPPFLAGS = $(HBCFLAGS)
+test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_ot_glyphname_SOURCES = test-ot-glyphname.cc
+test_ot_glyphname_CPPFLAGS = $(HBCFLAGS)
+test_ot_glyphname_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_use_table_SOURCES = test-use-table.cc
+test_use_table_CPPFLAGS = $(HBCFLAGS)
+test_use_table_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_gpos_size_params_SOURCES = test-gpos-size-params.cc
+test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
+test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
+test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
+test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+
+COMPILED_TESTS = \
+	test-algs \
+	test-array \
+	test-bimap \
+	test-iter \
+	test-machinery \
+	test-map \
+	test-number \
+	test-ot-tag \
+	test-priority-queue \
+	test-set \
+	test-serialize \
+	test-unicode-ranges \
+	test-vector \
+	test-repacker \
+	test-classdef-graph \
+	$(NULL)
+COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
+COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
+check_PROGRAMS += $(COMPILED_TESTS)
+TESTS += $(COMPILED_TESTS)
+
+test_algs_SOURCES = test-algs.cc hb-static.cc
+test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_algs_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_array_SOURCES = test-array.cc
+test_array_CPPFLAGS = $(HBCFLAGS)
+test_array_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_bimap_SOURCES = test-bimap.cc hb-static.cc
+test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_bimap_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_iter_SOURCES = test-iter.cc hb-static.cc
+test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_iter_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_machinery_SOURCES = test-machinery.cc hb-static.cc
+test_machinery_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_machinery_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_map_SOURCES = test-map.cc hb-static.cc
+test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_map_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_number_SOURCES = test-number.cc hb-number.cc
+test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_number_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)
+
+test_priority_queue_SOURCES = test-priority-queue.cc hb-static.cc
+test_priority_queue_CPPFLAGS = $(HBCFLAGS)
+test_priority_queue_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_repacker_SOURCES = test-repacker.cc hb-static.cc graph/gsubgpos-context.cc
+test_repacker_CPPFLAGS = $(HBCFLAGS)
+test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
+
+test_classdef_graph_SOURCES = graph/test-classdef-graph.cc hb-static.cc graph/gsubgpos-context.cc
+test_classdef_graph_CPPFLAGS = $(HBCFLAGS)
+test_classdef_graph_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
+
+test_set_SOURCES = test-set.cc hb-static.cc
+test_set_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_set_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_serialize_SOURCES = test-serialize.cc hb-static.cc
+test_serialize_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_serialize_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_unicode_ranges_SOURCES = test-unicode-ranges.cc
+test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_vector_SOURCES = test-vector.cc hb-static.cc
+test_vector_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_vector_LDADD = $(COMPILED_TESTS_LDADD)
+
+dist_check_SCRIPTS = \
+	check-c-linkage-decls.py \
+	check-externs.py \
+	check-header-guards.py \
+	check-includes.py \
+	check-static-inits.py \
+	check-symbols.py \
+	$(NULL)
+TESTS += $(dist_check_SCRIPTS)
+
+if !WITH_LIBSTDCXX
+dist_check_SCRIPTS += \
+	check-libstdc++.py \
+	$(NULL)
+endif
+
+TESTS_ENVIRONMENT = \
+	srcdir="$(srcdir)" \
+	base_srcdir="$(srcdir)" \
+	builddir="$(builddir)" \
+	MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
+	HBSOURCES="$(HBSOURCES)" \
+	HBHEADERS="$(HBHEADERS)" \
+	LDD="$(LDD)" \
+	NM="$(NM)" \
+	OBJDUMP="$(OBJDUMP)" \
+	OTOOL="$(OTOOL)" \
+	$(NULL)
+
+if HAVE_INTROSPECTION
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS = HarfBuzz-0.0.gir # What does the 0 mean anyway?!
+INTROSPECTION_SCANNER_ARGS = \
+	-I$(srcdir) \
+	--warn-all --verbose \
+	--namespace=HarfBuzz \
+	--nsversion=0.0 \
+	--symbol-prefix=hb \
+	--symbol-prefix=hb_gobject \
+	--identifier-prefix=hb_ \
+	--pkg-export=harfbuzz-gobject \
+	--c-include=hb-gobject.h
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+INTROSPECTION_SCANNER_ENV = CC="$(CC)"
+
+HarfBuzz-0.0.gir: libharfbuzz.la libharfbuzz-gobject.la
+HarfBuzz_0_0_gir_INCLUDES = GObject-2.0 freetype2-2.0
+HarfBuzz_0_0_gir_CFLAGS = \
+	$(INCLUDES) \
+	$(HBCFLAGS) \
+	-DHB_NO_SINGLE_HEADER_ERROR \
+	-DHAVE_GOBJECT \
+	-DHB_EXTERN= \
+	$(NULL)
+HarfBuzz_0_0_gir_LIBS = \
+	libharfbuzz.la \
+	libharfbuzz-gobject.la \
+	$(NULL)
+HarfBuzz_0_0_gir_FILES = \
+	$(HBHEADERS) \
+	$(HBSOURCES) \
+	$(HB_GOBJECT_sources) \
+	$(HB_GOBJECT_headers) \
+	$(NULL)
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES += $(gir_DATA) $(typelib_DATA)
+
+endif
+
+-include $(top_srcdir)/git.mk

+ 375 - 0
libs/harfbuzz/src/Makefile.sources

@@ -0,0 +1,375 @@
+# Base and default-included sources and headers
+
+HB_BASE_sources = \
+	hb-aat-layout-ankr-table.hh \
+	hb-aat-layout-bsln-table.hh \
+	hb-aat-layout-common.hh \
+	hb-aat-layout-feat-table.hh \
+	hb-aat-layout-just-table.hh \
+	hb-aat-layout-kerx-table.hh \
+	hb-aat-layout-morx-table.hh \
+	hb-aat-layout-opbd-table.hh \
+	hb-aat-layout-trak-table.hh \
+	hb-aat-layout.cc \
+	hb-aat-layout.hh \
+	hb-aat-ltag-table.hh \
+	hb-aat-map.cc \
+	hb-aat-map.hh \
+	hb-algs.hh \
+	hb-array.hh \
+	hb-atomic.hh \
+	hb-bimap.hh \
+	hb-bit-page.hh \
+	hb-bit-set.hh \
+	hb-bit-set-invertible.hh \
+	hb-blob.cc \
+	hb-blob.hh \
+	hb-buffer-serialize.cc \
+	hb-buffer-verify.cc \
+	hb-buffer.cc \
+	hb-buffer.hh \
+	hb-cache.hh \
+	hb-cff-interp-common.hh \
+	hb-cff-interp-cs-common.hh \
+	hb-cff-interp-dict-common.hh \
+	hb-cff1-interp-cs.hh \
+	hb-cff2-interp-cs.hh \
+	hb-common.cc \
+	hb-config.hh \
+	hb-debug.hh \
+	hb-dispatch.hh \
+	hb-draw.cc \
+	hb-draw.hh \
+	hb-face.cc \
+	hb-face.hh \
+	hb-fallback-shape.cc \
+	hb-font.cc \
+	hb-font.hh \
+	hb-iter.hh \
+	hb-kern.hh \
+	hb-machinery.hh \
+	hb-map.cc \
+	hb-map.hh \
+	hb-meta.hh \
+	hb-ms-feature-ranges.hh \
+	hb-mutex.hh \
+	hb-null.hh \
+	hb-number.cc \
+	hb-number.hh \
+	hb-object.hh \
+	hb-open-file.hh \
+	hb-open-type.hh \
+	hb-ot-cff-common.hh \
+	hb-ot-cff1-std-str.hh \
+	hb-ot-cff1-table.cc \
+	hb-ot-cff1-table.hh \
+	hb-ot-cff2-table.cc \
+	hb-ot-cff2-table.hh \
+	hb-ot-cmap-table.hh \
+	hb-ot-color-cbdt-table.hh \
+	hb-ot-color-colr-table.hh \
+	hb-ot-color-cpal-table.hh \
+	hb-ot-color-sbix-table.hh \
+	hb-ot-color-svg-table.hh \
+	hb-ot-color.cc \
+	hb-ot-face-table-list.hh \
+	hb-ot-face.cc \
+	hb-ot-face.hh \
+	hb-ot-font.cc \
+	hb-ot-gasp-table.hh \
+	hb-ot-glyf-table.hh \
+	hb-ot-hdmx-table.hh \
+	hb-ot-head-table.hh \
+	hb-ot-hhea-table.hh \
+	hb-ot-hmtx-table.hh \
+	hb-ot-kern-table.hh \
+	hb-ot-layout-base-table.hh \
+	hb-ot-layout-common.hh \
+	hb-ot-layout-gdef-table.hh \
+	hb-ot-layout-gpos-table.hh \
+	hb-ot-layout-gsub-table.hh \
+	OT/glyf/glyf.hh \
+	OT/glyf/glyf-helpers.hh \
+	OT/glyf/loca.hh \
+	OT/glyf/path-builder.hh \
+	OT/glyf/Glyph.hh \
+	OT/glyf/GlyphHeader.hh \
+	OT/glyf/SimpleGlyph.hh \
+	OT/glyf/CompositeGlyph.hh \
+	OT/glyf/SubsetGlyph.hh \
+	OT/Layout/types.hh \
+	OT/Layout/Common/Coverage.hh \
+	OT/Layout/Common/CoverageFormat1.hh \
+	OT/Layout/Common/CoverageFormat2.hh \
+	OT/Layout/Common/RangeRecord.hh \
+	OT/Layout/GPOS/AnchorFormat1.hh \
+	OT/Layout/GPOS/AnchorFormat2.hh \
+	OT/Layout/GPOS/AnchorFormat3.hh \
+	OT/Layout/GPOS/Anchor.hh \
+	OT/Layout/GPOS/AnchorMatrix.hh \
+	OT/Layout/GPOS/ChainContextPos.hh \
+	OT/Layout/GPOS/Common.hh \
+	OT/Layout/GPOS/ContextPos.hh \
+	OT/Layout/GPOS/CursivePosFormat1.hh \
+	OT/Layout/GPOS/CursivePos.hh \
+	OT/Layout/GPOS/ExtensionPos.hh \
+	OT/Layout/GPOS/GPOS.hh \
+	OT/Layout/GPOS/LigatureArray.hh \
+	OT/Layout/GPOS/MarkArray.hh \
+	OT/Layout/GPOS/MarkBasePosFormat1.hh \
+	OT/Layout/GPOS/MarkBasePos.hh \
+	OT/Layout/GPOS/MarkLigPosFormat1.hh \
+	OT/Layout/GPOS/MarkLigPos.hh \
+	OT/Layout/GPOS/MarkMarkPosFormat1.hh \
+	OT/Layout/GPOS/MarkMarkPos.hh \
+	OT/Layout/GPOS/MarkRecord.hh \
+	OT/Layout/GPOS/PairPosFormat1.hh \
+	OT/Layout/GPOS/PairPosFormat2.hh \
+	OT/Layout/GPOS/PairPos.hh \
+	OT/Layout/GPOS/PairSet.hh \
+	OT/Layout/GPOS/PairValueRecord.hh \
+	OT/Layout/GPOS/PosLookup.hh \
+	OT/Layout/GPOS/PosLookupSubTable.hh \
+	OT/Layout/GPOS/SinglePosFormat1.hh \
+	OT/Layout/GPOS/SinglePosFormat2.hh \
+	OT/Layout/GPOS/SinglePos.hh \
+	OT/Layout/GPOS/ValueFormat.hh \
+	OT/Layout/GSUB/AlternateSet.hh \
+	OT/Layout/GSUB/AlternateSubstFormat1.hh \
+	OT/Layout/GSUB/AlternateSubst.hh \
+	OT/Layout/GSUB/ChainContextSubst.hh \
+	OT/Layout/GSUB/Common.hh \
+	OT/Layout/GSUB/ContextSubst.hh \
+	OT/Layout/GSUB/ExtensionSubst.hh \
+	OT/Layout/GSUB/GSUB.hh \
+	OT/Layout/GSUB/Ligature.hh \
+	OT/Layout/GSUB/LigatureSet.hh \
+	OT/Layout/GSUB/LigatureSubstFormat1.hh \
+	OT/Layout/GSUB/LigatureSubst.hh \
+	OT/Layout/GSUB/MultipleSubstFormat1.hh \
+	OT/Layout/GSUB/MultipleSubst.hh \
+	OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh \
+	OT/Layout/GSUB/ReverseChainSingleSubst.hh \
+	OT/Layout/GSUB/Sequence.hh \
+	OT/Layout/GSUB/SingleSubstFormat1.hh \
+	OT/Layout/GSUB/SingleSubstFormat2.hh \
+	OT/Layout/GSUB/SingleSubst.hh \
+	OT/Layout/GSUB/SubstLookup.hh \
+	OT/Layout/GSUB/SubstLookupSubTable.hh \
+	hb-ot-layout-gsubgpos.hh \
+	hb-ot-layout-jstf-table.hh \
+	hb-ot-layout.cc \
+	hb-ot-layout.hh \
+	hb-ot-map.cc \
+	hb-ot-map.hh \
+	hb-ot-math-table.hh \
+	hb-ot-math.cc \
+	hb-ot-maxp-table.hh \
+	hb-ot-meta-table.hh \
+	hb-ot-meta.cc \
+	hb-ot-metrics.cc \
+	hb-ot-metrics.hh \
+	hb-ot-name-language-static.hh \
+	hb-ot-name-language.hh \
+	hb-ot-name-table.hh \
+	hb-ot-name.cc \
+	hb-ot-os2-table.hh \
+	hb-ot-os2-unicode-ranges.hh \
+	hb-ot-post-macroman.hh \
+	hb-ot-post-table.hh \
+	hb-ot-shaper-arabic-fallback.hh \
+	hb-ot-shaper-arabic-joining-list.hh \
+	hb-ot-shaper-arabic-pua.hh \
+	hb-ot-shaper-arabic-table.hh \
+	hb-ot-shaper-arabic-win1256.hh \
+	hb-ot-shaper-arabic.cc \
+	hb-ot-shaper-arabic.hh \
+	hb-ot-shaper-default.cc \
+	hb-ot-shaper-hangul.cc \
+	hb-ot-shaper-hebrew.cc \
+	hb-ot-shaper-indic-table.cc \
+	hb-ot-shaper-indic.cc \
+	hb-ot-shaper-indic.hh \
+	hb-ot-shaper-khmer.cc \
+	hb-ot-shaper-myanmar.cc \
+	hb-ot-shaper-syllabic.cc \
+	hb-ot-shaper-syllabic.hh \
+	hb-ot-shaper-thai.cc \
+	hb-ot-shaper-use-table.hh \
+	hb-ot-shaper-use.cc \
+	hb-ot-shaper-vowel-constraints.cc \
+	hb-ot-shaper-vowel-constraints.hh \
+	hb-ot-shaper.hh \
+	hb-ot-shape-fallback.cc \
+	hb-ot-shape-fallback.hh \
+	hb-ot-shape-normalize.cc \
+	hb-ot-shape-normalize.hh \
+	hb-ot-shape.cc \
+	hb-ot-shape.hh \
+	hb-ot-stat-table.hh \
+	hb-ot-tag-table.hh \
+	hb-ot-tag.cc \
+	hb-ot-var-avar-table.hh \
+	hb-ot-var-common.hh \
+	hb-ot-var-fvar-table.hh \
+	hb-ot-var-gvar-table.hh \
+	hb-ot-var-hvar-table.hh \
+	hb-ot-var-mvar-table.hh \
+	hb-ot-var.cc \
+	hb-ot-vorg-table.hh \
+	hb-pool.hh \
+	hb-sanitize.hh \
+	hb-serialize.hh \
+	hb-set-digest.hh \
+	hb-set.cc \
+	hb-set.hh \
+	hb-shape-plan.cc \
+	hb-shape-plan.hh \
+	hb-shape.cc \
+	hb-shaper-impl.hh \
+	hb-shaper-list.hh \
+	hb-shaper.cc \
+	hb-shaper.hh \
+	hb-static.cc \
+	hb-string-array.hh \
+	hb-style.cc \
+	hb-ucd-table.hh \
+	hb-ucd.cc \
+	hb-unicode-emoji-table.hh \
+	hb-unicode.cc \
+	hb-unicode.hh \
+	hb-utf.hh \
+	hb-vector.hh \
+	hb-priority-queue.hh \
+	hb.hh \
+	$(NULL)
+
+HB_BASE_RAGEL_GENERATED_sources = \
+	hb-buffer-deserialize-json.hh \
+	hb-buffer-deserialize-text.hh \
+	hb-number-parser.hh \
+	hb-ot-shaper-indic-machine.hh \
+	hb-ot-shaper-khmer-machine.hh \
+	hb-ot-shaper-myanmar-machine.hh \
+	hb-ot-shaper-use-machine.hh \
+	$(NULL)
+HB_BASE_RAGEL_sources = \
+	hb-buffer-deserialize-json.rl \
+	hb-buffer-deserialize-text.rl \
+	hb-number-parser.rl \
+	hb-ot-shaper-indic-machine.rl \
+	hb-ot-shaper-khmer-machine.rl \
+	hb-ot-shaper-myanmar-machine.rl \
+	hb-ot-shaper-use-machine.rl \
+	$(NULL)
+
+HB_BASE_headers = \
+	hb-aat-layout.h \
+	hb-aat.h \
+	hb-blob.h \
+	hb-buffer.h \
+	hb-common.h \
+	hb-cplusplus.hh \
+	hb-deprecated.h \
+	hb-draw.h \
+	hb-face.h \
+	hb-font.h \
+	hb-map.h \
+	hb-ot-color.h \
+	hb-ot-deprecated.h \
+	hb-ot-font.h \
+	hb-ot-layout.h \
+	hb-ot-math.h \
+	hb-ot-meta.h \
+	hb-ot-metrics.h \
+	hb-ot-name.h \
+	hb-ot-shape.h \
+	hb-ot-var.h \
+	hb-ot.h \
+	hb-set.h \
+	hb-shape-plan.h \
+	hb-shape.h \
+	hb-style.h \
+	hb-unicode.h \
+	hb-version.h \
+	hb.h \
+	$(NULL)
+
+# Optional Sources and Headers with external deps
+
+HB_FT_sources = hb-ft.cc
+HB_FT_headers = hb-ft.h
+
+HB_GLIB_sources = hb-glib.cc
+HB_GLIB_headers = hb-glib.h
+
+HB_GRAPHITE2_sources = hb-graphite2.cc
+HB_GRAPHITE2_headers = hb-graphite2.h
+
+# System-dependent sources and headers
+
+HB_CORETEXT_sources = hb-coretext.cc
+HB_CORETEXT_headers = hb-coretext.h
+
+HB_DIRECTWRITE_sources = hb-directwrite.cc
+HB_DIRECTWRITE_headers = hb-directwrite.h
+
+HB_GDI_sources = hb-gdi.cc
+HB_GDI_headers = hb-gdi.h
+
+HB_UNISCRIBE_sources = hb-uniscribe.cc
+HB_UNISCRIBE_headers = hb-uniscribe.h
+
+# Sources for libharfbuzz-gobject and libharfbuzz-icu
+HB_ICU_sources = hb-icu.cc
+HB_ICU_headers = hb-icu.h
+
+# Sources for libharfbuzz-subset
+HB_SUBSET_sources = \
+	hb-number.cc \
+	hb-number.hh \
+	hb-ot-cff1-table.cc \
+	hb-ot-cff2-table.cc \
+	hb-ot-color-colrv1-closure.hh \
+	hb-ot-post-table-v2subset.hh \
+	hb-static.cc \
+	hb-subset-cff-common.cc \
+	hb-subset-cff-common.hh \
+	hb-subset-cff1.cc \
+	hb-subset-cff1.hh \
+	hb-subset-cff2.cc \
+	hb-subset-cff2.hh \
+	hb-subset-input.cc \
+	hb-subset-input.hh \
+	hb-subset-accelerator.hh \
+	hb-subset-plan.cc \
+	hb-subset-plan.hh \
+	hb-subset-repacker.cc \
+	hb-subset.cc \
+	hb-subset.hh \
+	hb-repacker.hh \
+	graph/graph.hh \
+	graph/gsubgpos-graph.hh \
+	graph/gsubgpos-context.hh \
+	graph/gsubgpos-context.cc \
+	graph/coverage-graph.hh \
+	graph/classdef-graph.hh \
+	graph/pairpos-graph.hh \
+	graph/markbasepos-graph.hh \
+	graph/split-helpers.hh \
+	graph/serialize.hh \
+	$(NULL)
+
+HB_SUBSET_headers = \
+	hb-subset.h \
+	hb-subset-repacker.h \
+	$(NULL)
+
+HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
+HB_GOBJECT_DIST_headers = hb-gobject.h hb-gobject-structs.h
+HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc
+HB_GOBJECT_ENUM_headers = hb-gobject-enums.h
+HB_GOBJECT_NODIST_sources = $(HB_GOBJECT_ENUM_sources)
+HB_GOBJECT_NODIST_headers = $(HB_GOBJECT_ENUM_headers)
+HB_GOBJECT_sources = $(HB_GOBJECT_DIST_sources) $(HB_GOBJECT_NODIST_sources)
+HB_GOBJECT_headers = $(HB_GOBJECT_DIST_headers) $(HB_GOBJECT_NODIST_headers)

+ 338 - 0
libs/harfbuzz/src/OT/Layout/Common/Coverage.hh

@@ -0,0 +1,338 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2010,2012  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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
+#define OT_LAYOUT_COMMON_COVERAGE_HH
+
+#include "../types.hh"
+#include "CoverageFormat1.hh"
+#include "CoverageFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template<typename Iterator>
+static inline void Coverage_serialize (hb_serialize_context_t *c,
+                                       Iterator it);
+
+struct Coverage
+{
+
+  protected:
+  union {
+  HBUINT16                      format;         /* Format identifier */
+  CoverageFormat1_3<SmallTypes> format1;
+  CoverageFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+  CoverageFormat1_3<MediumTypes>format3;
+  CoverageFormat2_4<MediumTypes>format4;
+#endif
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return_trace (u.format3.sanitize (c));
+    case 4: return_trace (u.format4.sanitize (c));
+#endif
+    default:return_trace (true);
+    }
+  }
+
+  /* Has interface. */
+  static constexpr unsigned SENTINEL = NOT_COVERED;
+  typedef unsigned int value_t;
+  value_t operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  /* Predicate. */
+  bool operator () (hb_codepoint_t k) const { return has (k); }
+
+  unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_coverage (glyph_id);
+    case 2: return u.format2.get_coverage (glyph_id);
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return u.format3.get_coverage (glyph_id);
+    case 4: return u.format4.get_coverage (glyph_id);
+#endif
+    default:return NOT_COVERED;
+    }
+  }
+
+  unsigned get_population () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_population ();
+    case 2: return u.format2.get_population ();
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return u.format3.get_population ();
+    case 4: return u.format4.get_population ();
+#endif
+    default:return NOT_COVERED;
+    }
+  }
+
+  template <typename Iterator,
+      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);
+
+    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 <= num_ranges * 3 ? 1 : 2;
+
+#ifndef HB_NO_BORING_EXPANSION
+    if (count && last > 0xFFFFu)
+      u.format += 2;
+#endif
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs));
+    case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return_trace (u.format3.serialize (c, glyphs));
+    case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
+    default:return_trace (false);
+    }
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto it =
+    + iter ()
+    | hb_filter (c->plan->glyph_map_gsub)
+    | hb_map_retains_sorting (c->plan->glyph_map_gsub)
+    ;
+
+    // Cache the iterator result as it will be iterated multiple times
+    // by the serialize code below.
+    hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
+    Coverage_serialize (c->serializer, glyphs.iter ());
+    return_trace (bool (glyphs));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersects (glyphs);
+    case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return u.format3.intersects (glyphs);
+    case 4: return u.format4.intersects (glyphs);
+#endif
+    default:return false;
+    }
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersects_coverage (glyphs, index);
+    case 2: return u.format2.intersects_coverage (glyphs, index);
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return u.format3.intersects_coverage (glyphs, index);
+    case 4: return u.format4.intersects_coverage (glyphs, index);
+#endif
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool collect_coverage (set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.collect_coverage (glyphs);
+    case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return u.format3.collect_coverage (glyphs);
+    case 4: return u.format4.collect_coverage (glyphs);
+#endif
+    default:return false;
+    }
+  }
+
+  template <typename IterableOut,
+	    hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+  void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
+    case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+    case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
+    case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
+#endif
+    default:return ;
+    }
+  }
+
+  struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
+  {
+    static constexpr bool is_sorted_iterator = true;
+    iter_t (const Coverage &c_ = Null (Coverage))
+    {
+      memset (this, 0, sizeof (*this));
+      format = c_.u.format;
+      switch (format)
+      {
+      case 1: u.format1.init (c_.u.format1); return;
+      case 2: u.format2.init (c_.u.format2); return;
+#ifndef HB_NO_BORING_EXPANSION
+      case 3: u.format3.init (c_.u.format3); return;
+      case 4: u.format4.init (c_.u.format4); return;
+#endif
+      default:                               return;
+      }
+    }
+    bool __more__ () const
+    {
+      switch (format)
+      {
+      case 1: return u.format1.__more__ ();
+      case 2: return u.format2.__more__ ();
+#ifndef HB_NO_BORING_EXPANSION
+      case 3: return u.format3.__more__ ();
+      case 4: return u.format4.__more__ ();
+#endif
+      default:return false;
+      }
+    }
+    void __next__ ()
+    {
+      switch (format)
+      {
+      case 1: u.format1.__next__ (); break;
+      case 2: u.format2.__next__ (); break;
+#ifndef HB_NO_BORING_EXPANSION
+      case 3: u.format3.__next__ (); break;
+      case 4: u.format4.__next__ (); break;
+#endif
+      default:                   break;
+      }
+    }
+    typedef hb_codepoint_t __item_t__;
+    __item_t__ __item__ () const { return get_glyph (); }
+
+    hb_codepoint_t get_glyph () const
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_glyph ();
+      case 2: return u.format2.get_glyph ();
+#ifndef HB_NO_BORING_EXPANSION
+      case 3: return u.format3.get_glyph ();
+      case 4: return u.format4.get_glyph ();
+#endif
+      default:return 0;
+      }
+    }
+    bool operator != (const iter_t& o) const
+    {
+      if (unlikely (format != o.format)) return true;
+      switch (format)
+      {
+      case 1: return u.format1 != o.u.format1;
+      case 2: return u.format2 != o.u.format2;
+#ifndef HB_NO_BORING_EXPANSION
+      case 3: return u.format3 != o.u.format3;
+      case 4: return u.format4 != o.u.format4;
+#endif
+      default:return false;
+      }
+    }
+    iter_t __end__ () const
+    {
+      iter_t it = {};
+      it.format = format;
+      switch (format)
+      {
+      case 1: it.u.format1 = u.format1.__end__ (); break;
+      case 2: it.u.format2 = u.format2.__end__ (); break;
+#ifndef HB_NO_BORING_EXPANSION
+      case 3: it.u.format3 = u.format3.__end__ (); break;
+      case 4: it.u.format4 = u.format4.__end__ (); break;
+#endif
+      default: break;
+      }
+      return it;
+    }
+
+    private:
+    unsigned int format;
+    union {
+#ifndef HB_NO_BORING_EXPANSION
+    CoverageFormat2_4<MediumTypes>::iter_t      format4; /* Put this one first since it's larger; helps shut up compiler. */
+    CoverageFormat1_3<MediumTypes>::iter_t      format3;
+#endif
+    CoverageFormat2_4<SmallTypes>::iter_t       format2; /* Put this one first since it's larger; helps shut up compiler. */
+    CoverageFormat1_3<SmallTypes>::iter_t       format1;
+    } u;
+  };
+  iter_t iter () const { return iter_t (*this); }
+};
+
+template<typename Iterator>
+static inline void
+Coverage_serialize (hb_serialize_context_t *c,
+                    Iterator it)
+{ c->start_embed<Coverage> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif  // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH

+ 126 - 0
libs/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh

@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2010,2012  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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+#define NOT_COVERED             ((unsigned int) -1)
+
+template <typename Types>
+struct CoverageFormat1_3
+{
+  friend struct Coverage;
+
+  protected:
+  HBUINT16      coverageFormat; /* Format identifier--format = 1 */
+  SortedArray16Of<typename Types::HBGlyphID>
+                glyphArray;     /* Array of GlyphIDs--in numerical order */
+  public:
+  DEFINE_SIZE_ARRAY (4, glyphArray);
+
+  private:
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (glyphArray.sanitize (c));
+  }
+
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    unsigned int i;
+    glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
+    return i;
+  }
+
+  unsigned get_population () const
+  {
+    return glyphArray.len;
+  }
+
+  template <typename Iterator,
+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+  bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (glyphArray.serialize (c, glyphs));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    for (const auto& g : glyphArray.as_array ())
+      if (glyphs->has (g))
+        return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  { return glyphs->has (glyphArray[index]); }
+
+  template <typename IterableOut,
+	    hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+  void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
+  {
+    unsigned count = glyphArray.len;
+    for (unsigned i = 0; i < count; i++)
+      if (glyphs.has (glyphArray[i]))
+        intersect_glyphs << glyphArray[i];
+  }
+
+  template <typename set_t>
+  bool collect_coverage (set_t *glyphs) const
+  { return glyphs->add_sorted_array (glyphArray.as_array ()); }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct iter_t
+  {
+    void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
+    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; }
+    iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
+
+    private:
+    const struct CoverageFormat1_3 *c;
+    unsigned int i;
+  };
+  private:
+};
+
+}
+}
+}
+
+#endif  // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH

+ 233 - 0
libs/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh

@@ -0,0 +1,233 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2010,2012  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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+
+#include "RangeRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct CoverageFormat2_4
+{
+  friend struct Coverage;
+
+  protected:
+  HBUINT16      coverageFormat; /* Format identifier--format = 2 */
+  SortedArray16Of<RangeRecord<Types>>
+                rangeRecord;    /* Array of glyph ranges--ordered by
+                                 * Start GlyphID. rangeCount entries
+                                 * long */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+
+  private:
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
+    return likely (range.first <= range.last)
+         ? (unsigned int) range.value + (glyph_id - range.first)
+         : NOT_COVERED;
+  }
+
+  unsigned get_population () const
+  {
+    typename Types::large_int ret = 0;
+    for (const auto &r : rangeRecord)
+      ret += r.get_population ();
+    return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
+  }
+
+  template <typename Iterator,
+      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) Write more efficiently? */
+
+    unsigned num_ranges = 0;
+    hb_codepoint_t last = (hb_codepoint_t) -2;
+    for (auto g: glyphs)
+    {
+      if (last + 1 != g)
+        num_ranges++;
+      last = g;
+    }
+
+    if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+    if (!num_ranges) return_trace (true);
+
+    unsigned count = 0;
+    unsigned range = (unsigned) -1;
+    last = (hb_codepoint_t) -2;
+    for (auto g: glyphs)
+    {
+      if (last + 1 != g)
+      {
+        range++;
+        rangeRecord[range].first = g;
+        rangeRecord[range].value = count;
+      }
+      rangeRecord[range].last = g;
+      last = g;
+      count++;
+    }
+
+    return_trace (true);
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    return hb_any (+ hb_iter (rangeRecord)
+                   | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    auto cmp = [] (const void *pk, const void *pr) -> int
+    {
+      unsigned index = * (const unsigned *) pk;
+      const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr;
+      if (index < range.value) return -1;
+      if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
+      return 0;
+    };
+
+    auto arr = rangeRecord.as_array ();
+    unsigned idx;
+    if (hb_bsearch_impl (&idx, index,
+                         arr.arrayZ, arr.length, sizeof (arr[0]),
+                         (int (*)(const void *_key, const void *_item)) cmp))
+      return arr.arrayZ[idx].intersects (*glyphs);
+    return false;
+  }
+
+  template <typename IterableOut,
+	    hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+  void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
+  {
+    for (const auto& range : rangeRecord)
+    {
+      hb_codepoint_t last = range.last;
+      for (hb_codepoint_t g = range.first - 1;
+	   glyphs.next (&g) && g <= last;)
+	intersect_glyphs << g;
+    }
+  }
+
+  template <typename set_t>
+  bool collect_coverage (set_t *glyphs) const
+  {
+    for (const auto& range: rangeRecord)
+      if (unlikely (!range.collect_coverage (glyphs)))
+        return false;
+    return true;
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct iter_t
+  {
+    void init (const CoverageFormat2_4 &c_)
+    {
+      c = &c_;
+      coverage = 0;
+      i = 0;
+      j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
+      if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
+      {
+        /* Broken table. Skip. */
+        i = c->rangeRecord.len;
+        j = 0;
+      }
+    }
+    bool __more__ () const { return i < c->rangeRecord.len; }
+    void __next__ ()
+    {
+      if (j >= c->rangeRecord[i].last)
+      {
+        i++;
+        if (__more__ ())
+        {
+          unsigned int old = coverage;
+          j = c->rangeRecord[i].first;
+          coverage = c->rangeRecord[i].value;
+          if (unlikely (coverage != old + 1))
+          {
+            /* Broken table. Skip. Important to avoid DoS.
+             * Also, our callers depend on coverage being
+             * consecutive and monotonically increasing,
+             * ie. iota(). */
+           i = c->rangeRecord.len;
+           j = 0;
+           return;
+          }
+        }
+        else
+          j = 0;
+        return;
+      }
+      coverage++;
+      j++;
+    }
+    hb_codepoint_t get_glyph () const { return j; }
+    bool operator != (const iter_t& o) const
+    { return i != o.i || j != o.j; }
+    iter_t __end__ () const
+    {
+      iter_t it;
+      it.init (*c);
+      it.i = c->rangeRecord.len;
+      it.j = 0;
+      return it;
+    }
+
+    private:
+    const struct CoverageFormat2_4 *c;
+    unsigned int i, coverage;
+    hb_codepoint_t j;
+  };
+  private:
+};
+
+}
+}
+}
+
+#endif  // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH

+ 85 - 0
libs/harfbuzz/src/OT/Layout/Common/RangeRecord.hh

@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2010,2012  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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
+#define OT_LAYOUT_COMMON_RANGERECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct RangeRecord
+{
+  typename Types::HBGlyphID     first;          /* First GlyphID in the range */
+  typename Types::HBGlyphID     last;           /* Last GlyphID in the range */
+  HBUINT16                      value;          /* Value */
+
+  DEFINE_SIZE_STATIC (2 + 2 * Types::size);
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1; }
+
+  unsigned get_population () const
+  {
+    if (unlikely (last < first)) return 0;
+    return (last - first + 1);
+  }
+
+  bool intersects (const hb_set_t &glyphs) const
+  { return glyphs.intersects (first, last); }
+
+  template <typename set_t>
+  bool collect_coverage (set_t *glyphs) const
+  { return glyphs->add_range (first, last); }
+};
+
+}
+}
+}
+
+// TODO(garretrieger): This was previously implemented using
+//    DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
+//    but that only works when there is only a single namespace level.
+//    The macro should probably be fixed so it can work in this situation.
+extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
+template <typename Spec>
+struct Null<OT::Layout::Common::RangeRecord<Spec>> {
+  static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
+    return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
+  }
+};
+
+
+#endif  // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH

+ 83 - 0
libs/harfbuzz/src/OT/Layout/GPOS/Anchor.hh

@@ -0,0 +1,83 @@
+#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
+#define OT_LAYOUT_GPOS_ANCHOR_HH
+
+#include "AnchorFormat1.hh"
+#include "AnchorFormat2.hh"
+#include "AnchorFormat3.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct Anchor
+{
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  AnchorFormat1         format1;
+  AnchorFormat2         format2;
+  AnchorFormat3         format3;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 3: return_trace (u.format3.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                   float *x, float *y) const
+  {
+    *x = *y = 0;
+    switch (u.format) {
+    case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
+    case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
+    case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
+    default:                                          return;
+    }
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    switch (u.format) {
+    case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+    case 2:
+      if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+      {
+        // AnchorFormat 2 just containins extra hinting information, so
+        // if hints are being dropped convert to format 1.
+        return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+      }
+      return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
+    case 3: return_trace (u.format3.subset (c));
+    default:return_trace (false);
+    }
+  }
+
+  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+  {
+    switch (u.format) {
+    case 1: case 2:
+      return;
+    case 3:
+      u.format3.collect_variation_indices (c);
+      return;
+    default: return;
+    }
+  }
+};
+
+}
+}
+}
+
+#endif  // OT_LAYOUT_GPOS_ANCHOR_HH

+ 46 - 0
libs/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh

@@ -0,0 +1,46 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat1
+{
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 1 */
+  FWORD         xCoordinate;            /* Horizontal value--in design units */
+  FWORD         yCoordinate;            /* Vertical value--in design units */
+  public:
+  DEFINE_SIZE_STATIC (6);
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                   float *x, float *y) const
+  {
+    hb_font_t *font = c->font;
+    *x = font->em_fscale_x (xCoordinate);
+    *y = font->em_fscale_y (yCoordinate);
+  }
+
+  AnchorFormat1* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    AnchorFormat1* out = c->embed<AnchorFormat1> (this);
+    if (!out) return_trace (out);
+    out->format = 1;
+    return_trace (out);
+  }
+};
+
+
+}
+}
+}
+
+#endif  // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH

+ 58 - 0
libs/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh

@@ -0,0 +1,58 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat2
+{
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 2 */
+  FWORD         xCoordinate;            /* Horizontal value--in design units */
+  FWORD         yCoordinate;            /* Vertical value--in design units */
+  HBUINT16      anchorPoint;            /* Index to glyph contour point */
+  public:
+  DEFINE_SIZE_STATIC (8);
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                   float *x, float *y) const
+  {
+    hb_font_t *font = c->font;
+
+#ifdef HB_NO_HINTING
+    *x = font->em_fscale_x (xCoordinate);
+    *y = font->em_fscale_y (yCoordinate);
+    return;
+#endif
+
+    unsigned int x_ppem = font->x_ppem;
+    unsigned int y_ppem = font->y_ppem;
+    hb_position_t cx = 0, cy = 0;
+    bool ret;
+
+    ret = (x_ppem || y_ppem) &&
+          font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+    *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
+    *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
+  }
+
+  AnchorFormat2* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed<AnchorFormat2> (this));
+  }
+};
+
+}
+}
+}
+
+#endif  // OT_LAYOUT_GPOS_ANCHORFORMAT2_HH

+ 100 - 0
libs/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh

@@ -0,0 +1,100 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat3
+{
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 3 */
+  FWORD         xCoordinate;            /* Horizontal value--in design units */
+  FWORD         yCoordinate;            /* Vertical value--in design units */
+  Offset16To<Device>
+                xDeviceTable;           /* Offset to Device table for X
+                                         * coordinate-- from beginning of
+                                         * Anchor table (may be NULL) */
+  Offset16To<Device>
+                yDeviceTable;           /* Offset to Device table for Y
+                                         * coordinate-- from beginning of
+                                         * Anchor table (may be NULL) */
+  public:
+  DEFINE_SIZE_STATIC (10);
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+  }
+
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                   float *x, float *y) const
+  {
+    hb_font_t *font = c->font;
+    *x = font->em_fscale_x (xCoordinate);
+    *y = font->em_fscale_y (yCoordinate);
+
+    if (font->x_ppem || font->num_coords)
+      *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
+    if (font->y_ppem || font->num_coords)
+      *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    if (unlikely (!c->serializer->embed (format))) return_trace (false);
+    if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
+    if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
+
+    unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+    if (c->plan->layout_variation_idx_delta_map->has (x_varidx))
+    {
+      int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (x_varidx));
+      if (delta != 0)
+      {
+        if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
+                                          HB_SERIALIZE_ERROR_INT_OVERFLOW))
+          return_trace (false);
+      }
+    }
+
+    unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+    if (c->plan->layout_variation_idx_delta_map->has (y_varidx))
+    {
+      int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (y_varidx));
+      if (delta != 0)
+      {
+        if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
+                                          HB_SERIALIZE_ERROR_INT_OVERFLOW))
+          return_trace (false);
+      }
+    }
+
+    if (c->plan->all_axes_pinned)
+      return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+
+    if (!c->serializer->embed (xDeviceTable)) return_trace (false);
+    if (!c->serializer->embed (yDeviceTable)) return_trace (false);
+
+    out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
+    out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
+    return_trace (out);
+  }
+
+  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+  {
+    (this+xDeviceTable).collect_variation_indices (c);
+    (this+yDeviceTable).collect_variation_indices (c);
+  }
+};
+
+
+}
+}
+}
+
+#endif  // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH

+ 77 - 0
libs/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh

@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorMatrix
+{
+  HBUINT16      rows;                   /* Number of rows */
+  UnsizedArrayOf<Offset16To<Anchor>>
+                matrixZ;                /* Matrix of offsets to Anchor tables--
+                                         * from beginning of AnchorMatrix table */
+  public:
+  DEFINE_SIZE_ARRAY (2, matrixZ);
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+  {
+    TRACE_SANITIZE (this);
+    if (!c->check_struct (this)) return_trace (false);
+    if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
+    unsigned int count = rows * cols;
+    if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (!matrixZ[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  const Anchor& get_anchor (unsigned int row, unsigned int col,
+                            unsigned int cols, bool *found) const
+  {
+    *found = false;
+    if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
+    *found = !matrixZ[row * cols + col].is_null ();
+    return this+matrixZ[row * cols + col];
+  }
+
+  template <typename Iterator,
+            hb_requires (hb_is_iterator (Iterator))>
+  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+                                  Iterator index_iter) const
+  {
+    for (unsigned i : index_iter)
+      (this+matrixZ[i]).collect_variation_indices (c);
+  }
+
+  template <typename Iterator,
+      hb_requires (hb_is_iterator (Iterator))>
+  bool subset (hb_subset_context_t *c,
+               unsigned             num_rows,
+               Iterator             index_iter) const
+  {
+    TRACE_SUBSET (this);
+
+    auto *out = c->serializer->start_embed (this);
+
+    if (!index_iter) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
+
+    out->rows = num_rows;
+    for (const unsigned i : index_iter)
+    {
+      auto *offset = c->serializer->embed (matrixZ[i]);
+      if (!offset) return_trace (false);
+      offset->serialize_subset (c, matrixZ[i], this);
+    }
+
+    return_trace (true);
+  }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */

+ 14 - 0
libs/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh

@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ChainContextPos : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */

+ 33 - 0
libs/harfbuzz/src/OT/Layout/GPOS/Common.hh

@@ -0,0 +1,33 @@
+#ifndef OT_LAYOUT_GPOS_COMMON_HH
+#define OT_LAYOUT_GPOS_COMMON_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+enum attach_type_t {
+  ATTACH_TYPE_NONE      = 0X00,
+
+  /* Each attachment should be either a mark or a cursive; can't be both. */
+  ATTACH_TYPE_MARK      = 0X01,
+  ATTACH_TYPE_CURSIVE   = 0X02,
+};
+
+/* buffer **position** var allocations */
+#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
+#define attach_type() var.u8[2] /* attachment type */
+/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
+
+template<typename Iterator, typename SrcLookup>
+static void SinglePos_serialize (hb_serialize_context_t *c,
+                                 const SrcLookup *src,
+                                 Iterator it,
+                                 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
+                                 bool all_axes_pinned);
+
+
+}
+}
+}
+
+#endif  // OT_LAYOUT_GPOS_COMMON_HH

+ 14 - 0
libs/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh

@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ContextPos : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */

+ 35 - 0
libs/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh

@@ -0,0 +1,35 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
+
+#include "CursivePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct CursivePos
+{
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  CursivePosFormat1     format1;
+  } u;
+
+  public:
+  template <typename context_t, typename ...Ts>
+  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, std::forward<Ts> (ds)...));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */

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